Files

50 lines
2.1 KiB
TypeScript

"use client"
import { createContext, useContext, useId, type ComponentProps } from "react"
import {
Stepper as RegistryStepper,
StepperNav as RegistryNav,
StepperContent as RegistryContent,
StepperTrigger as RegistryTrigger,
useStepItem,
type StepperProps,
} from "@/components/reui/stepper"
export { StepperItem, StepperIndicator, StepperSeparator, StepperTitle, StepperPanel } from "@/components/reui/stepper"
// The registry Nav/Content do not forward HTML attributes. Keep its layout,
// focus handling and styling; supply tab semantics in transparent wrappers.
const Context = createContext<{ prefix: string; orientation: "horizontal" | "vertical" } | null>(null)
function useScope() {
const context = useContext(Context)
if (!context) throw new Error("Шаги должны находиться внутри Stepper")
return context
}
export function Stepper({ orientation = "horizontal", ...props }: StepperProps) {
const prefix = useId()
return <Context.Provider value={{ prefix, orientation }}>
<RegistryStepper {...props} orientation={orientation} role="group" aria-orientation={undefined} />
</Context.Provider>
}
export function StepperNav({ children, className }: Pick<ComponentProps<typeof RegistryNav>, "children" | "className">) {
const { orientation } = useScope()
return <RegistryNav className={className}>
<div role="tablist" aria-label="Шаги формы" aria-orientation={orientation} className="contents">{children}</div>
</RegistryNav>
}
export function StepperTrigger(props: ComponentProps<typeof RegistryTrigger>) {
const { prefix } = useScope()
const { step } = useStepItem()
return <RegistryTrigger {...props} id={`${prefix}-tab-${step}`} aria-controls={`${prefix}-panel-${step}`} />
}
export function StepperContent({ value, children, className }: Pick<ComponentProps<typeof RegistryContent>, "value" | "children" | "className">) {
const { prefix } = useScope()
return <RegistryContent value={value} forceMount className={className}>
<div role="tabpanel" id={`${prefix}-panel-${value}`} aria-labelledby={`${prefix}-tab-${value}`} className="contents">{children}</div>
</RegistryContent>
}