list.setSelectedKeys(keys)}
>
No team members}
>
{(user) => (
{user.fallback}
{user.name}
)}
Select team members for your project
{list.selectedKeys !== "all" && Array.from(list.selectedKeys).length > 0 && (
Selected:
{Array.from(list.selectedKeys).map((key) => {
const user = list.getItem(key);
if (!user) return null;
return (
{user.fallback}{user.name}
);
})}
)}
);
}
```
### Custom Render Function
```tsx
"use client";
import {PlanetEarth, Rocket, ShoppingBag, SquareArticle} from "@gravity-ui/icons";
import {Tag, TagGroup} from "@heroui/react";
export function CustomRenderFunction() {
return (
}
selectionMode="single"
>
News
Travel
Gaming
Shopping
);
}
```
## Related Components
- **Label**: Accessible label for form controls
- **Description**: Helper text for form fields
- **ErrorMessage**: Displays validation error messages for components with validation support
## Styling
### Passing Tailwind CSS classes
```tsx
import { TagGroup, Tag, Label } from '@heroui/react';
function CustomTagGroup() {
return (
Custom Styled
);
}
```
### Customizing the component classes
To customize the TagGroup component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.tag-group {
@apply flex flex-col gap-2;
}
.tag-group__list {
@apply flex flex-wrap gap-2;
}
.tag {
@apply rounded-full px-3 py-1;
}
.tag__remove-button {
@apply ml-1;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The TagGroup component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/tag-group.css) and [tag.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/tag.css)):
#### Base Classes
- `.tag-group` - Base tag group container
- `.tag-group__list` - Container for the list of tags
- `.tag` - Base tag styles
- `.tag__remove-button` - Remove button trigger
#### Slot Classes
- `.tag-group [slot="description"]` - Description slot styles
- `.tag-group [slot="errorMessage"]` - ErrorMessage slot styles
#### Size Classes
- `.tag--sm` - Small size tag
- `.tag--md` - Medium size tag (default)
- `.tag--lg` - Large size tag
#### Variant Classes
- `.tag--default` - Default variant
- `.tag--surface` - Surface variant with surface background
#### State Classes
- `.tag[data-selected="true"]` - Selected tag state
- `.tag[data-disabled="true"]` - Disabled tag state
- `.tag[data-hovered="true"]` - Hovered tag state
- `.tag[data-pressed="true"]` - Pressed tag state
- `.tag[data-focus-visible="true"]` - Focused tag state (keyboard focus)
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Hover**: `:hover` or `[data-hovered="true"]` on tag
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on tag
- **Pressed**: `:active` or `[data-pressed="true"]` on tag
- **Selected**: `[data-selected="true"]` or `[aria-selected="true"]` on tag
- **Disabled**: `:disabled` or `[data-disabled="true"]` on tag
## API Reference
### TagGroup Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `selectionMode` | `"none" \| "single" \| "multiple"` | `"none"` | The type of selection that is allowed |
| `selectedKeys` | `Selection` | - | The currently selected keys (controlled) |
| `defaultSelectedKeys` | `Selection` | - | The initial selected keys (uncontrolled) |
| `onSelectionChange` | `(keys: Selection) => void` | - | Handler called when the selection changes |
| `disabledKeys` | `Iterable` | - | Keys of disabled tags |
| `isDisabled` | `boolean` | - | Whether the tag group is disabled |
| `onRemove` | `(keys: Set) => void` | - | Handler called when tags are removed |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the tags in the group |
| `variant` | `"default" \| "surface"` | `"default"` | Visual variant of the tags |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | TagGroup content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function.|
### TagGroup.List Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `items` | `Iterable` | - | The items to display in the tag list |
| `renderEmptyState` | `() => ReactNode` | - | Function to render when the list is empty |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | TagList content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function.|
### Tag Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `id` | `Key` | - | The unique identifier for the tag |
| `textValue` | `string` | - | A string representation of the tag's content, used for accessibility |
| `isDisabled` | `boolean` | - | Whether the tag is disabled |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Tag content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function.|
**Note**: `size`, `variant` are inherited from the parent `TagGroup` component and cannot be set directly on individual `Tag` components.
### Tag.RemoveButton Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Custom remove button content (defaults to close icon) |
**Note**: The `Tag.RemoveButton` component supports customization similar to `SearchField.ClearButton`. When `onRemove` is provided to `TagGroup`:
- **Auto-rendering**: If no custom `Tag.RemoveButton` is included in the `Tag` children, a default remove button is automatically rendered.
- **Custom button**: If a custom `Tag.RemoveButton` is provided as a child of `Tag`, it will be used instead of the auto-rendered button.
- **Custom icon**: You can pass custom content (like icons) to `Tag.RemoveButton` children to customize the appearance.
**Example - Auto-rendered (default)**:
```tsx
News
{/* Remove button is automatically rendered */}
```
**Example - Custom RemoveButton with icon**:
```tsx
News
```
**Example - Custom RemoveButton in render props**:
```tsx
{(renderProps) => (
<>
News
{!!renderProps.allowsRemoving && (
)}
>
)}
```
### RenderProps
When using render functions with TagGroup.List, these values are provided:
| Prop | Type | Description |
|------|------|-------------|
| `isSelected` | `boolean` | Whether the tag is selected |
| `isDisabled` | `boolean` | Whether the tag is disabled |
| `isHovered` | `boolean` | Whether the tag is hovered |
| `isPressed` | `boolean` | Whether the tag is pressed |
| `isFocused` | `boolean` | Whether the tag is focused |
| `isFocusVisible` | `boolean` | Whether the tag has keyboard focus |