import React, { createContext, useContext, useRef, useState, useEffect, useMemo } from "react"; import * as TabsPrimitive from "@radix-ui/react-tabs"; import { cls } from "../util"; import { defaultBorderMixin } from "../styles"; export type TabVariant = "standard" | "boxy" | "pill"; const TabsContext = createContext<{ variant: TabVariant }>({ variant: "standard" }); import { IconButton } from "./IconButton"; import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"; import { iconSize } from "../icons/Icon"; export type TabsProps = { value: string, children: React.ReactNode, innerClassName?: string, className?: string, variant?: TabVariant, onValueChange: (value: string) => void }; export function Tabs({ value, onValueChange, className, innerClassName, variant = "standard", children }: TabsProps) { const scrollContainerRef = useRef(null); const [showLeftScroll, setShowLeftScroll] = useState(false); const [showRightScroll, setShowRightScroll] = useState(false); const [isScrollable, setIsScrollable] = useState(false); const checkScroll = () => { if (scrollContainerRef.current) { const { scrollLeft, scrollWidth, clientWidth } = scrollContainerRef.current; setShowLeftScroll(scrollLeft > 0); setShowRightScroll(Math.ceil(scrollLeft + clientWidth) < scrollWidth); setIsScrollable(scrollWidth > clientWidth); } }; useEffect(() => { checkScroll(); window.addEventListener("resize", checkScroll); let observer: ResizeObserver; if (scrollContainerRef.current) { observer = new ResizeObserver(checkScroll); observer.observe(scrollContainerRef.current); if (scrollContainerRef.current.firstElementChild) { observer.observe(scrollContainerRef.current.firstElementChild); } } return () => { window.removeEventListener("resize", checkScroll); observer?.disconnect(); }; }, [children]); const scroll = (direction: "left" | "right") => { if (scrollContainerRef.current) { const container = scrollContainerRef.current; const scrollAmount = Math.max(container.clientWidth / 2, 200); const targetScroll = container.scrollLeft + (direction === "left" ? -scrollAmount : scrollAmount); container.scrollTo({ left: targetScroll, behavior: "smooth" }); // checkScroll will be called by onScroll event } }; const contextValue = useMemo(() => ({ variant }), [variant]); return {isScrollable && ( )}
{children}
{isScrollable && ( )}
; } export type TabProps = { value: string, className?: string, innerClassName?: string, children: React.ReactNode, disabled?: boolean }; export function Tab({ value, className, innerClassName, children, disabled }: TabProps) { const { variant } = useContext(TabsContext); return ( {children} ); }