Cascader

Cascader (캐스케이더)

Cascader 컴포넌트는 캐스케이딩 컬럼을 통해 계층적 데이터에서 경로를 선택하는 컴포넌트예요. 한 컬럼에서 옵션을 고르면 오른쪽 새 컬럼에서 그 자식들이 나타나요.

출처: 문서

본문

Cascader는 캐스케이딩 컬럼을 드릴다운하며 계층적 데이터에서 값을 선택할 수 있게 해 줘요. 한 컬럼에서 옵션을 고르면 오른쪽 새 컬럼에서 그 자식이 나타나요. 값은 루트 옵션부터 선택된 노드까지의 정렬된 경로예요. 예: ['asia', 'jp', 'tokyo'].

Cascader는 중첩 드롭다운으로 탐색하기 어려운 큰 계층적 데이터셋(지역: 대륙 → 국가 → 도시, 카테고리, 조직 구조 등)에 유용해요.

이 페이지의 모든 데모는 작은 화면에서는 플랫 리스트 레이아웃으로 전환되므로, 캐스케이딩 컬럼과 호버 확장, 키보드 탐색 같은 기능은 모바일에서 완전히 테스트할 수 없어요. 더 큰 화면에서 데모를 열어 보세요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  // Switch to a flat list on small screens
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      label="Location"
      placeholder="Pick location"
      data={data}
    />
  );
}

Data prop

data prop에 전달되는 데이터는 CascaderOption 객체의 배열이에요.

  • 각 옵션은 데이터 트리 전체에서 고유한 value를 가져야 해요
  • label은 선택사항이며 설정되지 않으면 value가 사용돼요
  • children은 중첩된 옵션 배열을 담아요
  • disabled는 옵션을 선택하거나 확장할 수 없게 해요
import { CascaderOption } from '@mantine/core';

const data: CascaderOption[] = [
  {
    value: 'asia',
    label: 'Asia',
    children: [
      {
        value: 'jp',
        label: 'Japan',
        children: [{ value: 'tokyo', label: 'Tokyo' }],
      },
    ],
  },
];

Value와 onChange

Cascader 값은 옵션 값의 정렬된 배열(루트에서 노드까지의 경로) 또는 아무것도 선택되지 않았을 때의 null이에요. onChange 콜백은 선택된 경로와 해석된 CascaderOption 객체 체인과 함께 호출돼요.

import { useState } from 'react';
import { Cascader, CascaderOption } from '@mantine/core';

function Demo() {
  const [value, setValue] = useState<string[] | null>(['europe', 'fr', 'paris']);

  const handleChange = (path: string[] | null, options: CascaderOption[]) => {
    setValue(path);
    console.log(path, options);
  };

  return <Cascader data={data} value={value} onChange={handleChange} />;
}

기본적으로 리프(leaf, 자식이 없는) 옵션만 선택할 수 있어요. 부모 옵션을 클릭하면 다음 컬럼이 확장될 뿐이에요.

선택 시 변경 (Change on select)

changeOnSelect prop을 설정하면 리프뿐만 아니라 모든 옵션을 선택할 수 있게 돼요. 활성화하면 부모 옵션을 클릭할 때 그 경로를 선택하고 다음 컬럼도 확장하므로, 모든 중간 레벨이 유효한 값이 돼요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      changeOnSelect
      label="Location"
      placeholder="Pick any level"
      data={data}
    />
  );
}

선택 시 닫기 (Close on select)

closeOnSelect는 값이 선택된 후 드롭다운이 닫힐지 제어해요. 설정하지 않으면 allowDeselect의 반대 값(기본값)이 돼요. 즉 드롭다운은 기본적으로 열려 있고(선택을 토글 해제할 수 있도록), allowDeselect={false}가 설정되면 닫혀요. 이 동작을 덮어쓰려면 closeOnSelect를 명시적으로 설정해요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      closeOnSelect={false}
      label="Location"
      placeholder="Pick location"
      data={data}
    />
  );
}

선택 해제 허용 (Allow deselect)

기본적으로 선택된 옵션을 다시 클릭하면 값이 제거돼요. 이 동작을 비활성화하려면 allowDeselect={false}를 설정해요.

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      label="Location"
      placeholder="Pick location"
      allowDeselect
      defaultValue={['asia', 'jp', 'tokyo']}
      data={data}
    />
  );
}

확장 트리거 (Expand trigger)

기본적으로 옵션을 클릭하면 다음 컬럼이 열려요. expandTrigger="hover"를 설정하면 호버로 다음 컬럼을 열 수 있어요. 리프 선택은 여전히 클릭이 필요해요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      expandTrigger="hover"
      label="Location"
      placeholder="Hover to expand"
      data={data}
    />
  );
}

expandTrigger="hover"일 때, 커서가 대각선으로 열린 컬럼을 향해 이동하는 동안 열린 컬럼이 유지돼요. 이동 중 커서가 지나치는 옵션들이 그 자리를 대체하지 않아요. safeAreaPolygon={false}를 설정하면 매 호버마다 즉시 확장할 수 있고, 객체를 전달하면 Floating UI safePolygon 옵션을 설정할 수 있어요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      expandTrigger="hover"
      safeAreaPolygon={false}
      label="Location"
      placeholder="Hover to expand"
      data={data}
    />
  );
}

플랫 리스트 레이아웃 (Flat list layout)

캐스케이딩 컬럼은 가로 공간을 필요로 하므로 좁은 화면에 적합하지 않아요. 모바일 레이아웃과 잘 맞지 않아요. withColumns={false}를 설정하면 옵션을 컬럼 대신 전체 경로의 플랫 리스트(검색 결과와 같은 방식)로 렌더링해요. 이 레이아웃은 모바일에서 잘 동작해요.

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      withColumns={false}
      searchable
      label="Location"
      placeholder="Pick location"
      nothingFoundMessage="Nothing found..."
      data={data}
    />
  );
}

가장 흔한 사용 사례는 데스크톱에서는 컬럼을, 모바일에서는 플랫 리스트를 렌더링하는 것이에요. use-matches 훅과 withColumns를 결합해 화면 크기에 따라 두 레이아웃을 전환할 수 있어요. 이 페이지의 모든 데모는 이 기법을 사용하며, 창 크기를 조절하면 레이아웃이 바뀌는 것을 볼 수 있어요.

import { Cascader, useMatches } from '@mantine/core';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return <Cascader withColumns={withColumns} data={data} />;
}

최대 표시 레벨 (Max displayed levels)

깊은 계층은 컬럼이 많이 생길 수 있어요. maxDisplayedLevels prop(기본 3)으로 나란히 표시될 컬럼 수를 제한할 수 있어요. 한도를 넘어 더 깊이 들어가면 가장 이른 컬럼이 더 깊은 컬럼으로 대체되고 왼쪽에 컨트롤이 표시돼요. 그것을 클릭하면 이전 레벨을 드러내고, 오른쪽 컨트롤로 더 깊은 레벨로 돌아갈 수 있어요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      maxDisplayedLevels={2}
      label="Location"
      placeholder="Pick location"
      defaultValue={['asia', 'jp', 'tokyo']}
      data={data}
    />
  );
}

검색 가능 (Searchable)

searchable prop을 설정하면 옵션을 필터링할 수 있어요. 검색 모드에서는 컬럼이 쿼리와 일치하는 전체 경로의 플랫 리스트로 대체돼요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      searchable
      label="Location"
      placeholder="Search location"
      nothingFoundMessage="Nothing found..."
      data={data}
    />
  );
}

filter prop으로 경로가 매칭되는 방식을, renderSearchOption으로 검색 결과가 렌더링되는 방식을 커스터마이즈할 수 있어요.

import { Cascader, CascaderOption } from '@mantine/core';

function Demo() {
  return (
    <Cascader
      searchable
      data={data}
      filter={(query, options: CascaderOption[]) =>
        options.some((option) => String(option.label).toLowerCase().includes(query.toLowerCase()))
      }
      renderSearchOption={(query, options) => options.map((option) => option.label).join(' → ')}
    />
  );
}

제어되는 검색 값 (Controlled search value)

searchValue와 onSearchChange prop으로 검색 값을 제어할 수 있어요.

import { useState } from 'react';
import { Cascader } from '@mantine/core';

function Demo() {
  const [searchValue, setSearchValue] = useState('');
  return (
    <Cascader
      searchable
      data={data}
      searchValue={searchValue}
      onSearchChange={setSearchValue}
    />
  );
}

결과 없음 (Nothing found)

nothingFoundMessage prop을 설정하면 검색 쿼리와 일치하는 옵션이 없을 때 메시지를 표시해요.

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      searchable
      label="Location"
      placeholder="Search location"
      nothingFoundMessage="Nothing found..."
      data={data}
    />
  );
}

표시 값 (Display value)

기본적으로 선택된 경로가 separator(기본 /)로 연결된 옵션 라벨로 input에 표시돼요. separator prop으로 구분자를 바꾸고, formatValue prop으로 input 라벨을 완전히 커스터마이즈할 수 있어요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      label="Location"
      placeholder="Pick location"
      separator="›"
      defaultValue={['asia', 'jp', 'tokyo']}
      formatValue={({ options }) => options.map((option) => option.label).join(' › ')}
      data={data}
    />
  );
}

컬럼 너비 (Column width)

columnWidth prop으로 모든 컬럼의 고정 너비를 설정하고, maxDropdownHeight로 컬럼이 스크롤 가능해지기 전의 높이(기본 260)를 제어할 수 있어요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      columnWidth={140}
      maxDropdownHeight={200}
      label="Location"
      placeholder="Pick location"
      data={data}
    />
  );
}

커스텀 옵션 렌더링 (Custom option rendering)

renderOption prop으로 컬럼에서 옵션이 렌더링되는 방식을 커스터마이즈할 수 있어요. 함수는 옵션과 그 컬럼 레벨을 받아요.

import { Badge, Cascader, CascaderOption, CascaderProps, Group, useMatches } from '@mantine/core';
import { data } from './data';

const flags: Record<string, string> = {
  jp: '🇯🇵', kr: '🇰🇷', fr: '🇫🇷', de: '🇩🇪', us: '🇺🇸', ca: '🇨🇦',
};

function countCities(option: CascaderOption): number {
  if (!option.children || option.children.length === 0) {
    return 1;
  }
  return option.children.reduce((acc, child) => acc + countCities(child), 0);
}

// Regions display the number of cities, countries display a flag, cities display nothing extra
const renderCascaderOption: CascaderProps['renderOption'] = (option, level) => (
  <Group gap="xs" justify="space-between" wrap="nowrap" flex="1">
    <Group gap={6} wrap="nowrap">
      {level === 1 && <span>{flags[option.value]}</span>}
      <span>{option.label}</span>
    </Group>
    {level === 0 && (
      <Badge size="xs" variant="light" color="gray">
        {countCities(option)} cities
      </Badge>
    )}
  </Group>
);

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      label="Location"
      placeholder="Pick location"
      renderOption={renderCascaderOption}
      data={data}
    />
  );
}

체크 아이콘 (Check icon)

withCheckIcon prop으로 선택된 옵션의 체크 아이콘을 토글하고, checkIconPosition으로 위치(left 또는 right)를 바꿀 수 있어요.

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      checkIconPosition="left"
      label="Location"
      placeholder="Pick location"
      defaultValue={['asia', 'jp', 'tokyo']}
      data={data}
    />
  );
}

비활성 옵션 (Disabled options)

옵션에 disabled 속성을 설정하면 선택하거나 확장할 수 없게 돼요. 비활성 옵션은 키보드 탐색에서 건너뛰어져요.

import { Cascader, CascaderOption, useMatches } from '@mantine/core';

const data: CascaderOption[] = [
  {
    value: 'asia',
    label: 'Asia',
    children: [
      { value: 'jp', label: 'Japan', children: [{ value: 'tokyo', label: 'Tokyo' }] },
      { value: 'kr', label: 'South Korea', disabled: true },
    ],
  },
  { value: 'antarctica', label: 'Antarctica', disabled: true },
];

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      label="Location"
      placeholder="Pick location"
      data={data}
    />
  );
}

왼쪽·오른쪽 섹션 (Left and right sections)

Cascader는 다른 입력들과 같은 방식으로 leftSection과 rightSection prop을 지원해요. 이 섹션들은 보통 아이콘을 추가하는 데 사용돼요.

import { MapPinIcon } from '@phosphor-icons/react';
import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      label="Location"
      placeholder="Pick location"
      leftSectionPointerEvents="none"
      leftSection={<MapPinIcon size={16} />}
      data={data}
    />
  );
}

지우기 가능 (Clearable)

clearable prop을 설정하면 값이 선택되었을 때 지우기 버튼을 표시해요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      clearable
      label="Location"
      placeholder="Pick location"
      defaultValue={['asia', 'jp', 'tokyo']}
      data={data}
    />
  );
}

clearSectionMode prop으로 지우기 버튼과 rightSection이 렌더링되는 방식을 제어할 수 있어요.

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      label="Location"
      placeholder="Pick location"
      clearable
      clearSectionMode="clear"
      defaultValue={['asia', 'jp', 'tokyo']}
      data={data}
    />
  );
}

스크롤 가능한 컬럼 (Scrollable columns)

각 컬럼은 스크롤 가능해요. maxDropdownHeight prop으로 컬럼이 스크롤 가능해지기 전의 높이를 제어하고, scrollAreaProps로 각 컬럼의 ScrollArea에 props를 전달할 수 있어요.

import { Cascader, CascaderOption } from '@mantine/core';

const cities = Array.from({ length: 30 }, (_, index) => ({
  value: `city-${index + 1}`,
  label: `City ${index + 1}`,
}));

const data: CascaderOption[] = [
  { value: 'asia', label: 'Asia', children: [{ value: 'jp', label: 'Japan', children: cities }] },
  { value: 'europe', label: 'Europe', children: [{ value: 'fr', label: 'France', children: cities }] },
];

function Demo() {
  return (
    <Cascader
      label="Location"
      placeholder="Pick location"
      defaultValue={['asia', 'jp']}
      maxDropdownHeight={180}
      data={data}
    />
  );
}

드롭다운 열림 상태 제어

dropdownOpened, defaultDropdownOpened, onDropdownOpen, onDropdownClose prop으로 드롭다운 열림 상태를 제어할 수 있어요.

import { Cascader } from '@mantine/core';

function Demo() {
  const [dropdownOpened, setDropdownOpened] = useState(false);
  return (
    <Cascader
      data={data}
      dropdownOpened={dropdownOpened}
      onDropdownOpen={() => setDropdownOpened(true)}
      onDropdownClose={() => setDropdownOpened(false)}
    />
  );
}

드롭다운 위치 (Dropdown position)

comboboxProps로 내부의 Combobox와 Popover에 props를 전달할 수 있어요. 예를 들어 position을 설정해 드롭다운 위치를 바꿀 수 있어요.

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      label="Location"
      placeholder="Pick location"
      comboboxProps={{ position: 'top-start' }}
      data={data}
    />
  );
}

드롭다운 오프셋 (Dropdown offset)

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      label="Location"
      placeholder="Pick location"
      comboboxProps={{ offset: 0 }}
      data={data}
    />
  );
}

드롭다운 너비 (Dropdown width)

플랫 리스트 모드(withColumns={false})에서는 comboboxProps={{ width }}로 드롭다운 너비를 제어할 수 있어요. 컬럼 모드에서는 드롭다운이 컬럼에 맞춰 크기가 정해져요.

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      withColumns={false}
      label="Location"
      placeholder="Pick location"
      comboboxProps={{ width: 220, position: 'bottom-start' }}
      data={data}
    />
  );
}

드롭다운 패딩 (Dropdown padding)

import { Cascader } from '@mantine/core';
import { data } from './data';

// Dropdown padding is only applied to the flat list (withColumns={false});
// in columns mode each column manages its own padding.
function Demo() {
  return (
    <Cascader
      withColumns={false}
      label="Location"
      placeholder="Pick location"
      comboboxProps={{ dropdownPadding: 12 }}
      data={data}
    />
  );
}

드롭다운 그림자 (Dropdown shadow)

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      label="Location"
      placeholder="Pick location"
      comboboxProps={{ shadow: 'md' }}
      data={data}
    />
  );
}

드롭다운 애니메이션 (Dropdown animation)

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      label="Location"
      placeholder="Pick location"
      comboboxProps={{ transitionProps: { transition: 'pop', duration: 200 } }}
      data={data}
    />
  );
}

Popover 안에서 사용 (Inside Popover)

Popover 안에서 Cascader를 사용하려면 comboboxProps={{ withinPortal: false }}를 설정해요.

import { Button, Cascader, Popover } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Popover width={320} position="bottom" withArrow shadow="md">
      <Popover.Target>
        <Button>Toggle popover</Button>
      </Popover.Target>
      <Popover.Dropdown>
        <Cascader
          withColumns={false}
          label="Location"
          placeholder="Pick location"
          comboboxProps={{ withinPortal: false }}
          data={data}
        />
      </Popover.Dropdown>
    </Popover>
  );
}

Combobox props

comboboxProps로 Combobox props를 덮어쓸 수 있어요. Cascader가 노출하지 않는 props(예: withinPortal)를 바꿔야 할 때 유용해요.

import { Cascader } from '@mantine/core';

function Demo() {
  return <Cascader comboboxProps={{ withinPortal: false }} data={[]} />;
}

드롭다운 z-index 변경 (Change dropdown z-index)

import { Cascader } from '@mantine/core';

function Demo() {
  return <Cascader comboboxProps={{ zIndex: 1000 }} data={[]} />;
}

Styles API

Styles API로 Cascader 스타일을 커스터마이즈할 수 있어요.

주요 선택자는 다음과 같아요.

  • wrapper – Input의 루트 요소
  • input – input 요소
  • section – 왼쪽·오른쪽 섹션
  • bottomSection – input border 아래쪽에 렌더링되는 하단 섹션 요소
  • root – 루트 요소
  • label – 라벨 요소
  • required – 라벨 안에 렌더링되는 필수 별표 요소
  • description – 설명 요소
  • error – 오류 요소
  • success – 성공 요소
  • dropdown – 드롭다운 루트 요소
  • options – 옵션 wrapper
  • option – 옵션
  • empty – 결과 없음 메시지
  • group – 옵션 그룹 wrapper
  • groupLabel – 옵션 그룹 라벨
  • columnsList – 드롭다운의 모든 캐스케이딩 컬럼 wrapper
  • columnsOverflow – maxDisplayedLevels로 숨겨진 레벨을 드러내는 컨트롤
  • column – 단일 캐스케이딩 컬럼
  • columnScroll – 컬럼의 스크롤 가능한 옵션 영역
  • columnOption – 컬럼 안의 옵션 컨트롤
  • columnOptionLabel – 컬럼 옵션의 라벨
  • columnOptionIcon – 컬럼 옵션의 확장(expand) 셰브런
  • columnOptionCheck – 선택된 리프 옵션에 표시되는 체크 아이콘
  • columnEmpty – 컬럼의 빈 상태
  • flatOption – 플랫 리스트(검색 결과 / withColumns={false})의 옵션 콘텐츠

왼쪽·오른쪽 섹션 (Left and right sections)

Cascader는 leftSection과 rightSection prop을 지원해요. 이 섹션들은 input wrapper 안에 절대 위치로 렌더링돼요. 아이콘이나 다른 요소를 표시하는 데 사용할 수 있어요.

섹션 스타일과 콘텐츠를 제어하는 props:

  • rightSection / leftSection – input의 해당 쪽에 렌더링할 React 노드
  • rightSectionWidth/leftSectionWidth – right section의 너비와 input 해당 쪽의 패딩을 제어해요. 기본적으로 컴포넌트 size prop으로 제어돼요.
  • rightSectionPointerEvents/leftSectionPointerEvents – 섹션의 pointer-events 속성을 제어해요. 상호작용하지 않는 요소를 렌더링하려면 none으로 설정해 클릭이 input을 통과하게 해요.

Input props

Cascader 컴포넌트는 Input과 Input.Wrapper 컴포넌트의 기능과 모든 input 요소 props를 지원해요. Cascader 문서는 컴포넌트가 지원하는 모든 기능을 담고 있지 않아요. 사용 가능한 모든 기능은 Input 문서를 참고해요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';
function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      label="Input label"
      description="Input description"
      withColumns={withColumns}
      placeholder="Pick location"
      data={data}
    />
  );
}

읽기 전용 (Read only)

readOnly를 설정하면 input을 읽기 전용으로 만들어요. readOnly가 설정되면 Cascader는 드롭다운을 열지 않고 onChange 함수도 호출하지 않아요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      readOnly
      label="Location"
      placeholder="Pick location"
      defaultValue={['asia', 'jp', 'tokyo']}
      data={data}
    />
  );
}

비활성 (Disabled)

disabled를 설정하면 input을 비활성화해요. disabled가 설정되면 사용자가 input과 상호작용할 수 없고 Cascader는 드롭다운을 열지 않아요.

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      disabled
      label="Location"
      placeholder="Pick location"
      data={data}
    />
  );
}

오류 상태 (Error state)

import { Cascader, useMatches } from '@mantine/core';
import { data } from './data';

function Demo() {
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      label="Location"
      placeholder="Pick location"
      error="Pick a valid location"
      data={data}
    />
  );
}

성공 상태 (Success state)

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      label="Location"
      placeholder="Pick location"
      defaultValue={['asia', 'jp', 'tokyo']}
      success="Looks good!"
      data={data}
    />
  );
}

로딩 상태 (Loading state)

loading prop을 설정하면 셰브런 대신 오른쪽 섹션에 로더를 표시해요.

import { Cascader } from '@mantine/core';
import { data } from './data';

function Demo() {
  return (
    <Cascader
      label="Location"
      placeholder="Pick location"
      loading
      data={data}
    />
  );
}

접근성 (Accessibility)

Cascader 컬럼은 option 요소를 가진 중첩 listbox로 렌더링돼요. 컴포넌트를 접근 가능하게 만들려면 label prop을 설정하거나 컴포넌트에 aria-label을 전달해요.

import { Cascader } from '@mantine/core';

// Set aria-label when the input does not have a visible label
function Demo() {
  return <Cascader data={data} aria-label="Pick location" />;
}

키보드 상호작용 (Keyboard interactions)

키 설명
ArrowDown/ArrowUp 드롭다운을 열고, 현재 컬럼의 옵션 사이를 이동해요
ArrowRight 하이라이트된 옵션을 다음 컬럼으로 확장해요
ArrowLeft 현재 컬럼을 접고 이전 컬럼으로 돌아가요
Enter 부모 옵션을 확장하거나 하이라이트된 리프 옵션을 선택해요
Escape 드롭다운을 닫아요

더 알아보기 (Learn more)

  • Combobox — 콤보박스 컴포넌트
  • Select — 셀렉트 컴포넌트
  • Input — 입력 컴포넌트 기반 문서