diff --git a/e2e/work-companion.playwright.ts b/e2e/work-companion.playwright.ts index a8761d4..5494fbd 100644 --- a/e2e/work-companion.playwright.ts +++ b/e2e/work-companion.playwright.ts @@ -159,6 +159,34 @@ test('uses a focused reading column and a compact authored-message shape', async expect(authoredBox!.width).toBeLessThanOrEqual(680) expect(authoredBox!.x + authoredBox!.width).toBeCloseTo(answerBox!.x + answerBox!.width, 0) + const surfaces = await page.evaluate(() => { + const pick = (selector: string) => { + const element = document.querySelector(selector) + if (!element) throw new Error(`missing ${selector}`) + const style = getComputedStyle(element) + return { + background: style.backgroundColor, + color: style.color, + borderRadius: Number.parseFloat(style.borderRadius), + paddingLeft: Number.parseFloat(style.paddingLeft), + } + } + return { + chrome: pick('.companion-topbar'), + context: pick('.left-nav'), + conversation: pick('.main'), + answer: pick('.msg.assistant'), + authored: pick('.msg.user .bubble'), + } + }) + const rgb = (value: string) => value.match(/[\d.]+/g)?.slice(0, 3).map(Number) ?? [0, 0, 0] + const distance = (a: string, b: string) => rgb(a).reduce((sum, value, index) => sum + Math.abs(value - rgb(b)[index]), 0) + expect(distance(surfaces.chrome.background, surfaces.conversation.background)).toBeGreaterThan(300) + expect(distance(surfaces.context.background, surfaces.conversation.background)).toBeGreaterThan(300) + expect(distance(surfaces.authored.background, surfaces.answer.background)).toBeGreaterThan(300) + expect(surfaces.answer.borderRadius).toBeGreaterThanOrEqual(12) + expect(surfaces.answer.paddingLeft).toBeGreaterThanOrEqual(20) + const activeCard = page.locator('.right-panel .acard.status-active') await expect(activeCard).toBeVisible() const cardStyle = await activeCard.evaluate(element => { diff --git a/src/companion-conversation.css b/src/companion-conversation.css index 1fbfc6d..e8697ea 100644 --- a/src/companion-conversation.css +++ b/src/companion-conversation.css @@ -57,6 +57,13 @@ margin-right: max(0px, calc((100% - 840px) / 2)); margin-left: auto; } +.work-companion-chat .chat-body > .msg.assistant { + padding: 20px 24px 16px; + border: 1px solid var(--border); + border-radius: var(--radius-xl); + background: var(--bg-raised); + box-shadow: var(--shadow-md); +} .work-companion-chat .msg-role { margin-bottom: 10px; color: var(--text-dim); @@ -131,10 +138,12 @@ .work-companion-chat .msg.user .bubble { padding: 14px 18px; - background: var(--bg-active); - border: 1px solid var(--border-soft); + background: var(--primary); + border: 1px solid var(--primary); border-radius: var(--radius-lg) var(--radius-lg) var(--radius-xs) var(--radius-lg); + color: var(--primary-foreground); line-height: 1.7; + box-shadow: var(--shadow-md); } .work-companion-chat .process-collapse { margin: 12px 0 16px; diff --git a/src/companion-shell.css b/src/companion-shell.css index f224265..fc4cc0d 100644 --- a/src/companion-shell.css +++ b/src/companion-shell.css @@ -3,12 +3,48 @@ height: 100dvh; min-width: 0; max-width: 100%; + --companion-chrome: var(--primary); + --companion-chrome-text: var(--primary-foreground); + --companion-chrome-dim: color-mix(in srgb, var(--primary-foreground) 72%, transparent); + --companion-chrome-faint: color-mix(in srgb, var(--primary-foreground) 52%, transparent); + --companion-chrome-hover: color-mix(in srgb, var(--primary-foreground) 9%, transparent); + --companion-chrome-active: color-mix(in srgb, var(--primary-foreground) 15%, transparent); +} +[data-theme='dark'] .app.companion-app { + --companion-chrome: var(--bg-panel); + --companion-chrome-text: var(--text); + --companion-chrome-dim: var(--text-dim); + --companion-chrome-faint: var(--text-faint); + --companion-chrome-hover: var(--bg-hover); + --companion-chrome-active: var(--bg-active); +} +[data-theme='molv'] .app.companion-app { + --companion-chrome: var(--bg-sidebar); + --companion-chrome-text: var(--text-sidebar); + --companion-chrome-dim: var(--text-sidebar-dim); + --companion-chrome-faint: var(--text-sidebar-faint); + --companion-chrome-hover: var(--bg-hover); + --companion-chrome-active: var(--bg-active); } .companion-app .app-body { min-width: 0; overflow: hidden; } .companion-app .left-nav, .companion-app .main, .companion-app .right-panel { min-height: 0; max-width: 100%; overflow: hidden; } +.companion-app .left-nav, +.companion-app .companion-topbar { + --text: var(--companion-chrome-text); + --text-dim: var(--companion-chrome-dim); + --text-faint: var(--companion-chrome-faint); + --bg-hover: var(--companion-chrome-hover); + --bg-active: var(--companion-chrome-active); + --border: var(--companion-chrome-active); + --border-soft: var(--companion-chrome-hover); + --border-strong: var(--companion-chrome-dim); + background: var(--companion-chrome); + color: var(--companion-chrome-text); + border-color: var(--companion-chrome-hover); +} .companion-app .left-nav { transition: none; } .companion-app .left-nav[hidden], .companion-app .right-panel[hidden], @@ -66,8 +102,8 @@ .companion-app .right-panel .acard-summary-row p, .companion-app .right-panel .acard-findings li { color: var(--text); font-size: var(--fs-ui-base); } .companion-topbar .brand-mark { - background: var(--primary-sidebar); - color: var(--primary-sidebar-foreground); + background: var(--companion-chrome-text); + color: var(--companion-chrome); box-shadow: none; border-radius: var(--radius-sm) !important; } @@ -83,22 +119,22 @@ border: none; border-radius: var(--radius-sm); background: none; - color: var(--text-sidebar-dim); + color: var(--companion-chrome-dim); font-size: var(--fs-ui-caption); cursor: pointer; white-space: nowrap; } .shell-nav-button:hover, -.shell-return:hover { background: var(--bg-hover); color: var(--text-sidebar); } -.shell-nav-button[aria-pressed='true'] { background: var(--bg-active); color: var(--text-sidebar); } +.shell-return:hover { background: var(--companion-chrome-hover); color: var(--companion-chrome-text); } +.shell-nav-button[aria-pressed='true'] { background: var(--companion-chrome-active); color: var(--companion-chrome-text); } .shell-nav-button svg, .shell-return svg { flex: none; } .shell-back-icon { transform: rotate(180deg); } .shell-pending { padding: 0 4px; border-radius: var(--radius-xs); - background: var(--bg-active); - color: var(--text-sidebar); + background: var(--companion-chrome-active); + color: var(--companion-chrome-text); font-size: var(--fs-ui-xs); font-variant-numeric: tabular-nums; } @@ -110,11 +146,19 @@ .companion-app .tsb-projrow-stage { max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-dim); border-radius: var(--radius-sm); } .companion-app .tsb-iconbtn { width: 32px; height: 32px; flex: none; } .companion-app .tsb-actions { padding: 12px 14px; gap: 10px; } -.companion-app .tsb-newtask { min-height: 40px; height: auto; box-shadow: none; transition: none; } +.companion-app .tsb-newtask { + min-height: 40px; + height: auto; + background: var(--companion-chrome-text); + color: var(--companion-chrome); + box-shadow: none; + transition: none; +} +.companion-app .tsb-newtask:hover { background: color-mix(in srgb, var(--companion-chrome-text) 90%, var(--companion-chrome)); } .companion-app .tsb-newtask-main { justify-content: center; padding: 8px 12px; } .companion-app .tsb-newtask-caret { width: 36px; flex: none; } -.companion-app .tsb-search { min-height: 38px; height: auto; padding: 8px 12px; background: var(--bg-hover); border-color: transparent; } -.companion-app .tsb-search:focus-within { background: var(--bg-panel); } +.companion-app .tsb-search { min-height: 38px; height: auto; padding: 8px 12px; background: var(--companion-chrome-hover); border-color: var(--companion-chrome-hover); } +.companion-app .tsb-search:focus-within { background: var(--companion-chrome-active); border-color: var(--companion-chrome-dim); } .companion-app .tsb-orgrow { padding: 4px 16px 8px; } .companion-app .tsb-seclabel { color: var(--text-dim); font-size: var(--fs-ui-sm); font-weight: 600; } .companion-app .tsb-scroll { padding: 0 8px 12px; } @@ -154,7 +198,7 @@ cursor: pointer; } .companion-app .tsb-row-menu:hover { background: var(--bg-hover); color: var(--text); } -.companion-app .tsb-bottom { padding: 10px 12px; gap: 4px; background: var(--bg-hover); } +.companion-app .tsb-bottom { padding: 10px 12px; gap: 4px; background: var(--companion-chrome-hover); } .companion-app .tsb-tool { min-height: 38px; padding: 7px 10px; } .companion-app .tsb-avatar { background: var(--bg-active); color: var(--text); box-shadow: none; border-radius: var(--radius-full); } .companion-app .tsb-user-sub { color: var(--text-dim); }