From 3ae1548de0da47ac8b57f918e7520ab1301ac7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E4=B8=AB=E8=AE=B2=E6=A2=B5?= Date: Tue, 8 Sep 2026 01:21:12 +0800 Subject: [PATCH] feat(settings): preview theme and UI fonts on hover --- apps/desktop/src/App.vue | 12 +++- .../editor/EditorSettingsDialog.vue | 60 +++++++++++++++++-- ...ditorSettingsDialog.previewCleanup.spec.ts | 21 +++++++ .../ui/searchable-select/SearchableSelect.vue | 7 ++- .../composables/__tests__/useTheme.spec.ts | 27 +++++++++ .../__tests__/useUiFontFamilyPreview.spec.ts | 25 ++++++++ apps/desktop/src/composables/useTheme.ts | 40 ++++++++++--- .../src/composables/useUiFontFamilyPreview.ts | 19 ++++++ 8 files changed, 194 insertions(+), 17 deletions(-) create mode 100644 apps/desktop/src/components/editor/__tests__/EditorSettingsDialog.previewCleanup.spec.ts create mode 100644 apps/desktop/src/composables/__tests__/useUiFontFamilyPreview.spec.ts create mode 100644 apps/desktop/src/composables/useUiFontFamilyPreview.ts diff --git a/apps/desktop/src/App.vue b/apps/desktop/src/App.vue index a6629d5fa9..1d9592543a 100644 --- a/apps/desktop/src/App.vue +++ b/apps/desktop/src/App.vue @@ -118,6 +118,7 @@ import { shouldBlockAppNativeSelectAll } from "@/lib/common/clipboard"; import { APP_FONT_SANS_CSS_VAR, DATA_GRID_FONT_FAMILY_CSS_VAR, DEFAULT_DATA_GRID_FONT_FAMILY, DEFAULT_UI_FONT_FAMILY } from "@/lib/app/appFonts"; import { DATA_GRID_TYPE_COLOR_KEYS, dataGridTypeColorCssVar, resolveActiveDataGridTypeColors } from "@/lib/dataGrid/dataGridTypeColorScheme"; import { rankSavedSqlHistory } from "@/lib/savedSql/savedSqlHistory"; +import { useUiFontFamilyPreview } from "@/composables/useUiFontFamilyPreview"; import { savedSqlErrorMessage } from "@/lib/savedSql/savedSqlErrors"; import { savedSqlDefaultTargetForWrite } from "@/lib/savedSql/savedSqlExecutionTarget"; import { countActiveUpdateBlockingTasks } from "@/lib/app/appUpdateTaskGuard"; @@ -171,6 +172,7 @@ const { t } = useI18n(); const connectionStore = useConnectionStore(); const queryStore = useQueryStore(); const settingsStore = useSettingsStore(); +const { uiFontFamilyPreview } = useUiFontFamilyPreview(); const savedSqlStore = useSavedSqlStore(); const promptTemplateStore = usePromptTemplateStore(); const recentConnectionIds = ref(parseRecentConnectionIds(safeLocalStorageGet(RECENT_CONNECTION_IDS_STORAGE_KEY))); @@ -1128,7 +1130,7 @@ function applyDataGridTypeColors() { } const appUiFontFamilyStyle = computed>(() => { - const fontFamily = settingsStore.editorSettings.uiFontFamily || DEFAULT_UI_FONT_FAMILY; + const fontFamily = uiFontFamilyPreview.value || settingsStore.editorSettings.uiFontFamily || DEFAULT_UI_FONT_FAMILY; return { [APP_FONT_SANS_CSS_VAR]: fontFamily, fontFamily: `var(${APP_FONT_SANS_CSS_VAR}, ${DEFAULT_UI_FONT_FAMILY})`, @@ -1189,8 +1191,12 @@ watch( ); watch( - () => settingsStore.editorSettings.uiFontFamily, - (fontFamily) => { + [() => settingsStore.editorSettings.uiFontFamily, uiFontFamilyPreview], + ([fontFamily, preview]) => { + if (preview) { + applyUiFontFamily(preview); + return; + } applyUiFontFamily(fontFamily); }, { immediate: true }, diff --git a/apps/desktop/src/components/editor/EditorSettingsDialog.vue b/apps/desktop/src/components/editor/EditorSettingsDialog.vue index 2dc8d2073c..52477a5044 100644 --- a/apps/desktop/src/components/editor/EditorSettingsDialog.vue +++ b/apps/desktop/src/components/editor/EditorSettingsDialog.vue @@ -218,6 +218,7 @@ import { apiUrl, webPath } from "@/lib/common/webPath"; import { DEFAULT_DATA_GRID_FONT_FAMILY, DEFAULT_UI_FONT_FAMILY, normalizeCustomFontFamilyInput, readableFontFamily, SYSTEM_UI_FONT_FAMILY } from "@/lib/app/appFonts"; import { buildFontFamilyOptions, displayFontFamily, isPresetFontFamily, loadSystemFontNames } from "@/lib/app/fontFamilyOptions"; import { buildAppSupportInfoRows, formatAppSupportInfoForClipboard, type AppSupportInfoLabels } from "@/lib/app/supportInfo"; +import { useUiFontFamilyPreview } from "@/composables/useUiFontFamilyPreview"; import { DateTimePatterns, normalizeSupportedDateTimePattern } from "@/lib/dataGrid/columnFormatter"; import { MAX_RESULT_PAGE_SIZE, MIN_RESULT_PAGE_SIZE } from "@/lib/dataGrid/paginationPageSize"; import { MAX_QUERY_RESULT_MAX_ROWS } from "@/lib/dataGrid/queryResultRowLimit"; @@ -234,12 +235,37 @@ const connectionStore = useConnectionStore(); const savedSqlStore = useSavedSqlStore(); const promptTemplateStore = usePromptTemplateStore(); const tunnelProfileStore = useTunnelProfileStore(); -const { isDark, themeMode, themePalette, activeCustomUiColors, cornerStyle, setThemeMode, setThemePalette, setCustomUiColors, resetCustomUiColors, setCornerStyle } = useTheme(); +const { isDark, themeMode, themePalette, activeCustomUiColors, cornerStyle, setThemeMode, setThemePalette, previewThemePalette, clearThemePalettePreview, setCustomUiColors, resetCustomUiColors, setCornerStyle } = useTheme(); +const { previewUiFontFamily, clearUiFontFamilyPreview } = useUiFontFamilyPreview(); function updateCustomUiColor(key: keyof AppCustomUiColors, value: string) { setCustomUiColors({ ...activeCustomUiColors.value, [key]: value }); } +function onThemePaletteSelect(value: unknown) { + if (typeof value === "string") setThemePalette(value as AppThemePalette); +} + +function onThemePaletteOpenChange(open: boolean) { + if (!open) clearThemePalettePreview(); +} + +function previewUiFontOption(value: string | undefined) { + if (value) previewUiFontFamily(value); +} + +function restoreUiFontFamilyPreview() { + previewUiFontFamily(editUiFontFamily.value); +} + +function onUiFontFamilyOpenChange(open: boolean) { + if (open) { + void loadSystemFontOptions(); + } else { + restoreUiFontFamilyPreview(); + } +} + const appThemePaletteOptions = computed( (): Array<{ value: AppThemePalette; label: string; previewColor: string }> => APP_THEME_PALETTES.map((palette) => ({ @@ -1496,6 +1522,20 @@ watch( editMetadataCacheMaxMemoryMb.value = settingsStore.desktopSettings.metadata_cache_max_memory_mb; editDuckDbWorkerProcessIsolation.value = settingsStore.desktopSettings.duckdb_worker_process_isolation; editSidebarTablePageSize.value = settingsStore.desktopSettings.sidebar_table_page_size ?? DEFAULT_SIDEBAR_TABLE_PAGE_SIZE; + } else { + clearThemePalettePreview(); + clearUiFontFamilyPreview(); + } + }, + { immediate: true }, +); + +watch( + () => settingsStore.settingsPageActive, + (active) => { + if (isSettingsPage.value && !active) { + clearThemePalettePreview(); + clearUiFontFamilyPreview(); } }, { immediate: true }, @@ -2044,7 +2084,10 @@ function onTableFontFamilyChange(v: any) { } function onUiFontFamilyChange(v: any) { - if (typeof v === "string") editUiFontFamily.value = v; + if (typeof v === "string") { + editUiFontFamily.value = v; + previewUiFontFamily(v); + } } const themeSelectValue = computed(() => { @@ -3717,6 +3760,8 @@ onMounted(() => { }); onUnmounted(() => { + clearThemePalettePreview(); + clearUiFontFamilyPreview(); cleanupTableColumnTemplatePointerDrag(); cleanupTruncationObservers(); }); @@ -5682,7 +5727,7 @@ onUnmounted(() => {
- @@ -5696,8 +5741,8 @@ onUnmounted(() => { - - + +
{{ option.label }} @@ -5776,7 +5821,10 @@ onUnmounted(() => { :trigger-icon-class="appearanceFontSearchTriggerIconClass" content-class="w-[var(--reka-popover-trigger-width)] min-w-[260px]" @update:model-value="onUiFontFamilyChange" - @update:open="(open: boolean) => open && loadSystemFontOptions()" + @update:open="onUiFontFamilyOpenChange" + @option-hover="previewUiFontOption" + @option-highlight="previewUiFontOption" + @option-leave="restoreUiFontFamilyPreview" >