{{ provider.name }}
@@ -218,7 +218,7 @@ const handleSync = async (id: string) => {
/>
{
{
{{ t('common.buttons.delete') }}
diff --git a/tests/store/appStore.test.ts b/tests/store/appStore.test.ts
index 0a949eea..0bd3ff60 100644
--- a/tests/store/appStore.test.ts
+++ b/tests/store/appStore.test.ts
@@ -205,18 +205,18 @@ describe('appStore', () => {
})
describe('getEditorTheme', () => {
- it('should return vs for light theme', () => {
+ it('should return SQLKit theme for light appearance', () => {
const store = useAppStore()
store.uiThemeType = ThemeType.LIGHT
- expect(store.getEditorTheme()).toBe('vs')
+ expect(store.getEditorTheme()).toBe('sqlkit-light')
})
- it('should return vs-dark for dark theme', () => {
+ it('should return SQLKit theme for dark appearance', () => {
const store = useAppStore()
store.uiThemeType = ThemeType.DARK
- expect(store.getEditorTheme()).toBe('vs-dark')
+ expect(store.getEditorTheme()).toBe('sqlkit-dark')
})
})
diff --git a/uno.config.ts b/uno.config.ts
index 01425878..ec079e1d 100644
--- a/uno.config.ts
+++ b/uno.config.ts
@@ -31,9 +31,12 @@ export default defineConfig({
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
background: 'hsl(var(--background))',
+ chrome: 'hsl(var(--chrome))',
+ selection: 'hsl(var(--selection))',
foreground: 'hsl(var(--foreground))',
primary: {
DEFAULT: 'hsl(var(--primary))',
+ text: 'hsl(var(--primary-text))',
foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
@@ -42,6 +45,9 @@ export default defineConfig({
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
+ text: 'hsl(var(--destructive-text))',
+ muted: 'hsl(var(--destructive-muted))',
+ border: 'hsl(var(--destructive-border))',
foreground: 'hsl(var(--destructive-foreground))',
},
success: {
@@ -50,6 +56,12 @@ export default defineConfig({
muted: 'hsl(var(--success-muted))',
border: 'hsl(var(--success-border))',
},
+ warning: {
+ DEFAULT: 'hsl(var(--warning))',
+ foreground: 'hsl(var(--warning-foreground))',
+ muted: 'hsl(var(--warning-muted))',
+ border: 'hsl(var(--warning-border))',
+ },
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))',
@@ -105,13 +117,13 @@ export default defineConfig({
'text-accent-foreground',
'hover:bg-accent',
'hover:text-accent-foreground',
- 'text-primary',
+ 'text-primary-text',
'bg-popover',
'text-popover-foreground',
'bg-destructive/10',
- 'text-destructive',
+ 'text-destructive-text',
'hover:bg-destructive/10',
- 'hover:text-destructive-foreground',
+ 'hover:text-destructive-text',
'bg-success',
'text-success',
'border-success-border',
From 749d4d89d88571b99ecb4e356891faad7655ebcf Mon Sep 17 00:00:00 2001
From: blankll
Date: Wed, 21 Oct 2026 17:47:48 +0800
Subject: [PATCH 2/4] fix(ui): restore tree and toolbar icon recognition cues
---
AGENTS.md | 4 +-
DESIGN.md | 21 +++++--
src/__tests__/theme.test.ts | 9 +++
src/assets/index.css | 10 ++++
.../sidebar/DatabaseSelectorRow.vue | 4 +-
src/components/sidebar/SchemaTree.vue | 60 +++++++++----------
src/pages/QueriesPage.vue | 14 ++---
uno.config.ts | 12 ++++
8 files changed, 87 insertions(+), 47 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
index bf1992aa..3108161d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -9,8 +9,8 @@ Tauri-based cross-platform SQL database GUI client with Vue 3 + TypeScript front
**Before adding or changing client UI, read [DESIGN.md](DESIGN.md).** It is the canonical client design specification; feature design documents describe behavior within that system.
- Preserve SQLKit's existing **blue primary**, light/dark/system themes, compact desktop workspace, and shared shadcn-vue/Radix Vue components. Keep semantic color ownership consistent and retain SQLKit's blue brand and primary actions.
-- Use neutral surfaces, typography, spacing, and borders for hierarchy. Keep accent areas scarce (roughly 10% of application chrome); use at most one solid primary action per operation context. Secondary toolbar actions stay neutral.
-- Colors have fixed roles: `primary` = primary actions/interaction; `success` = actual success/connected/completed; `destructive` = errors/destructive actions. Ordinary information, counts, boolean values, database properties, and file formats are neutral. Do not assign a color to each feature or add a separate AI palette.
+- Use neutral surfaces, typography, spacing, and borders for hierarchy. Keep accent areas scarce (roughly 10% of application chrome); use at most one solid primary action per operation context. Toolbar button surfaces stay neutral; small query-action and object-type icons may use the bounded recognition palette in DESIGN.md.
+- Colors have fixed roles: `primary` = primary actions/interaction; `success` = actual success/connected/completed; `destructive` = errors/destructive actions. Ordinary information, counts, boolean values, database properties, and file formats are neutral. Do not tint whole features or add a separate AI palette. Object-type and query-action icon colors are recognition cues, separate from operational status.
- Reuse semantic CSS tokens from `src/assets/index.css` and their `uno.config.ts` mappings. Do not add palette classes or literal colors for existing UI semantics. `accent` is a neutral interaction surface, not a second brand color.
- `warning` is registered with light/dark foreground, muted-background, and border pairs; `info` is **not registered**. Use `primary-text` and `destructive-text` for readable colored text, reserving the corresponding base tokens for solid actions. Any new semantic token must include light/dark definitions, necessary foreground pairs, UnoCSS mappings, shared variants where needed, contrast verification, and a DESIGN.md update in the same change.
- Non-interactive badges explicitly use `outline`/`secondary` by default; status colors require real state and accompanying text or icons. Syntax highlighting, data charts, diffs, and small vendor logos have the bounded exceptions documented in DESIGN.md.
diff --git a/DESIGN.md b/DESIGN.md
index 838e282b..71c979a8 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -78,6 +78,11 @@ The table records CSS HSL components, used as `hsl(var(--token))`. The frontmatt
| `--warning-foreground` | `0.00 0.00% 100.00%` | `220.00 12.00% 9.80%` | Text on warning fills |
| `--warning-muted` | `39.00 100.00% 96.08%` | `36.67 20.45% 17.25%` | Warning feedback surface |
| `--warning-border` | `39.10 67.94% 74.31%` | `37.36 32.12% 32.35%` | Warning feedback boundary |
+| `--icon-table` | `142.43 71.81% 29.22%` | `143.02 47.25% 64.31%` | Table objects / Execute recognition |
+| `--icon-view` | `262.12 83.26% 57.84%` | `265.41 80.95% 79.41%` | Views / EXPLAIN recognition |
+| `--icon-procedure` | `224.28 76.33% 48.04%` | `218.46 100.00% 77.06%` | Procedures / collection groups / Save recognition |
+| `--icon-function` | `35.65 100.00% 27.06%` | `36.61 79.73% 70.98%` | Functions / Format recognition |
+| `--icon-database` | `43.91 100.00% 27.06%` | `45.00 55.17% 65.88%` | Database recognition |
Dark mode uses the approved softly cool graphite palette. Preserve blue primary actions. Use `primary-text` for blue text and icons, and `destructive-text` for error text and icons; solid fill tokens are not readable-text tokens. `success` and `warning` are paired with dark foregrounds in dark mode and white foregrounds in light mode.
@@ -87,7 +92,7 @@ Dark mode uses the approved softly cool graphite palette. Preserve blue primary
| --- | --- | --- |
| Blue `primary / primary-text` | Primary actions, links, selected controls, small active indicators | Success, ordinary badges, large panel backgrounds |
| Neutrals `foreground / muted / secondary / accent` | Body text, supporting information, toolbars, navigation backgrounds, counts, ordinary attributes, disconnected states | Important errors or risks hidden through low contrast |
-| Green `success` | Successful connection tests, connected states, successful execution, completed transfers | Execute buttons, boolean true, auto-increment attributes, decorative selling points |
+| Green `success` | Successful connection tests, connected states, successful execution, completed transfers | Filled Execute buttons, boolean true, auto-increment attributes, decorative selling points |
| Red `destructive / destructive-text` | Execution failures, connection failures, deletion confirmations | Ordinary task counts, disconnected states, boolean false, decoration |
| Amber `warning` | Actual warnings, risks, exceptional states requiring attention | JSON format, primary keys, ordinary unsaved indicators, arbitrary toolbar buttons |
@@ -97,15 +102,15 @@ Use neutral icons and text for ordinary information; do not introduce a separate
1. **Start with neutrals, then add emphasis.** Most backgrounds, borders, body text, and icons in a resting workspace use existing neutral tokens. Establish hierarchy through typography, spacing, and position first.
2. **Aim for accents to occupy no more than roughly 10% of the UI.** This is a review heuristic for the app shell, toolbars, panels, and forms, not a pixel-counting requirement. Evaluate SQL syntax highlighting, actual data charts, and local error feedback separately for readability; these exceptions must not expand decorative color use.
-3. **Use at most one solid primary action per operation context.** This is usually Execute in a query workspace or Save in a form dialog. Other actions use outline / secondary / ghost. An independent dialog may have its own primary action. Focus rings and status dots do not count as a second solid primary action.
+3. **Use at most one solid primary action per operation context.** Use a solid action only when the context benefits from it, such as Save in a form dialog. Query toolbar actions, including Execute, use compact ghost buttons with colored icons and neutral hover surfaces. An independent dialog may have its own primary action. Focus rings and status dots do not count as a second solid primary action.
4. **Success, warning, and failure may coexist when backed by actual state.** Default to an icon / status dot with text, adding a local, subdued background when needed. Do not tint an entire row, card, or panel.
-5. **Features do not own colors.** Do not give copy / export / format / EXPLAIN or individual filter operators a separate color. The result copy/export icons have the bounded exception below.
+5. **Features do not own colors.** Do not tint feature surfaces or filter operators by category. The object-type, query-action, and result copy/export icons have bounded recognition exceptions below.
### Allowed and avoided treatments
| Context | Default treatment | Avoid |
| --- | --- | --- |
-| Toolbars | Neutral icons and text; `accent` on hover | Blue / purple / orange / green buttons side by side |
+| Query toolbar | Small colored action icons, ghost buttons, neutral `accent` on hover | Solid blue Execute tiles or colored button backgrounds |
| Navigation / tabs | Neutral backgrounds and font weight; small blue indicators when needed | Solid saturated blue blocks or multicolor navigation entries |
| Attribute badges | Explicitly select `outline` or `secondary` on `Badge` | Solid blue badges chosen merely because that variant is the default |
| Connection cards | Name, engine icon, status text / dot | A different colored background for each database engine |
@@ -114,6 +119,10 @@ Use neutral icons and text for ordinary information; do not introduce a separate
### Color exceptions
+- The object browser uses small recognition icons: green table objects, violet views, blue procedures, amber functions, and gold database icons. Tables category nodes use a blue `table-properties` icon while individual tables use a green `table` icon. Labels, counts, chevrons, row backgrounds, and other chrome remain neutral. Materialized views retain a distinct layers glyph. These icon colors identify object types and do not indicate connection or execution state.
+- The query toolbar uses green Execute, violet EXPLAIN / ANALYZE, amber Format, and blue Save icons. All use compact ghost buttons with neutral hover and pressed surfaces; Execute has no persistent solid primary background. Enabled ANALYZE also retains its pressed state and an outline. Accessible labels and distinct glyphs remain required.
+- Recognition colors live in `--icon-table / view / procedure / function / database`, with light/dark definitions and `icon-*` UnoCSS mappings. Query-action mappings reuse this palette without borrowing the status token names. These are foreground-only icon roles; do not use them for button fills, panels, badges, text labels, or status feedback.
+
- Result copy/export icons retain their established format colors: sky blue for CSV, amber for JSON, and emerald for INSERT, including the overflow menu and light/dark variants. This is an icon-only recognition cue; buttons and menu surfaces remain neutral, and labels still identify each action. These colors do not indicate status or extend to other format controls.
- Monaco SQL syntax highlighting, code diffs, and actual data charts may use multiple colors when those colors explain content. Do not extend their palettes into application controls.
- Existing database vendor logos may retain identifying colors inside small icons. Do not extend those colors to cards, buttons, or navigation backgrounds.
@@ -298,7 +307,7 @@ Interactive components must cover default, hover, focus-visible, active / select
### Don't
- Do not assign a color to every feature, database type, filter operator, or file format.
-- Do not use success green for Execute, error red for ordinary counts, or warning colors for ordinary attributes.
+- Do not use success-status tokens for Execute, error red for ordinary counts, or warning colors for ordinary attributes. Execute uses its bounded recognition icon role.
- Do not replace SQLKit's blue theme, force pure-gray neutral surfaces, or switch to monochrome primary buttons to match the reference project.
- Do not add rainbow badges, gradient AI panels, large colored icon containers, or light effects without functional value.
- Do not use historical hardcoding, default Badge styling, or unimplemented tokens as the design basis for new UI.
@@ -320,7 +329,7 @@ Check each affected surface. Documentation-only changes need source, link, and i
### Theme maintenance
- Keep the CSS token source, UnoCSS mappings, Monaco adapter, and this specification synchronized.
-- Shared badges default to neutral secondary. Connection and transfer status signals use semantic tokens; database attributes, booleans, filter operators, task counts, feature icons, and vendor icon containers remain neutral.
+- Shared badges default to neutral secondary. Connection and transfer status signals use semantic tokens; database attributes, booleans, filter operators, task counts, and vendor icon containers remain neutral. Object-type and query-action icons retain the bounded recognition palette above.
- Theme preview tiles scope the same light/dark tokens instead of maintaining a second miniature palette.
- Automated contrast checks cover text on workspace, chrome, raised, selection, and semantic feedback surfaces, plus foregrounds on solid actions. Editor theme tests cover light/dark switching and token inheritance.
- Continue to verify real content, narrow windows, keyboard focus, system appearance changes, and native window controls on the target operating systems. Theme tests do not replace native-platform interaction checks.
diff --git a/src/__tests__/theme.test.ts b/src/__tests__/theme.test.ts
index 5c9b9902..49b34855 100644
--- a/src/__tests__/theme.test.ts
+++ b/src/__tests__/theme.test.ts
@@ -64,6 +64,15 @@ describe.each(['light', 'dark'] as const)('%s theme', (name) => {
},
)
+ it.each(['table', 'view', 'procedure', 'function', 'database'])(
+ 'keeps %s recognition icons readable on neutral surfaces',
+ (role) => {
+ ;['background', 'chrome', 'card', 'accent'].forEach((surface) => {
+ expect(contrast(tokens[`icon-${role}`], tokens[surface])).toBeGreaterThanOrEqual(4.5)
+ })
+ },
+ )
+
it.each(['keyword', 'string', 'number', 'comment'])(
'keeps SQL %s tokens readable',
(token) => {
diff --git a/src/assets/index.css b/src/assets/index.css
index d6d1ebbc..5a7e05b9 100644
--- a/src/assets/index.css
+++ b/src/assets/index.css
@@ -44,6 +44,11 @@
--syntax-string: 23.16 60.64% 36.86%;
--syntax-number: 270.65 39.66% 45.49%;
--syntax-comment: 98.18 12.09% 35.69%;
+ --icon-table: 142.43 71.81% 29.22%;
+ --icon-view: 262.12 83.26% 57.84%;
+ --icon-procedure: 224.28 76.33% 48.04%;
+ --icon-function: 35.65 100.00% 27.06%;
+ --icon-database: 43.91 100.00% 27.06%;
}
.dark {
@@ -90,6 +95,11 @@
--syntax-string: 26.40 47.77% 69.22%;
--syntax-number: 264.49 51.58% 81.37%;
--syntax-comment: 112.50 7.55% 58.43%;
+ --icon-table: 143.02 47.25% 64.31%;
+ --icon-view: 265.41 80.95% 79.41%;
+ --icon-procedure: 218.46 100.00% 77.06%;
+ --icon-function: 36.61 79.73% 70.98%;
+ --icon-database: 45.00 55.17% 65.88%;
}
* {
diff --git a/src/components/sidebar/DatabaseSelectorRow.vue b/src/components/sidebar/DatabaseSelectorRow.vue
index 90c1f45e..7f231c67 100644
--- a/src/components/sidebar/DatabaseSelectorRow.vue
+++ b/src/components/sidebar/DatabaseSelectorRow.vue
@@ -142,11 +142,11 @@ watch(() => props.connectionId, async (connId) => {
@update:model-value="handleSelect"
>
-
+
diff --git a/src/pages/QueriesPage.vue b/src/pages/QueriesPage.vue
index 7f134ddb..8b553e73 100644
--- a/src/pages/QueriesPage.vue
+++ b/src/pages/QueriesPage.vue
@@ -1262,9 +1262,9 @@ function closeResultPanel() {
Date: Wed, 21 Oct 2026 18:01:32 +0800
Subject: [PATCH 3/4] fix(ui): preserve existing functional color cues
---
AGENTS.md | 8 +-
DESIGN.md | 55 ++++---
src/__tests__/theme.test.ts | 9 --
src/assets/index.css | 10 --
.../connections/ConnectingModal.vue | 4 +-
.../connections/DatabaseFileField.vue | 4 +-
src/components/connections/ServerCard.vue | 6 +-
.../connections/ServerFormDialog.vue | 26 ++--
.../connections/SshProfileDialog.vue | 4 +-
.../connections/SshTunnelConfigPanel.vue | 12 +-
.../database-browser/DataTableView.vue | 18 +--
.../database-browser/IndexesTab.vue | 6 +-
src/components/database-browser/QueryTabs.vue | 4 +-
src/components/database-browser/SchemaTab.vue | 8 +-
.../database-browser/ServerInfoView.vue | 2 +-
.../er-diagram/EngineeringEntity.vue | 10 +-
src/components/er-diagram/TableCard.vue | 4 +-
.../explain-plan/ExplainPlanNodeTree.vue | 15 +-
src/components/grid/DataGrid.vue | 7 +-
src/components/grid/EditRowDialog.vue | 2 +-
src/components/grid/FilterBar.vue | 17 ++-
src/components/layout/AppHeader.vue | 2 +-
src/components/layout/UserMenu.vue | 2 +-
src/components/layout/WindowControls.vue | 2 +-
src/components/sidebar/ConnectionSelector.vue | 8 +-
.../sidebar/DatabaseSelectorRow.vue | 4 +-
src/components/sidebar/SchemaTree.vue | 60 ++++----
.../transfer/export/ExportWizard.vue | 4 +-
.../transfer/import/ImportMappingStep.vue | 2 +-
.../transfer/import/ImportWizard.vue | 8 +-
.../transfer/shared/ConnectionSelector.vue | 4 +-
.../transfer/shared/MultiTableSelector.vue | 8 +-
.../transfer/shared/ResultPanel.vue | 2 +-
src/components/transfer/tasks/TaskCard.vue | 10 +-
.../ui/combobox/SearchableSelect.vue | 2 +-
.../DestructiveConfirmDialog.vue | 4 +-
.../ui/notification/AppNotifications.vue | 12 +-
src/composables/useDatabaseIcon.ts | 134 +++++++++---------
src/pages/ConnectionsPage.vue | 28 ++--
src/pages/HistoryPage.vue | 6 +-
src/pages/QueriesPage.vue | 13 +-
.../components/modify-source-modal.vue | 20 +--
.../components/tool-confirmation-card.vue | 6 +-
src/views/setting/mcp-bridge.vue | 4 +-
src/views/setting/plan-section.vue | 6 +-
src/views/setting/provider-list.vue | 4 +-
uno.config.ts | 12 --
47 files changed, 291 insertions(+), 307 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
index 3108161d..8fb4cd82 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -9,13 +9,13 @@ Tauri-based cross-platform SQL database GUI client with Vue 3 + TypeScript front
**Before adding or changing client UI, read [DESIGN.md](DESIGN.md).** It is the canonical client design specification; feature design documents describe behavior within that system.
- Preserve SQLKit's existing **blue primary**, light/dark/system themes, compact desktop workspace, and shared shadcn-vue/Radix Vue components. Keep semantic color ownership consistent and retain SQLKit's blue brand and primary actions.
-- Use neutral surfaces, typography, spacing, and borders for hierarchy. Keep accent areas scarce (roughly 10% of application chrome); use at most one solid primary action per operation context. Toolbar button surfaces stay neutral; small query-action and object-type icons may use the bounded recognition palette in DESIGN.md.
-- Colors have fixed roles: `primary` = primary actions/interaction; `success` = actual success/connected/completed; `destructive` = errors/destructive actions. Ordinary information, counts, boolean values, database properties, and file formats are neutral. Do not tint whole features or add a separate AI palette. Object-type and query-action icon colors are recognition cues, separate from operational status.
-- Reuse semantic CSS tokens from `src/assets/index.css` and their `uno.config.ts` mappings. Do not add palette classes or literal colors for existing UI semantics. `accent` is a neutral interaction surface, not a second brand color.
+- Use neutral surfaces, typography, spacing, and borders for hierarchy. Keep accent areas scarce (roughly 10% of application chrome); use at most one solid primary action per operation context. Keep Execute compact and unfilled. Preserve the original functional icon and data colors documented in DESIGN.md.
+- Colors have fixed roles: `primary` = primary actions/interaction; `success` = actual success/connected/completed; `destructive` = errors/destructive actions. Preserve existing boolean, key/constraint, type, filter, permission, format, and icon recognition colors, with labels or distinct glyphs alongside them. Do not tint whole features or add a separate AI palette. Recognition colors describe content and actions independently of operational status; do not flatten them to gray during surface refactors.
+- Reuse semantic CSS tokens from `src/assets/index.css` and their `uno.config.ts` mappings. Preserve existing palette utilities for functional recognition; a token migration must retain the original hues and theme variants. `accent` is a neutral interaction surface, not a second brand color.
- `warning` is registered with light/dark foreground, muted-background, and border pairs; `info` is **not registered**. Use `primary-text` and `destructive-text` for readable colored text, reserving the corresponding base tokens for solid actions. Any new semantic token must include light/dark definitions, necessary foreground pairs, UnoCSS mappings, shared variants where needed, contrast verification, and a DESIGN.md update in the same change.
- Non-interactive badges explicitly use `outline`/`secondary` by default; status colors require real state and accompanying text or icons. Syntax highlighting, data charts, diffs, and small vendor logos have the bounded exceptions documented in DESIGN.md.
- Provide visible keyboard focus, accessible icon-button names, loading/empty/error states, readable contrast, and localized copy. Reuse runtime platform detection for shortcuts and native window behavior.
-- Existing hardcoded colors and component defaults are migration debt, not permission to repeat them. Distinguish documented targets from implemented behavior, and verify the affected themes, window sizes, and interactions when changing UI.
+- Existing functional recognition colors are intentional compatibility constraints. Avoid new unrelated hardcoded colors. Distinguish documented targets from implemented behavior, and verify the affected themes, window sizes, and interactions when changing UI.
## Build/Lint/Test Commands
diff --git a/DESIGN.md b/DESIGN.md
index 71c979a8..6764bd6f 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -78,11 +78,6 @@ The table records CSS HSL components, used as `hsl(var(--token))`. The frontmatt
| `--warning-foreground` | `0.00 0.00% 100.00%` | `220.00 12.00% 9.80%` | Text on warning fills |
| `--warning-muted` | `39.00 100.00% 96.08%` | `36.67 20.45% 17.25%` | Warning feedback surface |
| `--warning-border` | `39.10 67.94% 74.31%` | `37.36 32.12% 32.35%` | Warning feedback boundary |
-| `--icon-table` | `142.43 71.81% 29.22%` | `143.02 47.25% 64.31%` | Table objects / Execute recognition |
-| `--icon-view` | `262.12 83.26% 57.84%` | `265.41 80.95% 79.41%` | Views / EXPLAIN recognition |
-| `--icon-procedure` | `224.28 76.33% 48.04%` | `218.46 100.00% 77.06%` | Procedures / collection groups / Save recognition |
-| `--icon-function` | `35.65 100.00% 27.06%` | `36.61 79.73% 70.98%` | Functions / Format recognition |
-| `--icon-database` | `43.91 100.00% 27.06%` | `45.00 55.17% 65.88%` | Database recognition |
Dark mode uses the approved softly cool graphite palette. Preserve blue primary actions. Use `primary-text` for blue text and icons, and `destructive-text` for error text and icons; solid fill tokens are not readable-text tokens. `success` and `warning` are paired with dark foregrounds in dark mode and white foregrounds in light mode.
@@ -91,50 +86,50 @@ Dark mode uses the approved softly cool graphite palette. Preserve blue primary
| Visual signal | Allowed meaning | Must not represent |
| --- | --- | --- |
| Blue `primary / primary-text` | Primary actions, links, selected controls, small active indicators | Success, ordinary badges, large panel backgrounds |
-| Neutrals `foreground / muted / secondary / accent` | Body text, supporting information, toolbars, navigation backgrounds, counts, ordinary attributes, disconnected states | Important errors or risks hidden through low contrast |
-| Green `success` | Successful connection tests, connected states, successful execution, completed transfers | Filled Execute buttons, boolean true, auto-increment attributes, decorative selling points |
-| Red `destructive / destructive-text` | Execution failures, connection failures, deletion confirmations | Ordinary task counts, disconnected states, boolean false, decoration |
-| Amber `warning` | Actual warnings, risks, exceptional states requiring attention | JSON format, primary keys, ordinary unsaved indicators, arbitrary toolbar buttons |
+| Neutrals `foreground / muted / secondary / accent` | Body text, supporting information, toolbars, navigation backgrounds, layout hierarchy, disconnected states | Important errors or risks hidden through low contrast |
+| Green `success` | Successful connection tests, connected states, successful execution, completed transfers | Filled Execute buttons or decorative selling points; existing green recognition cues are independent of this status role |
+| Red `destructive / destructive-text` | Execution failures, connection failures, deletion confirmations | Disconnected states or decoration; existing false-value cues are independent of this status role |
+| Amber `warning` | Actual warnings, risks, exceptional states requiring attention | New decorative fills; existing key, format, and unsaved cues retain their recognition colors |
-Use neutral icons and text for ordinary information; do not introduce a separate sky-blue palette. SQLKit's `primary` already owns blue interaction emphasis. Warning includes foreground, muted-background, and border pairs in both themes. There is no `--info` mapping; ordinary information remains neutral. Add tokens only for semantics that require a distinct role.
+Preserve established icon and data colors during surface or theme refactors. Use neutral text for ordinary prose; recognition colors for actions, types, attributes, and values remain useful and must not be flattened to gray. SQLKit's `primary` already owns blue interaction emphasis. Warning includes foreground, muted-background, and border pairs in both themes. There is no `--info` mapping; ordinary information remains neutral. Add tokens only for semantics that require a distinct role.
### Color budget
1. **Start with neutrals, then add emphasis.** Most backgrounds, borders, body text, and icons in a resting workspace use existing neutral tokens. Establish hierarchy through typography, spacing, and position first.
2. **Aim for accents to occupy no more than roughly 10% of the UI.** This is a review heuristic for the app shell, toolbars, panels, and forms, not a pixel-counting requirement. Evaluate SQL syntax highlighting, actual data charts, and local error feedback separately for readability; these exceptions must not expand decorative color use.
-3. **Use at most one solid primary action per operation context.** Use a solid action only when the context benefits from it, such as Save in a form dialog. Query toolbar actions, including Execute, use compact ghost buttons with colored icons and neutral hover surfaces. An independent dialog may have its own primary action. Focus rings and status dots do not count as a second solid primary action.
+3. **Use at most one solid primary action per operation context.** Use a solid action only when the context benefits from it, such as Save in a form dialog. Query toolbar actions, including Execute, use compact ghost buttons with the original colored icons and subtle hover surfaces. An independent dialog may have its own primary action. Focus rings and status dots do not count as a second solid primary action.
4. **Success, warning, and failure may coexist when backed by actual state.** Default to an icon / status dot with text, adding a local, subdued background when needed. Do not tint an entire row, card, or panel.
-5. **Features do not own colors.** Do not tint feature surfaces or filter operators by category. The object-type, query-action, and result copy/export icons have bounded recognition exceptions below.
+5. **Preserve information-bearing color.** Existing object, action, value, attribute, filter, and vendor cues are part of the product vocabulary. Keep their original hues and combine them with distinct glyphs or labels. Use restraint on large surfaces rather than removing these cues.
### Allowed and avoided treatments
| Context | Default treatment | Avoid |
| --- | --- | --- |
-| Query toolbar | Small colored action icons, ghost buttons, neutral `accent` on hover | Solid blue Execute tiles or colored button backgrounds |
+| Query toolbar | Small colored action icons, ghost buttons, subtle hover feedback | Solid blue Execute tiles or colored button backgrounds |
| Navigation / tabs | Neutral backgrounds and font weight; small blue indicators when needed | Solid saturated blue blocks or multicolor navigation entries |
| Attribute badges | Explicitly select `outline` or `secondary` on `Badge` | Solid blue badges chosen merely because that variant is the default |
-| Connection cards | Name, engine icon, status text / dot | A different colored background for each database engine |
+| Connection cards | Name, engine icon, status text / dot | Extending small vendor icon colors across entire connection cards |
| Alerts / notifications | Neutral surfaces, status icons, readable text | Large saturated red or green backgrounds |
| AI assistant / Ultimate indicators | The same neutral containers and small primary accents | A separate purple theme, rainbow gradients, glowing borders |
### Color exceptions
-- The object browser uses small recognition icons: green table objects, violet views, blue procedures, amber functions, and gold database icons. Tables category nodes use a blue `table-properties` icon while individual tables use a green `table` icon. Labels, counts, chevrons, row backgrounds, and other chrome remain neutral. Materialized views retain a distinct layers glyph. These icon colors identify object types and do not indicate connection or execution state.
-- The query toolbar uses green Execute, violet EXPLAIN / ANALYZE, amber Format, and blue Save icons. All use compact ghost buttons with neutral hover and pressed surfaces; Execute has no persistent solid primary background. Enabled ANALYZE also retains its pressed state and an outline. Accessible labels and distinct glyphs remain required.
-- Recognition colors live in `--icon-table / view / procedure / function / database`, with light/dark definitions and `icon-*` UnoCSS mappings. Query-action mappings reuse this palette without borrowing the status token names. These are foreground-only icon roles; do not use them for button fills, panels, badges, text labels, or status feedback.
-
-- Result copy/export icons retain their established format colors: sky blue for CSV, amber for JSON, and emerald for INSERT, including the overflow menu and light/dark variants. This is an icon-only recognition cue; buttons and menu surfaces remain neutral, and labels still identify each action. These colors do not indicate status or extend to other format controls.
+- Preserve the object browser's existing palette: green table groups and objects, purple views, indigo materialized views, blue procedures, amber functions, yellow database icons, and sky schema folders. Keep the original category/leaf shades. Table groups use `table-properties`, table leaves use `table`, and materialized views use `layers`, so identification also has a shape cue.
+- Preserve the query toolbar's original emerald Execute, violet EXPLAIN, amber Format, and sky Save colors, including their light/dark variants and existing ANALYZE state. Execute stays a compact ghost button with no persistent solid primary fill. Accessible labels, pressed semantics, and distinct glyphs remain required.
+- Preserve existing colors for boolean values, primary/foreign keys, uniqueness, identity, filter operators, execution-plan details, permission levels, transfer roles, favorites, and unsaved markers. These encode content or recognition independently of operational success/failure. Keep the existing labels and symbols alongside color.
+- Result copy/export icons retain their established sky CSV, amber JSON, and emerald INSERT colors. Preserve format labels and scope information.
+- Existing palette utilities for these recognition cues remain valid. This surface refactor must not replace them with a new palette or collapse them to neutral tokens. A future migration to shared recognition tokens must preserve the existing hues and light/dark variants and be reviewed separately.
- Monaco SQL syntax highlighting, code diffs, and actual data charts may use multiple colors when those colors explain content. Do not extend their palettes into application controls.
- Existing database vendor logos may retain identifying colors inside small icons. Do not extend those colors to cards, buttons, or navigation backgrounds.
- Charts should emphasize the series of interest with primary and use neutrals for the others. When multiple series need distinction, a dedicated chart palette is allowed with labels, legends, or line styles. `--chart-1` through `--chart-5` exist in CSS but are not registered as UnoCSS color names; do not assume `text-chart-1` works.
-- Data diffs may use success / destructive for additions and deletions, accompanied by `+ / −` or text. Ordinary boolean values do not represent success or failure.
+- Data diffs may use success / destructive for additions and deletions, accompanied by `+ / −` or text. Boolean recognition colors describe values independently of success or failure.
### Token implementation process
1. Check whether an existing role can express the meaning before considering opacity variants. Opacity does not waive contrast requirements: text must remain readable against the actual composited background.
-2. Do not add hex / RGB / HSL literals or palette utilities such as `blue-500`, `green-600`, and `violet-*` in business components to replace existing semantic roles. Isolate chart, syntax, and vendor-asset exceptions in their respective modules.
+2. Do not add hex / RGB / HSL literals or palette utilities such as `blue-500`, `green-600`, and `violet-*` in business components to replace existing semantic roles. Preserve established recognition utilities described above; isolate new chart, syntax, and vendor-asset exceptions in their respective modules.
3. When adding a semantic token, include all of the following in the same change: `:root` and `.dark` definitions in `src/assets/index.css`, necessary foreground / subdued-background pairs, `uno.config.ts` mappings, shared component variants where needed, light/dark verification, and this document's update.
-4. Do not submit UI that depends on unimplemented utilities such as `text-warning` or `bg-info` before their mappings exist. Use `warning` for actual risk; ordinary attributes remain neutral.
+4. Do not submit UI that depends on unimplemented utilities such as `text-warning` or `bg-info` before their mappings exist. Use `warning` for actual risk; preserve the existing attribute recognition palette.
5. Check all consumers before changing shared tokens. Preserve the approved graphite surface hierarchy and blue brand when adjusting individual semantic colors.
## Typography
@@ -261,10 +256,10 @@ Interactive components must cover default, hover, focus-visible, active / select
- Use the shared pagination footer and state model in table browsing and query result grids, starting at 100 rows per page. Keep first / previous / next / last, direct page entry, common page-size presets, custom sizes, and the row range consistent. Wrap footer groups at narrow widths; keep navigation reachable for empty results and disable it while loading or showing an error. Table browsing fetches one page at a time; query grids page returned rows locally and additionally offer all returned rows. Copy / export retains its stated data scope. See [RESULT_PAGINATION_DESIGN.md](docs/RESULT_PAGINATION_DESIGN.md).
- Use the token-driven `sqlkit-light / sqlkit-dark` Monaco themes and preserve user font-size settings. Both inherit Monaco's built-in grammar support; editor, gutter, active-line, selection, completion and hover surfaces read the active CSS theme. Syntax hues live in `--syntax-keyword / string / number / comment` in the same CSS token source. Syntax highlighting is outside the application decoration color budget; reducing colors must not damage syntax recognition.
- Keep data central: neutral headers, subtle hover, stable selection, and clear sorting / filtering indicators. Preserve virtual scrolling; do not rebuild the whole grid for animation.
-- Distinguish `NULL`, empty strings, and booleans. Show true / false or equivalent text / symbols; do not default to red / green boolean mapping.
-- Primary keys, unique constraints, and auto-increment are attributes, not warnings or success. Use neutral identifiers such as a key icon or PK / UNIQUE / identity text.
+- Distinguish `NULL`, empty strings, and booleans. Preserve the existing green true / red false colors and check / cross symbols; color supplements the value glyphs.
+- Preserve existing key / constraint / auto-increment colors and PK / UNIQUE / identity labels. These attribute cues do not imply operational warnings or success.
- Show direction and priority for multi-column sorting. Preserve the capability limits in [GRID_SORT_DESIGN.md](docs/GRID_SORT_DESIGN.md): sorting applies to returned results / the current page, not the whole database or SQL re-execution.
-- Filters use operator text and removable entries, not a rainbow palette for eq / like / gt and other operators.
+- Filters retain their existing operator colors, operator text, and removable entries so repeated conditions remain easy to scan.
- Group formatting, execution plans, copying, and exporting by action. Identify CSV / JSON / INSERT by name. Make export scope and the currently displayed scope explicit.
- Provide details / copying for long text, JSON, and BLOBs rather than leaving an unrecoverable ellipsis. Clearly distinguish editable and read-only grid states.
@@ -272,8 +267,8 @@ Interactive components must cover default, hover, focus-visible, active / select
- AI uses the same neutral surfaces and primary color as the query page. Distinguish user messages, model messages, and code blocks through position, labels, and typography.
- Clearly separate generated SQL awaiting execution from executed results. Execution targets, risk messages, and confirmation follow the ordinary SQL workflow.
-- Imports / exports retain the scopes and steps in [TRANSFER_SCOPE_DESIGN.md](docs/TRANSFER_SCOPE_DESIGN.md). Express step state through names, numbers, and progress rather than a color per step.
-- Task panels clearly show running, completed, failed, and cancelled states. Keep rows neutral and color only local status signals. Normally running tasks must not appear as error alerts.
+- Imports / exports retain the scopes and steps in [TRANSFER_SCOPE_DESIGN.md](docs/TRANSFER_SCOPE_DESIGN.md). Preserve step recognition colors alongside names and numbers; express execution state through progress and status labels.
+- Task panels clearly show running, completed, failed, and cancelled states. Keep rows neutral and preserve local role icons and status signals. Normally running tasks must not appear as error alerts.
### Empty, loading, and error states
@@ -306,8 +301,8 @@ Interactive components must cover default, hover, focus-visible, active / select
### Don't
-- Do not assign a color to every feature, database type, filter operator, or file format.
-- Do not use success-status tokens for Execute, error red for ordinary counts, or warning colors for ordinary attributes. Execute uses its bounded recognition icon role.
+- Do not add decorative color to large feature surfaces or remove established type, filter, or format recognition cues during theme work.
+- Do not turn recognition colors into large filled actions or infer execution status from attribute/value colors. Preserve the compact Execute action and existing icon colors.
- Do not replace SQLKit's blue theme, force pure-gray neutral surfaces, or switch to monochrome primary buttons to match the reference project.
- Do not add rainbow badges, gradient AI panels, large colored icon containers, or light effects without functional value.
- Do not use historical hardcoding, default Badge styling, or unimplemented tokens as the design basis for new UI.
@@ -329,7 +324,7 @@ Check each affected surface. Documentation-only changes need source, link, and i
### Theme maintenance
- Keep the CSS token source, UnoCSS mappings, Monaco adapter, and this specification synchronized.
-- Shared badges default to neutral secondary. Connection and transfer status signals use semantic tokens; database attributes, booleans, filter operators, task counts, and vendor icon containers remain neutral. Object-type and query-action icons retain the bounded recognition palette above.
+- Shared badges default to neutral secondary. Preserve established icon, database-attribute, boolean, filter, permission, format, and vendor colors during theme changes. Use explicit labels or symbols alongside them. Surface tokens and readable semantic feedback remain coordinated across themes.
- Theme preview tiles scope the same light/dark tokens instead of maintaining a second miniature palette.
- Automated contrast checks cover text on workspace, chrome, raised, selection, and semantic feedback surfaces, plus foregrounds on solid actions. Editor theme tests cover light/dark switching and token inheritance.
- Continue to verify real content, narrow windows, keyboard focus, system appearance changes, and native window controls on the target operating systems. Theme tests do not replace native-platform interaction checks.
diff --git a/src/__tests__/theme.test.ts b/src/__tests__/theme.test.ts
index 49b34855..5c9b9902 100644
--- a/src/__tests__/theme.test.ts
+++ b/src/__tests__/theme.test.ts
@@ -64,15 +64,6 @@ describe.each(['light', 'dark'] as const)('%s theme', (name) => {
},
)
- it.each(['table', 'view', 'procedure', 'function', 'database'])(
- 'keeps %s recognition icons readable on neutral surfaces',
- (role) => {
- ;['background', 'chrome', 'card', 'accent'].forEach((surface) => {
- expect(contrast(tokens[`icon-${role}`], tokens[surface])).toBeGreaterThanOrEqual(4.5)
- })
- },
- )
-
it.each(['keyword', 'string', 'number', 'comment'])(
'keeps SQL %s tokens readable',
(token) => {
diff --git a/src/assets/index.css b/src/assets/index.css
index 5a7e05b9..d6d1ebbc 100644
--- a/src/assets/index.css
+++ b/src/assets/index.css
@@ -44,11 +44,6 @@
--syntax-string: 23.16 60.64% 36.86%;
--syntax-number: 270.65 39.66% 45.49%;
--syntax-comment: 98.18 12.09% 35.69%;
- --icon-table: 142.43 71.81% 29.22%;
- --icon-view: 262.12 83.26% 57.84%;
- --icon-procedure: 224.28 76.33% 48.04%;
- --icon-function: 35.65 100.00% 27.06%;
- --icon-database: 43.91 100.00% 27.06%;
}
.dark {
@@ -95,11 +90,6 @@
--syntax-string: 26.40 47.77% 69.22%;
--syntax-number: 264.49 51.58% 81.37%;
--syntax-comment: 112.50 7.55% 58.43%;
- --icon-table: 143.02 47.25% 64.31%;
- --icon-view: 265.41 80.95% 79.41%;
- --icon-procedure: 218.46 100.00% 77.06%;
- --icon-function: 36.61 79.73% 70.98%;
- --icon-database: 45.00 55.17% 65.88%;
}
* {
diff --git a/src/components/connections/ConnectingModal.vue b/src/components/connections/ConnectingModal.vue
index f6f2aadf..b484e3f3 100644
--- a/src/components/connections/ConnectingModal.vue
+++ b/src/components/connections/ConnectingModal.vue
@@ -153,7 +153,7 @@ defineExpose({
@@ -184,7 +184,7 @@ defineExpose({
no longer detected — the tunnel falls back to a direct connection -->