docs(popover): add storybook stories

This commit is contained in:
Ilia Mashkov
2026-06-02 16:16:28 +03:00
parent ffa897ee54
commit 3ae22ad515
@@ -0,0 +1,117 @@
<script module>
import { defineMeta } from '@storybook/addon-svelte-csf';
import Popover from './Popover.svelte';
const { Story } = defineMeta({
title: 'Shared/Popover',
component: Popover,
tags: ['autodocs'],
parameters: {
docs: {
description: {
component:
'Anchored popover on the native Popover API (top-layer, light-dismiss, ESC, focus return). Hand-rolled side/align/offset positioning with flip + shift.',
},
story: { inline: false }, // Render stories in iframe for state isolation
},
},
argTypes: {
side: {
control: 'select',
options: ['top', 'bottom', 'left', 'right'],
description: 'Preferred side',
},
align: {
control: 'select',
options: ['start', 'center', 'end'],
description: 'Cross-axis alignment',
},
sideOffset: {
control: 'number',
description: 'Gap between trigger and content (px)',
},
},
});
</script>
<script lang="ts">
import { Slider } from '$shared/ui';
let open = $state(false);
let value = $state(50);
</script>
<Story name="Bottom">
{#snippet template()}
<div class="p-32 flex-center min-h-screen">
<Popover bind:open side="bottom" align="center" sideOffset={8}>
{#snippet trigger(props)}
<button {...props} class="surface-card-elevated px-4 py-2">Open popover</button>
{/snippet}
{#snippet children()}
<div class="surface-popover p-4 w-56">Popover content</div>
{/snippet}
</Popover>
</div>
{/snippet}
</Story>
<Story name="Top">
{#snippet template()}
<div class="p-32 flex-center min-h-screen">
<Popover bind:open side="top" align="center" sideOffset={8}>
{#snippet trigger(props)}
<button {...props} class="surface-card-elevated px-4 py-2">Open popover</button>
{/snippet}
{#snippet children()}
<div class="surface-popover p-4 w-56">Popover content</div>
{/snippet}
</Popover>
</div>
{/snippet}
</Story>
<!--
Mirrors TypographyMenu: top/end placement with a programmatic Close button
wired to the `close()` param of the children snippet.
-->
<Story name="AlignedEnd">
{#snippet template()}
<div class="p-32 flex-center min-h-screen">
<Popover bind:open side="top" align="end" sideOffset={8}>
{#snippet trigger(props)}
<button {...props} class="surface-card-elevated px-4 py-2">Open menu</button>
{/snippet}
{#snippet children({ close })}
<div class="surface-popover p-4 w-72">
<h3 class="text-sm font-medium mb-3">Menu header</h3>
<p class="text-sm text-muted-foreground mb-4">
Aligned to the trigger's end edge.
</p>
<button class="surface-card-elevated px-3 py-1.5 text-sm" onclick={close}>
Close
</button>
</div>
{/snippet}
</Popover>
</div>
{/snippet}
</Story>
<!-- Mirrors ComboControl: a vertical Slider lives inside the popover content. -->
<Story name="WithSlider">
{#snippet template()}
<div class="p-32 flex-center min-h-screen">
<Popover bind:open side="top" align="center" sideOffset={8}>
{#snippet trigger(props)}
<button {...props} class="surface-card-elevated px-4 py-2">Adjust value</button>
{/snippet}
{#snippet children()}
<div class="surface-card-elevated p-3 h-64 flex-center">
<Slider orientation="vertical" min={0} max={100} bind:value />
</div>
{/snippet}
</Popover>
</div>
{/snippet}
</Story>