CSS component catalog

This page exercises the maintained selectors, semantic HTML defaults, interactive states, and motion preferences.

API quick reference

The package supplies CSS only. Applications supply state, events, validation, focus, live announcements, and persistence. Full markup, state, and customization reference.

Shell and navigation
.app-shell has a direct main and optional header/footer. .site-header, .site-header-brand, .site-header-links arrange native links and buttons; use aria-current="page" for the current destination. .skip-link targets main.
Buttons and X actions
data-barba-variant: primary, secondary, tertiary, text, and icon. data-barba-intent="danger" supplies destructive appearance. Icon actions also use data-barba-shape="icon"; data-barba-size="compact" reduces the face, not the target. Native type, name, and disabled state remain required.
Fields
.inline-field has a direct visible label. .input-row wraps a field/group and action. .input-action requires a direct-child text/search input and icon button; nested component inputs and textareas need application layout. Hide clear when empty; restore focus before hiding it.
Chips
.chip-list wraps. Informational .chip stays noninteractive. A selectable button needs aria-pressed and a .chip-face child. .chip-removable contains a label span and separate compact X button; applications restore focus after removal.
Disclosures
details.disclosure has a direct summary with .disclosure-label, .disclosure-title, optional .disclosure-description, then .disclosure-content. Add .disclosure--filled for a filled header, shared inward/downward chevron, and an accent body border. Native open owns expansion; both variants share markup.
Dialogs
A named native dialog contains a direct .dialog-content-container with .dialog-header, .dialog-body, .dialog-footer. Add .dialog-header-actions for a close row. Optional data-barba-dialog-*: spacing=compact, height=content, room=extra, dividers=full. Applications own cancellation and initial/restored focus.
Visibility and customization
.visually-hidden retains supplemental text for assistive technology. Ordinary hidden suppresses rendering and tab stops; remove the attribute to reveal (the string “false” still hides). hidden="until-found" remains browser-managed. Customize public --barba- tokens; private --_barba- and compiler properties are not API. Decorative .text-gradient and .scaleup-on-hover are optional. Recheck contrast, focus, and target sizes after overrides.

Typography and links

First-level heading

Second-level heading

Body text with inline code, a regular link, and a disabled link.

Data tables

Semantic tables receive only a readable foundation. The wide example's scrolling belongs to this specimen, not the library.

Compact table · light

Sample issue totals
StateCountOwner
Open8Joe
Closed12Joe

Wide table · dark

Sample release checklist
ReleaseStatusCSS buildSpecimen buildManual reviewOwner
Sample AReadyCompleteCompletePendingJoe
Sample BDraftCompletePendingPendingJoe

Semantic color contract

Every named text role below is guaranteed against both the page and surface backgrounds. Borders and focus rings have a separate non-text contrast guarantee.

Forced light scheme

Page background
  • Text
  • Muted text
  • Danger
Border sample
Focus-ring sample
Surface background
  • Text
  • Muted text
  • Danger
Border sample
Focus-ring sample

Primitive swatches; no foreground guarantee

Accent
Inverse surface

Forced dark scheme

Page background
  • Text
  • Muted text
  • Danger
Border sample
Focus-ring sample
Surface background
  • Text
  • Muted text
  • Danger
Border sample
Focus-ring sample

Primitive swatches; no foreground guarantee

Accent
Inverse surface

Form elements

Accessibility: Use visible associated labels, connect hints/errors with aria-describedby and preserve native validation. WAI forms guidance.

Choices

Submit is prevented in this non-networked example. Cancel is intentionally inert; Reset restores the initial values.

Placeholder text · light

Placeholder text · dark

Chips

Accessibility: Selectable chips use aria-pressed and stable names; removal has a separate named button and deliberate focus restoration. Informational chips are text. APG toggle-button guidance.

Use informational chips for labels, toggle buttons for filters, and a separate X for removing a selection. Informational chips stay 1.5rem high (24px at a 16px root). Interactive chips have compact 28px short faces inside targets at least 44×44 CSS pixels. Labels wrap rather than truncate.

The remove X shares the close/clear background-only treatment: a compact face with a 2px inset inside its own 44px-wide target. Only the X target removes the chip; its label is not clickable. The transparent area above and below a filter face or X is part of that button. Removing a selection does not delete the category or saved item. These examples keep all changes local.

Allow the target space in layout: rows are about 20px taller than 24px chips, and removable chips reserve extra width for the X. Use normal wrapping and gaps; do not enlarge targets with overlapping absolute hit areas or negative margins. Informational chips have no tab stop. Each filter uses a native button with aria-pressed and a child span.chip-face; the button owns state and the span draws the compact face.

Dashed boundaries include clickable padding. Gray boundaries mark disabled buttons. Tab shows focus around the full target; selection uses a thicker face border. Removing moves focus to the next enabled X, the previous X, or Restore selections when none remain.

Light mode

Informational

Item category: Produce

  • Produce
  • Pantry
  • Produce for the shared weekend shopping list

Selectable filters

Categories

Showing: Apples.

Removable selections

  • Produce
  • Pantry
  • Weekend shopping for the whole household
  • Locked

All sample selections are present.

Dark mode

Informational

Item category: Produce

  • Produce
  • Pantry
  • Produce for the shared weekend shopping list

Selectable filters

Categories

Showing: Apples.

Removable selections

  • Produce
  • Pantry
  • Weekend shopping for the whole household
  • Locked

All sample selections are present.

Disclosures

Accessibility: Keep native details/summary semantics; avoid redundant roles, tabindex and aria-expanded. Required instructions must remain visible. MDN summary guidance.

Use details.disclosure to group optional settings, filters, or supporting information. Both variants use the same native disclosure markup and a full-width summary target. Keep essential instructions visible outside collapsed sections.

Place the label in disclosure-label, its title in disclosure-title, optional supporting text in disclosure-description, and the body in disclosure-content. A heading can carry both label and title classes. Choose its level for the page hierarchy; the class only normalizes its appearance.

These examples use native disclosure behavior: Enter or Space opens a focused summary, and multiple sections can stay open. Checkboxes and Reset work locally without saving. Put links and inputs in the body. Extra header actions must be siblings outside the summary with separate targets, as in the filled filter example below. Nest only when the content needs that hierarchy.

Choose a disclosure style
StyleUse whenWhy
BorderedGrouping self-contained settings, help, or supporting information.The surrounding border connects the header and body.
FilledShowing filters or compact controls whose current state matters while collapsed.The filled header emphasizes the summary; the accent border connects expanded content.

These are recommendations, not restrictions. Both styles support the same content and native behavior. Chevrons point inward when collapsed and down when expanded, aligned with the title’s first line. Compare all disclosure states.

Bordered disclosure

Use .disclosure for an enclosing border, trailing chevron, and divider when open.

Bordered · light

Preferences

Choose which local hints to show. Closing this section preserves your choices; Reset restores this example’s defaults.

Shopping filtersAll stores · All categories

The supporting summary describes the current selection. An application updates it when its filters change.

Each section opens independently. The library does not save expansion state or require other sections to close.

How matching works

An item matches any selected store and any selected category. Both groups apply together.

See the chip examples for selectable filters.

Help with shopping preferences and shared lists across multiple devices

Long labels wrap while the chevron stays reachable. Allow room for translated text and increased text size.

Bordered · dark

Preferences

Choose which local hints to show. Closing this section preserves your choices; Reset restores this example’s defaults.

Shopping filtersAll stores · All categories

The supporting summary describes the current selection. An application updates it when its filters change.

Each section opens independently. The library does not save expansion state or require other sections to close.

How matching works

An item matches any selected store and any selected category. Both groups apply together.

See the chip examples for selectable filters.

Help with shopping preferences and shared lists across multiple devices

Long labels wrap while the chevron stays reachable. Allow room for translated text and increased text size.

The summary target is at least 2.75rem high (44px at a 16px root size). Keyboard focus uses the library’s separate outline; hover and press tint the summary. The same panel treatment applies in both themes.

Use the native open attribute for an initially expanded section. Leave off the native name attribute to allow independent expansion. Do not add a button role, tabindex, or manually maintained aria-expanded to the summary. Applications own persistence and control behavior; no JavaScript is needed for opening and closing. If heading navigation inside a summary matters, check it with your target assistive technology, or place a section heading outside the disclosure. See summary heading guidance.

Unclassed details keeps the browser’s native appearance. App layouts own spacing between panels; the examples use a grid gap. Customize through the existing color, spacing, and radius tokens or scoped application CSS.

<details class="disclosure">
  <summary>
    <span class="disclosure-label disclosure-title">Preferences</span>
  </summary>
  <div class="disclosure-content">
    <p>Settings and controls go here.</p>
  </div>
</details>

Filled disclosure · working filters

Add .disclosure--filled to details.disclosure for a filled header, shared chevron, and accent-colored body border with a gap below the header. Use a persistent summary when selections matter even while the controls are collapsed.

Try selecting aldis and costco, then black and blue, and collapse Filters. “All stores” and “All categories” clear their own group; the X clears both. Each theme has independent, synthetic state. Nothing is saved or sent.

Filled · light

Filled · dark

Application responsibilities: Keep the visible summary current in both states: show “All items” when neither group is restricted, otherwise join selected labels with middle dots in stable group order. Native aria-pressed buttons expose each selection; this example adds no duplicate live announcement. If filtering changes a results list, follow the result-status guidance for a persistent live region and concise counts.

Clear action: The X is a named button outside summary in the DOM, positioned inside the filled header before the chevron. Reserve its target space so it cannot cover the title or chevron. Clear and the chevron stay beside the first title line while the selected labels wrap together below it. Clear must not toggle expansion; focus summary before hiding the X. When expanded, keyboard navigation reaches Clear after the body controls; when collapsed, directly after summary. Empty groups select their “All” action. Applications own filtering, persistence, result announcements, and focus transitions.

Example-only code: The specimen-filter-* classes provide inline/wrapping summary text, field-group spacing, and sibling clear-action placement. They are not library APIs. disclosure-filters.js shares local selection/reset behavior with the state gallery; the CSS package contains no JavaScript. Reuse the public disclosure and chip hooks, then implement your application's layout and state.

<details class="disclosure disclosure--filled" open>
  <summary>
    <span class="disclosure-label">
      <span class="disclosure-title">Filters</span>
      <span class="disclosure-description">All items</span>
    </span>
  </summary>
  <div class="disclosure-content">
    <!-- Filter controls belong here. -->
  </div>
</details>

Full state gallery: no selections, short selections, and many selections, each collapsed and expanded, in both themes. The gallery includes reset, narrow panels, and bordered examples. The working controls are generated by example-only JavaScript; the markup and library styling remain reusable separately.

This minimal snippet stacks the description below the title. The working example adds application layout for the inline summary and clear button. The shared accessibility guidance above applies to both variants.

Visually hidden text

Use .visually-hidden to keep supplemental text available to assistive technology while removing it from the visual layout. The library supplies CSS only; the examples below use local catalog behavior.

Light and dark examples are identical. Shaded explanations mirror the hidden text for visual review; these noninteractive teaching aids are excluded from the accessibility tree to avoid repeating that text.

1. Announce filter results

Use a persistent, initially empty status region to report the result of a user action without moving focus. The visible list and count remain available to everyone.

The native category menu already announces its selected option. Our message adds only the result, such as “1 of 3 items shown.” The menu’s option names and keyboard instructions come from the browser and screen reader, separately from this message.

Choose one announcement source in an application: this catalog shows a hidden region for demonstration. If the visible result count already contains the complete message, give that visible element role="status" and omit the hidden duplicate. Use hidden status text when it adds a concise equivalent of information otherwise conveyed visually.

Light mode

3 items shown.

  • Apples
  • Carrots
  • Oats

Dark mode

3 items shown.

  • Apples
  • Carrots
  • Oats

<p class="visually-hidden" role="status" aria-atomic="true"></p>
<!-- Application code updates this existing node after filtering. -->

2. Give a repeated action context

The button visibly says “Edit”; its text includes the item name for assistive technology. Keeping the visible wording at the beginning also helps people refer to the control by its visible label.

Demo behavior: Edit only reports which item was chosen; it does not open an editor. That feedback region starts empty. In an application, implement the actual editing action and its focus behavior; do not copy this extra status announcement when the newly focused editor already communicates the change.

Light mode

  • Apples
  • Oats

Dark mode

  • Apples
  • Oats

<button type="button">Edit<span class="visually-hidden"> Apples</span></button>

3. Name an icon-only action

Hide only the label text inside the button. While the field has content, the clear button remains visible and keyboard accessible. This is an alternative to aria-label; existing close/clear buttons do not need to migrate just to use the utility.

Light mode

Dark mode

<button type="button" data-barba-variant="icon" data-barba-shape="icon">
  <svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">…</svg>
  <span class="visually-hidden">Clear item name</span>
</button>

Implementation guidance

These are implementation rules for this library’s examples, with links for the underlying accessibility requirements. The utility changes visual presentation only; it does not add naming, live announcements, focus management, or application behavior.

Choose the right use

  • Keep field labels, instructions, errors, and essential status information visible. Use .visually-hidden for supplemental text or an equivalent of information already conveyed visually.
  • Apply the class to noninteractive text, never to a focusable control or a container holding controls. Do not add hidden, display:none, visibility:hidden, aria-hidden="true", or inert to that text or its ancestors. The empty field’s clear button is intentionally hidden as a whole because its action is unavailable.
  • Use the existing .skip-link for a skip link that becomes visible on focus. This utility never reveals itself. See Bootstrap’s distinction between hidden and focus-revealed helpers.

1. Status updates: one concise announcement

  • Prefer role="status" aria-atomic="true" on an existing visible result message when it already says everything needed. Otherwise keep one persistent, initially empty hidden status region in the DOM before updates. Do not conditionally mount a populated region and assume it will be announced.
  • Update that region’s text after the result is ready. Leave focus on the initiating control. The status role is already polite; do not add role="alert" or aria-live="assertive" for ordinary filtering.
  • Announce useful results with context, such as “1 of 3 items shown.” Do not repeat the native control’s selected option, or make the entire results list live. Use one live region per update; check ancestors and visible copies for accidental additional live regions.
  • Avoid identical rewrites caused by rerenders. This example suppresses an unchanged count; that is not a universal rule for distinct operations that happen to have the same result. Decide whether new feedback is needed for the actual action. For live search, coordinate announcements with settled results, including cancellation of stale requests, instead of speaking every keystroke.

Read W3C’s status-region technique and tests and which changes qualify as status messages. A focus change can already communicate a new context; it does not automatically need a second announcement.

2. Repeated actions: name the item

  • Use a native button type="button" for an action, or a link with a real destination for navigation. For the Edit button, append the item’s name in a hidden span, including a separating space. Expected names here: “Edit Apples” and “Edit Oats”. Keep that context synchronized with the displayed item and translate the complete phrase appropriately.
  • Keep the visible label in the accessible name, preferably at the beginning. Prefer visible context when it would help everyone distinguish actions.
  • Use one deliberate naming source. Do not add aria-label or aria-labelledby on top of these button contents: they can override the content-derived name. Hidden text alone does not label an unrelated input; retain its associated visible label.

Read W3C’s label-in-name guidance and accessible naming techniques and precedence.

3. Icon actions: name the purpose and preserve focus

  • Give the visible native button a concise action name such as “Clear item name”, “Close settings”, or “Remove Apples”; do not name it “X”. Use either hidden text or aria-label. Existing correctly named icon buttons need no migration. Mark the decorative SVG aria-hidden="true" focusable="false"; do not rely on its appearance or a tooltip as the button’s only name.
  • Keep the standard close/clear target and focus treatment. On clear, return focus to the input before hiding the button. Hide it when the input is empty. For a populated disabled or read-only field, retain a disabled X as in the inline-form examples; it must not change the value.
  • Application code must clear the authoritative value and run the same validation, filtering, and state synchronization used by other value changes. Keep visibility synchronized after typing, reset, and programmatic updates. The catalog has no application state; its local clear handler assigns input.value and explicitly dispatches an input event to synchronize the example. Assigning the value alone does not fire that event. Framework applications should use their normal state-update path.
  • Do not add an automatic “cleared” announcement merely because the button disappears. First check what the focused field already communicates. Close and remove actions need their own appropriate focus destination; do not blindly reuse the clear handler.

Read MDN’s icon-button naming guidance and how input events relate to programmatic changes.

Verify the implementation, not just the markup

  1. Inspect the accessibility tree: confirm the expected button names, associated field labels, and no decorative SVG names or duplicate live regions. The hidden spans should remain available without adding keyboard stops.
  2. Use keyboard activation for both Edit actions and Clear. After clearing, verify the value and application state are empty, focus is on the input, and Clear is absent from the tab order. Type again and verify it returns. Check disabled/read-only fields and reset paths when implementing them.
  3. With a supported browser/screen-reader combination, change the filter and confirm the result is announced without moving focus or unnecessarily repeating the selected category. Check rapid changes, no results, and equal-count results in the consuming application. Record the browser, screen reader, and versions tested.
  4. Check both themes, narrow layouts, zoom, and visible keyboard focus. Automated DOM checks cannot establish the actual speech sequence or guarantee accessibility. The shaded mirrors here are noninteractive teaching aids excluded from the accessibility tree; do not copy them into application markup.

Migration from Our List

After adopting the library release, replace only the duplicated sr-only and row-announcement hiding styles. Preserve semantics and application behavior, then review status-region mounting and duplicate announcements separately. A CSS replacement does not fix announcement timing.

Inline forms and input actions

Accessibility: Keep labels visible and use one naming source for each X. Synchronize clear visibility and move focus to the input before hiding the control. WAI label guidance.

Use an inline-field wrapper for a visible standard-size, medium-weight label above an input-row. The input grows; Add wraps to the right when space runs out. An optional input-action groups a text input with its X. Ordinary stacked forms keep their existing appearance.

The X is our shared close/clear icon action: a native button with data-barba-variant="icon" and data-barba-shape="icon". It has a generous target, transparent resting face, a circular hover background inset by 2px, and a separate keyboard-focus outline. Disabled X actions use muted gray, retain the disabled opacity, and have no hover background. Its accessible name describes the action: “Clear item name” for an input, “Close dialog” for a modal. The icon is decorative; these actions do not delete saved data.

Input and Add

Add validates and reports locally; no information is saved or sent.

Nothing added yet.

Input with an X

Only show the X when there is content. Keep its space reserved, and return focus to the input before hiding it. Applications handle clearing and synchronize visibility after typing, resets and programmatic value changes.

Try the X, type again, or reset the example.

Initially empty

Type to reveal the X.

Controls associated with a separate form

Use the form attribute on both the input and its submit button. The label and row layout are identical.

Nothing added yet.

Outside a form

A standalone field can use the same input-action layout without a submit button.

Unavailable actions

For disabled or read-only inputs, a populated field retains a muted gray, disabled X instead of the enabled action color. It cannot change the value and has no hover background.

See the dialog examples for the same X button used to close a modal through its cancellation path.

Buttons

Accessibility: Use native types and disabled states, stable accessible names and visible keyboard focus. Color does not explain destructive behavior. Applications own action feedback and confirmation. APG button guidance.

Native submit, button, and reset types provide primary, secondary, and tertiary emphasis. Existing emphasis styles keep their text color on hover. Text and destructive actions below demonstrate the new optional treatments; their clicks only report local example state.

Light buttons

Primary text contrast: 9.40:1 resting, 15.36:1 hovered.

Text and destructive actions

Text actions reveal their face and border on hover or keyboard focus. Delete starts as red text; hover and disabled states use the red outline.

One application class

Application styles own the properties they set, including hover. The global keyboard focus ring remains.

Try an action. No data changes.

Dark buttons

Primary text contrast: 7.98:1 resting, 10.79:1 hovered (existing light gray).

Text and destructive actions

Text actions reveal their face and border on hover or keyboard focus. Delete starts as red text; hover and disabled states use the red outline.

One application class

Application styles own the properties they set, including hover. The global keyboard focus ring remains.

Try an action. No data changes.

Article footer

Only the application-shell footer receives page-specific margin and alignment.

Article metadata stays in the article's normal flow.

Motion and interaction

Accessibility: Keep meaning and operation available without animation or hover. Test reduced-motion preferences separately from static screenshots. MDN reduced-motion guidance.

Hover or focus within

This surface scales only when motion is acceptable.

Focus this link
Disabled scale surface

This example remains static.

Dialogs

Try the maintained item editor with Name, Notes, chips, disabled states, and long content.

Accessibility: Name each native dialog, choose initial focus deliberately, support Escape/cancellation and restore focus to the invoker or a logical fallback. APG dialog guidance.

Both dialogs start at the same viewport-relative top offset. Short content leaves the footer at the minimum-height bottom. Long content grows to the viewport cap, then only its body scrolls. Footer order is Reset, Cancel, Submit. Submit validates and closes; Cancel or clicking outside closes without validation; Reset restores initial values and stays open. Closing does not reset the form.

Short dialog

Clear the title to exercise native required-field validation.

Long dialog

Edit the values, then use Reset to restore them. Submit and Cancel close the dialog without making a network request.

Content-driven sizing

The dialog grows with its contents rather than reserving a fixed preferred height. Its minimum leaves space for a useful short form.

Viewport limits

The maximum is eighty percent of the visible viewport, with outer gutters retained on exceptionally short screens. The minimum shrinks when the viewport cannot accommodate it.

Scroll ownership

The header and footer remain visible while this body scrolls. Move through these fields with Tab or scroll with your pointer to review the whole form.

Keyboard and validation

Clear the required title and try Submit. Native validation keeps the dialog open. Cancel does not submit or validate the form. Escape also dismisses the native modal.

This is the end of the scrolling body. Footer actions remain independently accessible.

Content-fit dialogs with a close action

These examples keep the standard width and opt into compact padding, a content-fit minimum, and more vertical room. Full-width header and footer dividers meet the scrolling body. The close icon uses the background-only icon treatment and follows the same cancellation path as Cancel and Escape.

Content-fit short dialog

Content-fit long dialog

Scroll through this synthetic example. The header and actions stay in place while the body scrolls.

Section 1. Keep editing within the body while the close action and footer remain available. Longer content uses the available vertical room.

Section 2. Keep editing within the body while the close action and footer remain available. Longer content uses the available vertical room.

Section 3. Keep editing within the body while the close action and footer remain available. Longer content uses the available vertical room.

Section 4. Keep editing within the body while the close action and footer remain available. Longer content uses the available vertical room.

Section 5. Keep editing within the body while the close action and footer remain available. Longer content uses the available vertical room.

Section 6. Keep editing within the body while the close action and footer remain available. Longer content uses the available vertical room.

Section 7. Keep editing within the body while the close action and footer remain available. Longer content uses the available vertical room.

Section 8. Keep editing within the body while the close action and footer remain available. Longer content uses the available vertical room.