feat(layout): Layout Batch 3 — scroll-area, separator, splitter + splitter sema rewire
3 new layout primitives close the air port set (15 / 15 done).
`npm run component:audit`: 91 / 91 PASS, all 3 new PASS with 0 errors.
**scroll-area** — eidos compound wrapper over the existing soma:
`<ScrollArea><ScrollArea.Viewport>{content}</ScrollArea.Viewport>
<ScrollArea.Scrollbar orientation="vertical"><ScrollArea.Thumb />
</ScrollArea.Scrollbar><ScrollArea.Corner /></ScrollArea>`. Mirrors
Radix Primitives / Bits UI shape. Demo 667 lines.
**separator** — visual primitive (`scope: ['eidos']`) with conditional
ARIA: `role="separator"` + `aria-orientation` when not decorative,
`aria-hidden="true"` when decorative. New morfo
`src/uix/morfo/components/separator.ts`. Demo 645 lines.
**splitter** — eidos compound over existing soma:
`<Splitter orientation="horizontal"><Splitter.Panel>{a}</Splitter.Panel>
<Splitter.ResizeTrigger /><Splitter.Panel>{b}</Splitter.Panel>
</Splitter>`. Demo 824 lines.
**Splitter sema rewire — match Slider's handle/drag/commit shape:**
The morfo previously declared only `commit-resize`. Direct-manipulation
primitives (Slider, Splitter) should share the same event vocabulary so
audio/haptic projections feel coherent across the family. Renamed +
expanded to mirror Slider:
- `handle-pick` (family: handle, verb: pick, sequence: coincident,
target: resize-trigger) — fires on pointerdown when user grabs the
trigger.
- `handle-drag` (family: handle, verb: drag, sequence: coincident,
target: resize-trigger) — fires on each pointermove frame.
- `commit-set` (family: commit, verb: set, intent: neutral,
sequence: post, target: provider) — fires on pointerup. The runtime
`commit-set` handler is wired to call the consumer's `onResizeEnd`
callback, so sema and JS callback land at the same moment (parity
with Slider's `onValueCommit`).
Soma provider triggers these via `this.runtime.trigger(name)` in
`onpointerdown` / `onpointermove` / `notifyResizeEnd` (the latter
unchanged externally — internally now routes through the runtime
trigger).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
<script lang="ts">
|
|
|
|
|
import './separator.css';
|
feat(layout): Layout Batch 3 — scroll-area, separator, splitter + splitter sema rewire
3 new layout primitives close the air port set (15 / 15 done).
`npm run component:audit`: 91 / 91 PASS, all 3 new PASS with 0 errors.
**scroll-area** — eidos compound wrapper over the existing soma:
`<ScrollArea><ScrollArea.Viewport>{content}</ScrollArea.Viewport>
<ScrollArea.Scrollbar orientation="vertical"><ScrollArea.Thumb />
</ScrollArea.Scrollbar><ScrollArea.Corner /></ScrollArea>`. Mirrors
Radix Primitives / Bits UI shape. Demo 667 lines.
**separator** — visual primitive (`scope: ['eidos']`) with conditional
ARIA: `role="separator"` + `aria-orientation` when not decorative,
`aria-hidden="true"` when decorative. New morfo
`src/uix/morfo/components/separator.ts`. Demo 645 lines.
**splitter** — eidos compound over existing soma:
`<Splitter orientation="horizontal"><Splitter.Panel>{a}</Splitter.Panel>
<Splitter.ResizeTrigger /><Splitter.Panel>{b}</Splitter.Panel>
</Splitter>`. Demo 824 lines.
**Splitter sema rewire — match Slider's handle/drag/commit shape:**
The morfo previously declared only `commit-resize`. Direct-manipulation
primitives (Slider, Splitter) should share the same event vocabulary so
audio/haptic projections feel coherent across the family. Renamed +
expanded to mirror Slider:
- `handle-pick` (family: handle, verb: pick, sequence: coincident,
target: resize-trigger) — fires on pointerdown when user grabs the
trigger.
- `handle-drag` (family: handle, verb: drag, sequence: coincident,
target: resize-trigger) — fires on each pointermove frame.
- `commit-set` (family: commit, verb: set, intent: neutral,
sequence: post, target: provider) — fires on pointerup. The runtime
`commit-set` handler is wired to call the consumer's `onResizeEnd`
callback, so sema and JS callback land at the same moment (parity
with Slider's `onValueCommit`).
Soma provider triggers these via `this.runtime.trigger(name)` in
`onpointerdown` / `onpointermove` / `notifyResizeEnd` (the latter
unchanged externally — internally now routes through the runtime
trigger).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
/**
|
|
|
|
|
* Eidos `<Separator>` — visual divider between sections. Single
|
|
|
|
|
* `<div>` element; the recipe sizes it based on `data-orientation`.
|
|
|
|
|
* Two modes:
|
|
|
|
|
*
|
|
|
|
|
* - semantic (default): emits `role="separator"` +
|
|
|
|
|
* `aria-orientation`, exposing the divider to assistive tech.
|
|
|
|
|
* - decorative (`decorative` prop): drops the role and adds
|
|
|
|
|
* `aria-hidden="true"`.
|
|
|
|
|
*
|
|
|
|
|
* <Separator />
|
|
|
|
|
* <Separator orientation="vertical" />
|
|
|
|
|
* <Separator decorative />
|
|
|
|
|
*
|
|
|
|
|
* The `orientation` prop is responsive; it is resolved through
|
|
|
|
|
* `ActiveEidos.resolve()` so a `{ base: 'horizontal', md:
|
|
|
|
|
* 'vertical' }` value collapses to the active breakpoint at
|
|
|
|
|
* runtime.
|
|
|
|
|
*/
|
|
|
|
|
import { ActiveEidos } from '$uix/eidos';
|
|
|
|
|
import type { SeparatorOrientation, SeparatorProps } from './types';
|
|
|
|
|
|
|
|
|
|
let {
|
|
|
|
|
orientation = 'horizontal',
|
|
|
|
|
decorative = false,
|
|
|
|
|
class: className,
|
|
|
|
|
...restProps
|
|
|
|
|
}: SeparatorProps = $props();
|
|
|
|
|
|
|
|
|
|
const eidos = ActiveEidos.require();
|
|
|
|
|
const resolvedOrientation = $derived<SeparatorOrientation>(
|
|
|
|
|
eidos.resolve(orientation) ?? 'horizontal'
|
|
|
|
|
);
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
{...restProps}
|
|
|
|
|
class={className}
|
|
|
|
|
data-separator=""
|
|
|
|
|
data-orientation={resolvedOrientation}
|
|
|
|
|
role={decorative ? undefined : 'separator'}
|
|
|
|
|
aria-orientation={decorative ? undefined : resolvedOrientation}
|
|
|
|
|
aria-hidden={decorative ? 'true' : undefined}
|
|
|
|
|
></div>
|