Sakuga Back to Sakuga
Theme
Sound
Jump to a component

Core · Content

TagList

TagList keeps words as tags: a character's visual vibe, the garments read from a photo.

@anicanon/sakuga/uiv1.0Used onWeb · iOS · Android

Live, from @anicanon/sakuga 2.0.0

Sakuga for iOS and Android is coming

iOS

Coming soon

TagList for iOS is in the roughs. The tokens it will read are the ones on this page, the same on every platform.

Android

Coming soon

TagList for Android is in the roughs. The tokens it will read are the ones on this page, the same on every platform.

Use it for
Words kept as tags, each one removable and restorable: a character's visual vibe, the garments read from a photo.
Not for
  • Picking words from a set, such as traitsChip
  • A label over artworkBadge
  • Who or what a panel holds, with its pictureMentionChip
  • A free sentence someone typesTextField

Guidelines

  • A tag added after the list first draws rises in; a removed one keeps its place while it fades out, and focus moves to the tag that takes its place.
  • Each tag carries its own button: removeLabel names what it does ("Leave out Silver chain"). A tag that is off reads struck through and its button puts it back (restoreLabel).
  • With a placeholder the tags sit in a field you type more into.
  • Short words, lower case unless a name.
  • onRemove(label, index) and onRestore(label, index) make the tag buttons work; onAdd(words) takes what is typed in the box when Enter is pressed.
TagListExample.jsxReact
import { TagList } from '@anicanon/sakuga/ui';

export default function TagListExample() {
  return (
    <>
      <TagList
        label="Visual vibe"
        items={['fire', 'red and black', 'street hero']}
        placeholder="Add a vibe…"
      />
      <TagList
        removeLabel="Leave out"
        restoreLabel="Add back"
        items={[
          { label: 'Grey plaid overshirt' },
          { label: 'Black crew-neck tee' },
          { label: 'Canvas tote bag', off: true },
        ]}
      />
    </>
  );
}

PropsTagListProps

itemsrequired
(string | { label: string; off?: boolean; })[]
placeholder
string
label
string
inputLabel
string
removeLabel
string
restoreLabel
string
className
string
onRemove
(label: string, index: number) => void
onRestore
(label: string, index: number) => void
onAdd
(words: string) => void
Enter in the box hands its words over and empties it.
TagListExample.swiftiOS · coming soon
TagListExample.ktAndroid · coming soon

Each token reads a role, and the role lands on a value in each theme. Change the role and every component that reads it follows.

Space and shape

tag-icon-size
icon-size-xs
14px
tags-gap
gap-sm
6px
tags-input-min-height
size-target
44px
tags-input-padding-y
inset-sm
8px
tags-input-padding-x
inset-md
12px
tags-input-radius
radius-sm
8px
tags-input-inset-ring-width
line-hairline
1px
tag-gap
gap-2xs
2px
tag-height
its own value
28px
tag-padding-right
inset-xs
4px
tag-padding-left
inset-md
12px
tag-radius
radius-full
9999px
tag-x-active-scale
scale-press-sm
.94
tag-x-size
icon-size-md
20px
tag-x-radius
radius-full
9999px
tag-x-focus-outline-offset
focus-ring-offset
3px
tags-entry-min-width
its own value
120px
tags-entry-height
its own value
24px
tags-entry-padding-x
inset-xs
4px
tags-input-focus-inset-ring-width
line-strong
2px
tags-forced-edge-width
line-hairline
1px
tags-forced-focus-width
line-strong
2px
tag-x-target-size
space-6
24px

Type

tag-font
text-caption-strong
600 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
tags-entry-font
text-caption
500 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif

Motion

tag-x-press-duration
motion-fast
160ms
tag-x-press-easing
ease-standard
cubic-bezier(0.2, 0, 0, 1)
tag-x-active-duration
motion-instant
100ms
tag-x-duration
motion-fast
160ms
tag-arrive-animation
its own value
sk-emerge 240ms cubic-bezier(0, 0, 0, 1)
tag-leave-animation
its own value
sk-recede 160ms cubic-bezier(0.3, 0, 1, 1)

Checked automatically with axe-core 4.11.4 against WCAG 2.2 A and AA, on the live preview above, in light and dark, on 26 October 2026.

Result
No issues found, in light or in dark.
By design
A group named by label: Tab reaches each tag's button ("Remove Gentle", or "Add back Gentle" once it is out; removeLabel and restoreLabel change the verb), which runs onRemove or onRestore, and focus moves to the tag that takes its place; the change is said ("Gentle removed", "Gentle added back"). With placeholder, a text input named by inputLabel or the placeholder shows a focus ring and hands its words to onAdd on Enter.
Not tested
The automated check doesn't test keyboard use, focus order or what a screen reader says. The lines above are the design system's own account of them.