"use client" import clsx from "clsx" import { useCallback, useEffect, useMemo, useRef } from "react" import CodeBlock, { CodeBlockProps } from "../CodeBlock" import useTabs, { BaseTabType } from "../../hooks/use-tabs" import { useScrollPositionBlocker } from "../../hooks/scroll-utils" type TabType = { code?: CodeBlockProps codeBlock?: React.ReactNode } & BaseTabType type CodeTabsProps = { tabs: TabType[] className?: string group?: string } const CodeTabs = ({ tabs, className, group = "client" }: CodeTabsProps) => { const { selectedTab, changeSelectedTab } = useTabs({ tabs, group, }) const tabRefs: (HTMLButtonElement | null)[] = useMemo(() => [], []) const codeTabSelectorRef = useRef(null) const codeTabsWrapperRef = useRef(null) const { blockElementScrollPositionUntilNextRender } = useScrollPositionBlocker() const changeTabSelectorCoordinates = useCallback( (selectedTabElm: HTMLElement) => { if (!codeTabSelectorRef?.current || !codeTabsWrapperRef?.current) { return } const selectedTabsCoordinates = selectedTabElm.getBoundingClientRect() const tabsWrapperCoordinates = codeTabsWrapperRef.current.getBoundingClientRect() codeTabSelectorRef.current.style.left = `${ selectedTabsCoordinates.left - tabsWrapperCoordinates.left }px` codeTabSelectorRef.current.style.width = `${selectedTabsCoordinates.width}px` codeTabSelectorRef.current.style.height = `${selectedTabsCoordinates.height}px` }, [] ) useEffect(() => { if (codeTabSelectorRef?.current && tabRefs.length) { const selectedTabElm = tabRefs.find( (tab) => tab?.getAttribute("aria-selected") === "true" ) if (selectedTabElm) { changeTabSelectorCoordinates( selectedTabElm.parentElement || selectedTabElm ) } } }, [codeTabSelectorRef, tabRefs, changeTabSelectorCoordinates, selectedTab]) return (
    {tabs.map((tab, index) => (
  • ))}
<> {selectedTab?.code && ( )} {selectedTab?.codeBlock && <>{selectedTab.codeBlock}}
) } export default CodeTabs