49 lines
1.2 KiB
TypeScript
49 lines
1.2 KiB
TypeScript
"use client"
|
|
|
|
import { cn } from "@/lib/utils"
|
|
|
|
interface SegmentedControlProps<T extends string> {
|
|
value: T
|
|
onChange: (value: T) => void
|
|
options: { value: T; label: string; count?: number }[]
|
|
className?: string
|
|
}
|
|
|
|
function SegmentedControl<T extends string>({
|
|
value,
|
|
onChange,
|
|
options,
|
|
className,
|
|
}: SegmentedControlProps<T>) {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
"flex items-center gap-1 rounded-md border border-border bg-muted/40 p-0.5 w-fit",
|
|
className,
|
|
)}
|
|
>
|
|
{options.map((option) => (
|
|
<button
|
|
key={option.value}
|
|
type="button"
|
|
aria-pressed={value === option.value}
|
|
onClick={() => onChange(option.value)}
|
|
className={cn(
|
|
"flex items-center gap-1.5 rounded px-3 py-1 text-sm transition-colors",
|
|
value === option.value
|
|
? "bg-background text-foreground shadow-sm"
|
|
: "text-muted-foreground hover:text-foreground",
|
|
)}
|
|
>
|
|
{option.label}
|
|
{option.count != null && (
|
|
<span className="text-xs tabular-nums opacity-60">{option.count}</span>
|
|
)}
|
|
</button>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export { SegmentedControl, type SegmentedControlProps }
|