{
  "name": "TagGroup",
  "source": "src/components/TagGroup.tsx",
  "propsType": "TagGroupProps",
  "description": "TagGroup — labels a person applied and can take away: active filters, the\nlabels on a record, the recipients of a message.\n\nNOT A BADGE\n\nA Badge reports a state the system decided — Failing, Paid. A Tag is a\nchoice someone made, which is why it is removable and why it is neutral:\ncolouring tags by intent would make \"Status: Failing\" as a filter look like\nthe agent is failing.\n\nWHAT REACT ARIA GIVES IT\n\n`useTagGroup` makes the group one tab stop with arrow keys between tags, a\nremove button per tag named \"Remove <tag>\", and Delete / Backspace to remove\nthe focused one. When a tag goes, focus moves to its neighbour. The one case\nReact Aria leaves open is the last tag: focus would fall to <body>, so the\ngroup takes it instead and reads out `emptyLabel`.\n\nNo selection: a chip that toggles on and off is a SegmentedControl or a\nCheckbox, which already say \"selected\" the way a screen reader expects.",
  "import": "import { TagGroup } from 'ionbase-ui';",
  "status": "stable",
  "since": "0.79.0",
  "summary": "Labels a person applied and can take away: active filters, the labels on a record, recipients. Neutral and removable, unlike Badge.",
  "useWhen": [
    "showing which filters are applied, each removable on its own",
    "the labels or categories someone attached to a record",
    "a set of chosen values — recipients, assignees — shown after they are picked"
  ],
  "useInstead": [
    {
      "when": "it is a status the system reports — Failing, Paid, Draft",
      "use": "Badge"
    },
    {
      "when": "the chips toggle on and off rather than being removed",
      "use": "SegmentedControl"
    },
    {
      "when": "several options can be switched on at once from a fixed list",
      "use": "Checkbox"
    }
  ],
  "composition": {
    "order": [
      "TagGroup",
      "Tag"
    ],
    "note": "Tag is react-stately's collection Item: `key` identifies it and is what `onRemove` hands back, children are its label. Pass `items` and a render function for a list that changes. The children are one of three forms: tags written out, `items` with a render function, or a `.map()` that is the only child. Filters that are on or off are a list you build as data (`items`), not elements pushed into an array.",
    "example": "<TagGroup label=\"Active filters\" onRemove={(keys) => drop(keys)}><Tag key=\"status\">Status: Failing</Tag><Tag key=\"team\">Team: Finance</Tag></TagGroup>"
  },
  "variants": {
    "size": {
      "sm": {
        "use": "the default — filter rows, table toolbars, dense record headers"
      },
      "md": {
        "use": "a group that is the main content of its area, or sits beside md controls"
      }
    }
  },
  "a11y": {
    "guarantees": [
      "the group is one tab stop; arrow keys move between tags",
      "each remove button is named \"Remove\" plus the tag's label, so a screen reader hears which one",
      "Delete or Backspace on a focused tag removes it, and focus moves to its neighbour",
      "removing the last tag moves focus to the group, which reads `emptyLabel`, instead of dropping it to the page"
    ],
    "requires": [
      "a `label` or `aria-label` — it names the group, so \"Remove Finance\" is heard as a filter being removed",
      "`textValue` on a Tag whose children are not plain text",
      "`onRemove` to drop the keys from your own list; the group removes nothing itself"
    ],
    "notes": [
      "No selection. A chip that toggles is a SegmentedControl or a Checkbox, which already announce \"selected\" the way screen readers expect."
    ]
  },
  "antiPatterns": [
    {
      "dont": "using a TagGroup for statuses",
      "why": "tags are neutral and removable; a status is neither — use Badge"
    },
    {
      "dont": "`onRemove` that does not remove the tag",
      "why": "the button says \"Remove\", focus moves on, and the tag is still there — the one thing the control promised did not happen"
    },
    {
      "dont": "a filter row with no way to clear everything at once",
      "why": "removing six filters one by one is six targets; pair the group with a \"Clear filters\" Button"
    },
    {
      "dont": "collecting tags into `const tags: React.ReactElement[] = []` with `push`, then `<TagGroup>{tags}</TagGroup>`",
      "why": "the children are typed `CollectionChildren`: one collection element, an array of them, or a render function. `ReactElement` defaults its props to `unknown`, which is not an item's props, so the array fails to compile. Contracts-only generations of the demo's Agents screen did this on 2 of 3 tries. Build the active filters as data and pass them as `items`, with `(f) => <Tag key={f.id}>…</Tag>` as the children"
    }
  ],
  "stylesheet": "src/styles/tag-group.css",
  "tokens": [
    "--border-disabled",
    "--border-subtle",
    "--border-width-default",
    "--border-width-thick",
    "--font-family-sans",
    "--font-weight-medium",
    "--icon-default",
    "--icon-disabled",
    "--icon-secondary",
    "--icon-size-2xs",
    "--ion-duration-base",
    "--ion-ease-out",
    "--radius-md",
    "--radius-sm",
    "--radius-xs",
    "--ring-focus",
    "--spacing-12",
    "--spacing-16",
    "--spacing-20",
    "--spacing-24",
    "--spacing-32",
    "--spacing-4",
    "--spacing-6",
    "--spacing-8",
    "--surface-disabled",
    "--surface-hover",
    "--surface-subtle",
    "--text-default",
    "--text-disabled",
    "--text-secondary",
    "--text-tertiary",
    "--type-body",
    "--type-body-line-height",
    "--type-body-sm",
    "--type-body-sm-line-height"
  ],
  "props": {
    "onRemove": {
      "type": "((keys: Set<Key>) => void) | undefined",
      "required": false,
      "origin": "own",
      "description": "Called with the keys of the tags to remove — from a tag's × button, or\nDelete / Backspace on a focused tag. Pass it and every tag shows a remove\nbutton; leave it out and the tags are read-only labels. The group does\nnot remove anything itself: drop the keys from your own list."
    },
    "size": {
      "type": "TagGroupSize | undefined",
      "required": false,
      "origin": "own",
      "description": "Figma's `Size`. Set once here, so every tag in a group matches.",
      "values": [
        "sm",
        "md"
      ],
      "default": "sm"
    },
    "emptyLabel": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Shown in place of the tags when there are none — \"No filters applied\".\nWithout it an empty group renders nothing but its label."
    },
    "className": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    },
    "id": {
      "type": "string | undefined",
      "required": false,
      "origin": "aria",
      "description": "The element's unique identifier. See\n[MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id)."
    },
    "aria-describedby": {
      "type": "string | undefined",
      "required": false,
      "origin": "aria",
      "description": "Identifies the element (or elements) that describes the object."
    },
    "aria-details": {
      "type": "string | undefined",
      "required": false,
      "origin": "aria",
      "description": "Identifies the element (or elements) that provide a detailed, extended description for the\nobject."
    },
    "aria-label": {
      "type": "string | undefined",
      "required": false,
      "origin": "aria",
      "description": "Defines a string value that labels the current element."
    },
    "aria-labelledby": {
      "type": "string | undefined",
      "required": false,
      "origin": "aria",
      "description": "Identifies the element (or elements) that labels the current element."
    },
    "children": {
      "type": "CollectionChildren<T>",
      "required": true,
      "origin": "aria",
      "description": "The contents of the collection."
    },
    "description": {
      "type": "ReactNode",
      "required": false,
      "origin": "aria",
      "description": "A description for the field. Provides a hint such as specific requirements for what to choose."
    },
    "label": {
      "type": "ReactNode",
      "required": false,
      "origin": "aria",
      "description": "The content to display as the label."
    },
    "items": {
      "type": "Iterable<T> | undefined",
      "required": false,
      "origin": "aria",
      "description": "Item objects in the collection."
    },
    "disabledKeys": {
      "type": "Iterable<Key> | undefined",
      "required": false,
      "origin": "aria",
      "description": "The item keys that are disabled. These items cannot be selected, focused, or otherwise\ninteracted with."
    }
  },
  "propCounts": {
    "own": 4,
    "aria": 10,
    "dom": 0,
    "other": 0
  }
}
