Spaces:
Running
Running
File size: 1,593 Bytes
c03d895 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import { useRef } from 'react';
export default function Segmented({ label, options, value, onChange, variant = 'radio', className = '', itemClassName = '' }) {
const groupRef = useRef(null);
const tabs = variant === 'tabs';
function onKeyDown(e) {
const step = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[e.key];
if (!step) return;
e.preventDefault();
e.stopPropagation();
const i = options.findIndex(o => o.value === value);
const next = options[(i + step + options.length) % options.length];
onChange(next.value);
groupRef.current?.querySelector(`[data-value="${next.value}"]`)?.focus();
}
return (
<div ref={groupRef} className={className} role={tabs ? 'tablist' : 'radiogroup'} aria-label={label} onKeyDown={onKeyDown}>
{options.map(o => {
const active = o.value === value;
return (
<button
key={o.value} id={o.id} type="button" data-value={o.value}
className={`${itemClassName}${active ? ' is-active' : ''}`}
role={tabs ? 'tab' : 'radio'}
{...(tabs ? { 'aria-selected': active } : { 'aria-checked': active })}
tabIndex={active ? 0 : -1}
title={o.title}
onClick={() => onChange(o.value)}
>
{o.content ?? o.label}
</button>
);
})}
</div>
);
}
|