Component catalog
Browse the public controls by interaction purpose. Every result links to generated API facts, accessibility behavior, source, and exhaustive stories.
Browse the public controls by interaction purpose. Every result links to generated API facts, accessibility behavior, source, and exhaustive stories.
A disclosure widget: a single tappable header (a label + a trailing chevron indicator) that toggles the visibility of arbitrary content beneath it.
import { DisclosureGroup } from "@liquidify/react/disclosure-group"| Prop | Type | Default | Description |
|---|---|---|---|
| animated | boolean | undefined | true | When `false`, the expand/collapse roll (and its deferred unmount via {@link Presence}) is suppressed: toggling shows/hides `children` instantly, exactly as under `prefers-reduced-motion`. The chevron still rotates via CSS; kill that per-instance if an instant swap is wanted there too. Used by DatePicker, whose month/year wheel disclosure must not animate. |
| children | ReactNode | — | The revealed content (SwiftUI `\@ViewBuilder content:`). Mounted in the DOM only while expanded (unmounted, not merely `hidden`, while collapsed) — supports a nested `<DisclosureGroup>`, which renders its own independent root with no auto-indent. Optional: a childless DisclosureGroup is a pure header toggle whose only effect is its event callbacks (e.g. lazy-loading content in {@link DisclosureGroupProps.onExpandedChange}). |
| className | string | undefined | — | Optional additional CSS class merged into the glass surface class. The supported per-instance customisation seam: override any `--lq-*` custom property from this class's CSS — the token cascade the engine reads (ADR-0004). No raw inline style is involved, so this stays ADR-0003 clean. |
| defaultExpanded | boolean | undefined | false | Uncontrolled seed for the internal expanded state (ignored once {@link DisclosureGroupProps.expanded} is supplied). SwiftUI's own default is collapsed. |
| disabled | boolean | undefined | — | When `true`, sets the native `disabled` attribute on the header `<button>`: removed from the tab order, not activatable via pointer or keyboard, dimmed via `--lq-opacity-muted`. The group's current collapsed/expanded content freezes at whatever it was. |
| expanded | boolean | undefined | — | Controlled expanded state (SwiftUI `isExpanded: Binding<Bool>`). Passing this switches DisclosureGroup to controlled mode: the rendered state always reflects this value and the consumer owns it via {@link DisclosureGroupProps.onExpandedChange}. |
| icon | ReactNode | <Icon name="chevron-right" tint="accent" /> | The header's trailing glyph (SwiftUI disclosure indicator). Defaults to a right-pointing chevron `<Icon name="chevron-right" tint="accent" />` that rotates 90° on expand. To use a different glyph or colour, pass your OWN `<Icon>` (any `ReactNode`); it renders inside the rotating `.lq-disclosure-group-chevron` wrapper, so it still animates on toggle. |
| label required | ReactNode | — | The header's label (SwiftUI `titleKey:` / custom label view). A `string | number` routes through the shared `TextLabel` guard into an internal `Text` styled `variant="headline"`, `weight="bold"`, `color="primary"` — the fixed header typography (ADR-0028). To style it differently, pass your OWN `<Text>` (any `ReactNode`), which passes through unwrapped and owns its typography, OR use {@link DisclosureGroupProps.labelProps} to override individual axes while keeping the fixed structure. This is the button's accessible name. |
| labelProps | LabelProps | undefined | — | Per-instance typography override for a `string | number` {@link * DisclosureGroupProps.label} (ADR-0028 rule 2, charter §2) — spread last into the header's primary `TextLabel`, so an explicit value here wins over the fixed `variant="headline"`/`weight="bold"`/`color="primary"` defaults. Ignored when `label` is already a `ReactNode` element (e.g. a caller-supplied `<Text>`), which passes through unwrapped and owns its own axes. |
| onExpandedChange | ((expanded: boolean) => void) | undefined | — | Fires with the next boolean on every toggle path — pointer click anywhere in the header row, or `Space` / `Enter` on the focused header button. Always called, in both controlled and uncontrolled modes. The sole semantic callback (charter §1 rule 5) — there is no public click-level prop. |
| ref | Ref<HTMLDivElement> | undefined | — | Forwarded ref to the rendered element — the component's native root (or the merged child element on a component that opts into {@link SlottableProps}). Generic over `E` (charter `docs/api-conventions.md` §4 rule 1, default `HTMLElement`) so a component with a polymorphic root (Link's navigation / action mode union, Text's `as`) can instantiate the concrete element per variant instead of leaving every consumer with a widened `Ref<HTMLElement>`. A component that does not narrow simply inherits the `HTMLElement` default — source-compatible with every pre-existing non-generic `extends ControlProps`. |
| variant | DisclosureGroupVariant | undefined | plain | Material posture of the root. |
DisclosureGroup supports the documented keyboard interactions below.
| Name | Value |
|---|---|
| --lq-color-accent | #007aff |
| --lq-color-label-primary | Component-defined value |
| --lq-disclosure-group-gap | var(--lq-space-8) |
| --lq-disclosure-group-hpad | Component-defined value |
| --lq-disclosure-group-pad | var(--lq-space-16) |
| --lq-disclosure-group-thumb-h | Component-defined value |
| --lq-disclosure-group-track-h | Component-defined value |
| --lq-duration-standard | 250ms |
| --lq-easing-standard | cubic-bezier(0.25, 0.1, 0.25, 1) |
| --lq-focus-ring-color | var(--lq-button-ring, var(--lq-color-accent))var(--lq-toggle-ring, var(--lq-color-accent))var(--lq-slider-ring, var(--lq-color-accent))var(--lq-tint-current, var(--lq-color-accent)) |
| --lq-glass- | 440.71.15var(--lq-segmented-control-indicator-blur)calc(var(--lq-glass-material-blur) * 8)var(--lq-shadow-presentational) |
| --lq-radius-20 | Component-defined value |
| --lq-radius-22 | 1.375rem |
| --lq-space- | 0.0625rem0.125rem0.25rem0.5rem0.75rem1rem1.25rem1.5rem2rem2.5rem3rem3.5rem |
| --lq-space-16 | 1rem |
| --lq-space-2 | 0.125rem |