ComponentsData display

Tag group

Tags on one line: as many as fit, then +N with the rest in a tooltip. The row never wraps and never grows.

Playground

Change the controls to try each prop. The preview fills the group with five skills; the code under it lists only the props you changed.

PythonSparkSQLAirflowdbt
States
import { TagGroup } from '@/ui/tag-group';<TagGroup label="Skills" className="w-36" />

Fit and overflow

When every tag fits there is no count. Otherwise the group shows whole tags only, then +N; a tag is never cut in half. Tags sit 4px apart, and the group measures again when its width changes, such as when a column is resized.

PythonSparkSQLPythonSparkSQLAirflowdbt
import { Tag } from '@/ui/tag';
import { TagGroup } from '@/ui/tag-group';

const skills = ['Python', 'Spark', 'SQL', 'Airflow', 'dbt'];

export default function TagGroupFitAndOverflow() {
  return (
    <div className="flex flex-col gap-150">
      <TagGroup label="Skills" className="w-70">
        {skills.slice(0, 3).map((skill) => (
          <Tag key={skill}>{skill}</Tag>
        ))}
      </TagGroup>
      <TagGroup label="Skills" className="w-36">
        {skills.map((skill) => (
          <Tag key={skill}>{skill}</Tag>
        ))}
      </TagGroup>
    </div>
  );
}

One long tag

Only the first tag may shorten, with an ellipsis, so something always shows.

Machine learning infrastructureFintechPaymentsLendingInsurance
import { Tag } from '@/ui/tag';
import { TagGroup } from '@/ui/tag-group';

const sectors = ['Machine learning infrastructure', 'Fintech', 'Payments', 'Lending', 'Insurance'];

export default function TagGroupOneLongTag() {
  return (
    <TagGroup label="Sectors" className="w-40">
      {sectors.map((sector) => (
        <Tag key={sector}>{sector}</Tag>
      ))}
    </TagGroup>
  );
}

Tags with an option colour

An option with a colour keeps it as the tag's 6px dot; the tag stays white with ink text. The colour is the option's, never the group's.

FintechSeries BLondonHiring
import { Tag } from '@/ui/tag';
import { TagGroup } from '@/ui/tag-group';

export default function TagGroupOptionColours() {
  return (
    <TagGroup label="Labels" className="w-60">
      <Tag color="blue">Fintech</Tag>
      <Tag color="plum">Series B</Tag>
      <Tag color="teal">London</Tag>
      <Tag color="green">Hiring</Tag>
    </TagGroup>
  );
}

In a table cell

Pass inCell inside a table. The cell is the focus stop, so +N leaves the Tab order; the cell's editor shows every tag.

Maya ChenPythonSparkSQLAirflowdbt
import { Tag } from '@/ui/tag';
import { TagGroup } from '@/ui/tag-group';

const skills = ['Python', 'Spark', 'SQL', 'Airflow', 'dbt'];

export default function TagGroupInACell() {
  return (
    <div role="grid" aria-label="Candidates" className="w-120 rounded-large bg-surface text-body shadow-[inset_0_0_0_1px_var(--color-border)]">
      <div role="row" className="flex h-9 items-center">
        <span role="gridcell" className="w-45 shrink-0 px-150 font-medium">
          Maya Chen
        </span>
        <span role="gridcell" tabIndex={0} className="flex h-9 w-50 items-center border-s border-border px-150 outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-border-focused focus-visible:outline-solid">
          <TagGroup label="Skills" inCell>
            {skills.map((skill) => (
              <Tag key={skill}>{skill}</Tag>
            ))}
          </TagGroup>
        </span>
      </div>
    </div>
  );
}

On this page