54 lines
1.3 KiB
TypeScript
54 lines
1.3 KiB
TypeScript
|
|
import { memo } from 'react';
|
||
|
|
|
||
|
|
export const Segmented = memo(function Segmented<T extends string>({
|
||
|
|
options,
|
||
|
|
value,
|
||
|
|
onChange,
|
||
|
|
size = 'md',
|
||
|
|
testid,
|
||
|
|
}: {
|
||
|
|
options: { value: T; label: string }[];
|
||
|
|
value: T;
|
||
|
|
onChange: (v: T) => void;
|
||
|
|
size?: 'sm' | 'md';
|
||
|
|
testid?: string;
|
||
|
|
}): JSX.Element {
|
||
|
|
const sizeClasses = size === 'sm'
|
||
|
|
? 'px-2.5 py-0.5 text-xs'
|
||
|
|
: 'px-3.5 py-1 text-[13px]';
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
data-testid={testid}
|
||
|
|
className="inline-flex items-center gap-0.5 rounded-full bg-bg-hover p-0.5"
|
||
|
|
>
|
||
|
|
{options.map((opt) => {
|
||
|
|
const isActive = opt.value === value;
|
||
|
|
return (
|
||
|
|
<button
|
||
|
|
key={opt.value}
|
||
|
|
type="button"
|
||
|
|
data-testid={testid ? `${testid}-${opt.value}` : undefined}
|
||
|
|
onClick={() => onChange(opt.value)}
|
||
|
|
className={[
|
||
|
|
'rounded-full font-medium transition-colors',
|
||
|
|
sizeClasses,
|
||
|
|
isActive
|
||
|
|
? 'bg-primary text-white shadow-sm'
|
||
|
|
: 'text-text-secondary hover:bg-bg-active',
|
||
|
|
].join(' ')}
|
||
|
|
>
|
||
|
|
{opt.label}
|
||
|
|
</button>
|
||
|
|
);
|
||
|
|
})}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}) as <T extends string>(props: {
|
||
|
|
options: { value: T; label: string }[];
|
||
|
|
value: T;
|
||
|
|
onChange: (v: T) => void;
|
||
|
|
size?: 'sm' | 'md';
|
||
|
|
testid?: string;
|
||
|
|
}) => JSX.Element;
|