From 236b1c8a3747e62b211b5ddcda440b07e4a180ea Mon Sep 17 00:00:00 2001 From: Oleh Omelchenko Date: Sun, 14 Jun 2026 01:25:58 +0300 Subject: [PATCH] Chart tooltip: app-owned token styling, drop vega-tooltip's default sheet --- src/app/services/chart-renderer.ts | 8 ++++ styles/base.css | 66 ++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/app/services/chart-renderer.ts b/src/app/services/chart-renderer.ts index faea204..e6766af 100644 --- a/src/app/services/chart-renderer.ts +++ b/src/app/services/chart-renderer.ts @@ -173,6 +173,14 @@ export async function renderSpec( actions: false, // Astrolabe owns its own export/copy affordances renderer, config, + // Suppress vega-tooltip's bundled light/dark stylesheet so the app owns the + // tooltip's look. With the default style gone, the single `#vg-tooltip-element` + // it appends to is styled entirely from our design tokens in base.css — + // surface, type, and the key/value table — and follows `[data-theme]` for free + // (the element inherits the cascade from ). vega-tooltip still positions + // the element (inline top/left) and toggles `.visible`; our CSS supplies the + // structural rules (position/visibility/z-index) the default sheet used to. + tooltip: { disableDefaultStyle: true }, }); return { diff --git a/styles/base.css b/styles/base.css index cd9064e..cb27715 100644 --- a/styles/base.css +++ b/styles/base.css @@ -107,6 +107,72 @@ body { } } +/* + * Chart tooltip (vega-tooltip). The renderer disables vega-tooltip's bundled + * stylesheet (chart-renderer `disableDefaultStyle`), so the look is ours: an + * elevated surface matching the popover recipe (--layer-01 + border + shadow, + * square corners), in Plex, with the data laid out as a quiet key/value table. + * vega-tooltip appends one `#vg-tooltip-element` to and positions it + * inline; these rules supply everything the default sheet did — position, + * visibility toggle, z-index — plus the visual styling. Tokens cascade from + * , so the tooltip follows the active theme without a class. + */ +#vg-tooltip-element { + visibility: hidden; + position: fixed; + /* Cursor-following overlay: the topmost ephemeral layer. Must clear the feature + modal (900) that hosts the Chart Builder preview, toasts (1100), and an open + select (2000) — none of which it ever needs to sit beneath. */ + z-index: 2100; + padding: var(--space-3) var(--space-4); + background: var(--layer-01); + border: var(--border-width) solid var(--border); + border-radius: var(--radius); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); + font-family: var(--font-sans); + font-size: 12px; + line-height: 1.3; + color: var(--text); +} + +#vg-tooltip-element.visible { + visibility: visible; +} + +/* Title — shown when a tooltip channel resolves to a single labeled value. */ +#vg-tooltip-element h2 { + margin: 0 0 var(--space-2); + font-size: 12px; + font-weight: 600; +} + +#vg-tooltip-element table { + border-spacing: 0; +} + +#vg-tooltip-element td { + padding: var(--space-1) 0; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Field name: quiet, right-aligned against its value. */ +#vg-tooltip-element td.key { + max-width: 150px; + padding-inline-end: var(--space-3); + text-align: right; + color: var(--text-secondary); +} + +/* Value: primary text; tabular figures keep numeric columns aligned. */ +#vg-tooltip-element td.value { + display: block; + max-width: 300px; + max-height: 7em; + text-align: left; + font-variant-numeric: tabular-nums; +} + /* * Visually-hidden but available to assistive tech — the standard sr-only recipe. * Used for polite `aria-live`/`role="status"` announcements whose visible