.
All checks were successful
Deploy blog-frontend / build-and-deploy (push) Successful in 2m30s

This commit is contained in:
wypark
2026-05-28 21:45:30 +09:00
parent 58a012621a
commit 0273cae6e4
37 changed files with 2625 additions and 1319 deletions

View File

@@ -0,0 +1,54 @@
import { clsx } from 'clsx';
export interface SegmentedControlOption<T extends string> {
label: string;
value: T;
}
interface SegmentedControlProps<T extends string> {
ariaLabel: string;
options: SegmentedControlOption<T>[];
value: T;
onChange: (value: T) => void;
className?: string;
}
export default function SegmentedControl<T extends string>({
ariaLabel,
options,
value,
onChange,
className,
}: SegmentedControlProps<T>) {
return (
<div
className={clsx(
'inline-flex h-9 rounded-full border border-[var(--color-line)] bg-white/60 p-1 shadow-sm backdrop-blur-xl dark:bg-white/10',
className,
)}
role="group"
aria-label={ariaLabel}
>
{options.map((option) => {
const isSelected = option.value === value;
return (
<button
key={option.value}
type="button"
aria-pressed={isSelected}
onClick={() => onChange(option.value)}
className={clsx(
'min-w-14 rounded-full px-3 text-sm font-semibold transition duration-150',
isSelected
? 'bg-[var(--color-text)] text-white shadow-sm dark:bg-white dark:text-black'
: 'text-[var(--color-text-muted)] hover:bg-black/[0.04] hover:text-[var(--color-text)] dark:hover:bg-white/10',
)}
>
{option.label}
</button>
);
})}
</div>
);
}