sdxc

[ @sdxc/ui ]

Disclosure

A single expand/collapse section built on the native <details> and <summary> elements.

Advanced build settings

Overrides apply to this project only. Leave them alone to keep the detected defaults.

View code
let settings = { ...BUILD_DEFAULTS };

function editSetting(field: keyof typeof BUILD_DEFAULTS) {
	return on<HTMLInputElement, "input">("input", (event) => {
		settings[field] = event.currentTarget.value;
		void handle.update();
	});
}

function resetDefaults() {
	settings = { ...BUILD_DEFAULTS };
	void handle.update();
}

<Disclosure open>
	<Disclosure.Trigger>
		<Disclosure.Header mix={[grow()]}>Advanced build settings</Disclosure.Header>
		<ChevronDownIcon data-slot="icon" aria-hidden="true" />
	</Disclosure.Trigger>
	<Disclosure.Panel>
		<Description>
			Overrides apply to this project only. Leave them alone to keep the detected defaults.
		</Description>

		<Label htmlFor="buildCommand">Build command</Label>
		<Input id="buildCommand" name="buildCommand" value={settings.command} mix={[editSetting("command")]} />

		<Label htmlFor="outputDirectory">Output directory</Label>
		<Input id="outputDirectory" name="outputDirectory" value={settings.output} mix={[editSetting("output")]} />

		<Label htmlFor="installCommand">Install command</Label>
		<Input id="installCommand" name="installCommand" value={settings.install} mix={[editSetting("install")]} />

		<Switch name="buildCache" defaultChecked>Reuse the build cache between deploys</Switch>

		<Button
			variant="outline"
			color="neutral"
			size="sm"
			mix={[on<HTMLButtonElement, "click">("click", resetDefaults)]}
		>
			Reset to defaults
		</Button>
	</Disclosure.Panel>
</Disclosure>

Installation

An ordinary dependency: install it, import the theme once, and import the component where it is used.

npm add @sdxc/ui remix
import "@sdxc/ui/theme.css";

Usage

import { Disclosure } from "@sdxc/ui";

Renders the section's <details> host, revealing Disclosure.Panel's content while open. The ::details-content block-size transition is a progressive enhancement over the native toggle.

Composition

The parts the component publishes, each a static property of the host.

  • Disclosure
  • Disclosure.HeaderRenders Disclosure.HeaderProps.children as an accessible heading at the ambient level, nested directly inside Disclosure.Trigger, since <summary> must stay <details>'s direct child.
  • Disclosure.TriggerRenders Disclosure.TriggerProps.children inside a native <summary> with its marker suppressed, so the indicator is a glyph the consumer passes as a child carrying data-slot="icon" — which the section turns over while it is open.
  • Disclosure.PanelRenders Disclosure.PanelProps.children in a <div> positioned after Disclosure.Trigger, all <details> needs to treat it as the collapsible body.
  • Disclosure.GroupRenders Disclosure.GroupProps.children as a bordered, rounded list of Disclosure sections sharing one divider between them.

Examples

Open by default

How long does shipping take?

Orders leave the Acme warehouse within two business days and arrive in three to five.

View code
<Disclosure open>
	<Disclosure.Trigger>
		How long does shipping take?
		<ChevronDownIcon data-slot="icon" aria-hidden="true" />
	</Disclosure.Trigger>
	<Disclosure.Panel>
		<p mix={[m(0)]}>Orders leave the Acme warehouse within two business days and arrive in three to five.</p>
	</Disclosure.Panel>
</Disclosure>

Props

Read from the component's own types, so every prop, every default and every allowed value is listed.

PropTypeDescription
childrenRemixNodeThe section's compound parts: Disclosure.Trigger followed by Disclosure.Panel.

Also accepts everything in TagProps<"details">.

Disclosure.Header

PropTypeDescription
childrenRemixNodeThe trigger's label text, exposed as a heading for assistive technology.

Also accepts everything in TagProps<"h1">.

Disclosure.Trigger

PropTypeDescription
childrenRemixNodeThe always-visible label, typically plain text or Disclosure.Header.

Also accepts everything in TagProps<"summary">.

Disclosure.Panel

PropTypeDescription
childrenRemixNodeThe content revealed while the section is open.

Also accepts everything in TagProps<"div">.

Disclosure.Group

PropTypeDescription
childrenRemixNodeOne or more Disclosure sections to stack into a single bordered list.

Also accepts everything in TagProps<"div">.

Written by Sergio Xalambrí. Follow @sergiodxa for new packages, or sponsor the work.