From da0001e77e6d5d311334b939edfe03818d4ff6c3 Mon Sep 17 00:00:00 2001 From: Aleksey Shakhmatov Date: Sat, 23 May 2026 15:02:19 +0300 Subject: [PATCH] =?UTF-8?q?feat(ui):=20"Graphite=20&=20Honey"=20redesign?= =?UTF-8?q?=20=E2=80=94=20warm=20dark,=20monospace-first?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - new design system in globals.css: warm graphite surfaces, ivory text, honey accent; semantic status/data-type/syntax tokens replacing hardcoded colors - IBM Plex Mono as the universal UI font (sans + mono), tabular numerals - custom CodeMirror SQL theme (src/lib/editor-theme.ts) matching the palette - data grid: zebra striping + honey row hover, stronger sticky header - route status dots, JSON syntax, EXPLAIN cost, schema-tree icons and the read/write toggle through the new tokens - TUSK wordmark in the toolbar --- index.html | 5 +- src/components/chat/ChatPanel.tsx | 8 +- src/components/editor/SqlEditor.tsx | 3 +- src/components/history/HistoryPanel.tsx | 4 +- src/components/layout/ReadOnlyToggle.tsx | 4 +- src/components/layout/StatusBar.tsx | 8 +- src/components/layout/Toolbar.tsx | 9 + src/components/memory/MemoryPanel.tsx | 2 +- src/components/results/ExplainView.tsx | 8 +- src/components/results/ResultsJsonView.tsx | 6 +- src/components/results/ResultsTable.tsx | 6 +- .../saved-queries/SavedQueriesPanel.tsx | 2 +- src/components/schema/SchemaTree.tsx | 10 +- src/components/table-viewer/TableDataView.tsx | 4 +- src/lib/editor-theme.ts | 102 +++++ src/styles/globals.css | 374 +++++++++--------- 16 files changed, 346 insertions(+), 209 deletions(-) create mode 100644 src/lib/editor-theme.ts diff --git a/index.html b/index.html index 412e2f8..2f8069e 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,10 @@ Tusk - +
diff --git a/src/components/chat/ChatPanel.tsx b/src/components/chat/ChatPanel.tsx index 94e7424..f3089d2 100644 --- a/src/components/chat/ChatPanel.tsx +++ b/src/components/chat/ChatPanel.tsx @@ -111,13 +111,13 @@ function UsageBadge({ usage }: { usage: ContextUsage | undefined }) { let toneClass = "text-muted-foreground/70"; if (ratio >= 0.85) toneClass = "text-destructive"; - else if (ratio >= 0.6) toneClass = "text-amber-500"; - else if (ratio >= 0.3) toneClass = "text-emerald-500/80"; + else if (ratio >= 0.6) toneClass = "text-warning"; + else if (ratio >= 0.3) toneClass = "text-success/80"; const trackClass = "h-1.5 w-12 overflow-hidden rounded-full bg-muted"; - let fillClass = "bg-emerald-500/70"; + let fillClass = "bg-success/70"; if (ratio >= 0.85) fillClass = "bg-destructive"; - else if (ratio >= 0.6) fillClass = "bg-amber-500"; + else if (ratio >= 0.6) fillClass = "bg-warning"; return ( diff --git a/src/components/editor/SqlEditor.tsx b/src/components/editor/SqlEditor.tsx index 9cc61f6..5df0ff5 100644 --- a/src/components/editor/SqlEditor.tsx +++ b/src/components/editor/SqlEditor.tsx @@ -3,6 +3,7 @@ import { sql, PostgreSQL, StandardSQL } from "@codemirror/lang-sql"; import { keymap } from "@codemirror/view"; import { useCallback, useMemo } from "react"; import { useAppStore } from "@/stores/app-store"; +import { tuskEditorExtensions } from "@/lib/editor-theme"; interface Props { value: string; @@ -44,6 +45,7 @@ export function SqlEditor({ value, onChange, onExecute, onFormat, schema }: Prop const dialect = flavor === "clickhouse" ? StandardSQL : PostgreSQL; const defaultSchema = flavor === "clickhouse" ? undefined : "public"; return [ + tuskEditorExtensions, sql({ dialect, schema: sqlNamespace, @@ -80,7 +82,6 @@ export function SqlEditor({ value, onChange, onExecute, onFormat, schema }: Prop value={value} onChange={handleChange} extensions={extensions} - theme="dark" // height="100%" propagates down to .cm-editor so the inner .cm-scroller // can render a vertical scrollbar; without it, long queries overflow the // flex container and the editor cannot be scrolled. diff --git a/src/components/history/HistoryPanel.tsx b/src/components/history/HistoryPanel.tsx index e622b4d..6440ac4 100644 --- a/src/components/history/HistoryPanel.tsx +++ b/src/components/history/HistoryPanel.tsx @@ -57,9 +57,9 @@ export function HistoryPanel() { >
{entry.status === "success" ? ( - + ) : ( - + )} {entry.sql.length > 80 diff --git a/src/components/layout/ReadOnlyToggle.tsx b/src/components/layout/ReadOnlyToggle.tsx index cd82294..ad60543 100644 --- a/src/components/layout/ReadOnlyToggle.tsx +++ b/src/components/layout/ReadOnlyToggle.tsx @@ -39,8 +39,8 @@ export function ReadOnlyToggle() { size="xs" className={`gap-1.5 font-medium ${ isReadOnly - ? "text-amber-500 hover:bg-amber-500/10 hover:text-amber-500" - : "text-emerald-500 hover:bg-emerald-500/10 hover:text-emerald-500" + ? "text-warning hover:bg-warning/10 hover:text-warning" + : "text-success hover:bg-success/10 hover:text-success" }`} onClick={handleToggle} disabled={toggleMutation.isPending} diff --git a/src/components/layout/StatusBar.tsx b/src/components/layout/StatusBar.tsx index be2e37c..e574c76 100644 --- a/src/components/layout/StatusBar.tsx +++ b/src/components/layout/StatusBar.tsx @@ -42,7 +42,7 @@ export function StatusBar({ rowCount, executionTime }: Props) { @@ -56,8 +56,8 @@ export function StatusBar({ rowCount, executionTime }: Props) { {(readOnlyMap[activeConnectionId] ?? true) ? "READ" : "WRITE"} @@ -86,7 +86,7 @@ export function StatusBar({ rowCount, executionTime }: Props) { diff --git a/src/components/layout/Toolbar.tsx b/src/components/layout/Toolbar.tsx index b652bfc..66d6bb2 100644 --- a/src/components/layout/Toolbar.tsx +++ b/src/components/layout/Toolbar.tsx @@ -66,6 +66,15 @@ export function Toolbar() { "--strip-color": activeColor ?? "transparent", } as React.CSSProperties} > + + TUSK + + +
+