Skip to content

Expand

import { Expand } from '@delightstack/components';

Additional information that can be expanded and collapsed smoothly.

The height animates from 0 to auto without any JavaScript measurement.

View code
<script>
import { Expand, Button } from '@delightstack/components';
let showDetails = $state(false);
</script>
<Button onclick={() => showDetails = !showDetails}>
{showDetails ? 'Hide' : 'Show'} Details
</Button>
<Expand bind:show={showDetails}>
<div>
<p>Additional information that can be expanded and collapsed smoothly.</p>
<p>The height animates from 0 to auto without any JavaScript measurement.</p>
</div>
</Expand>

This content slides in and out smoothly.

View code
<script>
import { Expand, Button } from '@delightstack/components';
let visible = $state(false);
</script>
<Button onclick={() => visible = !visible}>
{visible ? 'Collapse' : 'Expand'}
</Button>
<Expand bind:show={visible}>
<div style="padding: 1rem;">
<p>This content slides in and out smoothly.</p>
</div>
</Expand>
Show advanced options
View code
<script>
import { Expand, Checkbox, Input } from '@delightstack/components';
let showAdvanced = $state(false);
let cache_ttl = $state(3600);
let max_retries = $state(3);
</script>
<Checkbox bind:checked={showAdvanced} label="Show advanced options" />
<Expand show={showAdvanced}>
<div style="padding: 1rem 0;">
<Input type="number" label="Cache TTL (seconds)" bind:value={cache_ttl} />
<Input type="number" label="Max retries" bind:value={max_retries} />
</div>
</Expand>

A simple example showing the Expand container in its open state.

This content is visible because show is true.

View code
<Expand show>
<div style="padding: 1rem;">
This content is visible because show is true.
</div>
</Expand>

This expand container has a custom inline style with an accent border and tinted background.

View code
<script>
import { Expand, Button } from '@delightstack/components';
let visible = $state(false);
</script>
<Button onclick={() => visible = !visible}>
{visible ? 'Hide' : 'Show'} Styled Content
</Button>
<Expand show={visible} style="border-top: 2px solid #6366f1; margin-top: 0.75rem;">
<div style="padding: 1rem; background: #f5f3ff; border-radius: 0 0 8px 8px;">
<p>This expand container has a custom inline style with an accent border and tinted background.</p>
</div>
</Expand>
PropTypeDefaultDescription
showbooleanfalseControls expanded/collapsed state, bindable
stylestring''Additional inline styles
childrenSnippet-Content to expand/collapse

The component uses the CSS Grid trick for animating height to/from auto:

  • Collapsed: grid-template-rows: min-content 0fr with opacity: 0
  • Expanded: grid-template-rows: min-content 1fr with opacity: 1
  • A ::before pseudo-element with min-content row prevents layout collapse
  • Content uses visibility: hidden when collapsed and visibility: visible when expanded

This approach provides smooth height animation without any JavaScript measurement of content height.

  • Uses the inert attribute when collapsed to prevent focus trapping in hidden content
  • Screen readers skip collapsed content entirely (content is not focusable or readable when hidden)
  • No explicit ARIA attributes are needed — the inert attribute handles accessibility
  • Content opacity fades alongside height for a polished transition
  • Collapsed state takes zero space in the layout