Disclosure
Disclosures progressively reveal content behind a trigger, such as FAQs, filter panels, or advanced settings that most users can skip.
Try it
Usage
Use RuiDisclosureTrigger and RuiDisclosurePanel inside RuiDisclosure. Group related disclosures with RuiDisclosureGroup when only one should be open.
import {
RuiDisclosure,
RuiDisclosureTrigger,
RuiDisclosurePanel,
} from '@ecopages/radiant-ui/disclosure';
<RuiDisclosure>
<RuiDisclosureTrigger>Shipping details</RuiDisclosureTrigger>
<RuiDisclosurePanel>Delivered in 3–5 business days.</RuiDisclosurePanel>
</RuiDisclosure>RuiDisclosureTrigger renders an indicator arrow defaulting to RuiIconChevronDown. It points downward when collapsed and rotates 180° when expanded.
Set iconPosition="end" to position the arrow at the trailing edge (default is "start"). Pass iconPosition and icon directly to RuiDisclosure when using the trigger prop, or configure them on RuiDisclosureTrigger. Pass icon={<RuiDisclosureIcon variant="plus" />} or icon={null} to customize.
Indicator position
Place the toggle arrow at the start or trailing end using iconPosition="end".
import { RuiDisclosure } from '@ecopages/radiant-ui/disclosure';
<RuiDisclosure trigger="Return policy" iconPosition="end">
Items can be returned within 30 days of delivery.
</RuiDisclosure>Custom markup
<rui-disclosure> coordinates any light-DOM tree that matches its query contract. The Rui* helpers stamp these targets; they are not required.
import '@ecopages/radiant-ui/disclosure';
<rui-disclosure>
<div class="rui-disclosure">
<button type="button" data-disclosure-trigger class="rui-disclosure__trigger">
Shipping details
</button>
<div data-disclosure-panel class="rui-disclosure__panel">
<div class="rui-disclosure__panel-inner">Delivered in 3–5 business days.</div>
</div>
</div>
</rui-disclosure>BEM classes are presentation-only. Do not set aria-expanded, aria-controls, hidden, or data-state — the host owns those.
Accordion groups
Wrap multiple disclosures in RuiDisclosureGroup with multiple=\{false} for accordion behavior.
import '@ecopages/radiant-ui/disclosure';
<rui-disclosure-group>
<rui-disclosure>
<button type="button" data-disclosure-trigger>Shipping</button>
<div data-disclosure-panel hidden>Delivered in 3–5 days.</div>
</rui-disclosure>
</rui-disclosure-group>Animated panels
Enable animated for height transitions. Verify content remains readable during the animation.
Theming
Disclosure surfaces map to semantic surface roles, never Tailwind palette steps:
| Part | CSS roles |
|---|---|
Trigger (rui-disclosure__trigger) | on-background; hover / focus surface, --focus-ring |
Panel (rui-disclosure__panel) | on-surface |
Group (rui-disclosure-group) | background, border, rounded-container; panel header surface |
Override roles at the theme layer, not in component CSS.
API
Disclosure provides two custom elements: <rui-disclosure> (show/hide) and <rui-disclosure-group> (accordion). Compose the view helpers to render triggers and panels, or mark up data-disclosure-trigger / data-disclosure-panel elements directly.
Attributes (<rui-disclosure>)
| Attribute | Type | Default | Description |
|---|---|---|---|
open | boolean | false | Whether the disclosure content starts expanded. |
value | string | '' | Optional value used when coordinating disclosures inside a group. |
animated | boolean | false | Animate panel height; also enabled inside an animated group. |
Light-DOM contract (<rui-disclosure>)
| Target | Required | Host writes | Author owns |
|---|---|---|---|
[data-disclosure-trigger] | yes | aria-expanded, aria-controls | the trigger element |
[data-disclosure-panel] | yes | id, data-state, hidden, aria-hidden (when animated) | panel content |
Do not set aria-expanded, aria-controls, hidden, or data-state. Nested hosts: none.
Attributes (<rui-disclosure-group>)
| Attribute | Type | Default | Description |
|---|---|---|---|
multiple | boolean | false | Allow more than one disclosure open (exclusive by default). |
animated | boolean | false | Animate panel height for child disclosures. |
Light-DOM contract (<rui-disclosure-group>)
| Target | Required | Host writes | Author owns |
|---|---|---|---|
rui-disclosure | yes | animated propagated | one section per child |
[data-disclosure-trigger] | yes (in each child) | roving tabIndex across group | trigger inside each rui-disclosure |
Nested host: rui-disclosure — owns [data-disclosure-trigger] and [data-disclosure-panel].
Events
| Event | Detail | Description |
|---|---|---|
rui-disclosure-toggle | { value, open } | Emitted on every trigger activation; groups listen for exclusive behavior. |
View helpers
| Component | Target stamped | Notes |
|---|---|---|
RuiDisclosure | <rui-disclosure> + [data-ref="root"] shell | trigger prop composes trigger + panel; accepts icon and iconPosition. |
RuiDisclosureGroup | <rui-disclosure-group> + [data-ref="root"] shell | Expects rui-disclosure children. |
RuiDisclosureTrigger | [data-disclosure-trigger] | Includes chevron down icon by default; accepts icon and iconPosition. |
RuiDisclosureIcon | — | Presentation only; renders RuiIconChevronDown by default. |
RuiDisclosurePanel | [data-disclosure-panel] | Wraps content in rui-disclosure__panel-inner. |
CSS classes
Public BEM classes on the composed light-DOM surface (documented via @cssclass):
| Class | Description |
|---|---|
.rui-disclosure | Root wrapper around trigger and panel regions. |
.rui-disclosure__trigger | Trigger button; reflects aria-expanded. |
.rui-disclosure__trigger--icon-end | Layout when iconPosition="end". |
.rui-disclosure__icon | Indicator wrapper (decorative, aria-hidden). |
.rui-disclosure__icon--chevron | Rotates 180° when open. |
.rui-disclosure__icon--plus | Toggles between + and ×. |
.rui-disclosure__label | Trigger text. |
.rui-disclosure__panel | Panel content region. |
.rui-disclosure__panel-inner | Panel padding wrapper (drives the height animation). |
.rui-disclosure-group | Group surface (bordered card around stacked disclosures). |
Theme roles
| Part | CSS variables consumed |
|---|---|
| Trigger | --on-background, --surface (hover), --focus-ring, --space-control-* |
| Panel | --on-surface |
| Group | --background, --border, --surface |
Accessibility
- Triggers expose
aria-expandedreflecting panel visibility. - Panel content is associated with its trigger via
aria-controls. - Keyboard users activate disclosures with Enter or Space on the trigger.