# Tag Group

Tags allow users to categorize content. They can represent keywords or people, and are grouped to describe an item or a search request.

## Example

```python
from deephaven import ui


tag_group_example = ui.tag_group(
    ui.item("News", key="news"),
    ui.item("Travel", key="travel"),
    ui.item("Gaming", key="gaming"),
    ui.item("Shopping", key="shopping"),
)
```

![Tag Group Basic Example](../_assets/tag_group_basic.png)

## Content

`tag_group` accepts `item` elements as children, each with a `key` prop. Basic usage of `tag_group`, seen in the example above, shows multiple items populated with a string.

## Labeling

To provide a visual label for the tag group, use the `label` prop.

```python
from deephaven import ui


tag_group_label_example = ui.tag_group(
    ui.item("News", key="news"),
    ui.item("Travel", key="travel"),
    ui.item("Gaming", key="gaming"),
    ui.item("Shopping", key="shopping"),
    label="Categories",
)
```

### Label Position

By default, the position of the label is above the tag group, but it can be moved to the side using the `label_position` prop.

```python
from deephaven import ui


tag_group_label_example = ui.tag_group(
    ui.item("News", key="news"),
    ui.item("Travel", key="travel"),
    ui.item("Gaming", key="gaming"),
    ui.item("Shopping", key="shopping"),
    label="Categories",
    label_position="side",
)
```

### Label Alignment

By default, the label is horizontally aligned to the start of the tag group element, but it can be moved to the end by using the `label_align` prop.

```python
from deephaven import ui


tag_group_label_example = ui.tag_group(
    ui.item("News", key="news"),
    ui.item("Travel", key="travel"),
    ui.item("Gaming", key="gaming"),
    ui.item("Shopping", key="shopping"),
    label="Categories",
    label_align="end",
)
```

## Events

Removing tags can be enabled by providing the `on_remove` prop to the tag group, which will receive the set of keys to remove.

```python
from deephaven import ui


@ui.component
def tag_group_remove_example():
    items, set_items = ui.use_state(
        [
            ui.item("News", key="news"),
            ui.item("Travel", key="travel"),
            ui.item("Gaming", key="gaming"),
            ui.item("Shopping", key="shopping"),
        ]
    )

    return (
        ui.tag_group(
            *items,
            on_remove=lambda keys: set_items(
                [item for item in items if item.key not in keys]
            )
        ),
    )


my_tag_group_remove_example = tag_group_remove_example()
```

Use the prop `action_label` to display an action button with that label at the end of the tags. The custom action that will be performed is specified by the `on_action` prop.

```python
from deephaven import ui


@ui.component
def tag_group_action_example():
    items, set_items = ui.use_state(
        [
            ui.item("News", key="news"),
            ui.item("Travel", key="travel"),
            ui.item("Gaming", key="gaming"),
            ui.item("Shopping", key="shopping"),
        ]
    )

    return ui.tag_group(
        *items,
        action_label="Delete Shopping",
        on_action=lambda: set_items([item for item in items if item.key != "shopping"])
    )


my_tag_group_action_example = tag_group_action_example()
```

## Links

Tags can become links to another page or website by passing the `href` prop to the `ui.item` component. The target window to open the link in can be configured using the `target` prop.

```python
from deephaven import ui


tag_group_links_example = ui.tag_group(
    ui.item("Adobe", key="adobe", href="https://adobe.com/", target="_blank"),
    ui.item("Apple", key="apple", href="https://apple.com/", target="_blank"),
    ui.item("Google", key="google", href="https://google.com/", target="_blank"),
)
```

## Help text

A tag group can have both a `description` and an `error_message`. The error message should offer specific guidance on how to correct the input.

The `is_invalid` prop can be used to set whether the current tag group state is valid or invalid.

```python
from deephaven import ui


@ui.component
def tag_group_help_text_example():
    items, set_items = ui.use_state(
        [
            ui.item("News", key="news"),
            ui.item("Travel", key="travel"),
            ui.item("Gaming", key="gaming"),
            ui.item("Shopping", key="shopping"),
        ]
    )

    return (
        ui.tag_group(
            *items,
            on_remove=lambda keys: set_items(
                [item for item in items if item.key not in keys]
            ),
            is_invalid=len(items) > 3,
            description="Please include tags for related categories.",
            error_message="Must contain no more than 3 tags. Please remove some.",
        ),
    )


my_tag_group_help_text_example = tag_group_help_text_example()
```

## Contextual help

Using the `contextual_help` prop, a `ui.contextual_help` can be placed next to the label to provide additional information about the tag group.

```python
from deephaven import ui


tag_group_contextual_help_example = ui.tag_group(
    ui.item("News", key="news"),
    ui.item("Travel", key="travel"),
    ui.item("Gaming", key="gaming"),
    ui.item("Shopping", key="shopping"),
    label="Categories",
    contextual_help=ui.contextual_help(
        heading="Hint", content="Pick your favorite category"
    ),
)
```

## Limit rows

To limit the number of rows initially shown, use the `max_rows` prop. A button to allow the user to expand to show all tags will be displayed if the tags would overflow the number of rows.

```python
from deephaven import ui

tag_group_max_rows_example = ui.flex(
    ui.view(
        ui.tag_group(
            ui.item("News", key="news"),
            ui.item("Travel", key="travel"),
            ui.item("Gaming", key="gaming"),
            ui.item("Shopping", key="shopping"),
        ),
        border_width="thin",
        border_color="accent-400",
        width="size-2000",
    ),
    ui.view(
        ui.tag_group(
            ui.item("News", key="news"),
            ui.item("Travel", key="travel"),
            ui.item("Gaming", key="gaming"),
            ui.item("Shopping", key="shopping"),
            max_rows=1,
        ),
        border_width="thin",
        border_color="accent-400",
        width="size-2000",
    ),
    direction="column",
)
```

## Empty state

By default the empty state displays the text “None”.

```python
from deephaven import ui


my_tag_group_empty_default = ui.tag_group()
```

Use the `render_empty_state` prop to specify the element to be displayed when the tag group will display when no tags are provided.

```python
from deephaven import ui


my_tag_group_empty_custom = ui.tag_group(
    render_empty_state=ui.flex(
        ui.icon("dh_warning_circle_filled", size="S"),
        ui.text("No tags here"),
        align_items="center",
    ),
)
```

## API reference

A tag group displays a list of keywords to describe an item.

**Returns:** `Element` The rendered tag group element.

<ParamTable param={{"module_name": "deephaven.ui.", "name": "tag_group", "parameters": [{"name": "*children", "type": "str | int | float | bool | BaseElement", "description": "The tags to render within the tag_group."}, {"name": "action_label", "type": "str | None", "description": "The label for the action button. If provided, an action button will be displayed.", "default": "None"}, {"name": "render_empty_state", "type": "Element | None", "description": "The element that will be rendered when there is no content to display.", "default": "None"}, {"name": "max_rows", "type": "int | None", "description": "The maximum amount of rows to show. If provided, will render a button that allows the user to expand the tag group.", "default": "None"}, {"name": "error_message", "type": "None | bool | float | int | str | Element | List[NodeType] | Tuple[NodeType, ...]", "description": "An error message for the field.", "default": "None"}, {"name": "label", "type": "None | bool | float | int | str | Element | List[NodeType] | Tuple[NodeType, ...]", "description": "The label for the tag group.", "default": "None"}, {"name": "description", "type": "None | bool | float | int | str | Element | List[NodeType] | Tuple[NodeType, ...]", "description": "A description for the tag group.", "default": "None"}, {"name": "label_position", "type": "Literal['top', 'side']", "description": "The position of the label relative to the input.", "default": "'top'"}, {"name": "label_align", "type": "Literal['start', 'end'] | None", "description": "The alignment of the label relative to the input.", "default": "'start'"}, {"name": "contextual_help", "type": "None | bool | float | int | str | Element | List[NodeType] | Tuple[NodeType, ...]", "description": "A ContextualHelp element to place next to the label.", "default": "None"}, {"name": "is_invalid", "type": "bool | None", "description": "Whether the tag group is in an invalid state.", "default": "None"}, {"name": "on_action", "type": "Callable[[None], None] | None", "description": "The handler that is called when action button is clicked.", "default": "None"}, {"name": "on_remove", "type": "Callable[[List[str | int | float | bool]], None] | None", "description": "The handler that is called when remove button is clicked. If provided, a remove button will be displayed on each tag.", "default": "None"}, {"name": "flex", "type": "str | float | bool | None", "description": "When used in a flex layout, specifies how the element will grow or shrink to fit the space available.", "default": "None"}, {"name": "flex_grow", "type": "float | None", "description": "When used in a flex layout, specifies how much the element will grow to fit the space available.", "default": "None"}, {"name": "flex_shrink", "type": "float | None", "description": "When used in a flex layout, specifies how much the element will shrink to fit the space available.", "default": "None"}, {"name": "flex_basis", "type": "str | float | None", "description": "When used in a flex layout, specifies the initial size of the element.", "default": "None"}, {"name": "align_self", "type": "Literal['auto', 'normal', 'start', 'end', 'center', 'flex-start', 'flex-end', 'self-start', 'self-end', 'stretch'] | None", "description": "Overrides the align_items property of a flex or grid container.", "default": "None"}, {"name": "justify_self", "type": "Literal['auto', 'normal', 'start', 'end', 'flex-start', 'flex-end', 'self-start', 'self-end', 'center', 'left', 'right', 'stretch'] | None", "description": "Specifies how the element is justified inside a flex or grid container.", "default": "None"}, {"name": "order", "type": "int | None", "description": "The layout order for the element within a flex or grid container.", "default": "None"}, {"name": "grid_area", "type": "str | None", "description": "The name of the grid area to place the element in.", "default": "None"}, {"name": "grid_row", "type": "str | None", "description": "The name of the grid row to place the element in.", "default": "None"}, {"name": "grid_row_start", "type": "str | None", "description": "The name of the grid row to start the element in.", "default": "None"}, {"name": "grid_row_end", "type": "str | None", "description": "The name of the grid row to end the element in.", "default": "None"}, {"name": "grid_column", "type": "str | None", "description": "The name of the grid column to place the element in.", "default": "None"}, {"name": "grid_column_start", "type": "str | None", "description": "The name of the grid column to start the element in.", "default": "None"}, {"name": "grid_column_end", "type": "str | None", "description": "The name of the grid column to end the element in.", "default": "None"}, {"name": "margin", "type": "str | float | None", "description": "The margin to apply around the element.", "default": "None"}, {"name": "margin_top", "type": "str | float | None", "description": "The margin to apply above the element.", "default": "None"}, {"name": "margin_bottom", "type": "str | float | None", "description": "The margin to apply below the element.", "default": "None"}, {"name": "margin_start", "type": "str | float | None", "description": "The margin to apply before the element.", "default": "None"}, {"name": "margin_end", "type": "str | float | None", "description": "The margin to apply after the element.", "default": "None"}, {"name": "margin_x", "type": "str | float | None", "description": "The margin to apply to the left and right of the element.", "default": "None"}, {"name": "margin_y", "type": "str | float | None", "description": "The margin to apply to the top and bottom of the element.", "default": "None"}, {"name": "width", "type": "str | float | None", "description": "The width of the element.", "default": "None"}, {"name": "height", "type": "str | float | None", "description": "The height of the element.", "default": "None"}, {"name": "min_width", "type": "str | float | None", "description": "The minimum width of the element.", "default": "None"}, {"name": "min_height", "type": "str | float | None", "description": "The minimum height of the element.", "default": "None"}, {"name": "max_width", "type": "str | float | None", "description": "The maximum width of the element.", "default": "None"}, {"name": "max_height", "type": "str | float | None", "description": "The maximum height of the element.", "default": "None"}, {"name": "position", "type": "Literal['static', 'relative', 'absolute', 'fixed', 'sticky'] | None", "description": "Specifies how the element is positioned.", "default": "None"}, {"name": "top", "type": "str | float | None", "description": "The distance from the top of the containing element.", "default": "None"}, {"name": "bottom", "type": "str | float | None", "description": "The distance from the bottom of the containing element.", "default": "None"}, {"name": "start", "type": "str | float | None", "description": "The distance from the start of the containing element.", "default": "None"}, {"name": "end", "type": "str | float | None", "description": "The distance from the end of the containing element.", "default": "None"}, {"name": "left", "type": "str | float | None", "description": "The distance from the left of the containing element.", "default": "None"}, {"name": "right", "type": "str | float | None", "description": "The distance from the right of the containing element.", "default": "None"}, {"name": "z_index", "type": "int | None", "description": "The stack order of the element.", "default": "None"}, {"name": "is_hidden", "type": "bool | None", "description": "Whether the element is hidden.", "default": "None"}, {"name": "id", "type": "str | None", "description": "A unique identifier for the element.", "default": "None"}, {"name": "aria_label", "type": "str | None", "description": "The label for the element.", "default": "None"}, {"name": "aria_labelledby", "type": "str | None", "description": "The id of the element that labels the element.", "default": "None"}, {"name": "aria_describedby", "type": "str | None", "description": "The id of the element that describes the element.", "default": "None"}, {"name": "aria_details", "type": "str | None", "description": "The details for the element.", "default": "None"}, {"name": "UNSAFE_class_name", "type": "str | None", "description": "A CSS class to apply to the element.", "default": "None"}, {"name": "UNSAFE_style", "type": "Dict[str, Any] | None", "description": "A CSS style to apply to the element.", "default": "None"}, {"name": "key", "type": "str | None", "description": "A unique identifier used by React to render elements in a list.", "default": "None"}]}} />
