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>
    );
}