From 5dc67c3bd4f84b00c589a7504828860df90176a3 Mon Sep 17 00:00:00 2001
From: Amruth Pillai
Date: Tue, 29 Sep 2026 08:17:12 +0200
Subject: [PATCH] fix(web): restyle the custom CSS editor in the app's inks and
show its toolbar icons
---
apps/web/package.json | 1 +
.../src/features/resume/stylesheet/editor.tsx | 19 ++++++++++++++++---
.../resume/stylesheet/legacy-banner.tsx | 2 +-
.../src/features/resume/stylesheet/status.tsx | 6 +++---
.../features/resume/stylesheet/toolbar.tsx | 14 +++++---------
packages/ui/src/components/icon.test.tsx | 5 +++++
packages/ui/src/components/icon.tsx | 3 ++-
pnpm-lock.yaml | 3 +++
8 files changed, 36 insertions(+), 17 deletions(-)
diff --git a/apps/web/package.json b/apps/web/package.json
index 61bbb0d14..6bd361a9c 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -34,6 +34,7 @@
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@fontsource-variable/manrope": "^5.3.0",
+ "@lezer/highlight": "^1.2.4",
"@lingui/core": "^6.8.0",
"@lingui/react": "^6.8.0",
"@orpc/client": "^1.15.4",
diff --git a/apps/web/src/features/resume/stylesheet/editor.tsx b/apps/web/src/features/resume/stylesheet/editor.tsx
index c8830710a..2d55afd11 100644
--- a/apps/web/src/features/resume/stylesheet/editor.tsx
+++ b/apps/web/src/features/resume/stylesheet/editor.tsx
@@ -6,7 +6,7 @@ import type { SemanticCssColorToken } from "./color-tokens";
import type { SemanticCssEditorMetadata } from "./protocol";
import { defaultKeymap, indentWithTab } from "@codemirror/commands";
import { css } from "@codemirror/lang-css";
-import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
+import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
import { Annotation, Compartment, EditorState, Prec, Transaction } from "@codemirror/state";
import {
drawSelection,
@@ -16,6 +16,7 @@ import {
keymap,
lineNumbers,
} from "@codemirror/view";
+import { tags } from "@lezer/highlight";
import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -54,6 +55,18 @@ type EditorCompartments = {
intelligence: Compartment;
};
+/** CSS in the app's own inks, so it reads the same in light and dark. */
+const highlightStyle = HighlightStyle.define([
+ { tag: [tags.comment, tags.meta], color: "var(--ink-3)", fontStyle: "italic" },
+ { tag: [tags.tagName, tags.className, tags.labelName], color: "var(--accent-text)" },
+ { tag: [tags.propertyName, tags.attributeName], color: "var(--info-text)" },
+ { tag: [tags.string, tags.number, tags.unit, tags.color, tags.atom], color: "var(--warn-text)" },
+ { tag: [tags.keyword, tags.modifier, tags.definitionKeyword, tags.controlKeyword], color: "var(--danger-text)" },
+ { tag: [tags.variableName, tags.function(tags.variableName)], color: "var(--ink)", fontWeight: "500" },
+ { tag: [tags.punctuation, tags.operator, tags.bracket], color: "var(--ink-2)" },
+ { tag: tags.invalid, color: "var(--danger-text)", textDecoration: "underline wavy" },
+]);
+
const editorTheme = (dark: boolean): Extension =>
EditorView.theme(
{
@@ -65,7 +78,7 @@ const editorTheme = (dark: boolean): Extension =>
},
".cm-scroller": {
overflow: "auto",
- fontFamily: '"JetBrains Mono Variable", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
+ fontFamily: "var(--font-mono)",
lineHeight: "1.5",
},
".cm-content": { minHeight: "100%", padding: "0.75rem 0" },
@@ -162,7 +175,7 @@ export function StylesheetCodeEditor({
drawSelection(),
highlightActiveLine(),
css(),
- syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
+ syntaxHighlighting(highlightStyle),
EditorView.editorAttributes.of({ dir: "ltr" }),
EditorView.contentAttributes.of({ "aria-label": initial.label, dir: "ltr", spellcheck: "false" }),
Prec.high(
diff --git a/apps/web/src/features/resume/stylesheet/legacy-banner.tsx b/apps/web/src/features/resume/stylesheet/legacy-banner.tsx
index 8934da52c..e5160df5d 100644
--- a/apps/web/src/features/resume/stylesheet/legacy-banner.tsx
+++ b/apps/web/src/features/resume/stylesheet/legacy-banner.tsx
@@ -21,7 +21,7 @@ export function LegacyStylesheetBanner({ disabled, onActivate }: LegacyStyleshee
diff --git a/apps/web/src/features/resume/stylesheet/status.tsx b/apps/web/src/features/resume/stylesheet/status.tsx
index 70acafc6b..11e93d3e0 100644
--- a/apps/web/src/features/resume/stylesheet/status.tsx
+++ b/apps/web/src/features/resume/stylesheet/status.tsx
@@ -23,19 +23,19 @@ export function StylesheetStatus({ mode, status, diagnostics }: StylesheetStatus
{hasFatalErrors ? (
-
+
Fatal error
) : isPending ? (
{mode === "legacy" ? Checking draft : Checking}
) : hasRecoverableErrors ? (
-
+
{mode === "legacy" ? Ready to activate with errors : Valid with errors}
) : warnings.length > 0 ? (
-
+
{mode === "legacy" ? Ready to activate with warnings : Valid with warnings}
) : (
diff --git a/apps/web/src/features/resume/stylesheet/toolbar.tsx b/apps/web/src/features/resume/stylesheet/toolbar.tsx
index 90b73022f..fe734b66f 100644
--- a/apps/web/src/features/resume/stylesheet/toolbar.tsx
+++ b/apps/web/src/features/resume/stylesheet/toolbar.tsx
@@ -52,23 +52,19 @@ export function StylesheetToolbar({
return (
-
+
-
+
void copySourceToClipboard(source)}>
-
+
-
+
- {focused ? (
-
- ) : (
-
- )}
+ {focused ? : }
);
diff --git a/packages/ui/src/components/icon.test.tsx b/packages/ui/src/components/icon.test.tsx
index 56d212a9b..42c2c4e6c 100644
--- a/packages/ui/src/components/icon.test.tsx
+++ b/packages/ui/src/components/icon.test.tsx
@@ -19,6 +19,11 @@ describe("Icon", () => {
expect(container.querySelector("button")).toHaveTextContent(/^Search$/);
});
+ it("keeps its glyph when a caller passes its own data-icon", () => {
+ const { container } = render(
);
+ expect(container.querySelector('[data-slot="icon"]')).toHaveAttribute("data-icon", "undo");
+ });
+
it("uses the filled glyph only when asked", () => {
const { container } = render(
);
expect(container.querySelector('[data-slot="icon"]')?.getAttribute("style")).toContain('"FILL" 1');
diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx
index 0102ffbd3..8e2398fef 100644
--- a/packages/ui/src/components/icon.tsx
+++ b/packages/ui/src/components/icon.tsx
@@ -29,6 +29,8 @@ function Icon({ name, filled = false, size = 20, className, style, ...props }: I
= 24 ? 24 : 20}`,
...style,
}}
- {...props}
/>
);
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 02c7f61f6..aaab17ffb 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -549,6 +549,9 @@ importers:
'@fontsource-variable/manrope':
specifier: ^5.3.0
version: 5.3.0
+ '@lezer/highlight':
+ specifier: ^1.2.4
+ version: 1.2.4
'@lingui/core':
specifier: ^6.8.0
version: 6.8.0(@babel/core@8.0.6)(babel-plugin-macros@3.1.0)