From d87d40a4ccfbde4ca2aca3d6624e1a7427c76f94 Mon Sep 17 00:00:00 2001 From: Marek Martuszewski Date: Thu, 20 Aug 2026 14:43:41 +0200 Subject: [PATCH] style(runner): unify the editor shell and panels on the design's type/grid scales MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A design-alignment pass over the authoring shell and both drawers, built against Figma 48:6560 (light) / 31:6438 (dark) and the docs assistant: - Typography: one scale in theme.type (base 12/20, small 10/20, row 12/16, label 10/20+tracking) replacing ~50 ad-hoc sizes; sidebar rows raised to 12px by decision, category labels stay 10. - Spacing: 4px grid discipline (8px rhythm) across shell and app pages; geometry-locked exceptions documented inline. - Editor: Fira Code 12/20 (bundled via @fontsource), 16px inset, chromeless gutter, editorBg token over githubDark's #0d1117 (Prec.high — the theme prop outranks plain extensions); Mod-F search panel restyled to shell idiom. - Drawers: full-height, slide-in from the right, docs-assistant chrome; Ask AI transcript/composer restyled after the Docs assistant; Style panel aligned on the 24px inset with Theme Builder's row layout (label + info tooltip left, control right), floating pickers with Common/Pick-color tabs, muted-track segmented controllers, framed menu lists shared with the chat suggestions, dismissible intro notice, and the AI tab on the chat composer. - Classes over inline styles: Drawer registers its stylesheet via installCss; the panels' rules live in panels.css with tokens as CSS variables (--hot-font-* added); the ADR-0026 hover-vs-inline trap disappears with it. - Tooltips for the two toolbar CTAs share one treatment; thin scrollbars shell-wide; theme toggle moved between Download and the avatar; lighter hover token in light mode (0.16 -> 0.10). E2E updated where intent changed: full-height drawers cover the top-bar triggers (switching is keyboard-reachable, tests activate via Enter), the composer is transparent over the drawer surface, the edit box and token rows are located by class/data-token instead of inline-style sniffing. Co-Authored-By: Claude Fable 5 --- runner/apps/authoring/index.html | 18 + runner/apps/authoring/package.json | 1 + runner/apps/authoring/src/Admin.tsx | 58 +-- runner/apps/authoring/src/Chat.tsx | 167 +++----- runner/apps/authoring/src/DocsCascader.tsx | 6 +- runner/apps/authoring/src/Guide.tsx | 8 +- runner/apps/authoring/src/MarkdownField.tsx | 6 +- runner/apps/authoring/src/MyDemos.tsx | 2 +- runner/apps/authoring/src/StylePanel.tsx | 340 ++++++++------- runner/apps/authoring/src/main.tsx | 8 + runner/apps/authoring/src/markdown.tsx | 18 +- runner/apps/authoring/src/panels.css | 396 ++++++++++++++++++ runner/apps/authoring/src/theme/controls.tsx | 224 ++++++---- runner/e2e/panels.spec.ts | 27 +- runner/e2e/style-panel.spec.ts | 11 +- .../packages/editor-shell/src/AccountMenu.tsx | 2 +- runner/packages/editor-shell/src/BoxInfo.tsx | 16 +- .../packages/editor-shell/src/CodeEditor.tsx | 90 +++- .../editor-shell/src/Dependencies.tsx | 8 +- runner/packages/editor-shell/src/Drawer.tsx | 157 ++++--- .../packages/editor-shell/src/EditorTabs.tsx | 6 +- runner/packages/editor-shell/src/FileTree.tsx | 18 +- .../packages/editor-shell/src/PreviewBar.tsx | 15 +- .../packages/editor-shell/src/PreviewPane.tsx | 10 +- runner/packages/editor-shell/src/SideNav.tsx | 8 +- runner/packages/editor-shell/src/TopBar.tsx | 9 +- runner/packages/editor-shell/src/icons/ui.tsx | 8 + runner/packages/editor-shell/src/styles.ts | 22 +- runner/packages/editor-shell/src/theme.ts | 49 ++- runner/pnpm-lock.yaml | 8 + 30 files changed, 1172 insertions(+), 544 deletions(-) create mode 100644 runner/apps/authoring/src/panels.css diff --git a/runner/apps/authoring/index.html b/runner/apps/authoring/index.html index 871c95ffc..3d1a65a5c 100644 --- a/runner/apps/authoring/index.html +++ b/runner/apps/authoring/index.html @@ -232,6 +232,24 @@ outline: 2px solid var(--hot-color-accent); outline-offset: 1px; } + /* The Ask AI panel's rules (bubble tail, suggestion arrows, composer states) + live in src/panels.css, imported from main.tsx — this block keeps only what + must exist pre-React or is shared across panels. */ + /* Thin scrollbars, shell-wide. `scrollbar-color` is inherited, so the root + declaration reaches every scroller — sidebar, drawers, CodeMirror — but + `scrollbar-width` is *not* (measured: a nested scroller computes `auto`), + hence the universal selector. Zero specificity, so `.hot-tab-strip`'s `none` + below still wins. The ::-webkit-* pseudos are for Safari only: Chrome + disables them the moment the standard properties are set, and Firefox never + reads them. Track mirrors the surface, thumb the border, so the bar sits in + the chrome instead of on top of it. Before React emits the custom properties + the var()s are unset and the UA default paints — one frame, unstyled, not + broken. */ + * { scrollbar-width: thin; } + html { scrollbar-color: var(--hot-color-border) var(--hot-color-surface); } + ::-webkit-scrollbar { width: 8px; height: 8px; } + ::-webkit-scrollbar-track { background: var(--hot-color-surface); } + ::-webkit-scrollbar-thumb { background: var(--hot-color-border); border-radius: 4px; } /* The strip scrolls when the open files outgrow it. Both properties: the WebKit pseudo-element alone still leaves a scrollbar in Firefox, and a 36px bar has no room for one — it would sit on the strip's inset hairline. */ diff --git a/runner/apps/authoring/package.json b/runner/apps/authoring/package.json index 084980df6..dbed4293f 100644 --- a/runner/apps/authoring/package.json +++ b/runner/apps/authoring/package.json @@ -10,6 +10,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { + "@fontsource/fira-code": "^5.3.0", "@handsontable/demo-editor-shell": "workspace:*", "@handsontable/demo-runtime": "workspace:*", "@sentry/react": "^10.68.0", diff --git a/runner/apps/authoring/src/Admin.tsx b/runner/apps/authoring/src/Admin.tsx index 64243e699..f3bd90722 100644 --- a/runner/apps/authoring/src/Admin.tsx +++ b/runner/apps/authoring/src/Admin.tsx @@ -297,7 +297,7 @@ export function AdminPanel({ apiBase, token }: AdminPanelProps) { const rows = dailyMetric(report.usage, metric); if (!rows.length) return null; return ( -
+
{METRIC_LABEL[metric] ?? metric}
@@ -444,8 +444,8 @@ function SettingsForm({ }, [settings]); const field = (key: keyof BudgetSettings, label: string, hint: string) => ( -