0.1.0

Tag Group

Tag groups display selected values as removable chips, commonly used in multi-select fields and filter bars.

Try it

reacttypescript

Usage

The live value property is always a string[] ([] when nothing is selected). The HTML attribute is those tokens as a comma-separated string. JSX may pass a string or an array; a string is parsed as CSV. rui-change emits { value: string[] }. Pass tags for the simple API, or compose RuiTagList and RuiTag. RuiTag already includes the remove control.

Not form-associated. Wrap in RuiField and read the value from RuiForm onSubmit. It does not appear in new FormData(form).

import { RuiTagGroup, RuiTagList, RuiTag } from '@ecopages/radiant-ui/tag-group';
 
<RuiTagGroup value={['react', 'typescript']} selectionMode="multiple" label="Skills">
  <RuiTagList>
    <RuiTag value="react" label="React">React</RuiTag>
    <RuiTag value="typescript" label="TypeScript">TypeScript</RuiTag>
  </RuiTagList>
</RuiTagGroup>

Custom markup

<rui-tag-group> coordinates any light-DOM tree that matches its query contract. The Rui* helpers stamp these targets; they are not required.

import '@ecopages/radiant-ui/tag-group';
 
<rui-tag-group value="react" label="Skills">
  <div data-tag-list class="rui-tag-group__list">
    <span data-tag data-value="react" data-label="React" class="rui-tag">
      React
      <button type="button" data-tag-remove class="rui-tag__remove"></button>
    </span>
  </div>
</rui-tag-group>

BEM classes are presentation-only. Omit [data-tag-remove] for a non-removable tag. Add [data-ref="root"] around the list only if you call setItems().

Embedded in selects

Set embedded when tags render inside a select or combobox trigger rather than standalone. Selection is disabled because the parent owns the value; removal still emits rui-remove.

Theming

Tag Group surfaces map to semantic surface roles, never Tailwind palette steps:

PartCSS roles
Tag (rui-tag)surface, border, on-background, rounded-pill
Selected tag (rui-tag[aria-selected='true'])primary, on-primary
Remove control (rui-tag__remove)currentColor; hover on-background
Disabled tag--opacity-muted

Override roles at the theme layer, not in component CSS.

API

RuiTagGroup is a custom element (<rui-tag-group>) wrapping a focusable list of tags. Compose RuiTagList and RuiTag, pass tags to the helper, or stamp the light-DOM contract directly. It is not form-associated.

Attributes

AttributeTypeDefaultDescription
valuestringomittedComma-separated selected tokens. Empty selection removes the attribute. The JS property is string[].
labelstring''Accessible name for the tag list.
disabledbooleanfalseDisable selection and removal.
selection-modesingle · multiplemultipleAllow one or many selected tags.
embeddedbooleanfalseDisable selection when a parent component owns the selected values.

Light-DOM contract

TargetRequiredHost writesAuthor owns
[data-tag-list]yesid, role="list", aria-label, aria-disabledthe list node
[data-tag]yesid if missing, role="listitem", aria-selected, roving tabIndexdata-value, data-label, hidden, aria-disabled
[data-value]per tag—selection identity; fallback trimmed text
[data-label]per tag—remove accessible name; fallback trimmed text
[data-tag-remove]notype="button", tabIndex="-1", aria-labelpresence
[data-ref="root"]for setItems()—wrapper around the list

Do not set role, aria-selected, or tabIndex on tags. Nested hosts: none.

Events

EventDetailDescription
rui-change{ value: string[] }Emitted when selection changes.
rui-remove{ value: string }Emitted when a tag is removed; value is the removed tag's value. Also followed by rui-change.

Methods

MethodDescription
resync()Re-read authored [data-tag] children after in-place DOM mutations.
setItems(items)Replace authored tags with a host-owned list. Requires [data-ref="root"].

View helpers

ComponentTarget stampedNotes
RuiTagGroup<rui-tag-group> + [data-ref="root"]Accepts tags (RuiTagData[]) or children.
RuiTagList[data-tag-list]Flex-wrap container.
RuiTag[data-tag], data-value, data-labelAlways includes RuiTagRemove.
RuiTagRemove[data-tag-remove]Host fills the accessible name on connect.

CSS classes

Public BEM classes on the composed light-DOM surface (documented via @cssclass):

ClassDescription
.rui-tag-groupRoot wrapper around the tag list.
.rui-tag-group__listTag row (flex-wrap container).
.rui-tagTag chip; selected state via [aria-selected='true'].
.rui-tag__removeTag remove control.

Theme roles

PartCSS variables consumed
Tag--surface, --border, --on-background, --radius-pill
Selected tag--primary, --on-primary
Remove hover--on-background
Disabled--opacity-muted
Focus ring--focus-ring

Accessibility

  • Each tag exposes its label text to screen readers.
  • Remove buttons have accessible names indicating which tag will be removed (Remove {label}).
  • The group has an accessible name via label when not described by surrounding text.