You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/eidos/components/context-menu
dev d229447a33
feat(floating): cascade the canonical gap to all menus + panels
4 months ago
..
README.md feat(motion): event-driven cascade rollout to the menu family (ContextMenu + Menubar) 4 months ago
context-menu-arrow.svelte feat(context-menu): port from soma to eidos (Tier 1 sprint, 4/5) 5 months ago
context-menu-checkbox-item.svelte feat(motion): event-driven cascade rollout to the menu family (ContextMenu + Menubar) 4 months ago
context-menu-content.svelte feat(floating): cascade the canonical gap to all menus + panels 4 months ago
context-menu-group-heading.svelte feat(context-menu): port from soma to eidos (Tier 1 sprint, 4/5) 5 months ago
context-menu-group.svelte feat(context-menu): port from soma to eidos (Tier 1 sprint, 4/5) 5 months ago
context-menu-item.svelte feat(motion): event-driven cascade rollout to the menu family (ContextMenu + Menubar) 4 months ago
context-menu-radio-group.svelte feat(context-menu): port from soma to eidos (Tier 1 sprint, 4/5) 5 months ago
context-menu-radio-item.svelte feat(motion): event-driven cascade rollout to the menu family (ContextMenu + Menubar) 4 months ago
context-menu-separator.svelte feat(context-menu): port from soma to eidos (Tier 1 sprint, 4/5) 5 months ago
context-menu-sub-content.svelte feat(floating): cascade the canonical gap to all menus + panels 4 months ago
context-menu-sub-trigger.svelte feat(context-menu): port from soma to eidos (Tier 1 sprint, 4/5) 5 months ago
context-menu-sub.svelte feat(context-menu): port from soma to eidos (Tier 1 sprint, 4/5) 5 months ago
context-menu-trigger.svelte feat(context-menu): port from soma to eidos (Tier 1 sprint, 4/5) 5 months ago
context-menu.css feat(menu-family): adopt the `overlay` elevation plane (B2) 4 months ago
context-menu.svelte perf(eidos): code-split 7 menu recipes + order-independent menu-indicator (Phase 3, batch 2) 4 months ago
index.ts feat(context-menu): port from soma to eidos (Tier 1 sprint, 4/5) 5 months ago
types.ts feat(eidos): non-modal menus + unified list-surface size layer (control-height rows) 4 months ago

README.md

<ContextMenu> — eidos

Right-click / long-press menu. Visually identical to <DropdownMenu> — same panel chrome, same item rows. Differences vs DropdownMenu:

DropdownMenu ContextMenu
Trigger <button> toggle <span> wrap intercepting contextmenu
Open via Click / Enter / Space / ArrowDown Right-click / Ctrl+Click / Long-press / Shift+F10
Anchored to Trigger's bounding box Cursor position
CheckboxGroup ✓ — (Bits parity gap; can be added later)

Motion parity too. Items fade in staggered on open — the event-driven cascade. The Content marks the panel [data-stagger] + sets the rhythm --motion-stagger-each: var(--motion-stagger); each item carries data-animation-style="fade"; the per-item index comes from :nth-child. Same mechanism + caveats (direct-child items only; enter-only) as DropdownMenu — see its README → Motion for the full explanation.

Usage

<script lang="ts">
  import { ContextMenu } from '$uix/eidos/components/context-menu';
  let showGrid = $state(true);
</script>

<ContextMenu>
  <ContextMenu.Trigger>
    <div class="canvas">Right-click anywhere on the canvas…</div>
  </ContextMenu.Trigger>
  <ContextMenu.Content>
    <ContextMenu.Item onSelect={() => copy()}>Copy</ContextMenu.Item>
    <ContextMenu.Item onSelect={() => paste()}>Paste</ContextMenu.Item>
    <ContextMenu.Separator />
    <ContextMenu.CheckboxItem bind:checked={showGrid}>
      Show grid
    </ContextMenu.CheckboxItem>
    <ContextMenu.Sub>
      <ContextMenu.SubTrigger>Format</ContextMenu.SubTrigger>
      <ContextMenu.SubContent>
        <ContextMenu.Item>Bold</ContextMenu.Item>
        <ContextMenu.Item>Italic</ContextMenu.Item>
      </ContextMenu.SubContent>
    </ContextMenu.Sub>
  </ContextMenu.Content>
</ContextMenu>

Parts

14 pass-through wrappers — same vocabulary as DropdownMenu minus CheckboxGroup.

Provider · Trigger · Content · Arrow · Item · Group · GroupHeading · Separator · CheckboxItem · RadioGroup · RadioItem · Sub · SubTrigger · SubContent.

Baseline

WAI-ARIA APG Menu pattern: https://www.w3.org/WAI/ARIA/apg/patterns/menu/

Soma owns:

  • contextmenu event interception, long-press detection, Shift+F10 handling
  • Floating positioning anchored to the cursor (not the trigger box)
  • Same keyboard navigation as DropdownMenu inside the open Content
  • Focus management on open / close / sub navigation

Comparativa

Lib Trigger source Long-press (touch) Shift+F10 Sub-menus Cursor anchor
Radix Primitives contextmenu event ✓ ✓ ✓ ✓
Bits UI same ✓ ✓ ✓ ✓
Ark UI same ✓ ✓ ✓ ✓
Eidos (this) same ✓ ✓ ✓ ✓

Full functional parity. No styled API additions at the eidos level — visual treatment identical to DropdownMenu (single recipe vocabulary across the menu family).

Decisiones

  • Recipe duplication, not aliasing. The CSS uses separate [data-context-menu-*] selectors rather than sharing [data-dropdown-menu-*]. Reason: the morfo emits distinct markers per component (correct contract behaviour), and aliasing the recipe would couple two independent components in CSS even though their visual vocabulary is identical. Cost: ~150 lines of CSS duplication. Benefit: each component evolves freely without cascade surprises.
  • Trigger gets a subtle data-state='open' outline. Users often forget which region they right-clicked; a 1px dashed border while the menu is open provides a quiet "this is the source" affordance without competing with the menu itself.
  • No CheckboxGroup. Soma doesn't ship one for context-menu (Bits doesn't either). Can be added later if needed.

Gaps

Gap Disposición Detalle
CheckboxGroup (array binding, Bits' addition for DropdownMenu) diferir Soma doesn't ship one for context-menu yet.
Per-item data-color cascade for destructive items implementar próximo turno Same gap as DropdownMenu — would be the same cascade rule. Resolve once for both.
Touch UX testing diferir Long-press is wired in soma but visual + haptic feedback during the hold could be richer (Material-style ripple, etc.).

Reference

Powered by TurnKey Linux.