Skip to Content
Hashti Design System
Components

Tag & Filter Tag

Compact label for categorizing, filtering, and organizing entities and content items.

Tag & Filter Tag

Tags represent concise pieces of metadata, status descriptors, categories, or active search filters. Hashti provides two distinct varieties:

  1. Tag: A static, lightweight visual label representing entity categories, badges, or read-only taxonomy terms.
  2. FilterTag & TagGroup: An interactive, accessible collection built on React Aria Components supporting item selection, keyboard navigation, and tag dismissal/removal.
Neutral 01Hashti PortalWCAG AAAAmber GlazeCritical Alert
WCAG AAAPersian GeometryAstro FumadocsTailwind v4
Portal Vault Integrity72%
72%

Import

import { Tag, FilterTag, TagGroup } from "@hashti/react";

Examples

Static Tags

Use <Tag> for read-only labels, statuses, and taxonomy indicators.

import { Tag } from "@hashti/react";

export function StaticTagsExample() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Tag color="gray">General</Tag>
      <Tag color="teal">Architecture</Tag>
      <Tag color="blue">Kubernetes</Tag>
      <Tag color="green">Healthy</Tag>
      <Tag color="red">Deprecated</Tag>
      <Tag color="purple">Enterprise</Tag>
    </div>
  );
}

Tag Sizes

Tags are available in two standard heights: sm (20px) for high-density tables and compact card metadata, and md (24px, default) for general UI layouts.

import { Tag } from "@hashti/react";

export function TagSizesExample() {
  return (
    <div className="flex items-center gap-4">
      <Tag size="sm" color="blue">
        Small Tag (20px)
      </Tag>
      <Tag size="md" color="blue">
        Medium Tag (24px)
      </Tag>
    </div>
  );
}

Color Palette

Hashti includes ten distinct color tokens mapped to the design system’s semantic color scales:

import { Tag } from "@hashti/react";

export function TagPaletteExample() {
  const colors = [
    "gray",
    "cool-gray",
    "warm-gray",
    "blue",
    "cyan",
    "teal",
    "green",
    "red",
    "purple",
    "magenta",
  ] as const;

  return (
    <div className="flex flex-wrap gap-2">
      {colors.map((color) => (
        <Tag key={color} color={color}>
          {color}
        </Tag>
      ))}
    </div>
  );
}

Dismissible Filter Tags with TagGroup

Use <TagGroup> combined with <FilterTag> to manage interactive filter collections. When onRemove is specified on TagGroup, each FilterTag automatically renders an accessible dismiss button with a close icon.

import { useState } from "react";
import { TagGroup, FilterTag } from "@hashti/react";

export function FilterTagGroupExample() {
  const [filters, setFilters] = useState([
    { id: "1", name: "Status: Active" },
    { id: "2", name: "Role: Administrator" },
    { id: "3", name: "Region: Middle East" },
    { id: "4", name: "Environment: Production" },
  ]);

  const handleRemove = (keys: Set<React.Key>) => {
    setFilters((prev) => prev.filter((item) => !keys.has(item.id)));
  };

  return (
    <div className="space-y-4">
      <TagGroup label="Active Filters" items={filters} onRemove={handleRemove}>
        {(item) => <FilterTag id={item.id}>{item.name}</FilterTag>}
      </TagGroup>

      {filters.length === 0 && <p className="text-sm text-subtle">No active filters applied.</p>}
    </div>
  );
}

Selectable Tags

TagGroup can also be configured with selectionMode="single" or selectionMode="multiple" for filter chips that toggle on and off.

import { useState } from "react";
import { TagGroup, FilterTag } from "@hashti/react";
import type { Selection } from "@hashti/react";

export function SelectableTagsExample() {
  const [selected, setSelected] = useState<Selection>(new Set(["architecture"]));

  const topics = [
    { id: "architecture", label: "Architecture" },
    { id: "tokens", label: "Design Tokens" },
    { id: "accessibility", label: "Accessibility" },
    { id: "performance", label: "Performance" },
  ];

  return (
    <TagGroup
      label="Topics"
      selectionMode="multiple"
      selectedKeys={selected}
      onSelectionChange={setSelected}
      items={topics}
    >
      {(item) => <FilterTag id={item.id}>{item.label}</FilterTag>}
    </TagGroup>
  );
}

Props Reference

Tag Props

PropTypeDefaultDescription
color'gray' | 'blue' | 'cyan' | 'green' | 'red' | 'teal' | 'purple' | 'magenta' | 'cool-gray' | 'warm-gray''gray'Preset color variant using Hashti token CSS variables.
size'sm' | 'md''md'Height and padding of the tag. sm is 20px, md is 24px.
childrenReactNode—Text or elements rendered inside the tag.
classNamestring—Additional CSS class names.

TagGroup Props

PropTypeDefaultDescription
labelReactNode—Accessible label rendered above or associated with the group.
itemsIterable<T>—The collection of tag data items for dynamic rendering.
children(item: T) => ReactNode—Render function returning <FilterTag> elements.
selectionMode'none' | 'single' | 'multiple''none'The selection behavior for tags in the group.
selectedKeys'all' | Iterable<Key>—Controlled set of selected keys.
onSelectionChange(keys: Selection) => void—Callback fired when the selection changes.
onRemove(keys: Set<Key>) => void—Callback fired when user clicks the remove button or presses Delete/Backspace on a tag.
disabledKeysIterable<Key>—Keys of tags that cannot be selected or removed.

FilterTag Props

PropTypeDefaultDescription
idKey—Unique identifier for the tag within the TagGroup.
textValuestring—Accessible string representation used for screen readers and keyboard typeahead.
childrenReactNode | ((values) => ReactNode)—Content of the tag, or render function with state arguments.
isDisabledbooleanfalseWhether this tag is disabled.

Accessibility (a11y)

  • Keyboard Navigation: In interactive <TagGroup> collections, use ArrowLeft and ArrowRight (or ArrowUp/ArrowDown) to move roving focus between tags.
  • Dismissal Controls: When onRemove is enabled, pressing Delete or Backspace on a focused tag triggers dismissal. The remove button within <FilterTag> is also accessible via keyboard and screen readers with an automatic slot="remove" designation.
  • Selection: Press Space or Enter to toggle the selection of a tag when selectionMode is enabled.
  • Screen Reader Semantics: TagGroup outputs an ARIA role="grid" or role="listbox" with appropriate group labelling via <Label>, and each tag provides aria-selected and accessible button states.

Keyboard Interactions

KeyAction
→ / ←Moves focus between tags in a tag group.
Space / EnterSelects tag or triggers remove action.
Delete / BackspaceRemoves focused tag if removable.

WAI-ARIA & Data Attributes

AttributeTargetDescription
[data-hovered]TagPresent on hover.
[data-selected]TagPresent when tag is selected.
[data-focused]TagActive on focus.
[data-disabled]TagPresent when tag is disabled.