soma test: instrument 5 overlay demos for permutation runner

Adds `data-perm-step` + `<meta name="perm-axes">` + perms seed to the
5 overlay demos sharing Dialog's open/close shape:

- alert-dialog — trigger open → cancel. `?perm.open=true` seeds.
  `disabled` deliberately NOT in axes: disabling the Provider blocks
  the Trigger click path the runner depends on.
- popover — trigger open → close button. `?perm.open=true` seeds open1.
- tooltip — focus trigger (mode=focus, 1s settle — tooltip opens after
  700ms delay). No close step: tooltip closes on blur.
- drawer — trigger open → close button (500ms settle for exit animation).
  `?perm.open=true` seeds basicOpen.
- dropdown-menu — trigger open → Escape close (mode=key, 500ms settle).
  Second step targets the Menu.Content selector because the Content
  only mounts after the Trigger step fires (runner handles dynamic
  step discovery).

All five declare `dir` as the only axis (universal RTL variant). The
other orientation / disabled axes don't apply to these overlay shapes.

## Coverage delta

- Before: 3 instrumented demos · 9 variants · 34 steps.
- After:  8 instrumented demos · 19 variants · 62 steps.

2x jump in per-CI-run validations with zero infra changes — just applying
the v1-v3 convention to additional demos.

## Verification

- `npm run check`: 0 errors in soma/morfo/test-route scope.
- `npm run smoke`: 65/65 routes.
- `npm run morfo:check`: 66/66 morfos.
- `npm run perm:check`: 8/8 demos · 62 steps · 19 variants.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
semantuix
dev 6 months ago
parent 545d47148c
commit 1e8500bfac

@ -4,10 +4,14 @@
import { createForm, type StandardSchemaV1 } from '$soma/components/form';
import * as Form from '$soma/components/form';
import Portal from '$soma/components/internal/portal.svelte';
import { Perms } from '../_perms.svelte';
// Perm-runner v2/v3 seed (see `<meta name="perm-axes">` below).
const perms = Perms.getOr({} as Record<string, string | number | boolean>);
// ── Example 1 — interactive testbed (every public prop wired) ────────────
let open = $state(false);
let disabled = $state(false);
let open = $state((perms.open as boolean) ?? false);
let disabled = $state((perms.disabled as boolean) ?? false);
let escapeBehavior = $state<'close' | 'ignore'>('close');
let actionLabel = $state('Delete account');
let cancelLabel = $state('Keep it');
@ -74,6 +78,11 @@
<svelte:head>
<title>AlertDialog · Soma</title>
<!-- Axes the perm-runner v3 should generate URL variants for. `disabled`
is deliberately NOT here: disabling the Provider blocks the Trigger
click and breaks the step cycle. The interactive control still
exercises disabled state at baseline for manual testing. -->
<meta name="perm-axes" content="dir" />
</svelte:head>
<div class="page">
@ -118,7 +127,9 @@
</div>
<AlertDialog.Provider bind:open {disabled}>
<AlertDialog.Trigger>Delete my account</AlertDialog.Trigger>
<AlertDialog.Trigger data-perm-step="0" data-perm-label="open alert dialog">
Delete my account
</AlertDialog.Trigger>
<Portal>
<AlertDialog.Overlay />
@ -128,7 +139,12 @@
This action is permanent and cannot be undone. All your data will be removed.
</AlertDialog.Description>
<div class="actions">
<AlertDialog.Cancel aria-label={cancelLabel} onclick={onCancel}>
<AlertDialog.Cancel
aria-label={cancelLabel}
onclick={onCancel}
data-perm-step="1"
data-perm-label="cancel alert dialog"
>
{cancelLabel}
</AlertDialog.Cancel>
<AlertDialog.Action

@ -1,7 +1,10 @@
<script lang="ts">
import * as Drawer from '$soma/components/drawer';
import { Perms } from '../_perms.svelte';
let basicOpen = $state(false);
const perms = Perms.getOr({} as Record<string, string | number | boolean>);
let basicOpen = $state((perms.open as boolean) ?? false);
let sideDrawer = $state<{ open: boolean; dir: Drawer.DrawerDirection }>({
open: false,
dir: 'bottom'
@ -24,6 +27,11 @@
}
</script>
<svelte:head>
<title>Drawer · Soma</title>
<meta name="perm-axes" content="dir" />
</svelte:head>
<div class="page">
<h1>Drawer</h1>
@ -33,7 +41,7 @@
<h2>Basic</h2>
<p>Bottom drawer, swipe down to dismiss.</p>
<Drawer.Provider bind:open={basicOpen}>
<Drawer.Trigger>Open</Drawer.Trigger>
<Drawer.Trigger data-perm-step="0" data-perm-label="open drawer">Open</Drawer.Trigger>
<Drawer.Overlay />
<Drawer.Content>
<Drawer.Handle><span class="pill"></span></Drawer.Handle>
@ -42,7 +50,9 @@
<Drawer.Description>Swipe down or tap overlay to dismiss.</Drawer.Description>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.</p>
<div class="actions">
<Drawer.Close>Close</Drawer.Close>
<Drawer.Close data-perm-step="1" data-perm-label="close drawer" data-perm-settle="500">
Close
</Drawer.Close>
</div>
</div>
</Drawer.Content>

@ -10,6 +10,7 @@
<svelte:head>
<title>DropdownMenu · Soma</title>
<meta name="perm-axes" content="dir" />
</svelte:head>
<div class="page">
@ -22,9 +23,15 @@
<p>Click trigger to open. Arrow keys navigate. Enter/Space selects. Escape closes.</p>
<Menu.Provider>
<Menu.Trigger>Actions</Menu.Trigger>
<Menu.Trigger data-perm-step="0" data-perm-label="open dropdown menu">Actions</Menu.Trigger>
<Portal>
<Menu.Content sideOffset={8}>
<Menu.Content
sideOffset={8}
data-perm-step="1"
data-perm-mode='key="Escape"'
data-perm-label="close via Escape"
data-perm-settle="500"
>
<Menu.Item onSelect={() => alert('New Tab')}>New Tab</Menu.Item>
<Menu.Item onSelect={() => alert('New Window')}>New Window</Menu.Item>
<Menu.Item disabled>New Private Window</Menu.Item>

@ -1,8 +1,12 @@
<script lang="ts">
import * as Popover from '$soma/components/popover';
import Portal from '$soma/components/internal/portal.svelte';
import { Perms } from '../_perms.svelte';
let open1 = $state(false);
// Perm-runner seed. `?perm.open=true` opens the first popover at mount.
const perms = Perms.getOr({} as Record<string, string | number | boolean>);
let open1 = $state((perms.open as boolean) ?? false);
let open2 = $state(false);
let open3 = $state(false);
let open4 = $state(false);
@ -13,6 +17,7 @@
<svelte:head>
<title>Popover · Soma</title>
<meta name="perm-axes" content="dir" />
</svelte:head>
<div class="page">
@ -28,14 +33,16 @@
<p>Click trigger to toggle. Closes on Escape or click outside.</p>
<Popover.Provider bind:open={open1}>
<Popover.Trigger>
<Popover.Trigger data-perm-step="0" data-perm-label="open popover">
Toggle popover ({open1 ? 'open' : 'closed'})
</Popover.Trigger>
<Portal>
<Popover.Content sideOffset={8}>
<p>This is a basic popover positioned below the trigger.</p>
<Popover.Close>Close</Popover.Close>
<Popover.Close data-perm-step="1" data-perm-label="close popover">
Close
</Popover.Close>
<Popover.Arrow />
</Popover.Content>
</Portal>

@ -8,6 +8,7 @@
<svelte:head>
<title>Tooltip · Soma</title>
<meta name="perm-axes" content="dir" />
</svelte:head>
<div class="page">
@ -22,7 +23,12 @@
<Tooltip.Group>
<Tooltip.Provider>
<Tooltip.Trigger>
<button>Hover me</button>
<button
data-perm-step="0"
data-perm-mode="focus"
data-perm-label="focus tooltip trigger (opens after delay)"
data-perm-settle="1000"
>Hover me</button>
</Tooltip.Trigger>
<Portal>
<Tooltip.Content sideOffset={8}>

Loading…
Cancel
Save

Powered by TurnKey Linux.