@@ -0,0 +1,66 @@
|
||||
import { type ComponentPropsWithoutRef, useEffect, useRef } from 'react';
|
||||
import { ToggleGroup as RToggleGroup } from 'radix-ui';
|
||||
import { cx } from '../utils';
|
||||
|
||||
type SegProps = Omit<
|
||||
ComponentPropsWithoutRef<typeof RToggleGroup.Root>,
|
||||
'type' | 'onValueChange' | 'defaultValue' | 'value'
|
||||
> & {
|
||||
value: string;
|
||||
defaultValue?: string;
|
||||
onValueChange: (v: string) => void;
|
||||
items: Array<{ value: string; label: string }>;
|
||||
};
|
||||
|
||||
export const SegmentedControl = ({
|
||||
value,
|
||||
onValueChange,
|
||||
items,
|
||||
className,
|
||||
...props
|
||||
}: SegProps) => {
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
const thumbRef = useRef<HTMLSpanElement>(null);
|
||||
const initialized = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const root = rootRef.current;
|
||||
const thumb = thumbRef.current;
|
||||
if (!root || !thumb) return;
|
||||
const selected = root.querySelector<HTMLElement>('[data-state="on"]');
|
||||
if (!selected) return;
|
||||
|
||||
if (!initialized.current) {
|
||||
thumb.style.transition = 'none';
|
||||
}
|
||||
thumb.style.transform = `translateX(${selected.offsetLeft}px)`;
|
||||
thumb.style.width = `${selected.offsetWidth}px`;
|
||||
if (!initialized.current) {
|
||||
thumb.getBoundingClientRect();
|
||||
thumb.style.transition = '';
|
||||
initialized.current = true;
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<RToggleGroup.Root
|
||||
ref={rootRef}
|
||||
type="single"
|
||||
className={cx('mta-seg', className)}
|
||||
value={value}
|
||||
onValueChange={(v) => v && onValueChange(v)}
|
||||
{...props}
|
||||
>
|
||||
<span ref={thumbRef} className="mta-seg__thumb" aria-hidden />
|
||||
{items.map((it) => (
|
||||
<RToggleGroup.Item
|
||||
key={it.value}
|
||||
value={it.value}
|
||||
className="mta-seg__item"
|
||||
>
|
||||
{it.label}
|
||||
</RToggleGroup.Item>
|
||||
))}
|
||||
</RToggleGroup.Root>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user