Skip to content
bref / ui

Svelte components, simply.

Star

Popover

An anchored native popover whose trigger snippet renders the owning control or component.

Usage

The trigger snippet renders TextInput directly. Its input and click handlers open the panel; click outside or press Escape to dismiss. The default soft glass panel fits its content and is at least as wide as the trigger, within the viewport. Toggle wide to check the anchor minimum.

Svelte
<script>
	import { Checkbox, Popover, TextInput } from 'bref-ui';
	let open = $state(false);
	let wide = $state(false);
</script>

<label><Checkbox bind:checked={wide} /> Wide input</label>
<Popover bind:open scroll>
	{#snippet trigger()}
		<TextInput
			{wide}
			value="Sample text"
			aria-label="Search"
			aria-expanded={open}
			oninput={() => (open = true)}
			onclick={() => (open = true)}
		/>
	{/snippet}
	<p>Helpful details beside the input.</p>
</Popover>

Playground

Live preview

Closed · Glass is always enabled

Settings

Appearance
Layout
Customization
Preview
View generated code
Svelte
<script>
	import { Button, Popover, TextInput } from 'bref-ui';
	let open = $state(false);
</script>

<Popover
	bind:open
	disabled={false}
	as="div"
	variant="soft"
	color="background"
	shadow={'medium'}
	spacing="medium"
	orientation="vertical"
	radius="small"
	scroll={false}
>
	{#snippet trigger()}
		<Button
			label="Toggle preview popover"
			wide={false}
			disabled={false}
			aria-expanded={open}
			onClick={() => (open = !open)}
		/>
	{/snippet}
	<p>Helpful details beside the trigger.</p>
	<Button label="Done" onClick={() => (open = false)} />
</Popover>
<p role="status">{open ? 'Open' : 'Closed'}</p>

Open the preview after changing settings. Width fill follows the trigger; fit and default follow content. Every panel uses glass.

Bound state

Settings closed.

Svelte
<script>
	import { Button, Popover, TextInput } from 'bref-ui';
	let open = $state(false);
</script>

<Popover bind:open variant="filled" spacing="medium" radius="small" shadow scroll>
	{#snippet trigger()}
		<Button label="Edit settings" onClick={() => (open = !open)} aria-expanded={open} />
	{/snippet}
	<label>Display name <TextInput value="Example" /></label>
	<Button label="Done" onClick={() => (open = false)} />
</Popover>

Scrolling and multiple instances

This bound example starts open when the page loads.

Resize the viewport, scroll the page and switch the shared theme control to test fitting, anchoring and light/dark modes.

Props

Component props
PropTypeRequiredDefaultDescription
triggerSnippetYes—The owning control or component; manages its own events and accessibility.
childrenSnippetYes—Parameterless content inside the popover.
openbooleanNofalseBindable visibility; native dismissals update it.
disabledbooleanNofalseKeep the panel closed; the trigger controls its own disabled state.
as'div' | 'section' | 'span'NodivNative root element of the Surface inside the panel.
variantVariantNosoftneutral, soft or filled; every variant uses glass.
colorColorNobackgroundTheme role for panel paint.
shadowBaseSize | booleanNomediumShadow strength; true means medium and false disables it.
hoverBaseSizeNoOmittedOptional hover treatment strength.
spacingSizeNomediumPadding and gap from x-small to x-large.
orientationOrientationNoverticalHorizontal or vertical Surface layout.
widthDimensionNoOmittedfill follows trigger width; fit or omitted grows with content, at least as wide as the trigger.
heightDimensionNoOmittedfit follows content; fill fills available Surface height within the viewport cap.
radiusSurfaceRadiusNosmallSize token, rem value or percentage.
scrollbooleanNofalseEnable scrolling within the Surface.
classstringNoOmittedAdditional Surface classes.
stylestringNoOmittedInline styles on the Surface.

Popover accepts Surface props for styling and layout, including class and style, without inheriting generic HTML attributes. Every panel uses glass, with soft as the default variant. Explicit spacing, radius, shadow, variant, color and class choices customize that material. Another instance uses a soft primary color.

Both snippets receive no arguments. The trigger owns its native attributes, events, accessible name and expanded state. Its handlers control bind:open ; Popover handles native dismissal and positioning.

Keyboard and focus

The trigger controls its keyboard behavior: buttons toggle with Enter or Space; the TextInput example opens on click or typing. Tab moves through the Surface and interactive content without trapping focus. Escape dismisses; closing from within the content returns focus to the owning control.

Content and explicit widths

Short content keeps the anchor minimum. Explicit fill follows the anchor; fit follows content. Both stay within the viewport and use glass automatically.