Skip to content

PillContainer

<caos-pill-container>

a row of tags that keeps its own overflow and keyboard model

May be placed on a record page, an app’s home page and a page inside an app.

Name Attribute Description Type Default Required
limit limit, also a property How many pills show before the rest go behind a “+N more” control, which shows them and becomes “Show fewer”. Unset, every pill shows and the row wraps. number none declared Optional
label label, markup only What the pills are, read as the name of the list — “Applied filters”, “Team”, “Tags”. text none declared Optional
Name When it fires What it carries
caos-tag-remove Delete or Backspace is pressed on a removable pill. It is raised BY THE PILL, exactly as its own dismiss control raises it, so one listener at the container hears both; the pill stays until the host removes it. nothing — the pill is the event target.
Name What goes in it
the default slot The pills: caos-tag elements, drawn in the order they are placed. Each is made a list item and given its place in the row’s single tab stop.
Design token What it controls
--caos-space-1 The gap between pills, across and down.
--caos-space-2 The side padding of the “+N more” control.
--caos-color-accent The lettering of the “+N more” control.
--caos-font The typeface of the “+N more” control.
--caos-radius-sm The corners of the “+N more” control’s focus ring.
--caos-focus-ring The ring on the “+N more” control reached by keyboard.

Nothing else drives this piece by calling it.

Name Type What it tells you
expanded boolean Whether the pills past the limit are showing.
Part Which piece of it When it is there
::part(container) the row that holds the pills Always
::part(more) the “+N more” / “Show fewer” control Always

A set of values that belong together is shown as tags — the values of a multi-select, the filters applied to a list, the people on a record — and there may be enough of them that the row needs a limit, or that a keyboard user should not have to tab through every one.

  • Tag — There is one label, or two sitting in a line of text, where a single tab stop and an overflow have nothing to manage.
  • PicklistField — The values are being CHOSEN rather than shown: a multi-select edits with the picklist field’s several-values presentation, and reads with this.
  • SegmentedFilter — The chips choose what a list shows from a fixed set, rather than showing values that are there.

The row is a role="list" named by label and each pill a role="listitem", so a screen reader says how many there are before reading them. The row is one tab stop: arrow keys, Home and End move between pills, Left and Right following the reading direction, and Delete or Backspace on a removable pill asks for it to be removed, with focus staying in the row once it has gone. A tag placed here takes its own dismiss control out of the tab order, since Delete does that job, and each removable pill names Delete and Backspace in aria-keyshortcuts; the dismiss control still works by pointer. Pills behind “+N more” are out of the tab order until shown, and the control carries aria-expanded and says how many it holds. Left to the author: a label for the row, and a host listening for caos-tag-remove wherever pills are removable — Delete on a pill nobody removes leaves it where it is.

The people on a record, each tag carrying their picture in its avatar slot, read as one named list.

Cannot be shown as a page placement: is ordinary markup, not an installable component — a page places components, never bare markup.

<caos-pill-container label="Team">
<caos-tag>
<img slot="avatar" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%3E%3Ccircle%20cx%3D%2216%22%20cy%3D%2216%22%20r%3D%2216%22%20fill%3D%22%234f5bd5%22%2F%3E%3Ctext%20x%3D%2216%22%20y%3D%2221%22%20font-family%3D%22sans-serif%22%20font-size%3D%2213%22%20font-weight%3D%22600%22%20fill%3D%22white%22%20text-anchor%3D%22middle%22%3EDR%3C%2Ftext%3E%3C%2Fsvg%3E" alt=""></img>
Dana Reyes
</caos-tag>
<caos-tag>
<img slot="avatar" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%3E%3Ccircle%20cx%3D%2216%22%20cy%3D%2216%22%20r%3D%2216%22%20fill%3D%22%231f8a70%22%2F%3E%3Ctext%20x%3D%2216%22%20y%3D%2221%22%20font-family%3D%22sans-serif%22%20font-size%3D%2213%22%20font-weight%3D%22600%22%20fill%3D%22white%22%20text-anchor%3D%22middle%22%3EMO%3C%2Ftext%3E%3C%2Fsvg%3E" alt=""></img>
Malik Osei
</caos-tag>
<caos-tag>
<img slot="avatar" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%3E%3Ccircle%20cx%3D%2216%22%20cy%3D%2216%22%20r%3D%2216%22%20fill%3D%22%23b54708%22%2F%3E%3Ctext%20x%3D%2216%22%20y%3D%2221%22%20font-family%3D%22sans-serif%22%20font-size%3D%2213%22%20font-weight%3D%22600%22%20fill%3D%22white%22%20text-anchor%3D%22middle%22%3EPL%3C%2Ftext%3E%3C%2Fsvg%3E" alt=""></img>
Priya Lal
</caos-tag>
</caos-pill-container>

Nine labels held to four, the other five behind “+5 more”, with a way back to fewer once shown.

{
"id": "example",
"section": "Past a limit",
"columns": 1,
"items": [
{
"id": "pill_container_1",
"type": "component",
"key": "pill_container",
"inputs": {
"label": "Tags",
"limit": 4
},
"children": [
{
"id": "tag_2",
"type": "component",
"key": "tag",
"children": [
"Rush"
]
},
{
"id": "tag_3",
"type": "component",
"key": "tag",
"children": [
"Repeat customer"
]
},
{
"id": "tag_4",
"type": "component",
"key": "tag",
"children": [
"Site visit needed"
]
},
{
"id": "tag_5",
"type": "component",
"key": "tag",
"children": [
"Freight"
]
},
{
"id": "tag_6",
"type": "component",
"key": "tag",
"children": [
"Net 30"
]
},
{
"id": "tag_7",
"type": "component",
"key": "tag",
"children": [
"Tax exempt"
]
},
{
"id": "tag_8",
"type": "component",
"key": "tag",
"children": [
"Key account"
]
},
{
"id": "tag_9",
"type": "component",
"key": "tag",
"children": [
"Referral"
]
},
{
"id": "tag_10",
"type": "component",
"key": "tag",
"children": [
"Spanish"
]
}
]
}
]
}
<caos-pill-container label="Tags" limit="4">
<caos-tag>Rush</caos-tag>
<caos-tag>Repeat customer</caos-tag>
<caos-tag>Site visit needed</caos-tag>
<caos-tag>Freight</caos-tag>
<caos-tag>Net 30</caos-tag>
<caos-tag>Tax exempt</caos-tag>
<caos-tag>Key account</caos-tag>
<caos-tag>Referral</caos-tag>
<caos-tag>Spanish</caos-tag>
</caos-pill-container>

Applied filters a person takes off with the dismiss control or with Delete, focus staying in the row as each goes.

The page around it: The surrounding page takes a filter off when its pill reports the request — the pill and the container only report it.

{
"id": "example",
"section": "Removing from the keyboard",
"columns": 1,
"items": [
{
"id": "pill_container_1",
"type": "component",
"key": "pill_container",
"inputs": {
"label": "Applied filters"
},
"children": [
{
"id": "tag_2",
"type": "component",
"key": "tag",
"inputs": {
"removable": true
},
"children": [
"Stage: Proposal"
]
},
{
"id": "tag_3",
"type": "component",
"key": "tag",
"inputs": {
"removable": true
},
"children": [
"Owner: Me"
]
},
{
"id": "tag_4",
"type": "component",
"key": "tag",
"inputs": {
"removable": true
},
"children": [
"Region: North"
]
},
{
"id": "tag_5",
"type": "component",
"key": "tag",
"inputs": {
"removable": true
},
"children": [
"Amount over 10,000"
]
}
]
}
]
}
<caos-pill-container label="Applied filters">
<caos-tag removable>Stage: Proposal</caos-tag>
<caos-tag removable>Owner: Me</caos-tag>
<caos-tag removable>Region: North</caos-tag>
<caos-tag removable>Amount over 10,000</caos-tag>
</caos-pill-container>

Recipients where one address bounced: that tag turns red and says so in words as well as in colour.

{
"id": "example",
"section": "A value in error",
"columns": 1,
"items": [
{
"id": "pill_container_1",
"type": "component",
"key": "pill_container",
"inputs": {
"label": "Recipients"
},
"children": [
{
"id": "tag_2",
"type": "component",
"key": "tag",
"children": [
"dana@meridian.example"
]
},
{
"id": "tag_3",
"type": "component",
"key": "tag",
"inputs": {
"error": true
},
"children": [
"orders@meridan.example"
]
},
{
"id": "tag_4",
"type": "component",
"key": "tag",
"children": [
"malik@meridian.example"
]
}
]
}
]
}
<caos-pill-container label="Recipients">
<caos-tag>dana@meridian.example</caos-tag>
<caos-tag error>orders@meridan.example</caos-tag>
<caos-tag>malik@meridian.example</caos-tag>
</caos-pill-container>