Checkbox
Checkbox (체크박스)
Checkbox 컴포넌트는 사용자로부터 불리언(boolean) 입력을 받는 컴포넌트예요. 네이티브 input[type="checkbox"]를 기반으로 하며 기본적으로 접근 가능해요.
출처: 문서
본문
Checkbox로 선택 여부를 나타내는 입력을 만들 수 있어요.
import { Checkbox } from '@mantine/core';
function Demo() {
return (
<Checkbox
defaultChecked
label="I agree to sell my privacy"
/>
);
}
제어 상태 (Controlled state)
checked와 onChange prop으로 Checkbox 상태를 제어할 수 있어요.
import { useState } from 'react';
import { Checkbox } from '@mantine/core';
function Demo() {
const [checked, setChecked] = useState(false);
return (
<Checkbox
checked={checked}
onChange={(event) => setChecked(event.currentTarget.checked)}
/>
);
}
읽기 전용 (Read only)
readOnly prop을 설정하면 사용자 상호작용으로 체크박스 값을 바꿀 수 없게 돼요. 체크박스는 현재 값을 계속 표시하고 checked prop의 프로그래밍 업데이트를 반영하지만, 클릭(또는 Space 키)해도 상태가 토글되지 않고 onChange 핸들러도 호출되지 않아요.
import { useState } from 'react';
import { Checkbox } from '@mantine/core';
function Demo() {
const [checked, setChecked] = useState(true);
return (
<>
<Checkbox checked={checked} readOnly label="Read only checkbox" />
<button type="button" onClick={() => setChecked((c) => !c)}>
Toggle from outside
</button>
</>
);
}
@mantine/form과 함께 사용하기
@mantine/form과 Checkbox를 사용하는 예시:
import { Button, Checkbox } from '@mantine/core';
import { isNotEmpty, useForm } from '@mantine/form';
function Demo() {
const form = useForm({
mode: 'uncontrolled',
initialValues: { terms: false },
validate: {
terms: isNotEmpty('You must accept terms and conditions'),
},
});
return (
<form onSubmit={form.onSubmit((values) => console.log(values))}>
<Checkbox
label="I accept the terms and conditions"
key={form.key('terms')}
{...form.getInputProps('terms', { type: 'checkbox' })}
/>
<Button type="submit" mt="md">
Submit
</Button>
</form>
);
}
비제어 폼과 함께 사용하기
Checkbox는 네이티브 input[type="checkbox"]처럼 비제어 폼에서도 사용할 수 있어요. 폼 제출 시 FormData 객체에 체크박스 값을 포함하려면 name 속성을 설정해요. 비제어 폼에서 초기 체크 상태를 제어하려면 defaultChecked prop을 사용해요.
import { Checkbox } from '@mantine/core';
function Demo() {
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
console.log('Checkbox value:', !!formData.get('terms'));
}}
>
<Checkbox label="Accept terms and conditions" name="terms" defaultChecked />
<button type="submit">Submit</button>
</form>
);
}
상태 (States)
Checkbox는 variant(기본/outline), 체크, indeterminate, disabled 상태를 지원해요.
import { Checkbox, Stack } from '@mantine/core';
function Demo() {
return (
<Stack>
<Checkbox checked={false} onChange={() => {}} label="Default checkbox" />
<Checkbox checked={false} onChange={() => {}} indeterminate label="Indeterminate checkbox" />
<Checkbox checked onChange={() => {}} label="Checked checkbox" />
<Checkbox checked variant="outline" onChange={() => {}} label="Outline checked checkbox" />
<Checkbox
variant="outline"
onChange={() => {}}
indeterminate
label="Outline indeterminate checkbox"
/>
<Checkbox disabled label="Disabled checkbox" />
<Checkbox disabled checked onChange={() => {}} label="Disabled checked checkbox" />
<Checkbox disabled indeterminate label="Disabled indeterminate checkbox" />
</Stack>
);
}
오류 상태 (Error state)
error prop으로 체크박스 라벨 아래에 오류 메시지를 표시할 수 있어요. 오류 메시지 없이 체크박스에 오류 스타일을 적용하려면 boolean error prop을 사용해요. 오류 스타일 없이 오류 메시지만 표시하려면 withErrorStyles={false}를 설정해요.
import { Checkbox, Stack } from '@mantine/core';
function Demo() {
return (
<Stack>
<Checkbox label="With boolean error" error />
<Checkbox label="With error message" error="Must be checked" />
<Checkbox label="With error message" error="No error styles" withErrorStyles={false} />
</Stack>
);
}
아이콘 바꾸기 (Change icons)
icon prop으로 체크 아이콘을 바꿀 수 있어요.
import { Checkbox, CheckboxIconComponent } from '@mantine/core';
import { BiohazardIcon, RadioactiveIcon } from '@phosphor-icons/react';
const CheckboxIcon: CheckboxIconComponent = ({ indeterminate, ...others }) =>
indeterminate ? <RadioactiveIcon {...others} /> : <BiohazardIcon {...others} />;
function Demo() {
return (
<>
<Checkbox icon={CheckboxIcon} label="Custom icon" defaultChecked />
<Checkbox icon={CheckboxIcon} label="Custom icon: indeterminate" indeterminate mt="sm" />
</>
);
}
아이콘 색상 바꾸기 (Change icon color)
iconColor prop으로 아이콘 색상을 바꿀 수 있어요. theme.colors의 색상을 참조하거나 유효한 CSS 색상을 사용할 수 있어요.
import { Checkbox } from '@mantine/core';
function Demo() {
return (
<Checkbox
defaultChecked
color="lime.4"
iconColor="dark.8"
size="md"
label="Bright lime checkbox"
/>
);
}
Indeterminate 상태 (Indeterminate state)
Checkbox는 indeterminate 상태를 지원해요. indeterminate prop이 설정되면 checked prop은 무시돼요(체크박스는 항상 체크 스타일을 가짐).
import { useListState, randomId } from '@mantine/hooks';
import { Checkbox } from '@mantine/core';
const initialValues = [
{ label: 'Receive email notifications', checked: false, key: randomId() },
{ label: 'Receive sms notifications', checked: false, key: randomId() },
{ label: 'Receive push notifications', checked: false, key: randomId() },
];
export function IndeterminateCheckbox() {
const [values, handlers] = useListState(initialValues);
const allChecked = values.every((value) => value.checked);
const indeterminate = values.some((value) => value.checked) && !allChecked;
const items = values.map((value, index) => (
<Checkbox
mt="xs"
ml={33}
label={value.label}
key={value.key}
checked={value.checked}
onChange={(event) => handlers.setItemProp(index, 'checked', event.currentTarget.checked)}
/>
));
return (
<>
<Checkbox
checked={allChecked}
indeterminate={indeterminate}
label="Receive all notifications"
onChange={() =>
handlers.setState((current) =>
current.map((value) => ({ ...value, checked: !allChecked }))
)
}
/>
{items}
</>
);
}
링크가 있는 라벨 (Label with link)
라벨에 React 노드를 전달해 링크를 포함할 수 있어요.
import { Checkbox, Anchor } from '@mantine/core';
function Demo() {
return (
<Checkbox
label={
<>
I accept{' '}
<Anchor href="https://mantine.dev" target="_blank" inherit>
terms and conditions
</Anchor>
</>
}
/>
);
}
툴팁이 있는 Checkbox
refProp으로 툴팁이 연결되는 대상 요소를 바꿀 수 있어요.
refProp이 설정되지 않으면 툴팁은 체크박스 input에 연결돼요refProp="rootRef"가 설정되면 툴팁은 루트 요소(라벨·input·다른 요소 포함)에 연결돼요
import { Tooltip, Checkbox } from '@mantine/core';
function Demo() {
return (
<>
<Tooltip label="Checkbox with tooltip">
<Checkbox label="Tooltip on checkbox only" />
</Tooltip>
<Tooltip label="Checkbox with tooltip" refProp="rootRef">
<Checkbox label="Tooltip the entire element" mt="md" />
</Tooltip>
</>
);
}
포인터 커서 (Pointer cursor)
기본적으로 체크박스 input과 라벨은 cursor: default(네이티브 input[type="checkbox"]와 동일)예요. 커서를 포인터로 바꾸려면 theme에 cursorType을 설정해요.
import { MantineProvider, createTheme, Checkbox } from '@mantine/core';
const theme = createTheme({
cursorType: 'pointer',
});
function Demo() {
return (
<>
<Checkbox label="Default cursor" />
<MantineProvider theme={theme}>
<Checkbox label="Pointer cursor" mt="md" />
</MantineProvider>
</>
);
}
autoContrast
Checkbox는 autoContrast prop과 theme.autoContrast를 지원해요. Checkbox나 테마에 autoContrast가 설정되면, color prop에 지정된 값과 충분한 대비를 가지도록 콘텐츠 색상이 조정돼요.
주의: autoContrast 기능은 배경색을 바꾸기 위해 color prop을 사용할 때만 동작해요. autoContrast는 filled variant에서만 동작해요.
import { Checkbox, Stack } from '@mantine/core';
function Demo() {
return (
<Stack>
<Checkbox checked label="regular checkbox" size="lg" color="lime.4" />
<Checkbox autoContrast checked label="autoContrast checkbox" size="lg" color="lime.4" />
</Stack>
);
}
커스텀 크기 추가
data-size 속성으로 커스텀 크기를 추가할 수 있어요.
import { MantineProvider, Checkbox, createTheme } from '@mantine/core';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
Checkbox: Checkbox.extend({ classNames: classes }),
},
});
function Demo() {
return (
<MantineProvider theme={theme}>
<Checkbox size="xxs" label="Extra small checkbox" />
<Checkbox size="xxl" label="Extra large checkbox" mt="md" />
</MantineProvider>
);
}
루트 요소에 prop 추가하기
컴포넌트에 전달된 모든 prop은 input 요소로 전달돼요. 루트 요소에 prop을 추가하려면 wrapperProps를 사용해요. 다음 예시에서:
data-testid="wrapper"는 루트 요소에 추가돼요data-testid="input"은 input 요소에 추가돼요
import { Checkbox } from '@mantine/core';
function Demo() {
return <Checkbox wrapperProps={{ 'data-testid': 'wrapper' }} data-testid="input" />;
}
Checkbox.Group
Checkbox.Group은 여러 체크박스의 상태를 관리해요. value와 onChange prop을 받아 그룹 안의 체크박스 상태를 제어해요. value prop은 문자열 배열이어야 하며, 각 문자열은 체크박스의 값이에요. onChange prop은 새 값을 문자열 배열로 받는 함수여야 해요.
import { useState } from 'react';
import { Checkbox } from '@mantine/core';
function Demo() {
const [value, setValue] = useState<string[]>([]);
return (
<Checkbox.Group value={value} onChange={setValue}>
<Checkbox value="react" label="React" />
<Checkbox value="svelte" label="Svelte" />
</Checkbox.Group>
);
}
Checkbox.Group 컴포넌트는 모든 Input.Wrapper props를 지원해요.
import { Checkbox, Group } from '@mantine/core';
function Demo() {
return (
<Checkbox.Group
defaultValue={['react']}
label="Select your favorite frameworks/libraries"
description="This is anonymous"
withAsterisk
>
<Group mt="xs">
<Checkbox value="react" label="React" />
<Checkbox value="svelte" label="Svelte" />
<Checkbox value="ng" label="Angular" />
<Checkbox value="vue" label="Vue" />
</Group>
</Checkbox.Group>
);
}
Checkbox.Group 비활성화
disabled prop으로 그룹 안의 모든 체크박스를 비활성화할 수 있어요.
import { Checkbox } from '@mantine/core';
function Demo() {
return (
<Checkbox.Group disabled>
<Stack>
<Checkbox value="react" label="React" />
<Checkbox value="svelte" label="Svelte" />
<Checkbox value="angular" label="Angular" />
<Checkbox value="vue" label="Vue" />
</Stack>
</Checkbox.Group>
);
}
maxSelectedValues
maxSelectedValues prop으로 Checkbox.Group에서 선택할 수 있는 값의 수를 제한할 수 있어요. 한도에 도달하면 나머지 체크박스는 비활성화되어 선택할 수 없어요.
import { Checkbox, Group } from '@mantine/core';
function Demo() {
return (
<Checkbox.Group defaultValue={['react']} maxSelectedValues={2}>
<Group>
<Checkbox value="react" label="React" />
<Checkbox value="svelte" label="Svelte" />
<Checkbox value="ng" label="Angular" />
<Checkbox value="vue" label="Vue" />
</Group>
</Checkbox.Group>
);
}
@mantine/form과 함께 쓰는 Checkbox.Group
import { Button, Checkbox, Group } from '@mantine/core';
import { hasLength, useForm } from '@mantine/form';
interface FormValues {
frameworks: string[];
}
function Demo() {
const form = useForm<FormValues>({
mode: 'uncontrolled',
initialValues: { frameworks: [] },
validate: {
frameworks: hasLength({ min: 1 }, 'Select at least one framework'),
},
});
return (
<form onSubmit={form.onSubmit((values) => console.log(values))}>
<Checkbox.Group
{...form.getInputProps('frameworks')}
key={form.key('frameworks')}
label="Select your favorite frameworks/libraries"
withAsterisk
>
<Group my={5}>
<Checkbox value="react" label="React" />
<Checkbox value="svelte" label="Svelte" />
<Checkbox value="ng" label="Angular" />
<Checkbox value="vue" label="Vue" />
</Group>
</Checkbox.Group>
<Button type="submit" mt="md">
Submit
</Button>
</form>
);
}
비제어 폼과 함께 쓰는 Checkbox.Group
Checkbox.Group은 비제어 폼에서 사용할 수 있어요. hiddenInputValuesSeparator prop으로 선택된 모든 값을 단일 문자열로 결합하는 숨겨진 input을 렌더링해요.
비제어 폼에서 사용하기 위한 props:
name– 숨겨진 input에 전달되는 name 속성hiddenInputValuesSeparator– 선택된 값을 단일 문자열로 결합하는 데 사용하는 문자열, 기본값은','hiddenInputProps– 숨겨진 input에 전달되는 추가 props
export function UncontrolledForm() {
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
console.log('Checkbox group value:', formData.get('frameworks'));
}}
>
<Checkbox.Group label="Frameworks" name="frameworks" hiddenInputValuesSeparator="|">
<Checkbox label="React" value="react" />
<Checkbox label="Angular" value="ng" />
</Checkbox.Group>
<button type="submit">Submit</button>
</form>
);
}
Checkbox.Indicator
Checkbox.Indicator는 Checkbox 컴포넌트와 모양이 완전히 같지만 시맨틱 의미가 없고 체크박스 상태의 시각적 표현일 뿐이에요. indicator와 관련된 상호작용 없이 체크박스 상태를 표시해야 하는 모든 곳에서 사용할 수 있어요. 버튼 기반 카드, 트리 등에서 유용해요.
주의: Checkbox.Indicator는 키보드로 포커스하거나 선택할 수 없어요. 접근 가능하지 않으며 Checkbox 컴포넌트의 대체재로 사용해서는 안 돼요.
import { Checkbox, Group } from '@mantine/core';
function Demo() {
return (
<Group>
<Checkbox.Indicator />
<Checkbox.Indicator checked />
<Checkbox.Indicator indeterminate />
<Checkbox.Indicator disabled />
<Checkbox.Indicator disabled checked />
<Checkbox.Indicator disabled indeterminate />
</Group>
);
}
Checkbox.Card 컴포넌트
Checkbox.Card 컴포넌트는 Checkbox의 대체재로 커스텀 카드/버튼/기타 체크박스처럼 동작하는 것을 만드는 데 사용할 수 있어요. 루트 요소에 role="checkbox" 속성이 있으며 기본적으로 접근 가능하고 input[type="checkbox"]와 동일한 키보드 상호작용을 지원해요.
import { useState } from 'react';
import { Checkbox, Group, Text } from '@mantine/core';
import classes from './Demo.module.css';
function Demo() {
const [checked, setChecked] = useState(false);
return (
<Checkbox.Card
className={classes.root}
checked={checked}
onClick={() => setChecked((c) => !c)}
>
<Group wrap="nowrap" align="flex-start">
<Checkbox.Indicator />
<div>
<Text className={classes.label}>mantine/core</Text>
<Text className={classes.description}>
Core components library: inputs, buttons, overlays, etc.
</Text>
</div>
</Group>
</Checkbox.Card>
);
}
Checkbox.Card를 Checkbox 컴포넌트와 같은 방식으로 Checkbox.Group과 함께 사용할 수 있어요.
import { useState } from 'react';
import { Checkbox, Group, Stack, Text } from '@mantine/core';
import classes from './Demo.module.css';
const data = [
{
name: 'mantine/core',
description: 'Core components library: inputs, buttons, overlays, etc.',
},
{ name: 'mantine/hooks', description: 'Collection of reusable hooks for React applications.' },
{ name: 'mantine/notifications', description: 'Notifications system' },
];
function Demo() {
const [value, setValue] = useState<string[]>([]);
const cards = data.map((item) => (
<Checkbox.Card className={classes.root} value={item.name} key={item.name}>
<Group wrap="nowrap" align="flex-start">
<Checkbox.Indicator />
<div>
<Text className={classes.label}>{item.name}</Text>
<Text className={classes.description}>{item.description}</Text>
</div>
</Group>
</Checkbox.Card>
));
return (
<>
<Checkbox.Group
value={value}
onChange={setValue}
label="Pick packages to install"
description="Choose all packages that you will need in your application"
>
<Stack pt="md" gap="xs">
{cards}
</Stack>
</Checkbox.Group>
<Text fz="xs" mt="md">
CurrentValue: {value.join(', ') || '–'}
</Text>
</>
);
}
요소 ref 가져오기
import { useRef } from 'react';
import { Checkbox } from '@mantine/core';
function Demo() {
const ref = useRef<HTMLInputElement>(null);
return <Checkbox ref={ref} />;
}
위 예시는 체크박스 input 요소의 ref를 얻는 방법을 보여 줘요. 루트 요소의 ref를 얻으려면 rootRef prop을 사용해요.
import { useRef } from 'react';
import { Checkbox } from '@mantine/core';
function Demo() {
const ref = useRef<HTMLDivElement>(null);
return <Checkbox rootRef={ref} />;
}
Styles API
Checkbox는 Styles API를 지원해요. classNames prop으로 내부 요소에 스타일을 추가할 수 있어요.
주요 선택자는 다음과 같아요.
root– 루트 요소input– input 요소(input[type="checkbox"])icon– 체크마크와 indeterminate 상태 아이콘을 표시하는 데 사용되는 체크박스 아이콘inner–icon과input을 감싸는 wrapperbody– 다른 모든 요소를 포함하는 input bodylabelWrapper–label,description,error포함label– 라벨 요소description– 라벨 아래에 표시되는 설명error– 라벨 아래에 표시되는 오류 메시지
예시: 행 선택이 있는 Table
import { useState } from 'react';
import { Table, Checkbox } from '@mantine/core';
const elements = [
{ position: 6, mass: 12.011, symbol: 'C', name: 'Carbon' },
{ position: 7, mass: 14.007, symbol: 'N', name: 'Nitrogen' },
{ position: 39, mass: 88.906, symbol: 'Y', name: 'Yttrium' },
{ position: 56, mass: 137.33, symbol: 'Ba', name: 'Barium' },
{ position: 58, mass: 140.12, symbol: 'Ce', name: 'Cerium' },
];
function Demo() {
const [selectedRows, setSelectedRows] = useState<number[]>([]);
const rows = elements.map((element) => (
<Table.Tr
key={element.name}
bg={selectedRows.includes(element.position) ? 'var(--mantine-color-blue-light)' : undefined}
>
<Table.Td>
<Checkbox
aria-label="Select row"
checked={selectedRows.includes(element.position)}
onChange={(event) =>
setSelectedRows(
event.currentTarget.checked
? [...selectedRows, element.position]
: selectedRows.filter((position) => position !== element.position)
)
}
/>
</Table.Td>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
return (
<Table>
<Table.Thead>
<Table.Tr>
<Table.Th />
<Table.Th>Element position</Table.Th>
<Table.Th>Element name</Table.Th>
<Table.Th>Symbol</Table.Th>
<Table.Th>Atomic mass</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
);
}
예시: Styles API로 커스터마이즈
import { useState } from 'react';
import { Checkbox } from '@mantine/core';
import classes from './Demo.module.css';
function Demo() {
const [checked, setChecked] = useState(false);
return (
<Checkbox
classNames={classes}
label="Checkbox button"
checked={checked}
onChange={(event) => setChecked(event.currentTarget.checked)}
wrapperProps={{
onClick: () => setChecked((c) => !c),
}}
/>
);
}
wrapperProps
대부분의 Checkbox props는 input 요소로 전달돼요. 루트 요소에 props를 전달하려면 wrapperProps prop을 사용해요.
import { Checkbox } from '@mantine/core';
function Demo() {
return (
<Checkbox
label="My checkbox"
wrapperProps={{ 'data-root-element': true }}
/>
);
}
id 속성
기본적으로 Checkbox는 input 요소를 라벨과 연결하기 위해 랜덤 id 속성을 생성해요. id prop으로 직접 id를 제공할 수 있어요. 이 id는 input 요소의 id 속성과 라벨 요소의 htmlFor 속성에서 사용돼요.
import { Checkbox } from '@mantine/core';
function Demo() {
return <Checkbox id="my-checkbox" label="My checkbox" />;
}
접근성 (Accessibility)
Checkbox 컴포넌트는 네이티브 input[type="checkbox"] 요소를 기반으로 하므로 기본적으로 접근 가능해요.
aria-label 또는 label prop을 설정해 스크린 리더에서 체크박스를 접근 가능하게 만들어요.
import { Checkbox } from '@mantine/core';
// Not ok, input is not labeled
function Bad() {
return <Checkbox />;
}
// Ok, input is labelled by aria-label
function GoodAriaLabel() {
return <Checkbox aria-label="My checkbox" />;
}
// Ok, input is labelled by label element
function GoodLabel() {
return <Checkbox label="My checkbox" />;
}