TagsInput

TagsInput

자유 입력과 제안(suggestions)으로 사용자로부터 값 목록을 받는 컴포넌트예요. 여러 값을 태그 형태로 입력받을 때 사용해요.

출처: 문서

본문

Combobox 기반 (Made with Combobox)

TagsInput은 Combobox 컴포넌트 위에 만들어진 고정된(opinionated) 컴포넌트예요. 기본 사용 사례만 다루는 제한된 기능을 가져요. 더 고급 기능이 필요하면 Combobox로 직접 컴포넌트를 만들 수 있어요. 커스텀 태그 입력 컴포넌트 예시는 예시 페이지에서 찾을 수 있어요.

사용법 (Usage)

TagsInput은 여러 값을 입력하는 방법을 제공해요. 제안과 함께 또는 제안 없이 사용할 수 있어요. TagsInput은 MultiSelect와 비슷하지만 커스텀 값을 입력할 수 있어요.

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

function Demo() {
  return (
    <TagsInput
      label="Press Enter to submit a tag"
      placeholder="Enter tag"
      data={['React', 'Angular', 'Svelte']}
    />
  );
}

로딩 상태 (Loading state)

loading prop을 설정하면 로딩 인디케이터를 표시해요. 기본적으로 로더는 입력 오른쪽에 표시돼요. loadingPosition prop을 'left' 또는 'right'로 설정해 위치를 바꿀 수 있어요. 이는 API 호출, 검색, 검증 같은 비동기 작업에 유용해요.

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

function Demo() {
  return <TagsInput data={[]} loading placeholder="Loading" />;
}

제어 컴포넌트 (Controlled)

TagsInput의 값은 문자열 배열이어야 해요. 다른 타입은 지원되지 않아요. onChange 함수는 문자열 배열을 단일 인자로 호출돼요.

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

function Demo() {
  const [value, setValue] = useState<string[]>([]);
  return <TagsInput data={[]} value={value} onChange={setValue} />;
}

제어된 검색 값 (Controlled search value)

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

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

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

지우기 가능 (Clearable)

clearable prop을 설정하면 오른쪽 섹션에 지우기 버튼을 표시해요. 버튼은 다음 경우에 표시되지 않아요.

  • 컴포넌트에 값이 없을 때
  • 컴포넌트가 비활성(disabled)일 때
  • 컴포넌트가 읽기 전용(read only)일 때
import { TagsInput } from '@mantine/core';

function Demo() {
  return (
    <TagsInput
      label="Press Enter to submit a tag"
      placeholder="Enter tag"
      defaultValue={['React']}
      clearable
    />
  );
}

지우기 섹션 모드 (Clear section mode)

clearSectionMode prop은 지우기 버튼과 rightSection이 어떻게 렌더링되는지 결정해요.

  • 'both' (기본) – 지우기 버튼과 rightSection 모두 렌더링해요
  • 'rightSection' – 사용자가 제공한 rightSection만 렌더링하고 지우기 버튼을 무시해요
  • 'clear' – 지우기 버튼만 렌더링하고 rightSection을 무시해요
import { CaretDownIcon } from '@phosphor-icons/react';
import { Stack, TagsInput } from '@mantine/core';

function Demo() {
  return (
    <Stack>
      <TagsInput data={['React']} defaultValue={['React']} rightSection={<CaretDownIcon size={16} />} clearSectionMode="both" />
      <TagsInput data={['React']} defaultValue={['React']} rightSection={<CaretDownIcon size={16} />} clearSectionMode="rightSection" />
      <TagsInput data={['React']} defaultValue={['React']} rightSection={<CaretDownIcon size={16} />} clearSectionMode="clear" />
    </Stack>
  );
}

최대 선택 값 (Max selected values)

maxTags prop으로 선택할 수 있는 값의 개수를 제한할 수 있어요. 한도에 도달하면 더 이상 값을 추가할 수 없어요.

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

function Demo() {
  return (
    <TagsInput
      label="Press Enter to submit a tag"
      description="Add up to 3 tags"
      placeholder="Enter tag"
      defaultValue={['first', 'second']}
      maxTags={3}
    />
  );
}

블러 시 값 수락 (Accept value on blur)

기본적으로 사용자가 값을 입력하고 입력란을 벗어나면(blur) 값이 목록에 추가돼요. acceptValueOnBlur를 false로 설정하면 이 동작을 바꿀 수 있어요. 이 경우 사용자가 Enter를 누르거나 제안을 클릭할 때만 값이 추가돼요.

중복 허용 (Allow duplicates)

기본적으로 TagsInput은 중복 값 추가를 허용하지 않지만, allowDuplicates prop을 설정하면 이 동작을 바꿀 수 있어요. 값이 value 배열에 이미 있으면 대소문자와 끝 공백과 관계없이 중복으로 간주돼요.

isDuplicate

isDuplicate prop으로 중복 감지 방식을 제어할 수 있어요. 이 함수는 태그 값과 현재 태그 두 인자를 받아요. 값이 중복이면 true를 반환해야 해요.

같은 값을 다른 대소문자로 사용할 수 있게 isDuplicate를 사용하는 예시:

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

function Demo() {
  return (
    <TagsInput
      isDuplicate={(tagValue, currentTags) => currentTags.some((val) => val === tagValue)}
      defaultValue={['Tag', 'TAG', 'tag']}
    />
  );
}

분할 문자 (Split chars)

기본적으로 TagsInput은 값들을 쉼표(,)로 분할해요. splitChars prop을 문자열 배열로 설정하면 이 동작을 바꿀 수 있어요. splitChars의 모든 값은 최종 값에 포함될 수 없어요. 값은 붙여넣기(paste) 시에도 분할돼요.

,, |, 공백으로 분할하는 예시:

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

function Demo() {
  return <TagsInput splitChars={[',', '|', ' ']} label="Press Enter to submit a tag" />;
}

제안과 함께 (With suggestions)

TagsInput은 제안과 함께 사용할 수 있어요. 입력 아래에 제안 목록을 렌더링하고 키보드나 마우스로 제안을 선택할 수 있게 해요. 사용자가 제안에 제한되지 않고 커스텀 값을 입력할 수 있다는 점에 주의해요. 제안의 값만 허용하려면 MultiSelect 컴포넌트를 대신 사용해요.

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

function Demo() {
  return (
    <TagsInput
      data={['React', 'Angular', 'Svelte', 'Vue']}
      label="Press Enter to submit a tag"
      placeholder="Enter tag"
    />
  );
}

데이터 형식 (Data formats)

TagsInput의 data prop은 다음 형식 중 하나의 데이터를 받아요.

문자열 배열:

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

function Demo() {
  return <TagsInput data={['React', 'Angular', 'Svelte']} />;
}

문자열 옵션이 있는 그룹 배열:

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

function Demo() {
  return (
    <TagsInput
      data={[
        { group: 'Frontend', items: ['React', 'Angular'] },
        { group: 'Backend', items: ['Node.js', 'Python'] },
      ]}
    />
  );
}

옵션 필터링 (Options filtering)

기본적으로 TagsInput은 옵션 라벨이 입력 값을 포함하는지 확인해 옵션을 필터링해요. filter prop으로 이 동작을 바꿀 수 있어요. filter 함수는 다음 속성이 있는 객체를 단일 인자로 받아요.

  • options – 옵션 또는 옵션 그룹 배열, 모든 옵션은 { value: string; label: string; disabled?: boolean } 형식
  • search – 현재 검색어
  • limit – TagsInput에 전달된 limit prop의 값

글자 시퀀스 대신 단어로 옵션을 매칭하는 커스텀 필터 함수 예시:

import { TagsInput, ComboboxItem, OptionsFilter } from '@mantine/core';

const optionsFilter: OptionsFilter = ({ options, search }) => {
  const splittedSearch = search.toLowerCase().trim().split(' ');
  return (options as ComboboxItem[]).filter((option) => {
    const words = option.label.toLowerCase().trim().split(' ');
    return splittedSearch.every((searchWord) => words.some((word) => word.includes(searchWord)));
  });
};

function Demo() {
  return (
    <TagsInput
      label="What countries have you visited?"
      placeholder="Pick countries that you have visited"
      data={['USA', 'Canada', 'Mexico']}
      filter={optionsFilter}
    />
  );
}

옵션 정렬 (Sort options)

기본적으로 옵션은 data 배열에서의 위치 순서로 정렬돼요. filter 함수로 이 동작을 바꿀 수 있어요.

import { TagsInput, ComboboxItem, OptionsFilter } from '@mantine/core';

const optionsFilter: OptionsFilter = ({ options, search }) => {
  const filtered = (options as ComboboxItem[]).filter((option) =>
    option.label.toLowerCase().trim().includes(search.toLowerCase().trim())
  );

  filtered.sort((a, b) => a.label.localeCompare(b.label));
  return filtered;
};

fuse.js로 퍼지 검색 (Fuzzy search with fuse.js)

fuse.js 라이브러리를 사용해 오타나 부분 일치에도 옵션을 매칭하는 퍼지 검색을 구현할 수 있어요.

import { TagsInput, ComboboxItem, OptionsFilter } from '@mantine/core';
import Fuse from 'fuse.js';

const optionsFilter: OptionsFilter = ({ options, search }) => {
  if (!search.trim()) {
    return options;
  }

  const fuse = new Fuse(options as ComboboxItem[], {
    keys: ['label'],
    threshold: 0.3,
    minMatchCharLength: 1,
  });

  return fuse.search(search).map((result) => result.item);
};

대규모 데이터셋 (Large data sets)

대규모 데이터셋에 대한 최선의 전략은 동시에 렌더링되는 옵션 수를 제한하는 거예요. limit prop으로 할 수 있어요. 커스텀 filter 함수를 사용한다면 filter 안에서 옵션 수를 제한하는 직접 로직을 구현해야 한다는 점에 주의해요.

100,000개 옵션이 있는 TagsInput 예시로, 동시에 5개 옵션만 렌더링돼요.

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

const largeData = Array(100_000)
  .fill(0)
  .map((_, index) => `Option ${index}`);

function Demo() {
  return <TagsInput data={largeData} limit={5} />;
}

renderOption

renderOption 콜백으로 옵션 렌더링을 커스터마이즈할 수 있어요. 옵션 객체로 호출돼요. 함수는 React 노드를 반환해야 해요.

import { Group, TagsInput, TagsInputProps, Text } from '@mantine/core';

const data: Record<string, { emoji: string; description: string }> = {
  Apples: { emoji: '🍎', description: 'Crisp and juicy snacking delight' },
  Bread: { emoji: '🍞', description: 'Freshly baked daily essential' },
  Bananas: { emoji: '🍌', description: 'Perfect for a healthy breakfast' },
  Eggs: { emoji: '🥚', description: 'Versatile protein source for cooking' },
  Broccoli: { emoji: '🥦', description: 'Nutrient-rich green vegetable' },
};

const renderTagsInputOption: TagsInputProps['renderOption'] = ({ option }) => (
  <Group>
    <Text>{data[option.value].emoji}</Text>
    <div>
      <Text>{option.value}</Text>
      <Text size="xs" opacity={0.5}>{data[option.value].description}</Text>
    </div>
  </Group>
);

필 커스터마이즈 (Pill customization)

renderPill 콜백으로 필(pill) 렌더링을 커스터마이즈할 수 있어요. option(combobox item), value(문자열), onRemove(함수), disabled를 포함하는 객체로 호출돼요. TagsInput은 커스텀 값을 추가할 수 있으므로 option 속성은 즉석에서 생성될 수 있다는 점에 주의해요.

import { TagsInput, Pill } from '@mantine/core';

function Demo() {
  return (
    <TagsInput
      data={['React', 'Angular']}
      label="Custom pills"
      description="Tags are rendered with a star prefix"
      defaultValue={['React', 'Angular']}
      renderPill={({ value }) => <Pill>★ {value}</Pill>}
    />
  );
}

필 재정렬 (Reorder pills)

withPillsReorder prop을 설정하면 필을 재정렬할 수 있어요. 다른 필 앞이나 뒤에 필을 놓으면(drop) 컴포넌트 값이 그에 따라 갱신돼요. disabled 또는 readOnly가 설정되면 재정렬은 자동으로 비활성화돼요.

필은 마우스(드래그 앤 드롭)나 키보드로 재정렬할 수 있어요.

  • 필은 Tab 순서에 포함되지 않아요. 입력에 포커스가 있는 상태에서 (입력의 시작 부분에 커서가 있을 때) ArrowLeft를 누르면 마지막 필로 포커스가 이동해요
  • ArrowLeft와 ArrowRight는 필 사이에서 포커스를 이동해요(RTL 인식). 마지막 필에서 ArrowRight를 누르면 입력으로 포커스가 돌아가요
  • Alt + ArrowLeft와 Alt + ArrowRight는 포커스된 필을 재정렬해요(RTL 인식)

포커스가 이동한 필을 따라가므로 다시 포커스하지 않고도 여러 이동을 연속으로 할 수 있어요.

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

function Demo() {
  const [value, setValue] = useState(['first', 'second', 'third']);

  return <TagsInput value={value} onChange={setValue} withPillsReorder />;
}

renderPill prop으로 커스텀 필 렌더러를 사용한다면, 렌더 콜백 페이로드에서 reorderProps를 포커스 가능한 필 루트 요소에 펼쳐 재정렬이 계속 동작하게 해요. reorderProps는 키보드 재정렬을 구동하는 tabIndex, data-mantine-pill-index 속성, 키보드 핸들러를 담고 있어서, 사용자가 포커스할 수 있는 요소에 위치해야 해요.

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

function Demo() {
  return (
    <TagsInput
      withPillsReorder
      renderPill={({ value, reorderProps }) => (
        <span {...reorderProps}>{value} ×</span>
      )}
    />
  );
}

스크롤 가능한 드롭다운 (Scrollable dropdown)

기본적으로 옵션 목록은 ScrollArea.Autosize로 감싸져요. 기본 설정을 바꾸지 않았다면 maxDropdownHeight prop으로 드롭다운 최대 높이를 제어할 수 있어요.

네이티브 스크롤바를 사용하려면 withScrollArea={false}를 설정해요. 이 경우 Styles API로 드롭다운 스타일을 변경해야 한다는 점에 주의해요.

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

const data = Array(100)
  .fill(0)
  .map((_, index) => `Option ${index}`);

function Demo() {
  return (
    <>
      <TagsInput data={data} label="With scroll area (default)" />
      <TagsInput data={data} label="With native scroll" withScrollArea={false} />
    </>
  );
}

뷰포트 높이에 맞는 드롭다운 (Fit dropdown to viewport height)

floatingHeight="viewport"을 설정하면 드롭다운이 뷰포트의 사용 가능한 세로 공간을 채우도록 커져요. 이 모드에서는 flip 미들웨어가 비활성화돼요. 드롭다운이 항상 설정된 방향으로 열리고, 반대쪽으로 뒤집히는 대신 뷰포트 가장자리로 제한돼요. 큰 옵션 목록을 다룰 때 유용해요.

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

const data = Array(100)
  .fill(0)
  .map((_, index) => `Option ${index}`);

function Demo() {
  return <TagsInput data={data} floatingHeight="viewport" />;
}

그룹 옵션 (Group options)

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

function Demo() {
  return (
    <TagsInput
      data={[
        { group: 'Frontend', items: ['React', 'Angular'] },
        { group: 'Backend', items: ['Node.js', 'Python'] },
      ]}
      label="Enter tags"
      placeholder="Enter tag"
    />
  );
}

비활성 옵션 (Disabled options)

옵션이 비활성이면 선택할 수 없고 키보드 내비게이션에서 무시돼요. 사용자가 비활성 옵션을 값으로 입력할 수는 있다는 점에 주의해요. 특정 값을 금지하려면 제어 컴포넌트를 사용하고 onChange 함수에서 필터링해요.

Combobox props

Combobox props를 comboboxProps로 덮어쓸 수 있어요. TagsInput이 노출하지 않는 일부 props(예: withinPortal)를 변경해야 할 때 유용해요.

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

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

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

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

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

Popover 안에서 (Inside Popover)

TagsInput를 popover 안에서 사용하려면 withinPortal: false를 설정해야 해요.

import { Popover, Button, TagsInput } from '@mantine/core';

function Demo() {
  return (
    <Popover width={400} position="bottom" withArrow shadow="md">
      <Popover.Target>
        <Button>Toggle popover</Button>
      </Popover.Target>
      <Popover.Dropdown>
        <TagsInput data={[]} withinPortal={false} label="Enter tags" />
      </Popover.Dropdown>
    </Popover>
  );
}

드롭다운 열림 상태 제어 (Control dropdown opened state)

dropdownOpened prop으로 드롭다운 열림 상태를 제어할 수 있어요. 또한 onDropdownClose와 onDropdownOpen으로 드롭다운 열림 상태 변경을 들을 수 있어요.

import { TagsInput, Button } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';

function Demo() {
  const [dropdownOpened, { toggle }] = useDisclosure();
  return (
    <>
      <Button onClick={toggle}>Toggle dropdown</Button>
      <TagsInput
        label="Your favorite library"
        data={['React', 'Angular', 'Svelte']}
        dropdownOpened={dropdownOpened}
      />
    </>
  );
}

드롭다운 위치 (Dropdown position)

기본적으로 드롭다운은 공간이 충분하면 입력 아래에 표시되고, 그렇지 않으면 입력 위에 표시돼요. position과 middlewares props를 설정해 이 동작을 바꿀 수 있어요. 이 props는 기반 Popover 컴포넌트로 전달돼요.

항상 입력 위에 표시되는 드롭다운 예시:

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

function Demo() {
  return <TagsInput label="Your favorite library" data={['React']} position="top" />;
}

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

기본적으로 드롭다운 애니메이션은 비활성화돼 있어요. transitionProps를 설정해 활성화할 수 있으며, 이 props는 기반 Transition 컴포넌트로 전달돼요.

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

function Demo() {
  return (
    <TagsInput
      label="Your favorite library"
      data={['React']}
      transitionProps={{ transition: 'pop', duration: 200 }}
    />
  );
}

드롭다운 너비 (Dropdown width)

드롭다운 너비를 바꾸려면 comboboxProps에서 width prop을 설정해요. 기본적으로 드롭다운 너비는 입력 너비와 같아요.

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

function Demo() {
  return (
    <TagsInput label="Your favorite library" data={['React']} comboboxProps={{ width: 400 }} />
  );
}

드롭다운 패딩 (Dropdown padding)

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

function Demo() {
  return (
    <>
      <TagsInput label="Zero padding" data={['React']} comboboxProps={{ dropdownPadding: 0 }} />
      <TagsInput label="10px padding" data={['React']} comboboxProps={{ dropdownPadding: 10 }} />
    </>
  );
}

드롭다운 그림자 (Dropdown shadow)

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

function Demo() {
  return (
    <TagsInput label="Your favorite library" data={['React']} comboboxProps={{ shadow: 'md' }} />
  );
}

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

TagsInput는 leftSection과 rightSection props를 지원해요. 이 섹션들은 입력 래퍼 안에 절대 위치로 렌더링돼요. 아이콘, 입력 컨트롤, 기타 요소를 표시하는 데 사용할 수 있어요.

  • rightSection / leftSection – 입력의 해당 측면에 렌더링할 React 노드
  • rightSectionWidth / leftSectionWidth – 오른쪽 섹션의 너비와 입력 해당 측면의 패딩을 제어해요. 기본적으로 컴포넌트 size prop으로 제어돼요.
  • rightSectionPointerEvents / leftSectionPointerEvents – 섹션의 pointer-events 속성을 제어해요. 비상호작용 요소를 렌더링하려면 none으로 설정해 클릭이 입력으로 전달되게 해요.
import { TagsInput } from '@mantine/core';
import { SquaresFourIcon } from '@phosphor-icons/react';

function Demo() {
  const icon = <SquaresFourIcon size={16} />;
  return (
    <>
      <TagsInput data={[]} label="Your favorite library" leftSection={icon} />
      <TagsInput data={[]} label="Your favorite library" rightSection={icon} />
    </>
  );
}

Input props

TagsInput 컴포넌트는 Input과 Input.Wrapper 컴포넌트의 기능과 모든 input 요소 props를 지원해요. TagsInput 문서에는 컴포넌트가 지원하는 모든 기능이 포함되어 있지 않아요. 사용 가능한 모든 기능은 Input 문서에서 확인할 수 있어요.

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

function Demo() {
  return (
    <TagsInput
      label="Input label"
      description="Input description"
      data={['First', 'Second']}
      defaultValue={['First', 'Second']}
      placeholder="Enter tags"
    />
  );
}

읽기 전용 (Read only)

readOnly를 설정하면 입력을 읽기 전용으로 만들어요. readOnly가 설정되면 TagsInput은 제안을 표시하지 않고 onChange 함수를 호출하지 않아요.

비활성 (Disabled)

disabled를 설정하면 입력을 비활성화해요. disabled가 설정되면 사용자가 입력과 상호작용할 수 없고 TagsInput은 제안을 표시하지 않아요.

오류 상태 (Error state)

불리언 오류 또는 오류 메시지와 함께 TagsInput을 표시할 수 있어요.

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

function Demo() {
  return (
    <>
      <TagsInput label="Boolean error" data={[]} defaultValue={['React', 'Angular']} error />
      <TagsInput label="With error message" data={[]} defaultValue={['React', 'Angular']} error="Invalid name" />
    </>
  );
}

성공 상태 (Success state)

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

function Demo() {
  return <TagsInput label="Tags Input" description="Looks good!" data={[]} />;
}

Styles API

TagsInput는 Styles API를 지원해요. classNames prop으로 컴포넌트의 내부 요소에 스타일을 추가할 수 있어요. 자세한 내용은 Styles API 문서를 참고해요.

selector 설명
wrapper Input의 루트 요소
input Input 요소
section 왼쪽 및 오른쪽 섹션
bottomSection 하단 섹션 요소, 입력 테두리 안쪽 하단에 렌더링돼요
root 루트 요소
label 라벨 요소
required 필수 별표 요소, 라벨 안에 렌더링돼요
description 설명 요소
error 오류 요소
success 성공 요소
dropdown 드롭다운 루트 요소
options 옵션 래퍼
option 옵션
empty 아무것도 찾지 못했을 때의 메시지
group 옵션 그룹 래퍼
groupLabel 옵션 그룹 라벨
pill 값 필
inputField 입력 필드
pillsList 필 목록, 입력 필드도 포함해요

요소 ref 가져오기 (Get element ref)

import { useRef } from 'react';
import { TagsInput } from '@mantine/core';

function Demo() {
  const ref = useRef<HTMLInputElement>(null);
  return <TagsInput data={[]} ref={ref} />;
}

접근성 (Accessibility)

TagsInput을 label prop 없이 사용하면 화면 판독기가 제대로 알려주지 못해요. aria-label을 설정하면 라벨이 보이지 않아도 화면 판독기가 알려줘요. label prop을 설정하면 별도로 aria-label을 지정할 필요 없이 접근성이 확보돼요.

지우기 버튼에 aria-label을 설정하려면 clearButtonProps를 사용해요. 이는 clearable이 설정된 경우에만 필요하다는 점에 주의해요.

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

function Demo() {
  return <TagsInput data={[]} clearable clearButtonProps={{ 'aria-label': 'Clear tags' }} />;
}

더 알아보기 (Learn more)