Chip

Chip

Chip(칩)은 입력, 속성 또는 동작을 나타내는 컴팩트한 요소예요.

Chip을 사용하면 사용자가 정보를 입력하거나, 선택을 하거나, 콘텐츠를 필터링하거나, 동작을 트리거할 수 있어요.

여기서는 독립형 컴포넌트로 포함되어 있지만, 가장 흔한 용도는 어떤 형태의 입력(input)이에요. 그래서 여기서 보여주는 동작 중 일부는 그 맥락에서 표시되지 않아요.

출처: 문서

본문

기본 칩 (Basic chip)

Chip 컴포넌트는 outlined(윤곽선)과 filled(채움) 스타일링을 지원해요.

import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';

export default function BasicChips() {
  return (
    <Stack direction="row" spacing={1}>
      <Chip label="Chip Filled" />
      <Chip label="Chip Outlined" variant="outlined" />
    </Stack>
  );
}

칩 동작 (Chip actions)

다음 동작들을 사용할 수 있어요.

  • onClick prop이 정의된 Chip은 포커스, 호버, 클릭 시 모양이 바뀌어요.
  • onDelete prop이 정의된 Chip은 호버 시 모양이 바뀌는 삭제 아이콘을 표시해요.

클릭 가능 (Clickable)

import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';

export default function ClickableChips() {
  const handleClick = () => {
    console.info('You clicked the Chip.');
  };

  return (
    <Stack direction="row" spacing={1}>
      <Chip label="Clickable" onClick={handleClick} />
      <Chip label="Clickable" variant="outlined" onClick={handleClick} />
    </Stack>
  );
}

삭제 가능 (Deletable)

import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';

export default function DeletableChips() {
  const handleDelete = () => {
    console.info('You clicked the delete icon.');
  };

  return (
    <Stack direction="row" spacing={1}>
      <Chip label="Deletable" onDelete={handleDelete} />
      <Chip label="Deletable" variant="outlined" onDelete={handleDelete} />
    </Stack>
  );
}

클릭 및 삭제 가능 (Clickable and deletable)

import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';

export default function ClickableAndDeletableChips() {
  const handleClick = () => {
    console.info('You clicked the Chip.');
  };

  const handleDelete = () => {
    console.info('You clicked the delete icon.');
  };

  return (
    <Stack direction="row" spacing={1}>
      <Chip
        label="Clickable Deletable"
        onClick={handleClick}
        onDelete={handleDelete}
      />
      <Chip
        label="Clickable Deletable"
        variant="outlined"
        onClick={handleClick}
        onDelete={handleDelete}
      />
    </Stack>
  );
}

import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';

export default function ClickableLinkChips() {
  return (
    <Stack direction="row" spacing={1}>
      <Chip label="Clickable Link" component="a" href="#basic-chip" clickable />
      <Chip
        label="Clickable Link"
        component="a"
        href="#basic-chip"
        variant="outlined"
        clickable
      />
    </Stack>
  );
}

커스텀 삭제 아이콘 (Custom delete icon)

import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';
import DoneIcon from '@mui/icons-material/Done';
import DeleteIcon from '@mui/icons-material/Delete';

export default function CustomDeleteIconChips() {
  const handleClick = () => {
    console.info('You clicked the Chip.');
  };

  const handleDelete = () => {
    console.info('You clicked the delete icon.');
  };

  return (
    <Stack direction="row" spacing={1}>
      <Chip
        label="Custom delete icon"
        onClick={handleClick}
        onDelete={handleDelete}
        deleteIcon={<DoneIcon />}
      />
      <Chip
        label="Custom delete icon"
        onClick={handleClick}
        onDelete={handleDelete}
        deleteIcon={<DeleteIcon />}
        variant="outlined"
      />
    </Stack>
  );
}

칩 장식 (Chip adornments)

컴포넌트의 시작 부분에 장식을 추가할 수 있어요.

avatar prop을 사용해 아바타를 추가하거나 icon prop을 사용해 아이콘을 추가해요.

아바타 칩 (Avatar chip)

import Avatar from '@mui/material/Avatar';
import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';

export default function AvatarChips() {
  return (
    <Stack direction="row" spacing={1}>
      <Chip avatar={<Avatar>M</Avatar>} label="Avatar" />
      <Chip
        avatar={<Avatar alt="Natacha" src="/static/images/avatar/1.jpg" />}
        label="Avatar"
        variant="outlined"
      />
    </Stack>
  );
}

아이콘 칩 (Icon chip)

import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';
import FaceIcon from '@mui/icons-material/Face';

export default function IconChips() {
  return (
    <Stack direction="row" spacing={1}>
      <Chip icon={<FaceIcon />} label="With Icon" />
      <Chip icon={<FaceIcon />} label="With Icon" variant="outlined" />
    </Stack>
  );
}

색상 칩 (Color chip)

color prop을 사용해 테마 팔레트에서 색상을 정의할 수 있어요.

import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';

export default function ColorChips() {
  return (
    <Stack spacing={1} sx={{ alignItems: 'center' }}>
      <Stack direction="row" spacing={1}>
        <Chip label="primary" color="primary" />
        <Chip label="success" color="success" />
      </Stack>
      <Stack direction="row" spacing={1}>
        <Chip label="primary" color="primary" variant="outlined" />
        <Chip label="success" color="success" variant="outlined" />
      </Stack>
    </Stack>
  );
}

크기 칩 (Sizes chip)

size prop을 사용해 작은 Chip을 정의할 수 있어요.

import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';

export default function SizesChips() {
  return (
    <Stack direction="row" spacing={1}>
      <Chip label="Small" size="small" />
      <Chip label="Small" size="small" variant="outlined" />
    </Stack>
  );
}

여러 줄 칩 (Multiline chip)

기본적으로 Chip은 라벨을 한 줄에만 표시해요. 여러 줄 콘텐츠를 지원하게 하려면 sx prop을 사용해 Chip 컴포넌트에 height:auto를 추가하고, label 스타일에 whiteSpace: normal을 추가하세요.

import Chip from '@mui/material/Chip';
import Box from '@mui/material/Box';

export default function MultilineChips() {
  return (
    <Box sx={{ width: 100 }}>
      <Chip
        sx={{
          height: 'auto',
          '& .MuiChip-label': {
            display: 'block',
            whiteSpace: 'normal',
          },
        }}
        label="This is a chip that has multiple lines."
      />
    </Box>
  );
}

칩 배열 (Chip array)

값 배열에서 여러 칩을 렌더링하는 예시예요. 칩을 삭제하면 배열에서 제거돼요. onClick prop이 정의되어 있지 않으므로, Chip은 포커스될 수 있지만 클릭하거나 터치할 때 깊이(depth)를 얻지는 않는다는 점에 주의하세요.

import * as React from 'react';
import { styled } from '@mui/material/styles';
import Chip from '@mui/material/Chip';
import Paper from '@mui/material/Paper';
import TagFacesIcon from '@mui/icons-material/TagFaces';

interface ChipData {
  key: number;
  label: string;
}

const ListItem = styled('li')(({ theme }) => ({
  margin: theme.spacing(0.5),
}));

export default function ChipsArray() {
  const [chipData, setChipData] = React.useState<readonly ChipData[]>([
    { key: 0, label: 'Angular' },
    { key: 1, label: 'jQuery' },
    { key: 2, label: 'Polymer' },
    { key: 3, label: 'React' },
    { key: 4, label: 'Vue.js' },
  ]);

  const handleDelete = (chipToDelete: ChipData) => () => {
    setChipData((chips) => chips.filter((chip) => chip.key !== chipToDelete.key));
  };

  return (
    <Paper
      sx={{
        display: 'flex',
        justifyContent: 'center',
        flexWrap: 'wrap',
        listStyle: 'none',
        p: 0.5,
        m: 0,
      }}
      component="ul"
    >
      {chipData.map((data) => {
        let icon;

        if (data.label === 'React') {
          icon = <TagFacesIcon />;
        }

        return (
          <ListItem key={data.key}>
            <Chip
              icon={icon}
              label={data.label}
              onDelete={data.label === 'React' ? undefined : handleDelete(data)}
            />
          </ListItem>
        );
      })}
    </Paper>
  );
}

칩 플레이그라운드 (Chip playground)

import * as React from 'react';
import Grid from '@mui/material/Grid';
import FormControl from '@mui/material/FormControl';
import FormLabel from '@mui/material/FormLabel';
import FormControlLabel from '@mui/material/FormControlLabel';
import RadioGroup from '@mui/material/RadioGroup';
import Radio from '@mui/material/Radio';
import Avatar from '@mui/material/Avatar';
import Chip from '@mui/material/Chip';
import FaceIcon from '@mui/icons-material/Face';
import DoneIcon from '@mui/icons-material/Done';
import { HighlightedCode } from '@mui/internal-core-docs/HighlightedCode';

function ChipsPlayground() {
  const [state, setState] = React.useState({
    color: 'default',
    onDelete: 'none',
    avatar: 'none',
    icon: 'none',
    variant: 'filled',
    size: 'medium',
  });
  const { color, onDelete, avatar, icon, variant, size } = state;

  const handleChange = (event) => {
    setState({
      ...state,
      [event.target.name]: event.target.value,
    });
  };

  const handleDeleteExample = () => {
    console.info('You clicked the delete icon.');
  };

  const colorToCode = color !== 'default' ? `color="${color}" ` : '';
  const sizeToCode = size === 'small' ? `size="small" ` : '';
  const variantToCode = variant !== 'filled' ? `variant="${variant}" ` : '';

  let onDeleteToCode;
  switch (onDelete) {
    case 'none':
      onDeleteToCode = '';
      break;
    case 'custom':
      onDeleteToCode = 'deleteIcon={<DoneIcon />} onDelete={handleDelete} ';
      break;
    default:
      onDeleteToCode = 'onDelete={handleDelete} ';
      break;
  }

  let iconToCode;
  let iconToPlayground;
  switch (icon) {
    case 'none':
      iconToCode = '';
      break;
    default:
      iconToCode = 'icon={<FaceIcon />} ';
      iconToPlayground = <FaceIcon />;
      break;
  }

  let avatarToCode;
  let avatarToPlayground;
  switch (avatar) {
    case 'none':
      avatarToCode = '';
      break;
    case 'img':
      avatarToCode = 'avatar={<Avatar src="/static/images/avatar/1.jpg" />} ';
      avatarToPlayground = <Avatar src="/static/images/avatar/1.jpg" />;
      break;
    case 'letter':
      avatarToCode = 'avatar={<Avatar>F</Avatar>} ';
      avatarToPlayground = <Avatar>F</Avatar>;
      break;
    default:
      break;
  }

  if (avatar !== 'none') {
    iconToCode = '';
    iconToPlayground = null;
  }

  const jsx = `
<Chip ${variantToCode}${colorToCode}${sizeToCode}${onDeleteToCode}${avatarToCode}${iconToCode}/>
`;

  return (
    <Grid container sx={{ flexGrow: 1 }}>
      <Grid size={12}>
        <Grid container sx={{ justifyContent: 'center', alignItems: 'center' }}>
          <Grid sx={(theme) => ({ height: theme.spacing(10) })}>
            <Chip
              label="Chip Component"
              color={color}
              deleteIcon={onDelete === 'custom' ? <DoneIcon /> : undefined}
              onDelete={onDelete !== 'none' ? handleDeleteExample : undefined}
              avatar={avatarToPlayground}
              icon={iconToPlayground}
              variant={variant}
              size={size}
            />
          </Grid>
        </Grid>
      </Grid>
      <Grid size={12}>
        <Grid container spacing={3}>
          <Grid
            size={{
              xs: 12,
              md: 6,
            }}
          >
            <FormControl component="fieldset">
              <FormLabel>variant</FormLabel>
              <RadioGroup
                row
                name="variant"
                aria-label="variant"
                value={variant}
                onChange={handleChange}
              >
                <FormControlLabel
                  value="filled"
                  control={<Radio />}
                  label="filled"
                />
                <FormControlLabel
                  value="outlined"
                  control={<Radio />}
                  label="outlined"
                />
              </RadioGroup>
            </FormControl>
          </Grid>
          <Grid
            size={{
              xs: 12,
              md: 6,
            }}
          >
            <FormControl component="fieldset">
              <FormLabel>color</FormLabel>
              <RadioGroup
                row
                name="color"
                aria-label="color"
                value={color}
                onChange={handleChange}
              >
                <FormControlLabel
                  value="default"
                  control={<Radio />}
                  label="default"
                />
                <FormControlLabel
                  value="primary"
                  control={<Radio />}
                  label="primary"
                />
                <FormControlLabel
                  value="secondary"
                  control={<Radio />}
                  label="secondary"
                />
                <FormControlLabel value="error" control={<Radio />} label="error" />
                <FormControlLabel value="info" control={<Radio />} label="info" />
                <FormControlLabel
                  value="success"
                  control={<Radio />}
                  label="success"
                />
                <FormControlLabel
                  value="warning"
                  control={<Radio />}
                  label="warning"
                />
              </RadioGroup>
            </FormControl>
          </Grid>
          <Grid
            size={{
              xs: 12,
              md: 6,
            }}
          >
            <FormControl component="fieldset">
              <FormLabel>size</FormLabel>
              <RadioGroup
                row
                name="size"
                aria-label="size"
                value={size}
                onChange={handleChange}
              >
                <FormControlLabel
                  value="medium"
                  control={<Radio />}
                  label="medium"
                />
                <FormControlLabel value="small" control={<Radio />} label="small" />
              </RadioGroup>
            </FormControl>
          </Grid>
          <Grid
            size={{
              xs: 12,
              md: 6,
            }}
          >
            <FormControl component="fieldset">
              <FormLabel>icon</FormLabel>
              <RadioGroup
                row
                name="icon"
                aria-label="icon"
                value={icon}
                onChange={handleChange}
              >
                <FormControlLabel value="none" control={<Radio />} label="none" />
                <FormControlLabel value="icon" control={<Radio />} label="icon" />
              </RadioGroup>
            </FormControl>
          </Grid>
          <Grid
            size={{
              xs: 12,
              md: 6,
            }}
          >
            <FormControl component="fieldset">
              <FormLabel>avatar</FormLabel>
              <RadioGroup
                row
                name="avatar"
                aria-label="avatar"
                value={avatar}
                onChange={handleChange}
              >
                <FormControlLabel value="none" control={<Radio />} label="none" />
                <FormControlLabel
                  value="letter"
                  control={<Radio />}
                  label="letter"
                />
                <FormControlLabel value="img" control={<Radio />} label="img" />
              </RadioGroup>
            </FormControl>
          </Grid>
          <Grid
            size={{
              xs: 12,
              md: 6,
            }}
          >
            <FormControl component="fieldset">
              <FormLabel>onDelete</FormLabel>
              <RadioGroup
                row
                name="onDelete"
                aria-label="on delete"
                value={onDelete}
                onChange={handleChange}
              >
                <FormControlLabel value="none" control={<Radio />} label="none" />
                <FormControlLabel
                  value="default"
                  control={<Radio />}
                  label="default"
                />
                <FormControlLabel
                  value="custom"
                  control={<Radio />}
                  label="custom"
                />
              </RadioGroup>
            </FormControl>
          </Grid>
        </Grid>
      </Grid>
      <Grid size={12}>
        <HighlightedCode code={jsx} language="jsx" />
      </Grid>
    </Grid>
  );
}
export default ChipsPlayground;

접근성 (Accessibility)

Chip이 삭제 가능하거나 클릭 가능하면 탭 순서상 버튼이에요. Chip이 포커스될 때(예: 탭 이동) Backspace 또는 Delete를 놓으면(keyup 이벤트) onDelete 핸들러가 호출되고, Escape를 놓으면 Chip이 블러(blur)돼요.

Chip API

데모 (Demos)

이 React 컴포넌트의 사용에 관한 예제와 자세한 내용은 컴포넌트 데모 페이지를 방문하세요:

Import

import Chip from '@mui/material/Chip';
// or
import { Chip } from '@mui/material';

Props

Name Type Default Required Description
avatar element - No
children unsupportedProp - No
classes object - No 컴포넌트에 적용되는 스타일을 오버라이드하거나 확장해요.
clickable bool - No
color 'default' | 'primary' | 'secondary' | 'error' | 'info' | 'success' | 'warning' | string 'default' No
component elementType - No
deleteIcon element - No
disabled bool false No
icon element - No
label node - No
nativeButton bool - No
onDelete func - No
size 'medium' | 'small' | string 'medium' No
skipFocusWhenDisabled bool false No
slotProps { label?: func | object, root?: func | object } {} No
slots { label?: elementType, root?: elementType } {} No
sx Array<func | object | bool> | func | object - No 시스템 오버라이드 및 추가 CSS 스타일을 정의할 수 있게 해주는 시스템 prop이에요.
variant 'filled' | 'outlined' | string 'filled' No

Note: ref는 루트 요소(HTMLDivElement)로 전달돼요.

제공된 다른 모든 props는 루트 요소(네이티브 요소)로 전달돼요.

테마 기본 props (Theme default props)

MuiChip을 사용해 테마로 이 컴포넌트의 기본 props를 변경할 수 있어요.

Slots

Name Default Class Description
root div .MuiChip-root 루트를 렌더링하는 컴포넌트예요.
label span .MuiChip-label 라벨을 렌더링하는 컴포넌트예요.

CSS

규칙 이름 (Rule name)

Global class Rule name Description
- avatar 아바타 요소에 적용되는 스타일이에요.
- clickable onClick이 정의되거나 clickable={true}일 때 루트 요소에 적용되는 스타일이에요.
- colorDefault color="default"일 때 루트 요소에 적용되는 스타일이에요.
- colorError color="error"일 때 루트 요소에 적용되는 스타일이에요.
- colorInfo color="info"일 때 루트 요소에 적용되는 스타일이에요.
- colorPrimary color="primary"일 때 루트 요소에 적용되는 스타일이에요.
- colorSecondary color="secondary"일 때 루트 요소에 적용되는 스타일이에요.
- colorSuccess color="success"일 때 루트 요소에 적용되는 스타일이에요.
- colorWarning color="warning"일 때 루트 요소에 적용되는 스타일이에요.
- deletable onDelete가 정의될 때 루트 요소에 적용되는 스타일이에요.
- deleteIcon deleteIcon 요소에 적용되는 스타일이에요.
.Mui-disabled - disabled={true}일 때 루트 요소에 적용되는 상태 클래스예요.
- filled variant="filled"일 때 루트 요소에 적용되는 스타일이에요.
.Mui-focusVisible - 키보드로 포커스될 때 루트 요소에 적용되는 상태 클래스예요.
- icon 아이콘 요소에 적용되는 스타일이에요.
- outlined variant="outlined"일 때 루트 요소에 적용되는 스타일이에요.
- sizeMedium size="medium"일 때 루트 요소에 적용되는 스타일이에요.
- sizeSmall size="small"일 때 루트 요소에 적용되는 스타일이에요.

소스 코드 (Source code)

이 페이지에서 정보를 찾지 못했다면, 더 자세한 내용을 위해 컴포넌트 구현을 살펴보세요.

더 알아보기 (Learn more)