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/context-menu.css

224 lines
9.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* ContextMenu recipe.
*
* Functionally identical to DropdownMenu — same panel chrome, same
* item row treatment. Only differences:
*
* - Trigger is a `<span>` wrapper (NOT a button) that intercepts
* `contextmenu`. The recipe gives it no chrome by default; the
* wrapper is meant to feel inert until invoked.
* - Anchoring is to the cursor position rather than the trigger's
* bounding box — soma's floating layer handles this. The visual
* panel reads identical to DropdownMenu's.
*
* To avoid recipe duplication we lean on attribute selectors that
* cover both `data-dropdown-menu-*` and `data-context-menu-*` for the
* shared parts (Content, Item, Group, Separator, etc.). The Trigger
* gets its own rule since its semantics differ.
*/
/* ── Panel (Content / SubContent) ──────────────────────────────────── */
[data-context-menu-content],
[data-context-menu-sub-content] {
min-inline-size: var(--context-menu-content-min-width, 12rem);
max-block-size: var(--context-menu-content-max-height, min(60vh, 22rem));
overflow-y: auto;
overscroll-behavior: contain;
padding: var(--context-menu-content-padding, var(--space-1));
/* Elevation — surface · border · shadow — from the `overlay` plane via
`data-depth` (A1, Decisión 8). Radius / font / color stay the panel's own. */
border-radius: var(--context-menu-content-radius, var(--radius-md));
/* DEAD here, and left as the literal source on purpose: the panel carries
`data-depth=overlay` and the PLANE declares font-family at the same
specificity, later in the cascade. Whether a depth plane may own the
typography is PLAN-theming §12.9, still unsigned. */
font-family: var(--style-label-font-family);
font-size: var(--context-menu-content-font-size, var(--font-size-sm));
color: var(--context-menu-content-fg);
}
[data-context-menu-content]:focus-visible,
[data-context-menu-sub-content]:focus-visible {
outline: none;
}
/* ── Size scale → shared list-surface ───────────────────────────────────
*
* The size rhythm (font / item-height / padding / gap / content-padding /
* radius, 1:1 with the control sizes) lives in `lib/list-surface.css` — the
* ONE source shared by every menu + selection popup. The panel carries
* `data-list-surface` + `data-size` (stamped by the eidos Content/SubContent),
* so that block sets `--list-*`; here we just BRIDGE the panel's own public
* tokens to it, keeping them as the per-component override knobs. Mirrors the
* DropdownMenu bridge — both menus read identically.
*/
[data-context-menu-content],
[data-context-menu-sub-content] {
--context-menu-content-font-size: var(--list-font-size);
--context-menu-item-height: var(--list-item-height);
--context-menu-item-padding-block: var(--list-item-padding-block);
--context-menu-item-padding-inline: var(--list-item-padding-inline);
--context-menu-item-gap: var(--list-item-gap);
--context-menu-content-padding: var(--list-content-padding);
--context-menu-content-radius: var(--list-content-radius);
}
/* Event-driven item cascade rhythm — the Content wrapper marks itself
`[data-stagger]`; each direct-child item carries `data-animation-style` and
gets its structural index from `:nth-child`. `var(--motion-stagger)` is the
canonical 20ms (0 = parallel). Same mechanism as DropdownMenu; the appearance
flows from the `open` (emerge) event — no JS writes the index. Applies to the
root panel AND fly-out SubContent (both mark themselves `[data-stagger]`). */
[data-context-menu-content],
[data-context-menu-sub-content] {
--motion-stagger-each: var(--motion-stagger);
}
/* ── Item rows ─────────────────────────────────────────────────────── */
[data-context-menu-item],
[data-context-menu-checkbox-item],
[data-context-menu-radio-item],
[data-context-menu-sub-trigger] {
display: flex;
align-items: center;
gap: var(--context-menu-item-gap, var(--space-2));
min-block-size: var(--context-menu-item-height, 2rem);
padding-block: var(--context-menu-item-padding-block, var(--space-1));
padding-inline: var(--context-menu-item-padding-inline, var(--space-2));
border-radius: var(--context-menu-item-radius, var(--radius-sm));
color: var(--context-menu-item-fg);
line-height: var(--context-menu-item-line-height);
cursor: pointer;
user-select: none;
transition:
background var(--duration-fast) var(--ease-default),
color var(--duration-fast) var(--ease-default);
}
[data-context-menu-item]:hover:not([data-disabled]),
[data-context-menu-checkbox-item]:hover:not([data-disabled]),
[data-context-menu-radio-item]:hover:not([data-disabled]),
[data-context-menu-sub-trigger]:hover:not([data-disabled]),
[data-context-menu-item]:focus-visible,
[data-context-menu-checkbox-item]:focus-visible,
[data-context-menu-radio-item]:focus-visible,
[data-context-menu-sub-trigger]:focus-visible,
[data-context-menu-sub-trigger][data-state='open'] {
outline: none;
background: var(--context-menu-hover-item-bg, var(--color-primary-element));
color: var(--context-menu-hover-item-fg, var(--color-content-primary));
}
[data-context-menu-item][data-disabled],
[data-context-menu-checkbox-item][data-disabled],
[data-context-menu-radio-item][data-disabled],
[data-context-menu-sub-trigger][data-disabled] {
cursor: default;
opacity: var(--context-menu-item-disabled-opacity, 0.55);
}
/* Indicator slot + ::before painting for checkbox-item / radio-item shared
with dropdown-menu via `lib/menu-indicator.css` (imported by eidos
entrypoint before this recipe). Override the private vars below if a
per-component tweak is needed. */
[data-context-menu-sub-trigger]::after {
content: '';
margin-inline-start: auto;
inline-size: 0.625rem;
block-size: 0.625rem;
border-inline-end: var(--context-menu-chevron-stroke) solid currentColor;
border-block-start: var(--context-menu-chevron-stroke) solid currentColor;
transform: rotate(45deg);
opacity: var(--opacity-muted);
}
/* ── Group / GroupHeading / Separator ─────────────────────────────── */
[data-context-menu-group] {
display: contents;
}
[data-context-menu-group-heading] {
padding-block: var(--context-menu-heading-padding-block, var(--space-1));
padding-inline: var(--context-menu-heading-padding-inline, var(--space-2));
color: var(--context-menu-heading-fg);
font-size: var(--context-menu-heading-font-size, var(--font-size-xs));
font-weight: var(--context-menu-heading-font-weight);
text-transform: uppercase;
letter-spacing: var(--context-menu-heading-letter-spacing);
}
[data-context-menu-separator] {
margin-block: var(--context-menu-separator-margin-block, var(--space-1));
block-size: 1px;
background: var(--context-menu-separator-bg, var(--color-border-subtle));
}
/* ── Trigger ──────────────────────────────────────────────────────── */
/*
* Default: no visual treatment. The Trigger is meant to feel inert
* until invoked. Consumers wrap whatever content they want
* right-clickable; the recipe stays out of the way.
*
* `data-state='open'` (set by soma when the menu is open) gets a
* subtle outline as a courtesy affordance — the user often forgets
* which area summoned the menu.
*/
[data-context-menu-trigger] {
display: inline-block;
}
[data-context-menu-trigger][data-state='open'] {
outline: var(--context-menu-open-trigger-outline-width) dashed var(--context-menu-open-trigger-outline);
outline-offset: 2px;
border-radius: var(--context-menu-open-trigger-radius);
}
/* ── Arrow ────────────────────────────────────────────────────────── */
/* Until 2026-08-12 this component rendered its own bare `<svg>` — polygon only,
no outline — instead of composing `soma/components/internal/arrow.svelte` like
the other five. Two of the system's seven arrows were drawn differently
(ledger D12). It composes the primitive now, so the shapes are addressed
inside the `<span>`: a `fill` on the wrapper cannot override the presentation
attributes the polygon/path carry. Same shape as tooltip / popover. */
[data-context-menu-arrow] svg {
display: block;
overflow: visible;
}
[data-context-menu-arrow] polygon {
/* The arrow is part of the elevation surface — consume the `overlay` plane so
it always matches the panel (A1, like popover), not a parallel token. */
fill: var(--depth-overlay-surface);
stroke: none;
}
/* The two exposed edges take the panel border; without it the matched caret
dissolves into the page. `non-scaling-stroke` because the 30×10 viewBox is
stretched with `preserveAspectRatio: none`, which would otherwise shrink the
stroke to a sub-pixel sliver. */
[data-context-menu-arrow] path {
stroke: var(--depth-overlay-border);
stroke-width: var(--border-width);
stroke-linejoin: round;
vector-effect: non-scaling-stroke;
}
/* ── State transitions ────────────────────────────────────────────── */
[data-context-menu-content][data-state='closed'],
[data-context-menu-sub-content][data-state='closed'] {
opacity: 0;
pointer-events: none;
}
/* Panel entrance/exit: the canonical `slide-fade` preset (side-aware, generated
from EidosConfig.motion), stamped by the wrapper as `data-animation-style`.
The local `context-menu-enter` keyframe it replaced lived outside the motion
channel (not themeable, no exit, no reduced-motion policy). */

Powered by TurnKey Linux.