chore: consolidate platform split checks
This commit is contained in:
76
webui/src/components/SegmentedControl.tsx
Normal file
76
webui/src/components/SegmentedControl.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
export type SegmentedControlSize = "content" | "equal";
|
||||
export type SegmentedControlWidth = "inline" | "fill";
|
||||
|
||||
export type SegmentedControlOption<TValue extends string = string> = {
|
||||
id: TValue;
|
||||
label: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
title?: string;
|
||||
ariaLabel?: string;
|
||||
};
|
||||
|
||||
export type SegmentedControlProps<TValue extends string = string> = {
|
||||
options: Array<SegmentedControlOption<TValue>>;
|
||||
value: TValue;
|
||||
onChange: (value: TValue) => void;
|
||||
ariaLabel?: string;
|
||||
ariaLabelledBy?: string;
|
||||
className?: string;
|
||||
optionClassName?: string;
|
||||
disabled?: boolean;
|
||||
role?: "group" | "tablist";
|
||||
size?: SegmentedControlSize;
|
||||
width?: SegmentedControlWidth;
|
||||
};
|
||||
|
||||
export default function SegmentedControl<TValue extends string = string>({
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
ariaLabel,
|
||||
ariaLabelledBy,
|
||||
className = "",
|
||||
optionClassName = "",
|
||||
disabled = false,
|
||||
role = "tablist",
|
||||
size = "content",
|
||||
width = "inline"
|
||||
}: SegmentedControlProps<TValue>) {
|
||||
const rootClassName = [
|
||||
"segmented-control",
|
||||
`segmented-control-size-${size}`,
|
||||
`segmented-control-width-${width}`,
|
||||
className
|
||||
].filter(Boolean).join(" ");
|
||||
const optionRole = role === "tablist" ? "tab" : undefined;
|
||||
|
||||
return (
|
||||
<div className={rootClassName} role={role} aria-label={ariaLabel} aria-labelledby={ariaLabelledBy}>
|
||||
{options.map((option) => {
|
||||
const selected = option.id === value;
|
||||
const buttonClassName = [
|
||||
"segmented-control-option",
|
||||
selected ? "is-active" : "",
|
||||
optionClassName
|
||||
].filter(Boolean).join(" ");
|
||||
|
||||
return (
|
||||
<button
|
||||
key={option.id}
|
||||
type="button"
|
||||
role={optionRole}
|
||||
aria-selected={role === "tablist" ? selected : undefined}
|
||||
aria-pressed={role === "group" ? selected : undefined}
|
||||
aria-label={option.ariaLabel}
|
||||
title={option.title}
|
||||
className={buttonClassName}
|
||||
disabled={disabled || option.disabled}
|
||||
onClick={() => onChange(option.id)}
|
||||
>
|
||||
{option.label}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user