Tag
Short label that classifies or attributes content with a category or keyword. Optionally clickable or removable.
Tag renders a <span> by default. With onClick, the whole tag becomes a <button>. With onRemove, the root becomes role="group" and the remove control is a separate focusable <button> labelled via removeLabel. Supports Backspace/Delete to remove when focused.
import { Tag } from '@arshad-shah/cynosure-react';
export default function Example() {
return <Tag>Design</Tag>;
}
Variants
Section titled “Variants”Tag ships four variants — solid, soft (default), outline, and ghost — across six colour schemes (accent, neutral, success, warning, danger, info).
import { Tag } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem', alignItems: 'center' }}>
<Tag variant="solid" colorScheme="accent">
Accent
</Tag>
<Tag variant="soft" colorScheme="success">
Success
</Tag>
<Tag variant="outline" colorScheme="warning">
Warning
</Tag>
<Tag variant="ghost" colorScheme="danger">
Danger
</Tag>
<Tag variant="soft" colorScheme="info">
Info
</Tag>
<Tag variant="soft" colorScheme="neutral">
Neutral
</Tag>
</div>
);
}
Three sizes are available: xs, sm, and md (default).
import { Tag } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem', alignItems: 'center' }}>
<Tag size="xs">Extra small</Tag>
<Tag size="sm">Small</Tag>
<Tag size="md">Medium</Tag>
</div>
);
}
With icon
Section titled “With icon”Pass any node to icon for a leading glyph. The icon is wrapped in an aria-hidden span so it stays decorative.
import { Tag } from '@arshad-shah/cynosure-react';
const HashIcon = () => (
<svg
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<line x1="4" y1="9" x2="20" y2="9" />
<line x1="4" y1="15" x2="20" y2="15" />
<line x1="10" y1="3" x2="8" y2="21" />
<line x1="16" y1="3" x2="14" y2="21" />
</svg>
);
export default function Example() {
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem', alignItems: 'center' }}>
<Tag icon={<HashIcon />} colorScheme="accent">
design-system
</Tag>
<Tag icon={<HashIcon />} colorScheme="success">
released
</Tag>
<Tag icon={<HashIcon />} colorScheme="warning">
in-review
</Tag>
</div>
);
}
Clickable
Section titled “Clickable”Provide onClick to make the entire tag a button. Use this for filter chips that should respond to a single activation.
import { Tag } from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [active, setActive] = useState('design');
const filters = ['design', 'engineering', 'research'];
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem', alignItems: 'center' }}>
{filters.map((filter) => (
<Tag
key={filter}
colorScheme={active === filter ? 'accent' : 'neutral'}
variant={active === filter ? 'solid' : 'soft'}
onClick={() => setActive(filter)}
>
{filter}
</Tag>
))}
</div>
);
}
Removable
Section titled “Removable”Pass onRemove to render a dismiss control. The root becomes role="group", the remove button is keyboard reachable, and pressing Backspace or Delete on the focused group calls onRemove.
import { Tag } from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [tags, setTags] = useState(['design', 'engineering', 'research']);
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem', alignItems: 'center' }}>
{tags.map((tag) => (
<Tag
key={tag}
colorScheme="accent"
onRemove={() => setTags((prev) => prev.filter((t) => t !== tag))}
>
{tag}
</Tag>
))}
</div>
);
}
Accessibility
Section titled “Accessibility”- Static tags render as
<span>— purely presentational. - Tags with
onClickupgrade to<button>and inherit native button semantics. - Tags with
onRemoverender asrole="group"with the focusable remove button labelled byremoveLabel(defaults toRemove {label}when children is a string, otherwiseRemove). - The group is
tabIndex={0}so keyboard users can press Backspace or Delete to remove it without targeting the close button. disabledpropagates to the remove and click buttons and removes the group from tab order.
Recipes
Section titled “Recipes”- Use tags to classify articles, issues, or library entries with consistent colour.
- Pair
onClickwith controlled filters to build a quick-filter row. - Provide
removeLabelfor non-string children so the remove action remains announced. - Use
shape="square"for compact metadata strips and the defaultpillshape for prose contexts.