TagGroup
Keyboard-navigable list of tags built on React Aria, with optional selection and removal. Arrow keys move between tags, so the group is a single tab stop rather than one per tag.
import { TagGroup } from "@pockets-ui/components"Anatomy
| Part | Role |
|---|---|
TagGroup.Root | Owns selectionMode, selectedKeys, disabledKeys, onRemove. |
TagGroup.Label | The group's visible label. |
TagGroup.List | The tag container. Takes static children or items. |
TagGroup.Tag | One tag. Needs an id when declared statically. |
TagGroup.StaticTag | A display-only tag with an intent wash. Never selected or removed. |
Selection
selectionMode opts the group into "single" or "multiple" selection. Without
it, tags are display-only.
Code
import { TagGroup } from "@pockets-ui/components"
export default function TagGroupSelection() {
return (
<TagGroup.Root
selectionMode="multiple"
defaultSelectedKeys={["laundry", "pool"]}
>
<TagGroup.Label>Amenities</TagGroup.Label>
<TagGroup.List>
<TagGroup.Tag id="laundry">Laundry</TagGroup.Tag>
<TagGroup.Tag id="fitness">Fitness center</TagGroup.Tag>
<TagGroup.Tag id="parking" isDisabled>
Parking
</TagGroup.Tag>
<TagGroup.Tag id="pool">Swimming pool</TagGroup.Tag>
<TagGroup.Tag id="breakfast">Breakfast</TagGroup.Tag>
</TagGroup.List>
</TagGroup.Root>
)
}Removable tags
Passing onRemove gives every tag a remove button and enables the Delete and
Backspace keys. The group doesn't hold the list — remove the item from your own
state and re-render, as this example does.
Code
import { TagGroup } from "@pockets-ui/components"
import { useState } from "react"
const INITIAL_INTERESTS = [
{ id: "news", name: "News" },
{ id: "travel", name: "Travel" },
{ id: "gaming", name: "Gaming" },
{ id: "shopping", name: "Shopping" },
]
export default function TagGroupRemovable() {
const [interests, setInterests] = useState(INITIAL_INTERESTS)
return (
// Passing onRemove to Root makes every tag grow a remove button.
<TagGroup.Root
onRemove={(keys) =>
setInterests((items) => items.filter((item) => !keys.has(item.id)))
}
>
<TagGroup.Label>Interests</TagGroup.Label>
<TagGroup.List items={interests}>
{(item) => <TagGroup.Tag>{item.name}</TagGroup.Tag>}
</TagGroup.List>
</TagGroup.Root>
)
}Static tags
TagGroup.StaticTag is a presentational chip. It sits in the same list as
regular tags (mix them freely, including inside an items render function) but
never takes part in selection or removal, and isn't a tab stop. Its intent
picks a wash from the semantic bg / fg intents: neutral (default),
action, info, success, warning, danger, brand, or premium.
Code
import { TagGroup } from "@pockets-ui/components"
export default function TagGroupStatic() {
return (
<TagGroup.Root>
<TagGroup.Label>Listing status</TagGroup.Label>
<TagGroup.List>
<TagGroup.StaticTag id="new">New</TagGroup.StaticTag>
<TagGroup.StaticTag id="verified" intent="success">
Verified
</TagGroup.StaticTag>
<TagGroup.StaticTag id="offer" intent="info">
Offer pending
</TagGroup.StaticTag>
<TagGroup.StaticTag id="inspection" intent="warning">
Inspection due
</TagGroup.StaticTag>
<TagGroup.StaticTag id="expired" intent="danger">
Expired
</TagGroup.StaticTag>
<TagGroup.StaticTag id="pro" intent="premium">
Pro
</TagGroup.StaticTag>
</TagGroup.List>
</TagGroup.Root>
)
}