From 1702948a7ed477140fcee69f122a3019a7c648a1 Mon Sep 17 00:00:00 2001 From: Zack Nelson Date: Tue, 1 Sep 2026 18:19:23 +0100 Subject: [PATCH] feat: lift light surfaces and neutralize chrome hover and focus WIP theme pass: compress the light elevation ramp, quiet shadows, and rebind hover/focus/selection off brand so crimson stays on tabs, notebook identity, and primary actions. Co-authored-by: Cursor --- THEME-STEERING.md | 286 ++++++++++++++++++ .../AssistantModesCompact.tsx | 2 +- src/components/Button/index.tsx | 2 +- src/components/Drawer/content-wrapper.tsx | 2 +- src/components/Drawer/index.tsx | 4 +- src/components/Form/FormInput/index.tsx | 3 + src/components/Input/index.tsx | 8 +- src/components/ResultGrid/styles.ts | 16 +- src/components/SegmentedControl/index.tsx | 7 +- src/components/SelectMenu/index.tsx | 2 +- src/components/Sidebar/index.tsx | 4 +- src/components/TableSelector/index.tsx | 12 +- src/components/Tooltip/index.tsx | 4 +- .../TopBar/InstanceSettingsPopper.tsx | 2 +- src/components/TopBar/index.tsx | 2 +- src/modules/OAuth2/views/login.tsx | 7 +- src/scenes/Console/index.tsx | 3 +- .../AIChatWindow/AIChatErrorBoundary.tsx | 2 +- .../Editor/AIChatWindow/AIChatWindowLazy.tsx | 2 +- .../Editor/AIChatWindow/ChatHistoryItem.tsx | 12 +- .../Editor/AIChatWindow/ChatHistoryView.tsx | 2 +- src/scenes/Editor/AIChatWindow/ChatInput.tsx | 4 +- .../Editor/AIChatWindow/ChatMessages.tsx | 5 +- src/scenes/Editor/AIChatWindow/index.tsx | 4 +- src/scenes/Editor/Menu/index.tsx | 2 +- src/scenes/Editor/Monaco/tabs.tsx | 7 +- .../Editor/Notebook/NotebookToolbar.tsx | 5 +- .../Notebook/cells/CellRunDrawToggles.tsx | 5 +- .../Editor/Notebook/cells/CellToolbar.tsx | 17 +- .../Editor/Notebook/cells/CellViewToggle.tsx | 7 + .../Editor/Notebook/cells/CellWrapper.tsx | 7 +- src/scenes/Layout/warning.tsx | 2 +- src/scenes/Schema/Row/index.tsx | 10 +- src/scenes/Schema/VirtualTables/index.tsx | 4 +- src/scenes/Schema/index.tsx | 6 + src/scenes/Search/SearchPanel.tsx | 12 +- src/scenes/Search/SearchResults.tsx | 8 +- src/scenes/SideMenu/index.tsx | 2 +- src/styles/_editor.scss | 2 +- src/styles/_grid.scss | 2 +- src/styles/_quick-vis.scss | 2 +- src/styles/lib/_react-chrome-tabs.scss | 24 +- src/styles/main.scss | 2 +- src/theme/global-styles.ts | 6 +- src/theme/global-styles/docsearch.ts | 2 +- src/theme/index.ts | 52 ++-- 46 files changed, 479 insertions(+), 104 deletions(-) create mode 100644 THEME-STEERING.md diff --git a/THEME-STEERING.md b/THEME-STEERING.md new file mode 100644 index 000000000..865b7a601 --- /dev/null +++ b/THEME-STEERING.md @@ -0,0 +1,286 @@ +# Theme steering log + +Designer-owned trail of palette experiments. `THEMING.md` stays the contract +until Emre reviews an entry and folds it in. + +Two lifts only: + +| Lift | What it is | Where it lands | Emre’s job | +| --- | --- | --- | --- | +| **Palette** | Retune an existing role in one or both themes | `src/theme/index.ts` only | Check neighbors in both modes, then update `THEMING.md` values | +| **Binding** | This component is using the wrong role, or needs a new role | Component file + maybe a new token in `index.ts` | Confirm the meaning, rebind, add the token only if reuse would lie | + +Palette is the default. Binding is the exception — including “brand crimson is +doing a job it should not.” Do not invent a component-named color +(`notebookCellBackground`). Either retune `surfaceRaised`, rebind the component +to a different existing role, or add a role whose *meaning* is new. + +Status: `applied locally` → `ready for Emre` → `accepted` / `tweaked` / `reverted`. + +--- + +## Entry template + +Copy this block. One decision per entry. If a palette change and a binding +change shipped together, split them. + +``` +### YYYY-MM-DD — short name +- Lift: palette | binding | palette + binding +- Status: applied locally +- Modes: light / dark / both +- Tokens: `tokenName` +- Before → after: `#old` → `#new` (light), … (dark) +- Binding: `Component` used `oldRole`, should use `newRole` +- Neighbors: stage / raised / inset / … +- Walked: notebook, SQL editor, details drawer, grid +- Why: +- Out of scope: +- For Emre: +``` + +--- + +## Log + +### 2026-09-01 — Light surfaces: lift baseline, compress elevation ramp +- Lift: palette +- Status: applied locally +- Modes: light +- Tokens: `surfaceCanvas`, `surfaceStage`, `surfaceBase`, `surfaceInset`, `surfaceRaised`, `surfaceInput`, `surfaceOverlay`, `surfaceValue`, `surfaceScrim`, `surfaceTabRail` +- Before → after (light): + - `surfaceStage` `#c9cdd4` → `#e2e5ea` + - `surfaceCanvas` `#d9dce2` → `#e8eaee` + - `surfaceBase` `#e3e5e9` → `#eef0f3` + - `surfaceRaised` `#e8eaee` → `#f4f5f7` + - `surfaceInset` `#eceef1` → `#f7f8f9` + - `surfaceInput` / `surfaceOverlay` `#f2f3f5` → `#fafbfc` + - `surfaceValue` `#fbfcfd` → `#ffffff` + - `surfaceScrim` ink `.38` → `.32` + - `surfaceTabRail` `(218,221,227,.94)` → `(232,234,238,.94)` +- Neighbors: stage still recedes from canvas; raised still sits above stage; inset stays the bright well. Stage→raised gap ~31 RGB points → ~18. +- Walked: notebook cells, SQL canvas, details drawer. Grids/charts were already working — `gridRow` / `gridHeader` / `chartSeries*` not touched. +- Why: Light mode felt washed. Baseline too gray; elevation ramp between field and cards too large, so SQL, notebook, and details went muddy while grids still read. +- Out of scope: dark mode; content/accent; interaction fills (`interactionNeutral` still `#d9dce2`). +- For Emre: Confirm the compressed light ladder still matches the spatial story in `THEMING.md` (darker stage, brighter embedded content). Update the Core palette table if accepted. + +### 2026-09-01 — Light SQL canvas follows the new baseline +- Lift: palette +- Status: applied locally +- Modes: light +- Tokens: `editorCanvas`, `editorBorder` +- Before → after (light): `editorCanvas` `#d9dce2` → `#eef0f3`; `editorBorder` `#c9cdd4` → `#e2e5ea` +- Neighbors: `editorCanvas` now matches `surfaceBase`; sits as a quiet well inside `surfaceRaised` cells. +- Why: The SQL editor does not read `surface*`. Leaving `editorCanvas` at the old gray would have stranded the named problem area inside the new cards. +- Out of scope: syntax colors, selection, active line. +- For Emre: This is still a palette steer, not a rebinding. Flag if editor should instead reuse `surfaceInset` / `surfaceBase` and drop the dedicated tokens. + +### 2026-09-01 — Light shadows quieter +- Lift: palette +- Status: applied locally +- Modes: light +- Tokens: `shadowSubtle`, `shadowSoft`, `shadowMedium`, `shadowStrong`, `shadowOverlay` +- Before → after (light): `.06/.11/.18/.27/.38` → `.035/.055/.08/.16/.22` +- Why: Card and overlay shadows were doing too much of the elevation job once surfaces got closer together. One primary cue (surface step), not surface + heavy shade. +- Out of scope: dark shadows; glass tokens; shadow *geometry* (see next entry). +- For Emre: Dialogs/menus use `shadowStrong` / `shadowOverlay` — check they still float after the opacity cut. + +### 2026-09-01 — Notebook cell and details drawer shadow geometry +- Lift: binding (geometry, same tokens) +- Status: applied locally +- Modes: both (geometry is shared; light opacity change is what you feel first) +- Binding: + - `CellWrapper` hover `0 16px 44px shadowSoft` → `0 1px 2px shadowSubtle, 0 3px 8px shadowSoft` + - `CellWrapper` focus extra `0 18px 50px shadowMedium` → `0 1px 2px shadowSubtle, 0 4px 10px shadowSoft` (accent ring unchanged) + - `Drawer` `-18px 0 52px shadowSoft` → `-4px 0 16px shadowSoft` +- Why: Token opacity alone cannot tuck a 50px blur. Notebook cells and the details drawer were the named surfaces. +- Out of scope: dropdown/modal stacks in `overlayStyles.ts` (`0 1.2rem 1.6rem`, `0 2.4rem 7.2rem`). Call out if those should follow. +- For Emre: Higher lift than the opacity cut. Resting cells still have no shadow (border only); hover/focus are the ones tucked. Dark mode inherits the tighter geometry — glance at a focused cell in dark. + +### 2026-09-01 — Light result grid follows the dense-data ladder +- Lift: palette +- Status: applied locally +- Modes: light +- Tokens: `gridRow`, `gridHeader` +- Before → after (light): `gridRow` `#e9ebef` → `#f4f5f7`; `gridHeader` `#dce0e6` → `#e7eaee` +- Neighbors (light, per `THEMING.md`): field `surfaceInset` `#f7f8f9` lightest → rows `#f4f5f7` → headers `#e7eaee` strongest gray. Same deltas as the pre-lift ladder (`#eceef1` / `#e9ebef` / `#dce0e6`), shifted with the new inset. `gridRow` now matches `surfaceRaised`, so a notebook cell’s body and its grid rows are one surface; the header bar is the structure cue. `gridSelection` / `gridFocus` / `contentObject` unchanged. +- Walked: standalone result grid, notebook inline grids. +- Why: The surface lift moved `surfaceInset` (empty field / viewport) and left `gridRow` / `gridHeader` on the old gray. The THEMING order was intact but the steps were the old muddy slab inside the new baseline. +- Out of scope: dark grid; zebra (the renderer does not stripe; hover uses `surfaceInset`); column-name crimson (`contentObject` — parking lot / binding). +- For Emre: Update the Result grid table in `THEMING.md` if accepted. Confirm header still reads as the strongest gray on a full-width grid and inside a raised cell. Selection `#e0afbf` was not retuned — glance at a selected row on the new `gridRow`. + +### 2026-09-01 — Light segmented chips sit on the new baseline +- Lift: palette +- Status: applied locally +- Modes: light +- Tokens: `controlTrack`, `interactionNeutral`, `interactionNeutralHover` +- Before → after (light): + - `controlTrack` / `interactionNeutral` `#d9dce2` → `#e8eaee` (same hex as new `surfaceCanvas`) + - `interactionNeutralHover` `#d2d6dd` → `#e2e5ea` (same hex as new `surfaceStage`) +- Neighbors: Table/Chart chips use `controlTrack` as the segmented substrate on `surfaceRaised` `#f4f5f7`. Old track was the pre-lift canvas, so the chip block jumped ~20 RGB points off the header. New track is a one-step inset. Selected segment is still the glass lens (`glassSurface`), not these fills. `borderStrong` on the track is unchanged. +- Walked: notebook cell Table/Chart chips. List/Grid uses the same `NotebookViewToggle` track. +- Why: Leftover `#d9dce2` after the surface lift. The chip group read as a dark elevated slab. +- Out of scope: `borderStrong` on the segmented control; glass lens opacity; dark mode. +- For Emre: `THEMING.md` already maps `controlTrack` to segmented substrate and switch tracks — update the light hexes. Switches and other segmented controls share this token; check a switch at rest. + +### 2026-09-01 — Chrome hairline stagger: rails vs panel/work +- Lift: binding +- Status: applied locally +- Modes: both +- Tokens: `borderDefault`, `borderSubtle` (values unchanged) +- Binding: icon rails (`Sidebar` left/right, `TopBar`) used `borderSubtle`; now `borderDefault`. Panel-to-work edges stay `borderSubtle` (`Console` left `Wrapper`, `SidePanelRight`, `Drawer`, allotment sash). +- Neighbors: `borderSubtle` is internal only — inside a panel or inside the working surface. Chrome rails sit one step stronger so the stagger reads. +- Walked: left rail | schema | editor; editor | details/AI | right rail; top bar under the logo/menu. +- Why: All chrome hairlines were the same weight, so rails and content panels sat on one plane. +- Out of scope: footer `border-top`; allotment sash hover (`contentAccent`); token values themselves. +- For Emre: Keep the stagger in the chrome composition notes. Do not bump panel-to-work to `borderDefault` — that would collapse the two weights. + +### 2026-09-01 — Content sidebars: both elevated +- Lift: binding +- Status: applied locally +- Modes: both +- Tokens: `surfaceRaised` (values unchanged) +- Binding: schema (`Schema` / `SearchPanel` wrappers + `PaneContent` + `Console` left `Wrapper`), details (`Drawer` shell + `ContentWrapper`, `SidePanelRight`), AI (`AIChatWindow` shells, lazy loader, error boundary, history), mobile schema (`SideMenu`) used `surfaceBase`; now `surfaceRaised`. Icon rails stay `surfaceBase`. +- Neighbors: light `surfaceBase` `#eef0f3` → panels `#f4f5f7` (`surfaceRaised`). Dark `surfaceBase` `#17181d` → panels `#1d1e24`. Work surface stays `surfaceStage` / editor canvas. `PaneWrapper` / `PaneContent` globally are still `surfaceBase` so Editor / Result / Import are untouched. +- Walked: tables tree vs notebook; details drawer vs notebook; AI chat vs notebook. Light and dark. First pass left the tree on `surfaceBase` because `PaneContent` paints that fill over the wrapper — override both, with `&&` so the shared primitives cannot win on equal specificity. +- Why: Dark treated details/AI as a lift and tables as mute. Light had almost no step from canvas to either sidebar. Same role on both sides, both modes. +- Out of scope: `Panel.Header` (already `surfaceRaised` — title bar now matches the panel body); filter input (`surfaceInput`); result/editor panes; palette retune of `surfaceRaised`; drawer drop shadow (still `shadowSoft` on the right only). +- For Emre: Left and right content panels share `surfaceRaised`. Rails stay `surfaceBase`. Schema/Search must override `PaneContent` as well as `PaneWrapper`. Drawer header no longer steps above the body — the step is panel vs work, not title vs body. + +### 2026-09-01 — Light chrome shadows: tighter geometry +- Lift: binding (geometry, same tokens) +- Status: applied locally +- Modes: light, except tab-rail hairline is both +- Tokens: `shadowSubtle`, `shadowSoft`, `shadowMedium`, `borderSubtle` (values unchanged) +- Binding: + - Table/Chart (and List/Grid) glass lens `0 3px 9px shadowSoft` → `0 1px 1px shadowSubtle, 0 1px 3px shadowSoft` in light. Dark kept. Hover-preview on Run/Draw matches. + - Notebook title bar `0 12px 24px shadowSoft` → `0 1px 2px shadowSubtle, 0 2px 6px shadowSoft` in light. Existing `borderSubtle` hairline kept. Dark kept. + - Tab rail under-shadow `0 8px 20px shadowSoft` → same tight pair as the notebook title in light. Dark kept. + - Tab rail hairline: `border-bottom: 0` → `borderSubtle` in both modes, sitting with the shadow. + - Tab overflow fades: 10px `shadowMedium` → transparent → 6px with the stop at 65%, light only. +- Neighbors: same two-stop recipe as cell hover (`shadowSubtle` contact + `shadowSoft` lift), just smaller because these sit on chrome not on the stage. +- Walked: Table/Chart chip, notebook heading, tab rail with enough tabs to overflow. +- Why: Light opacity was already cut; 20–24px blurs still read as haze. Cloudflare-style lift is a 1–2px offset and a short blur. +- Out of scope: dark geometry (except the new tab hairline); active-tab glass (`0 6px 18px` still); Metrics heading; cell hover (already tucked); drawer; token opacities. +- For Emre: Geometry only. Do not retune `shadowSoft`. Overflow uses `html[data-theme="light"]` because those fades live in SCSS. + +### 2026-09-01 — Chat history hover follows the raised panel +- Lift: binding +- Status: applied locally +- Modes: both +- Tokens: `surfaceBase` (light), `surfaceInput` (dark) — values unchanged +- Binding: `ChatHistoryItem` hover used `surfaceRaised`, which is now the panel fill. Hover inverts against the panel: one step darker in light (`surfaceBase` `#eef0f3`), one step lighter in dark (`surfaceInput` `#21222c`). +- Neighbors: panel `surfaceRaised` (`#f4f5f7` / `#1d1e24`). `surfaceInput` lightens both modes, so it is wrong in light. `surfaceOverlay` equals `surfaceRaised` in dark. `interactionHover` would invert, but as a wash rather than a surface step. +- Walked: AI chat history, light and dark. +- Why: Elevating the AI panel to `surfaceRaised` left hover on the same token. First rebind to `surfaceInput` everywhere; Zack caught that light hover should recede, not lift. +- Out of scope: rest/current row fill (still transparent); date separators; palette retune of `surfaceOverlay` in dark. +- For Emre: Hover on a raised list is not `surfaceRaised`. Light uses `surfaceBase`, dark uses `surfaceInput`. A single inverting overlay (`interactionHover`) would avoid the mode split if that role is the intended meaning. + +### 2026-09-01 — Tooltip border matches floating menus +- Lift: binding +- Status: applied locally +- Modes: both +- Tokens: `borderDefault` (values unchanged) +- Binding: `Tooltip` box and arrow stroke used `contentDisabled` (a type color, reads as heavy as `borderStrong` or heavier). Rebind to `borderDefault`, same as `floatingSurfaceStyles` / dropdown menus. +- Neighbors: `borderSubtle` → `borderDefault` → `borderStrong`. Menus sit on `borderDefault`. Tooltip should not sit above them. +- Walked: editor toolbar tooltips, notebook heading actions, both modes. +- Why: After the surface lift the `contentDisabled` stroke was a hard outline on a quiet panel. +- Out of scope: tooltip fill (`surfaceInset`); dropdown/popover borders (already `borderDefault`); `contentDisabled` as type. +- For Emre: Tooltip chrome is a floating surface. Its edge is `borderDefault`, not a content token. + +### 2026-09-01 — Inline AI action cards invert in light +- Lift: binding +- Status: applied locally +- Modes: light (dark kept) +- Tokens: `surfaceValue` (light), `authBackdrop` (dark) +- Binding: `UserRequestBox` (Explain / Fix / Schema / Ask cards) used `authBackdrop` in both modes. That token is the login field: dark `#1d070e` recedes, light `#c7cbd2` is a muddy slab darker than the raised chat panel. Light now uses `surfaceValue` `#ffffff`. Dark stays on `authBackdrop`. +- Neighbors: chat panel `surfaceRaised` `#f4f5f7`. Nested SQL uses `editorCanvas` `#eef0f3`, so the query block recedes slightly inside the white card. Login `authBackdrop` is untouched. +- Walked: Explain Query card in the AI panel, light mode. Dark glance to confirm the crimson well remains. +- Why: Darker-on-dark should invert to lighter-on-light. `authBackdrop` cannot do that job in both themes. +- Out of scope: plain user `MessageBubble` (still `authBackdrop`); login page; palette retune of `authBackdrop`; inner LiteEditor. +- For Emre: AI action cards are not login chrome. Light fill is `surfaceValue`. Consider whether `MessageBubble` should follow. + +### 2026-09-01 — Cell icon hover is one step darker in light +- Lift: binding +- Status: applied locally +- Modes: light (dark kept) +- Tokens: `surfaceBase`, `interactionNeutralHover` (values unchanged) +- Binding: Ghost `IconButton` hover is `surfaceRaised`, which is the cell fill, so Maximize / More vanish. Light hover on those is now `surfaceBase` (`#eef0f3` on `#f4f5f7`). Split / reset inside the Table/Chart track sit on `controlTrack`; light hover is `interactionNeutralHover` (`#e2e5ea` on `#e8eaee`). Dark still uses `surfaceRaised`. +- Neighbors: do not retune global ghost hover — on `surfaceBase` chrome (rails, notebook title) `surfaceRaised` is the correct lift. +- Walked: focused cell Maximize and More, Table/Chart split icon, light mode. +- Why: Same-token hover on a raised cell. Dark already reads; light needed one receding step. +- Out of scope: global ghost; Table/Chart unselected `interactionHover`; markdown Edit/Apply; token opacities. +- For Emre: Ghost hover cannot be one fill everywhere. On raised cells it must recede (`surfaceBase`); on base chrome it must lift (`surfaceRaised`). + +### 2026-09-01 — Neutralise brand on fields, lists, and grid hover +- Lift: binding +- Status: applied locally +- Modes: both +- Tokens: `borderStrong`, `borderDefault`, `interactionHover`, `interactionNeutral` (values unchanged) +- Binding: + - Default `Input` / `TextArea` focus: `contentAccent` → `borderStrong`. Accent is opt-in via `$tone="accent"` (AI chat composer, chat history search, login). + - Assistant Settings provider tab underline: `contentAccent` → `borderStrong`. Fields inherit the new default. + - `TableSelector` trigger and items: `borderAccent` / `interactionAccent*` → `borderDefault` / `interactionHover` / `interactionNeutral`. + - Schema tree row hover/focus and context-menu lock: `interactionAccent*` / `borderAccent` → `interactionHover` / `interactionNeutral` / `borderDefault`. Details `i` → `contentSecondary`. + - Result grid row hover wash: `interactionAccentHover` → `interactionHover`. Frozen-handle hover bar: `contentAccent` → `borderStrong`. +- Neighbors: rail `Navigation` stays `contentAccent` (tool selection). Table/column glyphs still `contentAccent`. `SelectMenu` check and open border stay accent (AI model dropdown). Grid *selection* `gridSelection` and column-resize ghost stay branded. Copy-pulse on schema rows stays accent. +- Walked: Filter... in tables, table picker, tree hover, result-grid hover, Assistant Settings provider + API key, AI composer (still crimson), login (still crimson). +- Why: Accent was doing hover, focus, and selection jobs that are not high-level brand actions. +- Out of scope: `contentObject` column names; tree type icons; rail icons; `SelectMenu`; `TabButton` globally (Monitoring/Details still accent); `gridSelection`; checkboxes/switches. +- For Emre: Default field focus is `borderStrong`. Accent is `$tone="accent"`. Do not retune `contentAccent` to fix these. **Superseded in part:** provider-tab underline reverted the same day (tabs stay branded); grid selection/resize and column names handled in the following two entries. + +### 2026-09-01 — Grid selection and cell-focus ring go slate +- Lift: palette +- Status: applied locally +- Modes: both +- Tokens: `gridSelection`, `gridFocus` +- Before → after: + - light `gridSelection` `#e0afbf` → `#d8dce3`; `gridFocus` `#8a0f35` → `#828b99` (same as light `borderStrong`) + - dark `gridSelection` `#2b1d25` → `#252830`; `gridFocus` `#b81447` → `#6b7382` (stronger than dark `borderStrong` `#3d414d` so the 1px inset still reads on the selected cell) +- Neighbors: light `gridRow` `#f4f5f7`, `gridHeader` `#e7eaee`. Dark `gridRow` `#17181d`, `gridHeader` `#202126`. Selection must stay stronger than the `interactionHover` overlay. +- Walked: result-grid row selection, focused cell ring, copy-pulse (now slate). Query-picker first-visit pulse rebound off `gridFocus` so it stays branded. +- Why: Selection wash and cell ring were still pink after hover went neutral. +- Out of scope: `editorSelection`; notebook cell focus (`CellWrapper`); checkboxes/switches. +- For Emre: `gridFocus` is the grid's keyboard/copy ring, not brand. Light matches `borderStrong`. Dark is a step lighter than `borderStrong` on purpose. + +### 2026-09-01 — Search, keyboard focus, column names, resize +- Lift: binding +- Status: applied locally +- Modes: both +- Tokens: `borderStrong`, `borderDefault`, `interactionHover`, `interactionNeutral`, `contentPrimary`, `contentSecondary` (values unchanged) +- Binding: + - Editor Search results: hover `interactionHover`; focused row `interactionNeutral` + `borderDefault` (same as schema tree). File icons `contentSecondary`. Case/word/regex toggles `$activeTone="neutral"` + `borderDefault`. + - Global keyboard focus outlines: `contentAccent` → `borderStrong` (`*:focus-visible`, `Button`, ghost buttons, chrome-tab outline, DocSearch button, warning link, instance-settings slider, chat-history item, assistant-modes compact, segmented-control inset ring). Tab *rename* field and other leftover field-focus borders follow (`_editor`, slim-select, quick-vis). Split sash hover fill → `borderStrong` (same job as column resize). + - Result-grid column names: `contentObject` → `contentPrimary` (`HeaderName` and legacy `.qg-header-name`). + - Column-resize ghost: `contentAccent` → `borderStrong` (matches frozen-handle hover bar). + - Revert: Assistant Settings provider tab underline back to `TabButton` `contentAccent`. +- Neighbors: `TabButton` underline stays `contentAccent`. Notebook cell focus (`CellWrapper`) and cell-name field stay branded. Notebook title glyph and chrome-tab notebook/metrics favicons stay `contentObject`. Switch/Checkbox outlines stay branded. +- Walked: Search sidebar, result grid headers/selection/resize, tab underlines (Monitoring/Details, AI setup), notebook cell ring, keyboard tab through chrome. +- Why: Second binding pass. Tabs and notebook identity stay brand; search, focus rings, grid type, and resize are chrome. +- Out of scope: checkboxes/switches; rail `Navigation`; schema tree glyphs; `SelectMenu`; AI sparkle/MCP/pairing. +- For Emre: Keyboard focus is `borderStrong`. List hover/focus matches the schema tree. Column names are type (`contentPrimary`), not object glyphs. + +### 2026-09-01 — Chat history fields and dropdown open state +- Lift: binding +- Status: applied locally +- Modes: both +- Tokens: `borderStrong` (values unchanged) +- Binding: + - Chat history search: drop `$tone="accent"` so it inherits default field focus (`borderStrong`). Composer stays `$tone="accent"`. + - Chat history rename: `actionPrimary` → `borderStrong`. + - `SelectMenu` open trigger: `borderAccent` → `borderStrong` (chart X-axis, AI model picker, and every other SelectMenu). Checkmark stays `contentAccent`. +- Neighbors: same `borderStrong` as Input focus and keyboard outlines. Login fields still `$tone="accent"`. +- Walked: chat history search + rename, AI model dropdown, chart X-axis dropdown. +- Why: These were still opted into brand after default field focus went neutral. +- Out of scope: SelectMenu check; AI Settings label; sparkle glyphs; composer; login; checkboxes/switches. +- For Emre: Open dropdown chrome is field focus, not brand. Check remains a selected-item glyph. + +--- + +## Parking lot — not logged as decisions yet + +Use this for hunches until they become an entry. + +- Brand core (`contentAccent`, `actionPrimary`, `contentObject` in light) may be overused. 2026-09-01 neutralized fields, lists, search, keyboard focus, dropdown open state, grid hover/selection/resize, and column names. Still branded: rail icons, tree glyphs, `SelectMenu` check, tab underlines, notebook cell focus + title glyphs, AI composer/login `$tone="accent"`, checkboxes/switches. Treat leftovers as **binding**. +- `interactionNeutral` / `controlTrack` leftover `#d9dce2` — addressed 2026-09-01 (table/chart chips). +- New surface roles: only if two neighbors with *different jobs* are forced to share a token. Propose the meaning first (`surfaceSomething`), then values in both themes. diff --git a/src/components/AIStatusIndicator/AssistantModesCompact.tsx b/src/components/AIStatusIndicator/AssistantModesCompact.tsx index c534c4557..37c3134f6 100644 --- a/src/components/AIStatusIndicator/AssistantModesCompact.tsx +++ b/src/components/AIStatusIndicator/AssistantModesCompact.tsx @@ -121,7 +121,7 @@ const ModeHeaderTop = styled.div<{ } &:focus-visible { - outline: 1px solid ${color("contentAccent")}; + outline: 1px solid ${color("borderStrong")}; outline-offset: 2px; } diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index 6ac332a95..0eefb05d1 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -185,7 +185,7 @@ export const ButtonBase = styled.button.attrs<{ filter 120ms ease; &&:focus-visible { - outline: 1px solid ${({ theme }) => theme.color.contentAccent}; + outline: 1px solid ${({ theme }) => theme.color.borderStrong}; outline-offset: 2px; } diff --git a/src/components/Drawer/content-wrapper.tsx b/src/components/Drawer/content-wrapper.tsx index 25a87e525..8332e654c 100644 --- a/src/components/Drawer/content-wrapper.tsx +++ b/src/components/Drawer/content-wrapper.tsx @@ -14,7 +14,7 @@ export const ContentWrapper = styled(Box).attrs({ flex: 1; min-height: 0; overflow: auto; - background: ${({ theme }) => theme.color.surfaceBase}; + background: ${({ theme }) => theme.color.surfaceRaised}; form { width: 100%; diff --git a/src/components/Drawer/index.tsx b/src/components/Drawer/index.tsx index c443eec35..95929f81d 100644 --- a/src/components/Drawer/index.tsx +++ b/src/components/Drawer/index.tsx @@ -59,9 +59,9 @@ const DrawerContent = styled(RadixDialog.Content).attrs({ forceMount: true })<{ }>` display: flex; flex-direction: column; - background-color: ${({ theme }) => theme.color.surfaceBase}; + background-color: ${({ theme }) => theme.color.surfaceRaised}; border-left: 1px solid ${({ theme }) => theme.color.borderSubtle}; - box-shadow: -18px 0 52px ${({ theme }) => theme.color.shadowSoft}; + box-shadow: -4px 0 16px ${({ theme }) => theme.color.shadowSoft}; position: ${({ mode }) => (mode === "modal" ? "fixed" : "inherit")}; top: 0; right: 0; diff --git a/src/components/Form/FormInput/index.tsx b/src/components/Form/FormInput/index.tsx index 14cb2f272..0cc04e6f4 100644 --- a/src/components/Form/FormInput/index.tsx +++ b/src/components/Form/FormInput/index.tsx @@ -12,6 +12,7 @@ export type FormInputProps = React.InputHTMLAttributes & { showPassword?: boolean autoFocus?: boolean autoComplete?: string + tone?: "neutral" | "accent" } const Wrapper = styled.div<{ @@ -69,6 +70,7 @@ export const FormInput = ({ showPassword, autoFocus, autoComplete, + tone, ...rest }: FormInputProps) => { const { formState, getFieldState, register, setFocus } = useFormContext() @@ -99,6 +101,7 @@ export const FormInput = ({ disabled={disabled} showPassword={showPassword} autoComplete={autoComplete} + $tone={tone} {...rest} id={name} aria-invalid={hasError || undefined} diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx index a312d0624..8c351d726 100644 --- a/src/components/Input/index.tsx +++ b/src/components/Input/index.tsx @@ -3,8 +3,11 @@ import React from "react" export type InputVariant = "transparent" | "error" +export type InputTone = "neutral" | "accent" + export type InputStyleProps = { variant?: InputVariant + $tone?: InputTone } type InputProps = React.InputHTMLAttributes & InputStyleProps @@ -42,7 +45,10 @@ export const inputStyles = css` &:focus-visible { outline: none; box-shadow: none; - border-color: ${({ theme }) => theme.color.contentAccent}; + border-color: ${({ theme, $tone }) => + $tone === "accent" + ? theme.color.contentAccent + : theme.color.borderStrong}; background: ${({ theme }) => theme.color.surfaceInput}; } diff --git a/src/components/ResultGrid/styles.ts b/src/components/ResultGrid/styles.ts index 68b4e89cf..b5d718d15 100644 --- a/src/components/ResultGrid/styles.ts +++ b/src/components/ResultGrid/styles.ts @@ -80,7 +80,7 @@ export const HeaderNameRow = styled.div<{ $align: string }>` ` export const HeaderName = styled.span` - color: ${color("contentObject")}; + color: ${color("contentPrimary")}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -138,7 +138,7 @@ export const ColResizer = styled.div` } &:hover::after { - background: ${color("contentAccent")}; + background: ${color("borderStrong")}; } ` @@ -157,7 +157,7 @@ export const ResizeGhost = styled.div` top: 0; bottom: 0; width: 2px; - background: ${color("contentAccent")}; + background: ${color("borderStrong")}; pointer-events: none; /* Above the resizer overlay (z-index 6) so the drag line isn't clipped. */ z-index: 7; @@ -180,16 +180,16 @@ export const Row = styled.div<{ $active: boolean }>` &:hover { background: linear-gradient( - ${theme.color.interactionAccentHover}, - ${theme.color.interactionAccentHover} + ${theme.color.interactionHover}, + ${theme.color.interactionHover} ), ${theme.color.surfaceInset}; [data-frozen="true"] { background: linear-gradient( - ${theme.color.interactionAccentHover}, - ${theme.color.interactionAccentHover} + ${theme.color.interactionHover}, + ${theme.color.interactionHover} ), ${theme.color.surfaceInset}; } @@ -350,7 +350,7 @@ export const FreezeHandle = styled.div<{ !$dragging && css` &:hover::after { - background: ${color("contentAccent")}; + background: ${color("borderStrong")}; } `} ` diff --git a/src/components/SegmentedControl/index.tsx b/src/components/SegmentedControl/index.tsx index 350d266d2..e7fc25ae3 100644 --- a/src/components/SegmentedControl/index.tsx +++ b/src/components/SegmentedControl/index.tsx @@ -56,7 +56,7 @@ const SegmentedControlRoot = styled.div` && > button[aria-pressed="true"]:focus-visible { outline: none; outline-offset: 0; - box-shadow: inset 0 0 0 2px ${({ theme }) => theme.color.contentAccent}; + box-shadow: inset 0 0 0 2px ${({ theme }) => theme.color.borderStrong}; } ` @@ -82,7 +82,10 @@ const GlassSelection = styled.div` border-bottom-width: 2px; border-bottom-color: ${({ theme }) => theme.color.glassEdge}; border-radius: 0.4rem; - box-shadow: 0 3px 9px ${({ theme }) => theme.color.shadowSoft}; + box-shadow: ${({ theme }) => + theme.mode === "light" + ? `0 1px 1px ${theme.color.shadowSubtle}, 0 1px 3px ${theme.color.shadowSoft}` + : `0 3px 9px ${theme.color.shadowSoft}`}; backdrop-filter: blur(6px) saturate(145%); -webkit-backdrop-filter: blur(5px) saturate(150%); transition: opacity 100ms ease; diff --git a/src/components/SelectMenu/index.tsx b/src/components/SelectMenu/index.tsx index a31d67003..72cc7d4eb 100644 --- a/src/components/SelectMenu/index.tsx +++ b/src/components/SelectMenu/index.tsx @@ -41,7 +41,7 @@ const TriggerRoot = styled(Button).attrs({ variant: "secondary" })<{ text-align: left; &[aria-expanded="true"] { - border-color: ${({ theme }) => theme.color.borderAccent}; + border-color: ${({ theme }) => theme.color.borderStrong}; } &[aria-expanded="true"] ${TriggerCaret} { diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx index 7eb14d05c..85d3b3bbe 100644 --- a/src/components/Sidebar/index.tsx +++ b/src/components/Sidebar/index.tsx @@ -13,7 +13,7 @@ export const Sidebar = styled(Box).attrs({ flexDirection: "column" })<{ width: ${SIDEBAR_WIDTH}; height: 100%; background: ${({ theme }) => theme.color.surfaceBase}; - border-right: 1px solid ${({ theme }) => theme.color.borderSubtle}; + border-right: 1px solid ${({ theme }) => theme.color.borderDefault}; gap: 0.8rem; flex-shrink: 0; justify-content: ${({ align }) => @@ -37,6 +37,6 @@ export const Sidebar = styled(Box).attrs({ flexDirection: "column" })<{ &:last-of-type { border-right: 0; - border-left: 1px solid ${({ theme }) => theme.color.borderSubtle}; + border-left: 1px solid ${({ theme }) => theme.color.borderDefault}; } ` diff --git a/src/components/TableSelector/index.tsx b/src/components/TableSelector/index.tsx index 21a4115f9..0e8bd1917 100644 --- a/src/components/TableSelector/index.tsx +++ b/src/components/TableSelector/index.tsx @@ -54,8 +54,8 @@ const TriggerContainer = styled.div` &:hover, &:focus-within { - border-color: ${({ theme }) => theme.color.borderAccent}; - background: ${({ theme }) => theme.color.interactionAccentHover}; + border-color: ${({ theme }) => theme.color.borderDefault}; + background: ${({ theme }) => theme.color.interactionHover}; } ` @@ -110,18 +110,18 @@ const Item = styled.div<{ $active: boolean; $disabled?: boolean }>` color: ${({ theme, $disabled }) => $disabled ? theme.color.contentDisabled : theme.color.contentPrimary}; background: ${({ $active, theme }) => - $active ? theme.color.interactionAccentActive : "transparent"}; + $active ? theme.color.interactionNeutral : "transparent"}; border: 1px solid ${({ $active, theme }) => - $active ? theme.color.borderAccent : "transparent"}; + $active ? theme.color.borderDefault : "transparent"}; &:hover { background: ${({ $disabled, $active, theme }) => $disabled ? "transparent" : $active - ? theme.color.interactionAccentActive - : theme.color.interactionAccentHover}; + ? theme.color.interactionNeutral + : theme.color.interactionHover}; } .highlight { diff --git a/src/components/Tooltip/index.tsx b/src/components/Tooltip/index.tsx index b62543cd9..9eee415fe 100644 --- a/src/components/Tooltip/index.tsx +++ b/src/components/Tooltip/index.tsx @@ -110,7 +110,7 @@ const ArrowWithBorder = React.forwardRef((props, ref) => { @@ -130,7 +130,7 @@ const TooltipContent = styled(RadixTooltip.Content)<{ max-width: ${({ $maxWidth }) => $maxWidth ?? "460px"}; padding: 1rem; background: ${color("surfaceInset")}; - border: 1px solid ${color("contentDisabled")}; + border: 1px solid ${color("borderDefault")}; border-radius: 6px; z-index: ${TOOLTIP_Z_INDEX}; animation-duration: 200ms; diff --git a/src/components/TopBar/InstanceSettingsPopper.tsx b/src/components/TopBar/InstanceSettingsPopper.tsx index bcf2a5c1f..7ee637d9a 100644 --- a/src/components/TopBar/InstanceSettingsPopper.tsx +++ b/src/components/TopBar/InstanceSettingsPopper.tsx @@ -154,7 +154,7 @@ const ColorSlider = styled.input.attrs({ type: "range", min: 0, max: 255 })` } &:focus-visible { - outline: 1px solid ${({ theme }) => theme.color.contentAccent}; + outline: 1px solid ${({ theme }) => theme.color.borderStrong}; outline-offset: 2px; } diff --git a/src/components/TopBar/index.tsx b/src/components/TopBar/index.tsx index 264165480..1c6ee493d 100644 --- a/src/components/TopBar/index.tsx +++ b/src/components/TopBar/index.tsx @@ -15,7 +15,7 @@ const Root = styled(Box).attrs({ min-height: ${TOP_BAR_HEIGHT}; gap: 0; background: ${({ theme }) => theme.color.surfaceBase}; - border-bottom: 1px solid ${({ theme }) => theme.color.borderSubtle}; + border-bottom: 1px solid ${({ theme }) => theme.color.borderDefault}; box-shadow: 0 6px 18px ${({ theme }) => theme.color.shadowSubtle}; z-index: 30; ` diff --git a/src/modules/OAuth2/views/login.tsx b/src/modules/OAuth2/views/login.tsx index 8aa013cc2..49940ac3a 100644 --- a/src/modules/OAuth2/views/login.tsx +++ b/src/modules/OAuth2/views/login.tsx @@ -443,13 +443,18 @@ export const Login = ({ > - + {errorMessage && ( diff --git a/src/scenes/Console/index.tsx b/src/scenes/Console/index.tsx index 8977b8db7..f0c41f556 100644 --- a/src/scenes/Console/index.tsx +++ b/src/scenes/Console/index.tsx @@ -78,13 +78,14 @@ const SidebarSpacer = styled.div` ` const SidePanelRight = styled.div` - background: ${({ theme }) => theme.color.surfaceBase}; + background: ${({ theme }) => theme.color.surfaceRaised}; height: 100%; border-left: 1px solid ${({ theme }) => theme.color.borderSubtle}; ` const Wrapper = styled.div` height: 100%; + background: ${({ theme }) => theme.color.surfaceRaised}; border-right: 1px solid ${({ theme }) => theme.color.borderSubtle}; ` diff --git a/src/scenes/Editor/AIChatWindow/AIChatErrorBoundary.tsx b/src/scenes/Editor/AIChatWindow/AIChatErrorBoundary.tsx index 79f6dcab9..b2989bbcb 100644 --- a/src/scenes/Editor/AIChatWindow/AIChatErrorBoundary.tsx +++ b/src/scenes/Editor/AIChatWindow/AIChatErrorBoundary.tsx @@ -23,7 +23,7 @@ const Wrapper = styled.div` width: 100%; height: 100%; padding: 2rem; - background: ${({ theme }) => theme.color.surfaceBase}; + background: ${({ theme }) => theme.color.surfaceRaised}; border-left: 0.2rem ${color("surfaceInset")} solid; ` diff --git a/src/scenes/Editor/AIChatWindow/AIChatWindowLazy.tsx b/src/scenes/Editor/AIChatWindow/AIChatWindowLazy.tsx index db07d5a2e..bdaf54bf5 100644 --- a/src/scenes/Editor/AIChatWindow/AIChatWindowLazy.tsx +++ b/src/scenes/Editor/AIChatWindow/AIChatWindowLazy.tsx @@ -11,7 +11,7 @@ const AIChatWindow = lazy(() => import("./index")) const LoaderContainer = styled.div` display: flex; align-items: center; - background: ${({ theme }) => theme.color.surfaceBase}; + background: ${({ theme }) => theme.color.surfaceRaised}; justify-content: center; height: 100%; width: 100%; diff --git a/src/scenes/Editor/AIChatWindow/ChatHistoryItem.tsx b/src/scenes/Editor/AIChatWindow/ChatHistoryItem.tsx index 358c5cce9..510b50fc5 100644 --- a/src/scenes/Editor/AIChatWindow/ChatHistoryItem.tsx +++ b/src/scenes/Editor/AIChatWindow/ChatHistoryItem.tsx @@ -25,8 +25,12 @@ const Container = styled.div<{ $disabled?: boolean }>` text-align: left; &:hover { - background: ${({ $disabled }) => - $disabled ? "transparent" : color("surfaceRaised")}; + background: ${({ $disabled, theme }) => + $disabled + ? "transparent" + : theme.mode === "light" + ? theme.color.surfaceBase + : theme.color.surfaceInput}; .chat-title { color: ${({ $disabled }) => @@ -35,7 +39,7 @@ const Container = styled.div<{ $disabled?: boolean }>` } &:focus-visible { - outline: 1px solid ${color("contentAccent")}; + outline: 1px solid ${color("borderStrong")}; outline-offset: 2px; } ` @@ -69,7 +73,7 @@ const Title = styled.div.attrs({ className: "chat-title" })` const TitleInput = styled.input` color: ${color("contentPrimary")}; background: transparent; - border: 1px solid ${color("actionPrimary")}; + border: 1px solid ${color("borderStrong")}; border-radius: 6px; outline: none; padding: 0.2rem 0.4rem; diff --git a/src/scenes/Editor/AIChatWindow/ChatHistoryView.tsx b/src/scenes/Editor/AIChatWindow/ChatHistoryView.tsx index ae7c2a2a3..67bc604cf 100644 --- a/src/scenes/Editor/AIChatWindow/ChatHistoryView.tsx +++ b/src/scenes/Editor/AIChatWindow/ChatHistoryView.tsx @@ -29,7 +29,7 @@ const Container = styled.div` height: 100%; width: 100%; padding: 2rem 1rem 4rem 1rem; - background: ${({ theme }) => theme.color.surfaceBase}; + background: ${({ theme }) => theme.color.surfaceRaised}; overflow: hidden; ` diff --git a/src/scenes/Editor/AIChatWindow/ChatInput.tsx b/src/scenes/Editor/AIChatWindow/ChatInput.tsx index 06b1ac03f..7ff451a4f 100644 --- a/src/scenes/Editor/AIChatWindow/ChatInput.tsx +++ b/src/scenes/Editor/AIChatWindow/ChatInput.tsx @@ -43,7 +43,9 @@ const InputWrapper = styled(Box)` overflow: hidden; ` -const StyledTextArea = styled(TextArea)<{ $hasContext: boolean }>` +const StyledTextArea = styled(TextArea).attrs({ $tone: "accent" })<{ + $hasContext: boolean +}>` flex: 1; min-height: 8rem; max-height: 30rem; diff --git a/src/scenes/Editor/AIChatWindow/ChatMessages.tsx b/src/scenes/Editor/AIChatWindow/ChatMessages.tsx index 42e6a9d99..76090730f 100644 --- a/src/scenes/Editor/AIChatWindow/ChatMessages.tsx +++ b/src/scenes/Editor/AIChatWindow/ChatMessages.tsx @@ -96,7 +96,10 @@ const UserRequestBox = styled(Box)` padding: 0.8rem; width: 100%; align-self: flex-end; - background: ${color("authBackdrop")}; + background: ${({ theme }) => + theme.mode === "light" + ? theme.color.surfaceValue + : theme.color.authBackdrop}; border: 1px solid ${color("borderDefault")}; border-radius: 0.6rem; flex-shrink: 0; diff --git a/src/scenes/Editor/AIChatWindow/index.tsx b/src/scenes/Editor/AIChatWindow/index.tsx index 4999bf773..07c4cc776 100644 --- a/src/scenes/Editor/AIChatWindow/index.tsx +++ b/src/scenes/Editor/AIChatWindow/index.tsx @@ -107,7 +107,7 @@ const ChatWindowContent = styled.div` height: 100%; width: 100%; overflow: hidden; - background: ${({ theme }) => theme.color.surfaceBase}; + background: ${({ theme }) => theme.color.surfaceRaised}; ` const InitialQueryContainer = styled.div` @@ -182,7 +182,7 @@ const ChatPanel = styled(Box)` height: 100%; width: 100%; gap: 0; - background: ${({ theme }) => theme.color.surfaceBase}; + background: ${({ theme }) => theme.color.surfaceRaised}; ` const AIChatWindow: React.FC = () => { diff --git a/src/scenes/Editor/Menu/index.tsx b/src/scenes/Editor/Menu/index.tsx index fc2414fc2..dad3c61df 100644 --- a/src/scenes/Editor/Menu/index.tsx +++ b/src/scenes/Editor/Menu/index.tsx @@ -100,7 +100,7 @@ const QueryPickerButton = styled(Button)<{ $firstTimeVisitor: boolean }>` ${({ $firstTimeVisitor, theme }) => $firstTimeVisitor ? css` - animation: ${queryPickerPulse(theme.color.gridFocus)} 2s infinite; + animation: ${queryPickerPulse(theme.color.contentAccent)} 2s infinite; ` : css` animation: none; diff --git a/src/scenes/Editor/Monaco/tabs.tsx b/src/scenes/Editor/Monaco/tabs.tsx index ed52ea915..5179482d0 100644 --- a/src/scenes/Editor/Monaco/tabs.tsx +++ b/src/scenes/Editor/Monaco/tabs.tsx @@ -59,8 +59,11 @@ const Root = styled(Box).attrs({ z-index: 12; isolation: isolate; background: transparent; - border-bottom: 0; - box-shadow: 0 8px 20px ${({ theme }) => theme.color.shadowSoft}; + border-bottom: 1px solid ${({ theme }) => theme.color.borderSubtle}; + box-shadow: ${({ theme }) => + theme.mode === "light" + ? `0 1px 2px ${theme.color.shadowSubtle}, 0 2px 6px ${theme.color.shadowSoft}` + : `0 8px 20px ${theme.color.shadowSoft}`}; padding-right: 1rem; gap: 0.4rem; diff --git a/src/scenes/Editor/Notebook/NotebookToolbar.tsx b/src/scenes/Editor/Notebook/NotebookToolbar.tsx index cafff4ef7..1ca9cfb1b 100644 --- a/src/scenes/Editor/Notebook/NotebookToolbar.tsx +++ b/src/scenes/Editor/Notebook/NotebookToolbar.tsx @@ -44,7 +44,10 @@ const Toolbar = styled(Box).attrs({ padding: 1rem 2rem; background: ${color("surfaceBase")}; border-bottom: 1px solid ${({ theme }) => theme.color.borderSubtle}; - box-shadow: 0 12px 24px ${({ theme }) => theme.color.shadowSoft}; + box-shadow: ${({ theme }) => + theme.mode === "light" + ? `0 1px 2px ${theme.color.shadowSubtle}, 0 2px 6px ${theme.color.shadowSoft}` + : `0 12px 24px ${theme.color.shadowSoft}`}; overflow: hidden; flex-shrink: 0; position: relative; diff --git a/src/scenes/Editor/Notebook/cells/CellRunDrawToggles.tsx b/src/scenes/Editor/Notebook/cells/CellRunDrawToggles.tsx index 39274b575..a46841d69 100644 --- a/src/scenes/Editor/Notebook/cells/CellRunDrawToggles.tsx +++ b/src/scenes/Editor/Notebook/cells/CellRunDrawToggles.tsx @@ -18,7 +18,10 @@ const ToggleButton = styled(NotebookViewToggleSegment)` box-shadow: inset 0 0 0 1px ${({ theme }) => theme.color.glassBorder}, inset 0 -2px 0 ${({ theme }) => theme.color.glassEdge}, - 0 3px 9px ${({ theme }) => theme.color.shadowSoft}; + ${({ theme }) => + theme.mode === "light" + ? `0 1px 1px ${theme.color.shadowSubtle}, 0 1px 3px ${theme.color.shadowSoft}` + : `0 3px 9px ${theme.color.shadowSoft}`}; backdrop-filter: blur(2px) saturate(150%); -webkit-backdrop-filter: blur(2px) saturate(150%); } diff --git a/src/scenes/Editor/Notebook/cells/CellToolbar.tsx b/src/scenes/Editor/Notebook/cells/CellToolbar.tsx index 73041b2bf..b8e87aea5 100644 --- a/src/scenes/Editor/Notebook/cells/CellToolbar.tsx +++ b/src/scenes/Editor/Notebook/cells/CellToolbar.tsx @@ -65,6 +65,15 @@ const ToolbarWrapper = styled.div<{ `} ` +const CellIconButton = styled(IconButton)` + &&:hover:not(:disabled):not([aria-disabled="true"]) { + background: ${({ theme }) => + theme.mode === "light" + ? theme.color.surfaceBase + : theme.color.surfaceRaised}; + } +` + type Props = { cellId: string cell: NotebookCell @@ -277,7 +286,7 @@ export const CellToolbar: React.FC = ({ $forceVisible={menuOpen} > - = ({ ) : ( )} - + {!isMaximized && ( = ({ > - + - + diff --git a/src/scenes/Editor/Notebook/cells/CellViewToggle.tsx b/src/scenes/Editor/Notebook/cells/CellViewToggle.tsx index f1ca2eabe..00c7993ac 100644 --- a/src/scenes/Editor/Notebook/cells/CellViewToggle.tsx +++ b/src/scenes/Editor/Notebook/cells/CellViewToggle.tsx @@ -39,6 +39,13 @@ const ViewIconButton = styled(IconButton)` width: 1.8rem; height: 1.8rem; } + + &&:hover:not(:disabled):not([aria-disabled="true"]) { + background: ${({ theme }) => + theme.mode === "light" + ? theme.color.interactionNeutralHover + : theme.color.surfaceRaised}; + } ` const Divider = styled.div` diff --git a/src/scenes/Editor/Notebook/cells/CellWrapper.tsx b/src/scenes/Editor/Notebook/cells/CellWrapper.tsx index 874529a2b..7ad6dc81b 100644 --- a/src/scenes/Editor/Notebook/cells/CellWrapper.tsx +++ b/src/scenes/Editor/Notebook/cells/CellWrapper.tsx @@ -23,7 +23,8 @@ export const CellWrapper = styled.div.attrs({ border-color: ${color("contentAccent")}; box-shadow: 0 0 0 3px ${color("interactionAccentActive")}, - 0 18px 50px ${color("shadowMedium")}; + 0 1px 2px ${color("shadowSubtle")}, + 0 4px 10px ${color("shadowSoft")}; `} ${({ $focused }) => @@ -31,7 +32,9 @@ export const CellWrapper = styled.div.attrs({ css` &:hover { border-color: ${color("borderDefault")}; - box-shadow: 0 16px 44px ${color("shadowSoft")}; + box-shadow: + 0 1px 2px ${color("shadowSubtle")}, + 0 3px 8px ${color("shadowSoft")}; } `} diff --git a/src/scenes/Layout/warning.tsx b/src/scenes/Layout/warning.tsx index 69f53e90e..9cbde94a3 100644 --- a/src/scenes/Layout/warning.tsx +++ b/src/scenes/Layout/warning.tsx @@ -65,7 +65,7 @@ const WorkaroundLink = styled.a` } &:focus-visible { - outline: 1px solid ${({ theme }) => theme.color.contentAccent}; + outline: 1px solid ${({ theme }) => theme.color.borderStrong}; outline-offset: 2px; border-radius: 0.2rem; } diff --git a/src/scenes/Schema/Row/index.tsx b/src/scenes/Schema/Row/index.tsx index d9d631a09..08a130e2d 100644 --- a/src/scenes/Schema/Row/index.tsx +++ b/src/scenes/Schema/Row/index.tsx @@ -138,7 +138,7 @@ const Wrapper = styled.div<{ `} &:hover { - background: ${({ theme }) => theme.color.interactionAccentHover}; + background: ${({ theme }) => theme.color.interactionHover}; .table-menu-button { opacity: 1; } @@ -148,14 +148,14 @@ const Wrapper = styled.div<{ $focused && ` outline: none; - background: ${theme.color.interactionAccentActive}; - box-shadow: inset 0 0 0 1px ${theme.color.borderAccent}; + background: ${theme.color.interactionNeutral}; + box-shadow: inset 0 0 0 1px ${theme.color.borderDefault}; .table-menu-button { opacity: 1; } &:hover { - background: ${theme.color.interactionAccentActive}; + background: ${theme.color.interactionNeutral}; } `} @@ -676,7 +676,7 @@ const Row = ({ onClick={onOpenDetailsDrawer} onDoubleClick={(e) => e.stopPropagation()} > - + )} diff --git a/src/scenes/Schema/VirtualTables/index.tsx b/src/scenes/Schema/VirtualTables/index.tsx index 1931d6672..22c416ca6 100644 --- a/src/scenes/Schema/VirtualTables/index.tsx +++ b/src/scenes/Schema/VirtualTables/index.tsx @@ -139,8 +139,8 @@ const TableRow = styled(Row)<{ $contextMenuOpen: boolean }>` ${({ $contextMenuOpen, theme }) => $contextMenuOpen && ` - background: ${theme.color.interactionAccentActive}; - box-shadow: inset 0 0 0 1px ${theme.color.borderAccent}; + background: ${theme.color.interactionNeutral}; + box-shadow: inset 0 0 0 1px ${theme.color.borderDefault}; `} ` diff --git a/src/scenes/Schema/index.tsx b/src/scenes/Schema/index.tsx index 391505b42..f300e66b6 100644 --- a/src/scenes/Schema/index.tsx +++ b/src/scenes/Schema/index.tsx @@ -93,6 +93,9 @@ const Wrapper = styled(PaneWrapper)<{ }>` overflow-x: auto; height: 100%; + && { + background: ${({ theme }) => theme.color.surfaceRaised}; + } ${({ open }) => !open && css` @@ -106,6 +109,9 @@ const Content = styled(PaneContent)<{ display: flex; flex-direction: column; overflow: auto; + && { + background: ${({ theme }) => theme.color.surfaceRaised}; + } ${({ _loading }) => _loading && loadingStyles}; ` diff --git a/src/scenes/Search/SearchPanel.tsx b/src/scenes/Search/SearchPanel.tsx index 7cc70386b..878046cd3 100644 --- a/src/scenes/Search/SearchPanel.tsx +++ b/src/scenes/Search/SearchPanel.tsx @@ -49,6 +49,9 @@ const Wrapper = styled(PaneWrapper)<{ }>` overflow-x: auto; height: 100%; + && { + background: ${({ theme }) => theme.color.surfaceRaised}; + } ${({ $open }) => !$open && css` @@ -60,6 +63,9 @@ const Content = styled(PaneContent)` display: flex; flex-direction: column; overflow: auto; + && { + background: ${({ theme }) => theme.color.surfaceRaised}; + } ` const SearchInputContainer = styled.div` @@ -96,14 +102,16 @@ const ToggleButtonsContainer = styled.div` gap: 0.2rem; ` -const ToggleButton = styled(SegmentedControlButton)` +const ToggleButton = styled(SegmentedControlButton).attrs({ + $activeTone: "neutral" as const, +})` && { width: 2rem; border: 1px solid transparent; } &&[aria-pressed="true"] { - border-color: ${({ theme }) => theme.color.borderAccentStrong}; + border-color: ${({ theme }) => theme.color.borderDefault}; } ` diff --git a/src/scenes/Search/SearchResults.tsx b/src/scenes/Search/SearchResults.tsx index 09b749c92..345f0316e 100644 --- a/src/scenes/Search/SearchResults.tsx +++ b/src/scenes/Search/SearchResults.tsx @@ -44,15 +44,15 @@ const ItemWrapper = styled.div<{ min-height: 3.2rem; &:hover { - background: ${({ theme }) => theme.color.interactionAccentHover}; + background: ${({ theme }) => theme.color.interactionHover}; } ${({ $focused, theme }) => $focused && ` outline: none; - background: ${theme.color.interactionAccentActive}; - border: 1px solid ${theme.color.borderAccent}; + background: ${theme.color.interactionNeutral}; + box-shadow: inset 0 0 0 1px ${theme.color.borderDefault}; `} ` @@ -80,7 +80,7 @@ const FileIcon = styled.div` svg { width: 1.4rem; height: 1.4rem; - color: ${({ theme }) => theme.color.contentAccent}; + color: ${({ theme }) => theme.color.contentSecondary}; } ` diff --git a/src/scenes/SideMenu/index.tsx b/src/scenes/SideMenu/index.tsx index d4f7472ce..bcf84c87c 100644 --- a/src/scenes/SideMenu/index.tsx +++ b/src/scenes/SideMenu/index.tsx @@ -58,7 +58,7 @@ const Wrapper = styled.div` width: ${RESPONSIVE_WIDTH}; min-height: 0; overflow: hidden; - background: ${({ theme }) => theme.color.surfaceBase}; + background: ${({ theme }) => theme.color.surfaceRaised}; border-left: 1px solid ${({ theme }) => theme.color.borderSubtle}; z-index: 25; diff --git a/src/styles/_editor.scss b/src/styles/_editor.scss index 89eee5722..42d973421 100644 --- a/src/styles/_editor.scss +++ b/src/styles/_editor.scss @@ -171,7 +171,7 @@ color: theme-color(contentPrimary); &:focus { - border-color: theme-color(contentAccent); + border-color: theme-color(borderStrong); box-shadow: none; } diff --git a/src/styles/_grid.scss b/src/styles/_grid.scss index 35714c0ec..1ff23d74b 100644 --- a/src/styles/_grid.scss +++ b/src/styles/_grid.scss @@ -221,7 +221,7 @@ $drag-handle-margin: 2px; } .qg-header-name { - color: theme-color(contentObject) !important; + color: theme-color(contentPrimary) !important; font-size: medium; } diff --git a/src/styles/_quick-vis.scss b/src/styles/_quick-vis.scss index c444b7696..66d82dde9 100644 --- a/src/styles/_quick-vis.scss +++ b/src/styles/_quick-vis.scss @@ -247,7 +247,7 @@ &:focus, &:focus-visible { background: theme-color(surfaceInput); - border-color: theme-color(contentAccent); + border-color: theme-color(borderStrong); box-shadow: none; outline: none; } diff --git a/src/styles/lib/_react-chrome-tabs.scss b/src/styles/lib/_react-chrome-tabs.scss index 362c5bd80..34e253a13 100644 --- a/src/styles/lib/_react-chrome-tabs.scss +++ b/src/styles/lib/_react-chrome-tabs.scss @@ -56,7 +56,7 @@ filter 150ms ease; &:focus-visible { - outline: 1px solid theme-color(contentAccent); + outline: 1px solid theme-color(borderStrong); outline-offset: 2px; } @@ -178,6 +178,26 @@ background: linear-gradient(to left, theme-color(shadowMedium), transparent); } +html[data-theme="light"] .chrome-tabs .chrome-tabs-overflow-shadow { + width: 6px; +} + +html[data-theme="light"] .chrome-tabs .chrome-tabs-overflow-shadow-left { + background: linear-gradient( + to right, + theme-color(shadowMedium) 0%, + theme-color(transparent) 65% + ); +} + +html[data-theme="light"] .chrome-tabs .chrome-tabs-overflow-shadow-right { + background: linear-gradient( + to left, + theme-color(shadowMedium) 0%, + theme-color(transparent) 65% + ); +} + .chrome-tabs[data-overflow-left="true"] .chrome-tabs-overflow-shadow-left { opacity: 1; } @@ -212,7 +232,7 @@ display: none; position: relative; z-index: 1; - border: 1px solid theme-color(contentAccent); + border: 1px solid theme-color(borderStrong); padding: 0.2rem 0.4rem; line-height: 20px; height: 20px; diff --git a/src/styles/main.scss b/src/styles/main.scss index 276533db8..3a6bc07bf 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -53,7 +53,7 @@ $spacing-s: 4px !default; } .ss-content .ss-search input:focus { - border-color: theme-color(contentAccent); + border-color: theme-color(borderStrong); box-shadow: none; } diff --git a/src/theme/global-styles.ts b/src/theme/global-styles.ts index d313dd502..59788d1e0 100644 --- a/src/theme/global-styles.ts +++ b/src/theme/global-styles.ts @@ -81,7 +81,7 @@ export const GlobalStyle = createGlobalStyle` } button[data-button-variant="ghost"]:focus-visible { - outline: 1px solid ${({ theme }) => theme.color.contentAccent}; + outline: 1px solid ${({ theme }) => theme.color.borderStrong}; outline-offset: 2px; } @@ -94,7 +94,7 @@ export const GlobalStyle = createGlobalStyle` } *:focus-visible { - outline: 1px solid ${({ theme }) => theme.color.contentAccent}; + outline: 1px solid ${({ theme }) => theme.color.borderStrong}; outline-offset: 2px; } @@ -183,6 +183,6 @@ export const GlobalStyle = createGlobalStyle` } .allotment-module_splitView__L-yRc > .allotment-module_sashContainer__fzwJF > .allotment-module_sash__QA-2t:hover::before { - background: ${({ theme }) => theme.color.contentAccent}; + background: ${({ theme }) => theme.color.borderStrong}; } ` diff --git a/src/theme/global-styles/docsearch.ts b/src/theme/global-styles/docsearch.ts index c3f05765f..9f656815f 100644 --- a/src/theme/global-styles/docsearch.ts +++ b/src/theme/global-styles/docsearch.ts @@ -108,7 +108,7 @@ export const DocSearchStyles = css` } .DocSearch.DocSearch-Button:focus-visible { - outline: 1px solid ${({ theme }) => theme.color.contentAccent}; + outline: 1px solid ${({ theme }) => theme.color.borderStrong}; outline-offset: 2px; } diff --git a/src/theme/index.ts b/src/theme/index.ts index bb339be7d..9990ae52b 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -157,8 +157,8 @@ export const darkColors: ColorShape = { // Result grid gridRow: "#17181d", gridHeader: "#202126", - gridSelection: "#2b1d25", - gridFocus: "#b81447", + gridSelection: "#252830", + gridFocus: "#6b7382", // Editor editorCanvas: "#17181d", @@ -229,16 +229,16 @@ export const lightColors: ColorShape = { onboardingAccent: "#176f87", // Surfaces - surfaceCanvas: "#d9dce2", - surfaceStage: "#c9cdd4", - surfaceBase: "#e3e5e9", - surfaceInset: "#eceef1", - surfaceRaised: "#e8eaee", - surfaceInput: "#f2f3f5", - surfaceOverlay: "#f2f3f5", - surfaceValue: "#fbfcfd", - surfaceScrim: "rgba(27, 31, 39, 0.38)", - surfaceTabRail: "rgba(218, 221, 227, 0.94)", + surfaceCanvas: "#e8eaee", + surfaceStage: "#e2e5ea", + surfaceBase: "#eef0f3", + surfaceInset: "#f7f8f9", + surfaceRaised: "#f4f5f7", + surfaceInput: "#fafbfc", + surfaceOverlay: "#fafbfc", + surfaceValue: "#ffffff", + surfaceScrim: "rgba(27, 31, 39, 0.32)", + surfaceTabRail: "rgba(232, 234, 238, 0.94)", // Content contentPrimary: "#1c2029", @@ -258,8 +258,8 @@ export const lightColors: ColorShape = { borderAccentStrong: "rgba(184, 20, 71, 0.56)", // Interaction and controls - interactionNeutral: "#d9dce2", - interactionNeutralHover: "#d2d6dd", + interactionNeutral: "#e8eaee", + interactionNeutralHover: "#e2e5ea", interactionHover: "#1c202913", interactionAccentHover: "rgba(184, 20, 71, 0.07)", interactionAccentActive: "rgba(184, 20, 71, 0.13)", @@ -267,7 +267,7 @@ export const lightColors: ColorShape = { scrollbarThumb: "#62656b", controlSurface: "#f6f7f8", controlSurfaceHover: "#e7e9ed", - controlTrack: "#d9dce2", + controlTrack: "#e8eaee", controlKnob: "#505968", // Actions and status @@ -292,11 +292,11 @@ export const lightColors: ColorShape = { statusFeature: "#6553aa", // Shadows - shadowSubtle: "rgba(27, 31, 39, 0.06)", - shadowSoft: "rgba(27, 31, 39, 0.11)", - shadowMedium: "rgba(27, 31, 39, 0.18)", - shadowStrong: "rgba(27, 31, 39, 0.27)", - shadowOverlay: "rgba(27, 31, 39, 0.38)", + shadowSubtle: "rgba(27, 31, 39, 0.035)", + shadowSoft: "rgba(27, 31, 39, 0.055)", + shadowMedium: "rgba(27, 31, 39, 0.08)", + shadowStrong: "rgba(27, 31, 39, 0.16)", + shadowOverlay: "rgba(27, 31, 39, 0.22)", // Liquid glass glassSurface: "rgba(255, 255, 255, 0.58)", @@ -310,14 +310,14 @@ export const lightColors: ColorShape = { aiGradientEnd: "#76184c", // Result grid - gridRow: "#e9ebef", - gridHeader: "#dce0e6", - gridSelection: "#e0afbf", - gridFocus: "#8a0f35", + gridRow: "#f4f5f7", + gridHeader: "#e7eaee", + gridSelection: "#d8dce3", + gridFocus: "#828b99", // Editor - editorCanvas: "#d9dce2", - editorBorder: "#c9cdd4", + editorCanvas: "#eef0f3", + editorBorder: "#e2e5ea", editorSelection: "#aec8ec", editorSelectionAccent: "#7a99c4", editorActiveLine: "#1c202909",