Components
TagGroup
Focusable tag list with selection, sizes, variants, optional icons and removal — aligned with @heroui/react and tag-group.css.
Usage
Default: single selection with leading icons (HeroUI Default story).
RiseTagGroup<String>(
selectionMode: RiseTagGroupSelectionMode.single,
values: ['news', 'travel', 'gaming', 'shopping'],
leadingBuilder: (v) => Icon(/* article · planet · rocket · bag */, size: 16),
labelBuilder: (v) => capitalize(v),
selected: selected,
onChanged: (next) => setState(() => selected = next),
)Sizes
sm · md · lg with Label captions.
RiseTagGroup<String>(
selectionMode: RiseTagGroupSelectionMode.single,
size: RiseTagSize.sm,
values: ['news', 'travel', 'gaming'],
labelBuilder: (v) => capitalize(v),
selected: selected,
onChanged: (next) => setState(() => selected = next),
)Variants
default (outlined) vs surface (muted fill).
RiseTagGroup<String>(
selectionMode: RiseTagGroupSelectionMode.single,
variant: RiseTagVariant.surface,
values: ['news', 'travel', 'gaming'],
labelBuilder: (v) => capitalize(v),
selected: selected,
onChanged: (next) => setState(() => selected = next),
)Disabled
Per-tag disabledKeys and helper copy below the list.
RiseTagGroup<String>(
disabledKeys: {'news', 'gaming'},
values: ['news', 'travel', 'gaming'],
labelBuilder: (v) => capitalize(v),
selected: selected,
description: 'Some tags are disabled',
onChanged: (next) => setState(() => selected = next),
)
RiseTagGroup<String>(
disabledKeys: {'travel'},
values: ['news', 'travel', 'gaming'],
labelBuilder: (v) => capitalize(v),
selected: selectedB,
description: 'Tags disabled via disabledKeys prop',
onChanged: (next) => setState(() => selectedB = next),
)Selection modes
Single vs multiple with helper text.
RiseTagGroup<String>(
selectionMode: RiseTagGroupSelectionMode.single,
values: ['news', 'travel', 'gaming', 'shopping'],
labelBuilder: (v) => capitalize(v),
selected: selected,
onChanged: (next) => setState(() => selected = next),
)Controlled
External selection state with summary line.
RiseTagGroup<String>(
selectionMode: RiseTagGroupSelectionMode.multiple,
label: 'Categories (controlled)',
values: ['news', 'travel', 'gaming', 'shopping'],
labelBuilder: (v) => capitalize(v),
selected: selected,
onChanged: (next) => setState(() => selected = next),
)With prefix
Icons and avatars (HeroUI WithPrefix).
RiseTagGroup<String>(
selectionMode: RiseTagGroupSelectionMode.single,
leadingBuilder: (v) => Icon(iconFor(v), size: 16),
values: ['news', 'travel', 'gaming', 'shopping'],
labelBuilder: (v) => capitalize(v),
selected: selected,
description: 'Tags with icons',
onChanged: (next) => setState(() => selected = next),
)With remove button
Removable lists and empty state.
RiseTagGroup<String>(
values: values,
labelBuilder: (v) => capitalize(v),
selected: selected,
onChanged: (next) => setState(() => selected = next),
onRemove: (v) => setState(() => values.remove(v)),
)With error message
Label, dynamic description after tags, and validation line.
RiseTagGroup<String>(
label: 'Amenities',
description: invalid ? 'Select at least one category' : 'Selected: …',
errorMessage: invalid ? 'Please select at least one category' : null,
values: ['laundry', 'fitness', 'parking'],
labelBuilder: (v) => capitalize(v),
selected: selected,
onChanged: (next) => setState(() => selected = next),
)With list data
Avatars, removal, and selected summary (HeroUI WithListData).
RiseTagGroup<String>(
label: 'Team Members',
selectionMode: RiseTagGroupSelectionMode.multiple,
values: ids,
leadingBuilder: (id) => RiseAvatar(
size: RiseAvatarSize.sm,
image: NetworkImage(avatarUrlFor(id)),
name: nameFor(id),
),
labelBuilder: (id) => nameFor(id),
selected: selected,
description: 'Select team members for your project',
onChanged: (next) => setState(() => selected = next),
onRemove: (id) => setState(() => removeUser(id)),
)