Skip to main content
Pricing

Tag

Free

A removable label used for categorisation, filtering, and multi-value inputs. Includes an optional close button for removal. Tags can be interactive (clickable to filter) or static (display only). Used in filter bars, form fields, and content metadata.

12 variants

Variant
Default

Variants

VariantDescriptionWhen to use
DefaultNeutral tag with optional close button for removal.Use for general categorisation — skills, topics, filters.
Removable
Selectable

Usage Guidelines

Do

Keep tag labels concise — one to three words.

Don't

Use tags for status information — use Badge instead.

Do

Include a close button for removable tags with aria-label="Remove [tag name]".

Don't

Make tags too small to read or tap — minimum height 28px.

Do

Use consistent tag styles within a group.

Don't

Mix removable and non-removable tags in the same group without visual distinction.

Do

Allow tags to wrap to multiple lines in constrained containers.

Don't

Use more than 6 colour variants — limit categories to maintain scannability.

Code

HTML
<div class="lex-tag-group" role="list" aria-label="Selected skills">
  <span class="lex-tag" role="listitem">
    <span class="lex-tag__label">React</span>
    <button class="lex-tag__remove" aria-label="Remove React">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
        stroke="currentColor" stroke-width="2">
        <line x1="18" y1="6" x2="6" y2="18" />
        <line x1="6" y1="6" x2="18" y2="18" />
      </svg>
    </button>
  </span>
  <span class="lex-tag" role="listitem">
    <span class="lex-tag__label">TypeScript</span>
    <button class="lex-tag__remove" aria-label="Remove TypeScript">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
        stroke="currentColor" stroke-width="2">
        <line x1="18" y1="6" x2="6" y2="18" />
        <line x1="6" y1="6" x2="18" y2="18" />
      </svg>
    </button>
  </span>
</div>
CSS Custom Properties
.lex-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--lex-tag-gap, 4px);
  padding: 0 var(--lex-tag-px, 10px);
  height: var(--lex-tag-height, 28px);
  font-size: var(--lex-tag-font-size, 13px);
  font-weight: 500;
  border-radius: var(--lex-tag-radius, var(--lex-radius-sm));
  background: var(--lex-tag-bg, var(--lex-bg-surface-subtle));
  color: var(--lex-tag-text, var(--lex-text-primary));
  line-height: 1;
}

.lex-tag__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: none;
  background: transparent;
  border-radius: var(--lex-radius-xxs);
  cursor: pointer;
  color: var(--lex-tag-remove-color, var(--lex-text-muted));
  transition: background 150ms ease, color 150ms ease;
}

.lex-tag__remove:hover {
  background: var(--lex-tag-remove-bg-hover, rgba(0, 0, 0, 0.08));
  color: var(--lex-tag-remove-color-hover, var(--lex-text-primary));
}
React
// Using Lexicon CSS classes with React

export function SkillTags() {
  const [skills, setSkills] = useState(['React', 'TypeScript', 'Node.js']);

  const removeSkill = (skill: string) => {
    setSkills(prev => prev.filter(s => s !== skill));
  };

  return (
    <TagGroup label="Selected skills">
      {skills.map(skill => (
        <Tag key={skill} onRemove={() => removeSkill(skill)}>
          {skill}
        </Tag>
      ))}
    </TagGroup>
  );
}

Design Tokens

TokenValue (dark)Value (light)CSS property
--lex-tag-bgbg
--lex-tag-texttext
--lex-tag-borderborder
--lex-tag-radiusradius
--lex-tag-paddingpadding

Accessibility

  • Remove buttons must have aria-label="Remove [tag name]" for screen readers.
  • Tag groups should use role="list" with individual role="listitem" tags.
  • Provide a visible group label via aria-label on the container.
  • When a tag is removed, move focus to the next tag or the container.

Keyboard Interactions

TabMoves focus to the next tag remove button.
Enter/SpaceActivates the remove button on a focused tag.
Backspace/DeleteRemoves the focused tag (when tag itself is focused).