Switch
Switch
사용자로부터 불리언(참/거짓) 입력을 받는 컴포넌트예요. 네이티브 input[type="checkbox"] 기반이에요.
출처: 문서
본문
사용법 (Usage)
Switch 컴포넌트로 색상, 라벨 위치, 설명, 오류, 크기, 반경(radius), 비활성 상태 등을 지정할 수 있어요.
import { Switch } from '@mantine/core';
function Demo() {
return <Switch label="I agree to sell my privacy" />;
}
제어 컴포넌트 (Controlled)
import { useState } from 'react';
import { Switch } from '@mantine/core';
function Demo() {
const [checked, setChecked] = useState(false);
return (
<Switch
checked={checked}
onChange={(event) => setChecked(event.currentTarget.checked)}
/>
);
}
비제어 컴포넌트 (Uncontrolled)
Switch는 네이티브 input[type="checkbox"]와 같은 방식으로 비제어 폼과 함께 사용할 수 있어요. 폼 제출 시 FormData 객체에 스위치 값을 포함하려면 name 속성을 설정해요. 비제어 폼에서 초기 체크 상태를 제어하려면 defaultChecked prop을 사용해요.
import { Switch } from '@mantine/core';
function Demo() {
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
console.log('Switch value:', !!formData.get('notifications'));
}}
>
<Switch name="notifications" label="Enable notifications" />
<button type="submit">Submit</button>
</form>
);
}
상태 (States)
기본 스위치, 체크된 스위치, 비활성 스위치, 체크된 비활성 스위치 등 다양한 상태를 만들 수 있어요.
import { Switch, Stack } from '@mantine/core';
function Demo() {
return (
<Stack>
<Switch label="Default switch" />
<Switch label="Checked switch" defaultChecked />
<Switch label="Disabled switch" disabled />
<Switch label="Disabled checked switch" disabled defaultChecked />
</Stack>
);
}
내부 라벨 (Inner Labels)
onLabel과 offLabel prop으로 스위치 트랙 안쪽에 라벨을 표시할 수 있어요.
import { Switch, Group } from '@mantine/core';
function Demo() {
return <Switch onLabel="ON" offLabel="OFF" />;
}
아이콘 라벨 (Icon labels)
스위치 온/오프 상태에 아이콘을 표시할 수 있어요.
import { Switch } from '@mantine/core';
import { SunIcon, MoonStarsIcon } from '@phosphor-icons/react';
function Demo() {
return (
<Switch
onLabel={<SunIcon size={16} />}
offLabel={<MoonStarsIcon size={16} />}
/>
);
}
썸 아이콘 (Thumb icon)
thumbIcon prop으로 스위치 썸(thumb) 안에 아이콘을 표시할 수 있어요.
import { useState } from 'react';
import { Switch } from '@mantine/core';
import { CheckIcon, XIcon } from '@phosphor-icons/react';
function Demo() {
const [checked, setChecked] = useState(false);
return (
<Switch
checked={checked}
onChange={(event) => setChecked(event.currentTarget.checked)}
color="teal"
size="md"
label="Switch with thumb icon"
thumbIcon={checked ? <CheckIcon size={14} /> : <XIcon size={14} />}
/>
);
}
툴팁과 함께 (With tooltip)
Tooltip 및 이와 유사한 컴포넌트에 refProp="rootRef"를 설정하면 Switch와 함께 동작하게 할 수 있어요.
import { Switch, Tooltip } from '@mantine/core';
function Demo() {
return (
<Tooltip label="Switch with tooltip" refProp="rootRef">
<Switch label="Switch" />
</Tooltip>
);
}
포인터 커서 (Pointer cursor)
기본적으로 스위치 입력과 라벨은 네이티브 input[type="checkbox"]와 같이 cursor: default를 사용해요. 커서를 포인터로 바꾸려면 theme에서 cursorType을 설정해요.
import { createTheme, MantineProvider, Switch } from '@mantine/core';
const theme = createTheme({
cursorType: 'pointer',
});
루트 요소에 props 추가하기 (Add props to the root element)
컴포넌트에 전달된 모든 props는 입력 요소로 전달돼요. 루트 요소에 props를 추가하려면 wrapperProps를 사용해요. 예를 들어 data-testid="wrapper"는 루트 요소에, data-testid="input"은 입력 요소에 추가돼요.
import { Switch } from '@mantine/core';
function Demo() {
return (
<Switch
label="Switch"
wrapperProps={{ 'data-testid': 'wrapper' }}
inputProps={{ 'data-testid': 'input' }}
/>
);
}
Switch.Group
여러 Switch를 묶어 그룹으로 만들 수 있어요. 라벨, 설명, 오류, 별표(asterisk) 등을 지원해요.
import { Switch, Group } from '@mantine/core';
function Demo() {
return (
<Switch.Group label="Select your favorite framework/library" description="This is anonymous" withAsterisk>
<Group mt="xs">
<Switch value="react" label="React" />
<Switch value="svelte" label="Svelte" />
<Switch value="angular" label="Angular" />
<Switch value="vue" label="Vue" />
</Group>
</Switch.Group>
);
}
비제어 폼과 함께 사용하는 Switch.Group (Switch.Group with uncontrolled forms)
Switch.Group는 비제어 폼과 함께 사용할 수 있어요. 체크된 모든 값을 hiddenInputValuesSeparator prop으로 하나의 문자열로 합치는 숨은 입력(hidden input)을 렌더링해요.
비제어 폼 사용을 위한 props:
name– 숨은 입력에 전달되는 name 속성hiddenInputValuesSeparator– 체크된 값을 하나의 문자열로 합치는 데 사용되는 문자열, 기본값','hiddenInputProps– 숨은 입력에 전달되는 추가 props
function UncontrolledForm() {
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
console.log('Switch group value:', formData.get('frameworks'));
}}
>
<Switch.Group name="frameworks" label="Select your favorite frameworks">
<Switch value="react" label="React" />
<Switch value="svelte" label="Svelte" />
</Switch.Group>
<button type="submit">Submit</button>
</form>
);
}
maxSelectedValues
maxSelectedValues prop으로 Switch.Group에서 선택할 수 있는 값의 개수를 제한할 수 있어요. 한도에 도달하면 나머지 스위치는 비활성화되어 선택할 수 없어요.
import { Group, Switch } from '@mantine/core';
function Demo() {
return (
<Switch.Group label="Select your favorite framework" maxSelectedValues={2}>
<Group mt="xs">
<Switch value="react" label="React" />
<Switch value="svelte" label="Svelte" />
<Switch value="angular" label="Angular" />
<Switch value="vue" label="Vue" />
</Group>
</Switch.Group>
);
}
비활성 Switch.Group (Switch.Group disabled)
import { Switch, Group } from '@mantine/core';
function Demo() {
return (
<Switch.Group label="Select your favorite framework/library" description="This is anonymous" disabled>
<Group mt="xs">
<Switch value="react" label="React" />
<Switch value="svelte" label="Svelte" />
<Switch value="angular" label="Angular" />
<Switch value="vue" label="Vue" />
</Group>
</Switch.Group>
);
}
제어 Switch.Group (Controlled Switch.Group)
import { useState } from 'react';
import { Switch } from '@mantine/core';
function Demo() {
const [value, setValue] = useState<string[]>([]);
return <Switch.Group value={value} onChange={setValue} />;
}
체크 상태에 따른 스타일 변경 (Change styles based on checked state)
input:checked + & 선택자를 사용해 체크 상태에 따른 스타일을 지정할 수 있어요.
.track {
transition:
background-color 200ms ease,
border-color 200ms ease;
input:checked + & {
background-color: var(--mantine-color-lime-5);
border-color: var(--mantine-color-lime-5);
& > .thumb {
background-color: var(--mantine-color-black);
&::before {
background-color: var(--mantine-color-lime-5);
}
}
}
}
Styles API
Switch는 Styles API를 지원해요. classNames prop으로 컴포넌트의 내부 요소에 스타일을 추가할 수 있어요. 자세한 내용은 Styles API 문서를 참고해요.
| selector | 설명 |
|---|---|
| root | 루트 요소 |
| track | 스위치 트랙, thumb과 trackLabel을 포함해요 |
| trackLabel | track 안에 표시되는 라벨 |
| thumb | track 안에 표시되는 썸 |
| input | 입력 요소(input[type="checkbox"]), 기본적으로 숨겨져 있어요 |
| body | 입력 바디, 다른 모든 요소를 포함해요 |
| labelWrapper | label, description, error를 포함해요 |
| label | 라벨 요소 |
| description | 라벨 아래에 표시되는 설명 |
| error | 라벨 아래에 표시되는 오류 메시지 |
입력 ref 가져오기 (Get input ref)
import { useRef } from 'react';
import { Switch } from '@mantine/core';
function Demo() {
const ref = useRef<HTMLInputElement>(null);
return <Switch ref={ref} />;
}
접근성 (Accessibility)
Switch는 일반적인 input[type="checkbox"]예요. Switch를 label prop 없이 사용하면 입력에 라벨이 없으므로 aria-label을 설정해야 해요.
import { Switch } from '@mantine/core';
// -> ok, input has aria-label
function Good() {
return <Switch aria-label="Enable notifications" />;
}
// -> ok, input has associated label
function AlsoGood() {
return <Switch label="Enable notifications" />;
}