diff --git a/packages/app/e2e/regression/workspace-accent.spec.ts b/packages/app/e2e/regression/workspace-accent.spec.ts index 5394cc4a911..cfe6f1542c4 100644 --- a/packages/app/e2e/regression/workspace-accent.spec.ts +++ b/packages/app/e2e/regression/workspace-accent.spec.ts @@ -75,11 +75,12 @@ for (const theme of ["light", "dark"] as const) { await expectBackground(view.send, "contrast") const message = page.locator('[data-slot="user-message-text"]') await expect(message).toHaveText("Check this fixture workspace.") - await expectBackground( + await expectToken( message, - scenario.accent ? "accent" : theme === "light" ? "layer-02" : "layer-01", "background-color", + scenario.accent ? "--v2-background-bg-accent" : "--v2-state-bg-info", ) + await expectToken(message, "color", scenario.accent ? "--v2-text-text-contrast" : "--v2-text-text-accent") }) } @@ -245,3 +246,16 @@ async function expectBackground(element: Locator, token: string, property = "bac }, token) await expect(element).toHaveCSS(property, new RegExp(color.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))) } + +async function expectToken(element: Locator, property: string, token: string) { + const color = await element.evaluate((element, token) => { + const probe = document.createElement("span") + probe.hidden = true + probe.style.color = `var(${token})` + element.append(probe) + const color = getComputedStyle(probe).color + probe.remove() + return color + }, token) + await expect(element).toHaveCSS(property, color) +} diff --git a/packages/app/src/runtime/server/errors.test.ts b/packages/app/src/runtime/server/errors.test.ts index 6a8e34eb082..2634bb156b8 100644 --- a/packages/app/src/runtime/server/errors.test.ts +++ b/packages/app/src/runtime/server/errors.test.ts @@ -155,6 +155,16 @@ describe("isSessionNotFoundError", () => { expect(isSessionNotFoundError(new Error(body.message, { cause: { body, status: 404 } }), body.sessionID)).toBe(true) }) + test("matches a structured error stored directly as the cause", () => { + const body = { + _tag: "SessionNotFoundError", + sessionID: "ses_missing", + message: "Session not found", + } satisfies SessionNotFoundError + + expect(isSessionNotFoundError(new Error("Unknown error", { cause: body }), body.sessionID)).toBe(true) + }) + test("rejects errors for other sessions and other 404 responses", () => { const body = { _tag: "SessionNotFoundError", diff --git a/packages/app/src/runtime/server/errors.ts b/packages/app/src/runtime/server/errors.ts index 6186f005342..71cbbf8ca83 100644 --- a/packages/app/src/runtime/server/errors.ts +++ b/packages/app/src/runtime/server/errors.ts @@ -36,10 +36,9 @@ export function formatServerError(error: unknown, translate?: Translator, fallba } function unwrapNamedError(error: unknown): unknown { - if (error instanceof Error && error.cause && typeof error.cause === "object" && "body" in error.cause) { - return (error.cause as Record).body - } - return error + if (!(error instanceof Error) || !error.cause || typeof error.cause !== "object") return error + if ("body" in error.cause) return (error.cause as Record).body + return error.cause } // Client-synthesized session not-found errors share one constructor and diff --git a/packages/app/src/session/timeline/virtualizer.tsx b/packages/app/src/session/timeline/virtualizer.tsx index c41d79e6fff..d27bfcd8221 100644 --- a/packages/app/src/session/timeline/virtualizer.tsx +++ b/packages/app/src/session/timeline/virtualizer.tsx @@ -478,7 +478,11 @@ export function createTimelineVirtualizer(input: Input) { } return ( -
+
{ + const probe = document.createElement("span") + probe.style.color = `var(${token})` + document.body.append(probe) + const color = getComputedStyle(probe).color + probe.remove() + return color + }, token) +} + story("keeps inline code backgrounds 18px tall", async ({ page }) => { await page.evaluate(async (fixture) => { const { mountMarkdown } = await import(fixture) diff --git a/packages/session-ui/src/components/markdown.css b/packages/session-ui/src/components/markdown.css index f0e91e35eb8..317f9b2bad0 100644 --- a/packages/session-ui/src/components/markdown.css +++ b/packages/session-ui/src/components/markdown.css @@ -1,5 +1,6 @@ [data-component="markdown"] { - --markdown-inline-code-path-color: var(--v2-text-text-code-accent); + --markdown-inline-code-path-color: var(--v2-text-text-code-path); + --markdown-inline-code-path-background: var(--v2-background-bg-code-path); --markdown-inline-code-color: var(--v2-text-text-code-accent); --markdown-inline-code-bg-mix: 8%; --markdown-shell-code-background: var(--v2-background-bg-layer-02); @@ -290,11 +291,7 @@ :not(pre) > code[data-inline-code-kind="path"] { color: var(--markdown-inline-code-path-color); - background: color-mix( - in oklch, - var(--markdown-inline-code-path-color) var(--markdown-inline-code-bg-mix), - transparent - ); + background: var(--markdown-inline-code-path-background); } a.external-link > code[data-inline-code-kind="url"] { diff --git a/packages/session-ui/src/components/message-part.css b/packages/session-ui/src/components/message-part.css index a81f9b0a40e..ff2440e4441 100644 --- a/packages/session-ui/src/components/message-part.css +++ b/packages/session-ui/src/components/message-part.css @@ -1547,3 +1547,9 @@ background: var(--v2-background-bg-accent); color: var(--v2-text-text-contrast); } + +:root body [data-local-session] [data-component="user-message"] [data-slot="user-message-text"] { + background: var(--v2-state-bg-info); + color: var(--v2-text-text-accent); + border-radius: 8px; +} diff --git a/packages/ui/src/styles/tokens/theme.css b/packages/ui/src/styles/tokens/theme.css index 41593dfff32..09764982c9c 100644 --- a/packages/ui/src/styles/tokens/theme.css +++ b/packages/ui/src/styles/tokens/theme.css @@ -13,6 +13,7 @@ --v2-background-bg-contrast: var(--v2-grey-1000); --v2-background-bg-button-neutral: var(--v2-grey-50); --v2-background-bg-accent: var(--v2-blue-600); + --v2-background-bg-code-path: var(--v2-cyan-100); /* ── Text ── */ --v2-text-text-base: var(--v2-grey-1100); @@ -23,6 +24,7 @@ --v2-text-text-accent: var(--v2-blue-600); --v2-text-text-accent-hover: var(--v2-blue-700); --v2-text-text-code-accent: var(--v2-blue-900); + --v2-text-text-code-path: var(--v2-cyan-900); /* ── Icon ── */ --v2-icon-icon-base: var(--v2-grey-800); @@ -151,6 +153,7 @@ --v2-background-bg-contrast: var(--v2-grey-700); --v2-background-bg-button-neutral: var(--v2-alpha-light-6); --v2-background-bg-accent: var(--v2-blue-600); + --v2-background-bg-code-path: var(--v2-cyan-1200); --v2-text-text-base: var(--v2-grey-200); --v2-text-text-muted: var(--v2-grey-500); @@ -160,6 +163,7 @@ --v2-text-text-accent: var(--v2-blue-400); --v2-text-text-accent-hover: var(--v2-blue-300); --v2-text-text-code-accent: var(--v2-blue-400); + --v2-text-text-code-path: var(--v2-cyan-400); --v2-icon-icon-base: var(--v2-grey-400); --v2-icon-icon-muted: var(--v2-grey-600); @@ -265,6 +269,7 @@ --v2-background-bg-contrast: var(--v2-grey-1000); --v2-background-bg-button-neutral: var(--v2-grey-50); --v2-background-bg-accent: var(--v2-blue-600); + --v2-background-bg-code-path: var(--v2-cyan-100); --v2-text-text-base: var(--v2-grey-1100); --v2-text-text-muted: var(--v2-grey-700); @@ -274,6 +279,7 @@ --v2-text-text-accent: var(--v2-blue-600); --v2-text-text-accent-hover: var(--v2-blue-700); --v2-text-text-code-accent: var(--v2-blue-900); + --v2-text-text-code-path: var(--v2-cyan-900); --v2-icon-icon-base: var(--v2-grey-800); --v2-icon-icon-muted: var(--v2-grey-600); @@ -388,6 +394,7 @@ --v2-background-bg-contrast: var(--v2-grey-700); --v2-background-bg-button-neutral: var(--v2-alpha-light-6); --v2-background-bg-accent: var(--v2-blue-600); + --v2-background-bg-code-path: var(--v2-cyan-1200); --v2-text-text-base: var(--v2-grey-100); --v2-text-text-muted: var(--v2-grey-500); @@ -397,6 +404,7 @@ --v2-text-text-accent: var(--v2-blue-400); --v2-text-text-accent-hover: var(--v2-blue-300); --v2-text-text-code-accent: var(--v2-blue-400); + --v2-text-text-code-path: var(--v2-cyan-400); --v2-icon-icon-base: var(--v2-grey-400); --v2-icon-icon-muted: var(--v2-grey-600); diff --git a/packages/ui/src/theme/v2/mapping.ts b/packages/ui/src/theme/v2/mapping.ts index e019fa466ef..1af6ee38be3 100644 --- a/packages/ui/src/theme/v2/mapping.ts +++ b/packages/ui/src/theme/v2/mapping.ts @@ -42,11 +42,13 @@ const light: Record = { "v2-background-bg-contrast": ref("v2-grey-900"), "v2-background-bg-button-neutral": ref("v2-grey-100"), "v2-background-bg-accent": ref("v2-blue-600"), + "v2-background-bg-code-path": ref("v2-cyan-100"), "v2-text-text-inverse": ref("v2-grey-100"), "v2-text-text-contrast": ref("v2-grey-100"), "v2-text-text-accent": ref("v2-blue-600"), "v2-text-text-accent-hover": ref("v2-blue-700"), "v2-text-text-code-accent": ref("v2-blue-900"), + "v2-text-text-code-path": ref("v2-cyan-900"), "v2-border-border-muted": ref("v2-alpha-dark-8"), "v2-border-border-base": ref("v2-alpha-dark-10"), "v2-border-border-strong": ref("v2-alpha-dark-20"), @@ -107,11 +109,13 @@ const dark: Record = { "v2-background-bg-contrast": ref("v2-grey-700"), "v2-background-bg-button-neutral": ref("v2-alpha-light-6"), "v2-background-bg-accent": ref("v2-blue-600"), + "v2-background-bg-code-path": ref("v2-cyan-1200"), "v2-text-text-inverse": ref("v2-grey-1000"), "v2-text-text-contrast": ref("v2-grey-100"), "v2-text-text-accent": ref("v2-blue-400"), "v2-text-text-accent-hover": ref("v2-blue-300"), "v2-text-text-code-accent": ref("v2-blue-400"), + "v2-text-text-code-path": ref("v2-cyan-400"), "v2-border-border-muted": ref("v2-alpha-light-8"), "v2-border-border-base": ref("v2-alpha-light-10"), "v2-border-border-strong": ref("v2-alpha-light-20"),