Skip to Content

Tag

A tag is a user-generated keyword associated with certain items to categorize them and make them easily discoverable.

import * as React from 'react';
import { TagContainer, Tag } from '@itwin/itwinui-react';

export default () => {
  return (
    <TagContainer>
      <Tag>Tag 1</Tag>
      <Tag onRemove={() => {}}>Tag 2</Tag>
      <Tag onRemove={() => {}}>Tag 3</Tag>
    </TagContainer>
  );
};

Tags are user-generated keywords used to label, categorize, or organize items and files. A group of multiple tags is a standard way of labeling an item to make it easily discoverable by peers who may not know the exact title of said item. A single tag may be mapped to more than one project at once if these projects fit in similar categories. Tags may also be used as a way to filter out content; in that context, the tags are pre-existing, and users select tags that fit their search to narrow down the results.

Usage

import * as React from 'react';
import { TagContainer, Tag } from '@itwin/itwinui-react';

export default () => {
  return <Tag onRemove={() => {}}>Tag 1</Tag>;
};

Basic tags

Tags in the basic state are static and cannot be removed or edited by the user. No new tags can be added through this state either. This state is commonly seen in tile metadata.

import * as React from 'react';
import { TagContainer, Tag } from '@itwin/itwinui-react';

export default () => {
  return (
    <TagContainer>
      <Tag variant='basic'>Tag 1</Tag>
      <Tag variant='basic'>Tag 2</Tag>
    </TagContainer>
  );
};

Props

Prop Description Default
children
Text inside the tag.
ReactNode
onClick
Callback invoked when the tag is clicked.
When this prop is passed, the tag will be rendered as a button.
MouseEventHandler<Element>
onRemove
Callback function that handles click on the remove ("❌") button. If not passed, the remove button will not be shown.
If both onClick and onRemove are passed, then the tag label (rather than the tag itself) will be rendered as a button, to avoid invalid markup (nested buttons).
MouseEventHandler<Element>
removeButtonProps
Props for customizing the remove ("❌") button.
Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & { ...; }
variant
Variant of tag. Basic tags don't have an outline.
"default" | "basic"
'default'
labelProps
Props for customizing the label.
Only relevant for the 'default' Tag.
Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: Ref<...>; }
as
"symbol" | "object" | "span" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 159 more ... | FunctionComponent<...>

Usage guidelines

  • Tags are meant to be used for display purposes. While interactivity is possible, it is not the primary use case.
  • Use basic tags when you need to make tags read-only.

Accessibility

When the onClick prop is passed to Tag, it is automatically rendered as a <button> element. This gives the tag proper semantics and makes it keyboard interactable.

When the onRemove prop is passed to Tag, a remove button is rendered inside the tag. This button has an aria-label set to "Delete tag", which can be customized using the removeButtonProps prop.

If both onClick and onRemove props are passed, then the tag label (rather than the tag itself) will be rendered as a button, to avoid invalid markup (button nested inside another button). This is achieved using the LinkAction component.

Tag container

Tag containers may be used to group tags, depending on the page layout and usage.

import * as React from 'react';
import { TagContainer, Tag } from '@itwin/itwinui-react';

export default () => {
  return (
    <TagContainer background='filled'>
      <Tag onRemove={() => {}}>Tag 1</Tag>
      <Tag onRemove={() => {}}>Tag 2</Tag>
      <Tag onRemove={() => {}}>Tag 3</Tag>
      <Tag onRemove={() => {}}>Tag 4</Tag>
    </TagContainer>
  );
};

Wrapping

The wrapping container wraps tags around to the following line when the maximum width is reached on the previous line. This allows display of the full tags without label truncation.

import * as React from 'react';
import { TagContainer, Tag } from '@itwin/itwinui-react';

export default () => {
  return (
    <TagContainer background='filled' className='demo-container'>
      <Tag onRemove={() => {}}>Tag 1</Tag>
      <Tag onRemove={() => {}}>Tag 2</Tag>
      <Tag onRemove={() => {}}>Tag 3</Tag>
      <Tag onRemove={() => {}}>Medium tag 4</Tag>
      <Tag onRemove={() => {}}>Very long tag 5</Tag>
      <Tag onRemove={() => {}}>Tag 6</Tag>
      <Tag onRemove={() => {}}>Tag 7</Tag>
      <Tag onRemove={() => {}}>Long tag 8</Tag>
      <Tag onRemove={() => {}}>Tag 9</Tag>
    </TagContainer>
  );
};

Truncating

The truncating container has fixed height, so it only displays tags that fit on a single line, and truncates tags that exceeds the maximum width. It uses ellipsis (…) to inform the user that there are hidden extra tags beyond what is currently shown.

import * as React from 'react';
import { TagContainer, Tag } from '@itwin/itwinui-react';

export default () => {
  return (
    <TagContainer
      overflow='truncate'
      background='filled'
      className='demo-container'
    >
      <Tag onRemove={() => {}}>Tag 1</Tag>
      <Tag onRemove={() => {}}>Tag 2</Tag>
      <Tag onRemove={() => {}}>Tag 3</Tag>
      <Tag onRemove={() => {}}>Medium tag 4</Tag>
      <Tag onRemove={() => {}}>Very long tag 5</Tag>
      <Tag onRemove={() => {}}>Tag 6</Tag>
      <Tag onRemove={() => {}}>Tag 7</Tag>
      <Tag onRemove={() => {}}>Long tag 8</Tag>
      <Tag onRemove={() => {}}>Tag 9</Tag>
    </TagContainer>
  );
};

Scrollable

The scrollable container is much like the truncating container, except it allows the user to horizontally scroll to reveal the tags that go beyond the maximum width. The tag that extends past the width is cut off, to hint at the scrolling possibility.

import * as React from 'react';
import { TagContainer, Tag } from '@itwin/itwinui-react';

export default () => {
  return (
    <TagContainer
      overflow='scroll'
      background='filled'
      className='demo-container'
    >
      <Tag onRemove={() => {}}>Tag 1</Tag>
      <Tag onRemove={() => {}}>Tag 2</Tag>
      <Tag onRemove={() => {}}>Tag 3</Tag>
      <Tag onRemove={() => {}}>Medium tag 4</Tag>
      <Tag onRemove={() => {}}>Very long tag 5</Tag>
      <Tag onRemove={() => {}}>Tag 6</Tag>
      <Tag onRemove={() => {}}>Tag 7</Tag>
      <Tag onRemove={() => {}}>Long tag 8</Tag>
      <Tag onRemove={() => {}}>Tag 9</Tag>
    </TagContainer>
  );
};

Props

Prop Description Default
children
Tags inside the container.
ReactNode
overflow
Overflow solution to the tag container. Set max-width to have scroll or truncated tags.
"truncate" | "scroll"
background
Use background to have tags standout in your layout. Container gets colored background and some spacing applied.
"none" | "filled"
'none'
as
"symbol" | "object" | "div" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 158 more ... | FunctionComponent<...>

Usage guidelines

  • Wrapping tag containers are ideal for layouts with plenty of vertical space, in situations where seeing all the tags is necessary.
  • Use truncating tag containers when you have limited space, and display of the full tags is not necessary.
  • Scrollable tag containers are a good choice when the space in a layout is limited, but viewing all the tags is essential.