Tag Group
A wrapping set of selectable tags for filters and multi-choice chip sets.
Tag Group is a wrapping row of tags the user can select, one at a time or
several at once. It is built for filters, such as the category pills above the
base.org ecosystem grid, and for chip sets where any number of options can be
on. Put the tags in a TagList; the group carries the size, selection and
label, and every tag restyles itself from it.
import { TagGroup, TagList, Tag } from '@base-org/bds-web/product/tag-group';
<TagGroup aria-label="Category" selectionMode="multiple">
<TagList>
<Tag id="defi">DeFi</Tag>
<Tag id="ai">AI</Tag>
</TagList>
</TagGroup>;Sizes
Medium
The default. A 36px pill with a full radius, 16px of side padding, a hairline border and 14px text. An unselected tag is transparent and fills light gray on hover; a selected tag fills gray, a step darker on hover. Use it for filters on wider screens.
<TagGroup aria-label="Category" selectionMode="single" defaultSelectedKeys={['all']}>
<TagList>
<Tag id="all">All</Tag>
<Tag id="defi">DeFi</Tag>
<Tag id="ai">AI</Tag>
<Tag id="boost">Boost Campaigns</Tag>
</TagList>
</TagGroup>Small
size="sm" is a 32px chip with an 8px radius and 8px of side padding. An
unselected chip has muted text and border and darkens on hover; a selected chip
takes the inverse fill. Use it in compact layouts and mobile filter sheets.
<TagGroup size="sm" aria-label="Subcategory" selectionMode="multiple" defaultSelectedKeys={['dex']}>
<TagList>
<Tag id="dex">DEX</Tag>
<Tag id="lending">Lending</Tag>
<Tag id="payments">Payments</Tag>
</TagList>
</TagGroup>Selection
Single
selectionMode="single" keeps at most one tag selected; choosing another moves
the selection. Use defaultSelectedKeys for uncontrolled use, or
selectedKeys with onSelectionChange when the parent owns the filter. Add
disallowEmptySelection when one tag must always stay on, such as an All tag.
<TagGroup
aria-label="Category"
selectionMode="single"
disallowEmptySelection
defaultSelectedKeys={['all']}
>
<TagList>
<Tag id="all">All</Tag>
<Tag id="defi">DeFi</Tag>
<Tag id="nft">NFT</Tag>
</TagList>
</TagGroup>Multiple
selectionMode="multiple" lets any number of tags be on at once. Give every
Tag Group a selectionMode or onRemove; tags that only display a label
belong in a Badge, not a Tag Group.
<TagGroup aria-label="Networks" selectionMode="multiple" defaultSelectedKeys={['base', 'ethereum']}>
<TagList>
<Tag id="base">Base</Tag>
<Tag id="ethereum">Ethereum</Tag>
<Tag id="optimism">Optimism</Tag>
</TagList>
</TagGroup>Label and removal
With label
label puts a visible label above the tags and names the group. Without one,
pass aria-label.
<TagGroup label="Category" selectionMode="multiple">
<TagList>
<Tag id="defi">DeFi</Tag>
<Tag id="ai">AI</Tag>
</TagList>
</TagGroup>Removable
Pass onRemove and every tag gets a remove button after its text. The handler
receives the keys to remove; the group does not remove anything itself, so drop
the keys from your own list. Backspace and Delete remove the focused tag too.
const [tags, setTags] = useState(['DeFi', 'AI', 'Gaming']);
<TagGroup
aria-label="Active filters"
onRemove={(keys) => setTags(tags.filter((tag) => !keys.has(tag)))}
>
<TagList>
{tags.map((tag) => (
<Tag key={tag} id={tag}>{tag}</Tag>
))}
</TagList>
</TagGroup>When to use
Use Tag Group for filters and chip sets where the user turns options on and off, especially when several can be on at once or the options wrap onto more than one line.
Use something else when:
- The choice is one of two to five short options, a compact mode switch that always has a value. Use Segment.
- The tags only display labels and the user never selects or removes them.
Use a Badge with
variant="tag". Badge shows tags; Tag Group lets the user choose them. - The list is long or changes at runtime and belongs in a dropdown. Use
Select with
selectionMode="multiple". - The options switch whole panels of content. Use Tabs.
Usage
Do
Keep tag text to one or two words, and use one size per group: md for
page filters, sm for compact sheets and chip sets.
Don't
Use a Tag Group for actions. Tags change a selection; a tag that runs a command is a Button.
Props
TagGroup
| Prop | Type | Default |
|---|---|---|
childrenThe children of the component. | TypeReactNode | Default— |
classNameThe CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the | Typestring | Default— |
defaultSelectedKeysThe initial selected keys in the collection (uncontrolled). | TypeIterable<Key> | "all" | Default— |
disabledKeysThe item keys that are disabled. These items cannot be selected, focused, or otherwise | TypeIterable<Key> | Default— |
disallowEmptySelectionWhether the collection allows empty selection. | Typeboolean | Default— |
escapeKeyBehaviorWhether pressing the escape key should clear selection in the TagGroup or not. | Type"clearSelection" | "none" | Default'clearSelection' |
labelA visible label above the tags. Without one, pass `aria-label`. | TypeReactNode | Default— |
selectedKeysThe currently selected keys in the collection (controlled). | TypeIterable<Key> | "all" | Default— |
selectionBehaviorHow multiple selection should behave in the collection. | Type"toggle" | "replace" | Default'toggle' |
selectionModeThe type of selection that is allowed in the collection. | Type"none" | "single" | "multiple" | Default— |
shouldSelectOnPressUpWhether selection should occur on press up instead of press down. | Typeboolean | Default— |
size`md` is the 36px rounded pill for desktop filters. `sm` is the 32px chip | Type"sm" | "md" | Defaultmd |
TagList
| Prop | Type | Default |
|---|---|---|
childrenThe contents of the collection. | TypeReactNode | ((item: T) => ReactNode) | Default— |
classNameThe CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the | Typestring | Default— |
dependenciesValues that should invalidate the item cache when using dynamic collections. | Typereadonly any[] | Default— |
itemsItem objects in the collection. | TypeIterable<T> | Default— |
renderEmptyStateProvides content to display when there are no items in the tag list. | Type((props: TagListRenderProps) => ReactNode) | Default— |
Tag
| Prop | Type | Default |
|---|---|---|
childrenThe children of the component. A function may be provided to alter the children based on | TypeChildrenOrFunction<TagRenderProps> | Default— |
classNameThe CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the | Typestring | Default— |
hrefA URL to link to. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href). | Typestring | Default— |
isDisabledWhether the tag is disabled. | Typeboolean | Default— |
relThe relationship between the linked resource and the current page. See | Typestring | Default— |
targetThe target window for the link. See | TypeHTMLAttributeAnchorTarget | Default— |
textValueA string representation of the tags's contents, used for accessibility. | Typestring | Default— |
TagGroupLabel
| Prop | Type | Default |
|---|---|---|
elementType | Typestring | Default— |
TagRemoveButton
| Prop | Type | Default |
|---|---|---|
childrenThe children of the component. A function may be provided to alter the children based on | TypeChildrenOrFunction<TagRenderProps> | Default— |
classNameThe CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the | TypeClassNameOrFunction<ButtonRenderProps> | Default— |
isDisabledWhether the button is disabled. | Typeboolean | Default— |
isPendingWhether the button is in a pending state. This disables press and hover events | Typeboolean | Default— |
typeThe behavior of the button when used in an HTML form. | Type"button" | "submit" | "reset" | Default'button' |
Accessibility
Tag Group wraps React Aria's TagGroup, TagList and Tag. The list is a
grid and each tag a row, so the group is one tab stop and the arrow keys move
between tags. Space or Enter toggles the focused tag, and each selected tag is
announced as selected. Name the group with label or aria-label.
With onRemove, Backspace and Delete remove the focused tag. The remove button
is named "Remove" by React Aria and sits out of the tab order, so keyboard users
remove with those keys instead; its icon is hidden from screen readers.
Colour transitions are instant when the reader prefers reduced motion.