SegmentedControl
SegmentedControl
둘 이상의 세그먼트로 이루어진 선형 세트를 제공하는 컴포넌트예요. 라디오 그룹 요소를 기반으로 하며, 선택된 항목 위에 떠다니는 인디케이터를 표시해요.
출처: 문서
본문
사용법 (Usage)
SegmentedControl로 둘 이상의 세그먼트를 가지는 선형 세트를 만들어요. orientation(가로/세로), fullWidth, withItemsBorders, size, radius 등의 prop을 지원해요.
import { SegmentedControl } from '@mantine/core';
function Demo() {
return (
<SegmentedControl data={['React', 'Angular', 'Vue']} />
);
}
제어 방식 (Controlled)
import { useState } from 'react';
import { SegmentedControl } from '@mantine/core';
function Demo() {
const [value, setValue] = useState('react');
return <SegmentedControl value={value} onChange={setValue} data={['react', 'angular', 'vue']} />;
}
비제어 방식 (Uncontrolled)
SegmentedControl은 네이티브 인풋 요소와 같은 방식으로 비제어 폼에서 사용할 수 있어요. 폼 제출 시 FormData 객체에 세그먼트 컨트롤 값을 포함하려면 name 속성을 설정해요. 비제어 폼에서 초기 값을 제어하려면 defaultValue prop을 사용해요.
FormData와 함께 비제어 SegmentedControl을 사용하는 예시:
import { SegmentedControl } from '@mantine/core';
function Demo() {
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
console.log('Segmented control value:', formData.get('framework'));
}}
>
<SegmentedControl name="framework" data={['react', 'angular', 'vue']} />
<button type="submit">Submit</button>
</form>
);
}
data prop
SegmentedControl은 두 가지 data 형식을 지원해요.
- 원시 값의 배열 –
value와label이 같은 때 사용 - 객체의 배열 –
value와label이 다를 때 사용
import { SegmentedControl } from '@mantine/core';
function ArrayOfStrings() {
return <SegmentedControl data={['react', 'angular', 'vue']} />;
}
function ArrayOfObjects() {
return (
<SegmentedControl
data={[
{ value: 'react', label: 'React' },
{ value: 'angular', label: 'Angular' },
{ value: 'vue', label: 'Vue' },
]}
/>
);
}
제네릭 값 타입 (Generic value type)
SegmentedControl은 제네릭 값 타입을 지원해요. 타입 인자로 원시 값(숫자, 문자열, boolean, null)을 전달할 수 있어요. 제네릭 타입은 value, defaultValue, onChange, data prop에 사용돼요.
import { SegmentedControl } from '@mantine/core';
function Demo() {
return (
<SegmentedControl<number | string>
data={[
{ value: 16, label: '16' },
{ value: 17, label: '17' },
{ value: '18+', label: '18 or older' },
]}
/>
);
}
문자열 유니온 예시:
import { SegmentedControl } from '@mantine/core';
function Demo() {
return (
<SegmentedControl<'orange' | 'grape' | 'apple'>
data={[
{ value: 'orange', label: 'Orange' },
{ value: 'grape', label: 'Grape' },
{ value: 'apple', label: 'Apple' },
]}
/>
);
}
비활성 (Disabled)
SegmentedControl 항목을 비활성화하려면 객체 배열 data 형식을 사용하고 비활성화할 항목에 disabled: true를 설정해요. 컴포넌트 전체를 비활성화하려면 disabled prop을 사용해요.
import { SegmentedControl } from '@mantine/core';
function Demo() {
return (
<>
<SegmentedControl disabled data={['Preview', 'Code', 'Export']} />
<SegmentedControl
data={[
{ value: 'preview', label: 'Preview' },
{ value: 'code', label: 'Code', disabled: true },
{ value: 'export', label: 'Export' },
]}
/>
</>
);
}
라벨로 React 노드 (React node as label)
라벨로 어떤 React 노드든 사용할 수 있어요.
import { Center, SegmentedControl } from '@mantine/core';
import { EyeIcon, CodeIcon, ArrowSquareOutIcon } from '@phosphor-icons/react';
function Demo() {
return (
<SegmentedControl
data={[
{ value: 'preview', label: (<Center><EyeIcon size={16}/></Center>) },
{ value: 'code', label: (<Center><CodeIcon size={16}/></Center>) },
{ value: 'export', label: (<Center><ArrowSquareOutIcon size={16}/></Center>) },
]}
/>
);
}
색상 (Color)
기본적으로 SegmentedControl은 라이트 색상 스킴에서 shadow가 있는 theme.white를, 인디케이터 배경에는 var(--mantine-color-dark-6)를 사용해요. color prop으로 인디케이터 background-color를 변경해요.
import { SegmentedControl } from '@mantine/core';
function Demo() {
return <SegmentedControl color="red" data={['React', 'Angular', 'Vue', 'Svelte']} />;
}
자동 대비 (Auto contrast)
SegmentedControl은 autoContrast prop을 지원해요. true로 설정하면 인디케이터 배경색에 대한 최적의 대비를 보장하도록 라벨 텍스트 색상이 자동으로 조정돼요.
import { SegmentedControl, Stack } from '@mantine/core';
function Demo() {
return (
<Stack>
<SegmentedControl color="red" data={['React', 'Angular', 'Vue', 'Svelte']} />
<SegmentedControl color="red" autoContrast data={['React', 'Angular', 'Vue', 'Svelte']} />
</Stack>
);
}
전환 (Transitions)
다음으로 전환 속성을 변경할 수 있어요.
transitionDuration– 모든 전환 지속 시간(ms), 기본값200transitionTimingFunction– 모든 전환 타이밍 함수, 기본값ease
import { SegmentedControl, Text } from '@mantine/core';
function Demo() {
return (
<>
<Text>No transitions</Text>
<SegmentedControl transitionDuration={0} data={['React', 'Angular', 'Vue', 'Svelte']} />
<Text>500ms linear transition</Text>
<SegmentedControl transitionDuration={500} transitionTimingFunction="linear" data={['React', 'Angular', 'Vue', 'Svelte']} />
</>
);
}
readOnly
readOnly prop을 설정하면 값을 변경할 수 없어요.
import { SegmentedControl } from '@mantine/core';
function Demo() {
return <SegmentedControl readOnly defaultValue="react" data={['React', 'Angular', 'Vue']} />;
}
Styles API
SegmentedControl은 Styles API를 지원해요. classNames prop으로 컴포넌트의 내부 요소에 스타일을 추가할 수 있어요.
Styles API 셀렉터:
root– 루트 요소control– 인풋과 라벨의 래퍼 요소input– 인풋 요소 (input[type="radio"]), 기본적으로 숨김label– 인풋과 연결된 라벨 요소indicator– 항목 사이를 이동하는 떠다니는 인디케이터innerLabel– 라벨 요소 children의 래퍼
접근성과 사용성 (Accessibility and usability)
SegmentedControl은 내부적으로 라디오 인풋을 사용하므로, 라벨에 텍스트가 있으면 추가 단계 없이 기본적으로 접근 가능해요. 컴포넌트는 일반 라디오 그룹과 동일한 키보드 이벤트를 지원해요.
라벨에 텍스트가 없다면(예: 아이콘만 사용하는 SegmentedControl), VisuallyHidden을 사용해 컴포넌트를 접근 가능하게 만들어요.
import { SegmentedControl, VisuallyHidden } from '@mantine/core';
import { EyeIcon, CodeIcon, ArrowSquareOutIcon } from '@phosphor-icons/react';
function Demo() {
const iconProps = { style: { display: 'block' }, size: 20 };
return (
<SegmentedControl
data={[
{ value: 'preview', label: (<><VisuallyHidden>Preview</VisuallyHidden><EyeIcon {...iconProps} /></>) },
{ value: 'code', label: (<><VisuallyHidden>Code</VisuallyHidden><CodeIcon {...iconProps} /></>) },
{ value: 'export', label: (<><VisuallyHidden>Export</VisuallyHidden><ArrowSquareOutIcon {...iconProps} /></>) },
]}
/>
);
}