diff --git a/src/crates/core/src/service/config/types.rs b/src/crates/core/src/service/config/types.rs index 87514fbb..819bb55a 100644 --- a/src/crates/core/src/service/config/types.rs +++ b/src/crates/core/src/service/config/types.rs @@ -7,6 +7,30 @@ use async_trait::async_trait; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +/// Web UI font preferences (settings → basics). Keys match `FontPreference` in the frontend (camelCase). +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct FontPreferenceSnapshot { + pub ui_size: UiFontSizeSnapshot, + pub flow_chat: FlowChatFontSnapshot, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UiFontSizeSnapshot { + pub level: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub custom_px: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct FlowChatFontSnapshot { + pub mode: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub base_px: Option, +} + /// Global configuration structure - matches the frontend `GlobalConfig` exactly. #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(default)] @@ -23,6 +47,9 @@ pub struct GlobalConfig { /// Theme system configuration. #[serde(skip_serializing_if = "Option::is_none")] pub themes: Option, + /// Web UI font size preferences (`get_config` / `set_config` path `font`). + #[serde(skip_serializing_if = "Option::is_none")] + pub font: Option, pub version: String, #[serde(with = "chrono::serde::ts_milliseconds")] pub last_modified: chrono::DateTime, @@ -910,6 +937,7 @@ impl Default for GlobalConfig { ai: AIConfig::default(), mcp_servers: None, themes: Some(ThemesConfig::default()), + font: None, version: "1.0.0".to_string(), last_modified: chrono::Utc::now(), } diff --git a/src/web-ui/src/app/components/GalleryLayout/GalleryDetailModal.scss b/src/web-ui/src/app/components/GalleryLayout/GalleryDetailModal.scss index 38dd17ff..0c99eb76 100644 --- a/src/web-ui/src/app/components/GalleryLayout/GalleryDetailModal.scss +++ b/src/web-ui/src/app/components/GalleryLayout/GalleryDetailModal.scss @@ -46,7 +46,7 @@ &__description { margin: 0; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-relaxed; } @@ -56,7 +56,7 @@ gap: $size-gap-2; flex-wrap: wrap; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__content { diff --git a/src/web-ui/src/app/components/GalleryLayout/GalleryLayout.scss b/src/web-ui/src/app/components/GalleryLayout/GalleryLayout.scss index b669cdfb..aec3ad12 100644 --- a/src/web-ui/src/app/components/GalleryLayout/GalleryLayout.scss +++ b/src/web-ui/src/app/components/GalleryLayout/GalleryLayout.scss @@ -75,7 +75,7 @@ $content-max: 1480px; &__subtitle { margin: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); line-height: $line-height-relaxed; @@ -130,13 +130,13 @@ $content-max: 1480px; } &__title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); } &__subtitle { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); line-height: $line-height-relaxed; } @@ -197,7 +197,7 @@ $content-max: 1480px; justify-content: center; gap: $size-gap-3; padding: $size-gap-8 $size-gap-6; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); text-align: center; @@ -268,7 +268,7 @@ $content-max: 1480px; } .gallery-action-btn { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; &--primary { @@ -317,7 +317,7 @@ $content-max: 1480px; border-radius: $size-radius-full; background: transparent; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; cursor: pointer; @@ -377,7 +377,7 @@ $content-max: 1480px; border-radius: $size-radius-full; background: var(--element-bg-medium); border: 1px solid var(--border-subtle); - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-muted); white-space: nowrap; @@ -396,7 +396,7 @@ $content-max: 1480px; } .gallery-run-empty { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); padding: $size-gap-3 0; text-align: center; diff --git a/src/web-ui/src/app/components/NavPanel/NavPanel.scss b/src/web-ui/src/app/components/NavPanel/NavPanel.scss index 119d0968..8ddf0ed6 100644 --- a/src/web-ui/src/app/components/NavPanel/NavPanel.scss +++ b/src/web-ui/src/app/components/NavPanel/NavPanel.scss @@ -134,7 +134,7 @@ $_section-header-height: 24px; &__mode-pill-caption { margin: 0; padding: 0 4px; - font-size: 10px; + font-size: var(--font-size-xxs); line-height: 1.35; color: var(--color-text-muted); opacity: 0.78; @@ -254,7 +254,7 @@ $_section-header-height: 24px; gap: 4px; min-width: 0; padding: 6px 4px; - font-size: 10px; + font-size: var(--font-size-xxs); font-weight: 600; line-height: 1.15; color: var(--color-text-muted); @@ -355,7 +355,7 @@ $_section-header-height: 24px; border-radius: $size-radius-base 0 0 $size-radius-base; background: var(--element-bg-soft); color: var(--color-text-primary); - font-size: 12px; + font-size: var(--font-size-xs); font-weight: 600; cursor: pointer; transition: background $motion-fast $easing-standard, @@ -473,7 +473,7 @@ $_section-header-height: 24px; background: transparent; color: var(--color-text-secondary); cursor: pointer; - font-size: $font-size-sm; + font-size: var(--font-size-sm); text-align: left; transition: color $motion-fast $easing-standard, background $motion-fast $easing-standard; @@ -576,7 +576,7 @@ $_section-header-height: 24px; } &__section-label { - font-size: 11px; + font-size: var(--font-size-2xs); font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; @@ -589,7 +589,7 @@ $_section-header-height: 24px; } &__section-header--scene-entry &__section-label { - font-size: 13px; + font-size: var(--font-size-sm); font-weight: 600; letter-spacing: normal; text-transform: none; @@ -659,7 +659,7 @@ $_section-header-height: 24px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: 13px; + font-size: var(--font-size-sm); font-weight: 500; line-height: 1.1; } @@ -728,7 +728,7 @@ $_section-header-height: 24px; position: absolute; top: 0; right: -36px; - font-size: 9px; + font-size: var(--font-size-xxs); padding: 1px 5px; border-radius: 4px; } @@ -738,7 +738,7 @@ $_section-header-height: 24px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: 13px; + font-size: var(--font-size-sm); font-weight: 500; line-height: 1.1; } @@ -794,7 +794,7 @@ $_section-header-height: 24px; &--more { background: color-mix(in srgb, var(--element-bg-medium) 92%, transparent); color: var(--color-text-secondary); - font-size: 10px; + font-size: var(--font-size-xxs); font-weight: 700; letter-spacing: 0.01em; filter: none; @@ -902,7 +902,7 @@ $_section-header-height: 24px; background: transparent; color: var(--color-text-secondary); cursor: pointer; - font-size: $font-size-sm; + font-size: var(--font-size-sm); text-align: left; transition: color $motion-fast $easing-standard, background $motion-fast $easing-standard; @@ -984,7 +984,7 @@ $_section-header-height: 24px; gap: $size-gap-1; padding: $size-gap-1 $size-gap-3; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); text-transform: uppercase; letter-spacing: 0.04em; } @@ -992,7 +992,7 @@ $_section-header-height: 24px; &__workspace-menu-empty { padding: $size-gap-2 $size-gap-3; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__workspace-menu-workspaces { @@ -1129,7 +1129,7 @@ $_section-header-height: 24px; color: var(--color-text-primary); cursor: pointer; text-align: left; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; width: 100%; position: relative; @@ -1215,7 +1215,7 @@ $_section-header-height: 24px; &__item-badge { flex-shrink: 0; - font-size: 10px; + font-size: var(--font-size-xxs); color: var(--color-text-muted); margin-left: auto; max-width: 80px; @@ -1561,7 +1561,7 @@ $_section-header-height: 24px; background: transparent; color: var(--color-text-secondary); cursor: pointer; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; text-align: left; white-space: nowrap; @@ -1660,7 +1660,7 @@ $_section-header-height: 24px; background: transparent; color: var(--color-text-secondary); cursor: pointer; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; text-align: left; white-space: nowrap; @@ -1718,7 +1718,7 @@ $_section-header-height: 24px; .bitfun-nav-panel__remote-disclaimer-text { margin: 0; - font-size: 12px; + font-size: var(--font-size-xs); line-height: 1.2; color: var(--color-text-muted); } @@ -1731,7 +1731,7 @@ $_section-header-height: 24px; gap: 0; li { - font-size: 12px; + font-size: var(--font-size-xs); line-height: 1.2; color: var(--color-text-secondary); padding-right: 0; @@ -1752,7 +1752,7 @@ $_section-header-height: 24px; border: 1px solid transparent; min-width: 112px; padding: 7px 16px; - font-size: 12px; + font-size: var(--font-size-xs); cursor: pointer; transition: all $motion-fast $easing-standard; } @@ -1898,7 +1898,7 @@ $_section-header-height: 24px; border-radius: $size-radius-base; background: transparent; color: var(--color-text-primary); - font-size: 12.5px; + font-size: var(--font-size-sm); font-weight: 500; cursor: pointer; text-align: left; diff --git a/src/web-ui/src/app/components/NavPanel/NavSearchDialog.scss b/src/web-ui/src/app/components/NavPanel/NavSearchDialog.scss index 20a58790..99767449 100644 --- a/src/web-ui/src/app/components/NavPanel/NavSearchDialog.scss +++ b/src/web-ui/src/app/components/NavPanel/NavSearchDialog.scss @@ -94,7 +94,7 @@ } &.search .search__input { - font-size: $font-size-sm; + font-size: var(--font-size-sm); &::placeholder { color: var(--color-text-disabled); @@ -142,7 +142,7 @@ padding: $size-gap-4 $size-gap-2; text-align: center; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); animation: bitfun-nav-search-fade-rise 0.32s cubic-bezier(0.22, 1, 0.36, 1) 0.06s both; } @@ -172,7 +172,7 @@ .bitfun-nav-search-dialog__group-label { padding: $size-gap-1 $size-gap-1 $size-gap-1 2px; - font-size: 10px; + font-size: var(--font-size-xxs); font-weight: 700; color: var(--color-text-muted); text-transform: uppercase; @@ -229,7 +229,7 @@ } .bitfun-nav-search-dialog__item-label { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-primary); white-space: nowrap; overflow: hidden; @@ -237,7 +237,7 @@ } .bitfun-nav-search-dialog__item-sublabel { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; @@ -276,7 +276,7 @@ inset 0 0 0 1px color-mix(in srgb, var(--border-subtle) 65%, transparent); cursor: text; color: var(--color-text-primary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); text-align: left; box-sizing: border-box; transition: diff --git a/src/web-ui/src/app/components/NavPanel/components/BranchQuickSwitch.scss b/src/web-ui/src/app/components/NavPanel/components/BranchQuickSwitch.scss index bfa45ffc..09f218b4 100644 --- a/src/web-ui/src/app/components/NavPanel/components/BranchQuickSwitch.scss +++ b/src/web-ui/src/app/components/NavPanel/components/BranchQuickSwitch.scss @@ -31,7 +31,7 @@ .branch-quick-switch__input { width: 100%; padding: 6px 10px; - font-size: 12px; + font-size: var(--font-size-xs); border: 1px solid var(--border-subtle); border-radius: 4px; background: var(--color-bg-secondary); @@ -73,7 +73,7 @@ justify-content: center; gap: 8px; color: var(--color-text-muted); - font-size: 12px; + font-size: var(--font-size-xs); } // ── Item ──────────────────────────────────────────────── @@ -106,7 +106,7 @@ } .branch-quick-switch__item-icon { flex-shrink: 0; color: var(--color-text-primary); } -.branch-quick-switch__item-name { flex: 1; font-size: 12px; color: var(--color-text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.branch-quick-switch__item-name { flex: 1; font-size: var(--font-size-xs); color: var(--color-text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .branch-quick-switch__item-check { flex-shrink: 0; color: var(--color-text-primary); } .branch-quick-switch__spinner { diff --git a/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.scss b/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.scss index efc563b7..342c8424 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.scss +++ b/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.scss @@ -29,7 +29,7 @@ border-radius: $size-radius-sm; background: transparent; color: var(--color-text-primary); - font-size: 12px; + font-size: var(--font-size-xs); cursor: pointer; flex: 1; min-width: 0; @@ -48,7 +48,7 @@ } &__inline-empty { - font-size: 12px; + font-size: var(--font-size-xs); color: var(--color-text-muted); padding: 4px $size-gap-1; font-style: italic; @@ -64,7 +64,7 @@ border-radius: 4px; background: transparent; color: var(--color-text-primary); - font-size: 13px; + font-size: var(--font-size-sm); font-weight: 500; cursor: pointer; width: 100%; @@ -94,7 +94,7 @@ &.is-child { min-height: 24px; - font-size: 12px; + font-size: var(--font-size-xs); padding-left: calc(#{$size-gap-1} + 14px); position: relative; @@ -192,7 +192,7 @@ border-radius: 999px; background: color-mix(in srgb, var(--element-bg-soft) 42%, transparent); color: var(--color-text-muted); - font-size: 9px; + font-size: var(--font-size-xxs); font-weight: 500; letter-spacing: 0.02em; opacity: 0.78; @@ -206,7 +206,7 @@ } &__inline-item-tooltip-title { - font-size: 12px; + font-size: var(--font-size-xs); font-weight: 600; color: var(--color-text-primary); line-height: 1.4; @@ -214,7 +214,7 @@ } &__inline-item-tooltip-meta { - font-size: 11px; + font-size: var(--font-size-2xs); color: var(--color-text-secondary); line-height: 1.4; word-break: break-word; @@ -279,7 +279,7 @@ border: none; background: transparent; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; cursor: pointer; text-align: left; @@ -328,7 +328,7 @@ } .bitfun-input { - font-size: 12px; + font-size: var(--font-size-xs); line-height: 16px; } @@ -349,7 +349,7 @@ border-radius: 4px; background: transparent; color: var(--color-text-primary); - font-size: 11px; + font-size: var(--font-size-2xs); cursor: pointer; width: 100%; transition: color $motion-fast $easing-standard, @@ -363,7 +363,7 @@ &__inline-toggle-dots { letter-spacing: 1px; - font-size: 13px; + font-size: var(--font-size-sm); line-height: 1; opacity: 0.7; } @@ -415,7 +415,7 @@ // Inline item badge (count / status text) &__inline-item-badge { flex-shrink: 0; - font-size: 10px; + font-size: var(--font-size-xxs); line-height: 1; color: var(--color-text-muted); margin-left: auto; diff --git a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceListSection.scss b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceListSection.scss index f653a4f1..aafbb7c1 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceListSection.scss +++ b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceListSection.scss @@ -28,7 +28,7 @@ justify-content: space-between; gap: $size-gap-1; color: var(--color-text-primary); - font-size: 10px; + font-size: var(--font-size-xxs); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; @@ -66,7 +66,7 @@ padding: $size-gap-2; border-radius: $size-radius-base; color: var(--color-text-muted); - font-size: 12px; + font-size: var(--font-size-xs); background: color-mix(in srgb, var(--element-bg-soft) 55%, transparent); } @@ -236,7 +236,7 @@ overflow: hidden; .bitfun-nav-panel__workspace-item-avatar-letter { - font-size: 16px; + font-size: var(--font-size-lg); font-weight: 700; line-height: 1; text-transform: uppercase; @@ -312,7 +312,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: 12px; + font-size: var(--font-size-xs); font-weight: 600; } @@ -338,7 +338,7 @@ min-width: 0; max-width: 100%; color: var(--color-text-muted); - font-size: 10px; + font-size: var(--font-size-xxs); line-height: 1.2; opacity: 0.75; @@ -384,7 +384,7 @@ border-radius: 999px; background: color-mix(in srgb, var(--color-accent-200) 88%, transparent); color: var(--color-text-secondary); - font-size: 10px; + font-size: var(--font-size-xxs); font-weight: 700; line-height: 1.4; white-space: nowrap; @@ -401,7 +401,7 @@ border-radius: 999px; background: color-mix(in srgb, var(--element-bg-medium) 75%, transparent); color: var(--color-text-primary); - font-size: 10px; + font-size: var(--font-size-xxs); transition: max-width $motion-fast $easing-standard, padding $motion-fast $easing-standard, opacity $motion-fast $easing-standard, @@ -473,7 +473,7 @@ border-radius: $size-radius-sm; background: transparent; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; cursor: pointer; text-align: left; @@ -681,7 +681,7 @@ } &__assistant-item-avatar-letter { - font-size: 15px; + font-size: var(--font-size-base); font-weight: 700; line-height: 1; text-transform: uppercase; @@ -733,7 +733,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: 12px; + font-size: var(--font-size-xs); font-weight: 600; } @@ -746,7 +746,7 @@ border-radius: 999px; background: color-mix(in srgb, var(--color-accent-200) 88%, transparent); color: var(--color-text-secondary); - font-size: 10px; + font-size: var(--font-size-xxs); font-weight: 700; line-height: 1.4; white-space: nowrap; diff --git a/src/web-ui/src/app/components/RemoteConnectDialog/RemoteConnectDialog.scss b/src/web-ui/src/app/components/RemoteConnectDialog/RemoteConnectDialog.scss index 91a8fcdb..e61d6cf3 100644 --- a/src/web-ui/src/app/components/RemoteConnectDialog/RemoteConnectDialog.scss +++ b/src/web-ui/src/app/components/RemoteConnectDialog/RemoteConnectDialog.scss @@ -468,7 +468,7 @@ .bitfun-remote-connect__mode-btn { padding: 5px 14px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: $color-text-muted; background: transparent; diff --git a/src/web-ui/src/app/components/SceneBar/SceneBar.scss b/src/web-ui/src/app/components/SceneBar/SceneBar.scss index 86b85179..9253b773 100644 --- a/src/web-ui/src/app/components/SceneBar/SceneBar.scss +++ b/src/web-ui/src/app/components/SceneBar/SceneBar.scss @@ -63,7 +63,7 @@ $_tab-v-margin: 6px; // symmetric top/bottom gap inside SceneBar position: relative; cursor: pointer; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; white-space: nowrap; // Slightly lift off --color-bg-primary so tabs never disappear into the chrome @@ -166,13 +166,13 @@ $_tab-v-margin: 6px; // symmetric top/bottom gap inside SceneBar &__sep { color: var(--color-text-disabled); - font-size: $font-size-xs; + font-size: var(--font-size-xs); flex-shrink: 0; } &__subtitle { color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; diff --git a/src/web-ui/src/app/components/TitleBar/InsightsButton.scss b/src/web-ui/src/app/components/TitleBar/InsightsButton.scss index 8a29b422..154a0c8c 100644 --- a/src/web-ui/src/app/components/TitleBar/InsightsButton.scss +++ b/src/web-ui/src/app/components/TitleBar/InsightsButton.scss @@ -40,7 +40,7 @@ } &__progress-text { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); white-space: nowrap; } diff --git a/src/web-ui/src/app/components/TitleBar/NotificationButton.scss b/src/web-ui/src/app/components/TitleBar/NotificationButton.scss index 30547f45..3364e9f7 100644 --- a/src/web-ui/src/app/components/TitleBar/NotificationButton.scss +++ b/src/web-ui/src/app/components/TitleBar/NotificationButton.scss @@ -14,7 +14,7 @@ cursor: pointer; padding: 4px 6px; border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); flex-shrink: 0; position: relative; transition: color $motion-fast $easing-standard, @@ -41,7 +41,7 @@ } &__progress-text { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); white-space: nowrap; } @@ -72,7 +72,7 @@ border: 1px solid var(--border-medium); border-radius: $size-radius-sm; padding: 4px 8px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-primary); box-shadow: var(--shadow-md); max-width: 300px; diff --git a/src/web-ui/src/app/components/TitleBar/TitleBar.scss b/src/web-ui/src/app/components/TitleBar/TitleBar.scss index a76fdbdc..b4f2258b 100644 --- a/src/web-ui/src/app/components/TitleBar/TitleBar.scss +++ b/src/web-ui/src/app/components/TitleBar/TitleBar.scss @@ -482,7 +482,7 @@ $_app-icon-size: 20px; // App title text .bitfun-app-title { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-weight: tokens.$font-weight-bold; color: tokens.$color-text-primary; text-shadow: tokens.$shadow-xs; diff --git a/src/web-ui/src/app/components/panels/FilesPanel.scss b/src/web-ui/src/app/components/panels/FilesPanel.scss index 274c110e..7128a877 100644 --- a/src/web-ui/src/app/components/panels/FilesPanel.scss +++ b/src/web-ui/src/app/components/panels/FilesPanel.scss @@ -98,7 +98,7 @@ padding: $size-gap-2 $size-gap-3; background: var(--element-bg-subtle); border-bottom: 1px solid $border-base; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: $color-accent-600; flex-shrink: 0; } @@ -174,7 +174,7 @@ } &__transfer-label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); margin-bottom: $size-gap-1; white-space: nowrap; @@ -226,7 +226,7 @@ text-align: center; p { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); margin: 0; } @@ -254,7 +254,7 @@ padding: $size-gap-5; p { - font-size: $font-size-sm; + font-size: var(--font-size-sm); margin: 0 0 $size-gap-3 0; } } @@ -267,7 +267,7 @@ color: var(--color-text-muted); cursor: pointer; transition: all $motion-base $easing-standard; - font-size: $font-size-xs; + font-size: var(--font-size-xs); &:hover { background: var(--element-bg-soft); @@ -288,7 +288,7 @@ padding: $size-gap-5; p { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); margin: 0; } @@ -397,14 +397,14 @@ &__search-status { padding: $size-gap-3 $size-gap-4; - font-size: $font-size-sm; + font-size: var(--font-size-sm); } &__placeholder { padding: $size-gap-8; p { - font-size: $font-size-base; + font-size: var(--font-size-base); } } @@ -415,7 +415,7 @@ &__loading { p { - font-size: $font-size-base; + font-size: var(--font-size-base); } } @@ -428,13 +428,13 @@ padding: $size-gap-8; p { - font-size: $font-size-base; + font-size: var(--font-size-base); } } &__retry-button { padding: $size-gap-2 $size-gap-4; - font-size: $font-size-sm; + font-size: var(--font-size-sm); } } } diff --git a/src/web-ui/src/app/components/panels/base/FlexiblePanel.scss b/src/web-ui/src/app/components/panels/base/FlexiblePanel.scss index c8f48928..5202e733 100644 --- a/src/web-ui/src/app/components/panels/base/FlexiblePanel.scss +++ b/src/web-ui/src/app/components/panels/base/FlexiblePanel.scss @@ -85,14 +85,14 @@ .bitfun-flexible-panel__content-title { @include mixins.text-ellipsis; - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); } .bitfun-flexible-panel__content-type { @include mixins.text-ellipsis; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); } @@ -138,7 +138,7 @@ p { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); } } @@ -163,14 +163,14 @@ h3 { margin: 0 0 $size-gap-2 0; - font-size: $font-size-xl; + font-size: var(--font-size-xl); font-weight: $font-weight-semibold; color: var(--color-text-primary); } p { margin: 0; - font-size: $font-size-base; + font-size: var(--font-size-base); color: var(--color-text-secondary); } } @@ -196,7 +196,7 @@ border: none; border-radius: 0; font-family: $font-family-mono; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-relaxed; overflow: auto; } @@ -267,7 +267,7 @@ background: var(--color-bg-secondary); color: var(--color-text-primary); font-family: $font-family-mono; - font-size: $font-size-base; + font-size: var(--font-size-base); line-height: $line-height-relaxed; resize: vertical; outline: none; @@ -295,7 +295,7 @@ border: 1px solid var(--border-base); border-radius: $size-radius-base; font-family: $font-family-mono; - font-size: $font-size-base; + font-size: var(--font-size-base); line-height: $line-height-relaxed; white-space: pre-wrap; word-break: break-word; @@ -323,14 +323,14 @@ h3 { margin: 0; - font-size: $font-size-xl; + font-size: var(--font-size-xl); font-weight: $font-weight-semibold; color: var(--color-text-primary); } p { margin: 0; - font-size: $font-size-base; + font-size: var(--font-size-base); color: var(--color-text-secondary); max-width: 400px; } @@ -344,7 +344,7 @@ font-family: $font-family-mono; code { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-primary); background: transparent; padding: 0; @@ -371,7 +371,7 @@ p { margin: 0; - font-size: $font-size-base; + font-size: var(--font-size-base); color: var(--color-error); } } @@ -387,7 +387,7 @@ p { margin: 0; - font-size: $font-size-base; + font-size: var(--font-size-base); color: var(--color-text-muted); font-style: italic; } @@ -401,7 +401,7 @@ p { margin: 0; - font-size: $font-size-base; + font-size: var(--font-size-base); color: var(--color-text-secondary); } @@ -412,7 +412,7 @@ border: 1px solid var(--border-base); border-radius: $size-radius-base; font-family: $font-family-mono; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-relaxed; overflow: auto; max-width: 100%; @@ -434,7 +434,7 @@ h4 { margin: 0 0 4px 0; - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); } @@ -442,7 +442,7 @@ .bitfun-flexible-panel__file-path { margin: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); font-family: $font-family-mono; } @@ -455,7 +455,7 @@ pre { margin: 0; font-family: $font-family-mono; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-relaxed; color: var(--color-text-primary); white-space: pre-wrap; @@ -568,11 +568,11 @@ } .bitfun-flexible-panel__content-title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); } .bitfun-flexible-panel__content-type { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } .bitfun-flexible-panel__code-content, diff --git a/src/web-ui/src/app/scenes/SceneViewport.scss b/src/web-ui/src/app/scenes/SceneViewport.scss index 7fc70e9e..e13fbd45 100644 --- a/src/web-ui/src/app/scenes/SceneViewport.scss +++ b/src/web-ui/src/app/scenes/SceneViewport.scss @@ -75,7 +75,7 @@ &__empty-hint { color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); margin: 0; } diff --git a/src/web-ui/src/app/scenes/agents/AgentsScene.scss b/src/web-ui/src/app/scenes/agents/AgentsScene.scss index accaac24..292cac87 100644 --- a/src/web-ui/src/app/scenes/agents/AgentsScene.scss +++ b/src/web-ui/src/app/scenes/agents/AgentsScene.scss @@ -2,7 +2,7 @@ .bitfun-agents-scene { .gallery-zone__subtitle { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); } diff --git a/src/web-ui/src/app/scenes/agents/AgentsView.scss b/src/web-ui/src/app/scenes/agents/AgentsView.scss index dc8f066f..d5caa9b7 100644 --- a/src/web-ui/src/app/scenes/agents/AgentsView.scss +++ b/src/web-ui/src/app/scenes/agents/AgentsView.scss @@ -38,7 +38,7 @@ align-items: center; gap: 5px; padding: 4px $size-gap-3; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-sans; font-weight: $font-weight-medium; color: var(--color-text-muted); @@ -78,7 +78,7 @@ &__panel-label { flex-shrink: 0; padding: 10px $size-gap-4; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-muted); text-transform: uppercase; @@ -128,7 +128,7 @@ &__title { margin: 0; - font-size: $font-size-2xl; + font-size: var(--font-size-2xl); font-weight: $font-weight-semibold; color: var(--color-text-primary); letter-spacing: -0.4px; @@ -136,13 +136,13 @@ &__sub { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); line-height: 1.7; } &__section-label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-muted); text-transform: uppercase; @@ -199,13 +199,13 @@ } &__tpl-name { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); } &__tpl-desc { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; @@ -214,7 +214,7 @@ &__tpl-cnt { flex-shrink: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-disabled); background: var(--element-bg-medium); padding: 2px 7px; @@ -239,7 +239,7 @@ border-radius: $size-radius-sm; padding: 7px $size-gap-6; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); cursor: pointer; transition: all $motion-fast $easing-standard; font-family: $font-family-sans; diff --git a/src/web-ui/src/app/scenes/agents/components/AgentCard.scss b/src/web-ui/src/app/scenes/agents/components/AgentCard.scss index 4d130c65..324be254 100644 --- a/src/web-ui/src/app/scenes/agents/components/AgentCard.scss +++ b/src/web-ui/src/app/scenes/agents/components/AgentCard.scss @@ -142,7 +142,7 @@ margin-top: auto; padding-top: $size-gap-2; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: $line-height-base; } @@ -245,7 +245,7 @@ &__cap-label { flex-shrink: 0; width: 80px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; white-space: nowrap; overflow: hidden; @@ -271,7 +271,7 @@ flex-shrink: 0; width: 28px; text-align: right; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; } @@ -295,7 +295,7 @@ display: inline-flex; align-items: center; gap: $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-secondary); text-transform: uppercase; @@ -396,7 +396,7 @@ // ── Empty inline state ─────────────────────────────────────────────────── &__empty-inline { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); font-style: italic; } diff --git a/src/web-ui/src/app/scenes/agents/components/CoreAgentCard.scss b/src/web-ui/src/app/scenes/agents/components/CoreAgentCard.scss index e7d383b3..72747f26 100644 --- a/src/web-ui/src/app/scenes/agents/components/CoreAgentCard.scss +++ b/src/web-ui/src/app/scenes/agents/components/CoreAgentCard.scss @@ -102,7 +102,7 @@ display: inline-flex; align-items: center; gap: 4px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--core-accent, var(--color-accent-500)); opacity: 0.9; diff --git a/src/web-ui/src/app/scenes/agents/components/CreateAgentPage.scss b/src/web-ui/src/app/scenes/agents/components/CreateAgentPage.scss index c7b12ad1..e95ec5fa 100644 --- a/src/web-ui/src/app/scenes/agents/components/CreateAgentPage.scss +++ b/src/web-ui/src/app/scenes/agents/components/CreateAgentPage.scss @@ -23,7 +23,7 @@ } .th__title { - font-size: $font-size-xl; + font-size: var(--font-size-xl); font-weight: $font-weight-semibold; color: var(--color-text-primary); margin: 0; @@ -31,7 +31,7 @@ } .th__title-sub { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); margin: 0; line-height: $line-height-relaxed; @@ -71,7 +71,7 @@ } .th-create-panel__label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-secondary); } @@ -83,7 +83,7 @@ } .th-create-panel__error { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-error); } @@ -108,7 +108,7 @@ border: 1px solid var(--border-subtle); border-radius: $size-radius-full; background: transparent; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-secondary); cursor: pointer; @@ -149,7 +149,7 @@ border-radius: $size-radius-sm; border: 1px solid var(--border-subtle); background: var(--element-bg-base); - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); cursor: pointer; transition: diff --git a/src/web-ui/src/app/scenes/browser/BrowserPanel.scss b/src/web-ui/src/app/scenes/browser/BrowserPanel.scss index 2711911b..5c13d3c6 100644 --- a/src/web-ui/src/app/scenes/browser/BrowserPanel.scss +++ b/src/web-ui/src/app/scenes/browser/BrowserPanel.scss @@ -44,7 +44,7 @@ box-shadow: none; background: transparent; color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); appearance: none; -webkit-appearance: none; border-radius: 0; @@ -68,7 +68,7 @@ border-radius: $size-radius-base; background: color-mix(in srgb, var(--color-warning) 12%, transparent); color: var(--color-text-secondary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); flex-shrink: 0; svg { @@ -104,7 +104,7 @@ justify-content: center; gap: $size-gap-2; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); background: radial-gradient(circle at top, color-mix(in srgb, var(--color-accent-500) 8%, transparent), transparent 42%), var(--color-bg-primary); diff --git a/src/web-ui/src/app/scenes/browser/BrowserScene.scss b/src/web-ui/src/app/scenes/browser/BrowserScene.scss index 0ca42a9f..72864ead 100644 --- a/src/web-ui/src/app/scenes/browser/BrowserScene.scss +++ b/src/web-ui/src/app/scenes/browser/BrowserScene.scss @@ -44,7 +44,7 @@ box-shadow: none; background: transparent; color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); appearance: none; -webkit-appearance: none; border-radius: 0; @@ -68,7 +68,7 @@ border-radius: $size-radius-base; background: color-mix(in srgb, var(--color-warning) 12%, transparent); color: var(--color-text-secondary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); svg { color: var(--color-warning); @@ -103,7 +103,7 @@ justify-content: center; gap: $size-gap-2; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); background: radial-gradient(circle at top, color-mix(in srgb, var(--color-accent-500) 8%, transparent), transparent 42%), var(--color-bg-primary); diff --git a/src/web-ui/src/app/scenes/file-viewer/FileViewerNav.scss b/src/web-ui/src/app/scenes/file-viewer/FileViewerNav.scss index cc027b04..0f3203f4 100644 --- a/src/web-ui/src/app/scenes/file-viewer/FileViewerNav.scss +++ b/src/web-ui/src/app/scenes/file-viewer/FileViewerNav.scss @@ -48,7 +48,7 @@ background: var(--element-bg-soft); margin: 0 $size-gap-2; color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 500; flex-shrink: 0; } diff --git a/src/web-ui/src/app/scenes/git/GitNav.scss b/src/web-ui/src/app/scenes/git/GitNav.scss index c2ff0280..b553f150 100644 --- a/src/web-ui/src/app/scenes/git/GitNav.scss +++ b/src/web-ui/src/app/scenes/git/GitNav.scss @@ -22,7 +22,7 @@ } &__title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 600; color: var(--color-text-primary); white-space: nowrap; @@ -55,7 +55,7 @@ display: flex; align-items: center; gap: $size-gap-2; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); margin-bottom: $size-gap-1; } @@ -95,7 +95,7 @@ color: var(--color-text-secondary); cursor: pointer; text-align: left; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; width: 100%; position: relative; diff --git a/src/web-ui/src/app/scenes/mermaid/MermaidEditorScene.scss b/src/web-ui/src/app/scenes/mermaid/MermaidEditorScene.scss index 01f0c7c3..9c8927a1 100644 --- a/src/web-ui/src/app/scenes/mermaid/MermaidEditorScene.scss +++ b/src/web-ui/src/app/scenes/mermaid/MermaidEditorScene.scss @@ -82,7 +82,7 @@ border-right: 1px solid var(--border-subtle); background: transparent; color: var(--color-text-secondary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); white-space: nowrap; cursor: pointer; transition: background $motion-fast $easing-standard, color $motion-fast $easing-standard; @@ -139,6 +139,6 @@ justify-content: center; flex: 1; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); } } diff --git a/src/web-ui/src/app/scenes/miniapps/MiniAppScene.scss b/src/web-ui/src/app/scenes/miniapps/MiniAppScene.scss index 2a7092b4..52f09e9a 100644 --- a/src/web-ui/src/app/scenes/miniapps/MiniAppScene.scss +++ b/src/web-ui/src/app/scenes/miniapps/MiniAppScene.scss @@ -27,7 +27,7 @@ } &__title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); white-space: nowrap; @@ -62,7 +62,7 @@ height: 100%; gap: $size-gap-3; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); } &__error { @@ -73,7 +73,7 @@ height: 100%; gap: $size-gap-3; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); text-align: center; padding: $size-gap-6; diff --git a/src/web-ui/src/app/scenes/miniapps/views/MiniAppGalleryView.scss b/src/web-ui/src/app/scenes/miniapps/views/MiniAppGalleryView.scss index a2dbf7d7..4f89cf18 100644 --- a/src/web-ui/src/app/scenes/miniapps/views/MiniAppGalleryView.scss +++ b/src/web-ui/src/app/scenes/miniapps/views/MiniAppGalleryView.scss @@ -21,7 +21,7 @@ border-radius: $size-radius-full; background: var(--element-bg-medium); border: 1px solid var(--border-subtle); - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); } } diff --git a/src/web-ui/src/app/scenes/my-agent/AssistantScheduleView.scss b/src/web-ui/src/app/scenes/my-agent/AssistantScheduleView.scss index 00f9c0cb..027c0553 100644 --- a/src/web-ui/src/app/scenes/my-agent/AssistantScheduleView.scss +++ b/src/web-ui/src/app/scenes/my-agent/AssistantScheduleView.scss @@ -19,7 +19,7 @@ &__head-title { flex: 1; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; text-transform: uppercase; letter-spacing: 0.08em; @@ -60,14 +60,14 @@ &__empty-title { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-secondary); } &__empty-text { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); line-height: $line-height-relaxed; } @@ -139,7 +139,7 @@ &__item-name { flex: 1; min-width: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); overflow: hidden; @@ -148,7 +148,7 @@ } &__item-meta { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); line-height: $line-height-relaxed; @@ -158,7 +158,7 @@ } &__item-error { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-danger-500, #f87171); line-height: $line-height-relaxed; word-break: break-word; @@ -209,13 +209,13 @@ } &__field-label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-secondary); } &__warning { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-danger-500, #f87171); line-height: $line-height-relaxed; padding: $size-gap-3 $size-gap-4; diff --git a/src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.scss b/src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.scss index 4fceeca9..a0e480da 100644 --- a/src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.scss +++ b/src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.scss @@ -55,7 +55,7 @@ background: transparent !important; color: var(--color-text-primary); font-family: $font-family-sans; - font-size: $font-size-base; + font-size: var(--font-size-base); line-height: $line-height-relaxed; resize: none; box-sizing: border-box; @@ -93,7 +93,7 @@ } &__hint { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); opacity: 0.72; user-select: none; diff --git a/src/web-ui/src/app/scenes/profile/views/NurseryView.scss b/src/web-ui/src/app/scenes/profile/views/NurseryView.scss index cbc8bfcc..a0c64f88 100644 --- a/src/web-ui/src/app/scenes/profile/views/NurseryView.scss +++ b/src/web-ui/src/app/scenes/profile/views/NurseryView.scss @@ -130,7 +130,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__title { margin: 0; - font-size: $font-size-xl; + font-size: var(--font-size-xl); font-weight: $font-weight-semibold; color: var(--color-text-primary); letter-spacing: -0.02em; @@ -139,7 +139,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__subtitle { margin: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); line-height: $line-height-relaxed; } @@ -149,7 +149,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); align-items: center; gap: 5px; margin-top: 2px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: #34d399; opacity: 0.72; @@ -180,7 +180,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); border-radius: $size-radius-full; border: 1px solid rgba(52, 211, 153, 0.18); background: rgba(52, 211, 153, 0.06); - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-medium; color: var(--color-text-muted); letter-spacing: 0.1px; @@ -370,7 +370,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__name { min-width: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); line-height: $line-height-base; @@ -399,7 +399,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__vibe { margin: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-normal; color: var(--color-text-secondary); line-height: $line-height-relaxed; @@ -459,7 +459,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__footer-hint { flex: 1; min-width: 0; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); font-weight: $font-weight-medium; letter-spacing: 0.2px; @@ -549,7 +549,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); margin-left: 6px; padding: 1px 6px; border-radius: 4px; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; color: var(--color-accent-400, #60a5fa); background: rgba(96, 165, 250, 0.12); @@ -581,14 +581,14 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__title { margin: 0 0 10px; - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); } &__message { margin: 0 0 20px; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); line-height: $line-height-relaxed; } @@ -602,7 +602,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__btn { padding: 7px 16px; border-radius: 8px; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; cursor: pointer; border: none; @@ -699,14 +699,14 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); margin: 0; } &__subtitle { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); } @@ -837,7 +837,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__title { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-secondary); text-transform: uppercase; @@ -904,14 +904,14 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-secondary); flex: 1; } &__desc { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); } } @@ -932,7 +932,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); display: flex; justify-content: space-between; align-items: center; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); gap: $size-gap-2; @@ -960,7 +960,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__label { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); margin-top: 3px; text-align: right; @@ -996,13 +996,13 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__name { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-primary); } &__desc { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; @@ -1019,7 +1019,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } .nursery-skill-chip { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); padding: 3px $size-gap-2; border-radius: $size-radius-full; border: 1px solid var(--border-subtle); @@ -1057,7 +1057,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__dim-label { width: 60px; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); flex-shrink: 0; } @@ -1079,7 +1079,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__dim-val { width: 26px; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); text-align: right; font-variant-numeric: tabular-nums; @@ -1087,7 +1087,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__hint { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); margin-top: $size-gap-3; text-align: center; @@ -1134,7 +1134,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__meta-label { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; color: var(--color-text-muted); text-transform: uppercase; @@ -1144,7 +1144,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__meta-value { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); cursor: pointer; padding: 2px $size-gap-2; @@ -1173,7 +1173,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); // ── Empty state ──────────────────────────────────────────────────────────── .nursery-empty { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); font-style: italic; padding: $size-gap-3 0; @@ -1420,7 +1420,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } .nursery-identity__header-meta-label { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; color: var(--color-text-muted); text-transform: uppercase; @@ -1432,7 +1432,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); .nursery-identity__header-meta-value { flex: 1; min-width: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); cursor: pointer; padding: 2px $size-gap-2; @@ -1593,7 +1593,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); display: inline; margin-bottom: 0; flex-shrink: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-tight; font-weight: $font-weight-semibold; text-transform: none; @@ -1607,7 +1607,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-tight; font-weight: $font-weight-semibold; } @@ -1619,7 +1619,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__kind { display: block; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; text-transform: uppercase; letter-spacing: 0.5px; @@ -1629,7 +1629,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__title { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); line-height: $line-height-tight; @@ -1672,7 +1672,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); flex-direction: column; gap: $size-gap-3; padding: $size-gap-3 $size-gap-4 $size-gap-4; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); } @@ -1688,7 +1688,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__desc { margin: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: $line-height-relaxed; color: var(--color-text-secondary); white-space: pre-wrap; @@ -1697,13 +1697,13 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__meta { margin: 0; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); } &__subhead { margin: 0; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; color: var(--color-text-muted); text-transform: uppercase; @@ -1717,7 +1717,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__tool-names { margin: 0; padding-left: $size-gap-4; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); line-height: $line-height-relaxed; } @@ -1729,7 +1729,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__error { margin: 0; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-danger-600, #e11d48); line-height: $line-height-relaxed; } @@ -1763,7 +1763,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); border: none; background: var(--color-bg-scene); color: var(--color-text-primary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); text-align: left; cursor: pointer; transition: background $motion-fast $easing-standard; @@ -1790,7 +1790,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__file { flex-shrink: 0; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-family: $font-family-mono, ui-monospace, monospace; color: var(--color-text-muted); } @@ -1942,7 +1942,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__name { flex: 1; min-width: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-secondary); overflow: hidden; @@ -1979,7 +1979,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__title { margin: 0; padding: 7px $size-gap-3; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; text-transform: uppercase; letter-spacing: 0.5px; @@ -1991,7 +1991,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__empty { margin: 0; padding: $size-gap-3; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); font-style: italic; text-align: center; @@ -2115,7 +2115,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__name { flex: 1; min-width: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-secondary); overflow: hidden; @@ -2208,7 +2208,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__tag { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; text-transform: uppercase; letter-spacing: 0.8px; @@ -2218,7 +2218,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__name { margin: 0; - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); letter-spacing: -0.02em; @@ -2227,7 +2227,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__desc { margin: 0; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); line-height: $line-height-relaxed; } @@ -2256,7 +2256,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); border-radius: $size-radius-full; border: 1px solid rgba(52, 211, 153, 0.18); background: rgba(52, 211, 153, 0.06); - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-medium; color: var(--color-text-muted); letter-spacing: 0.1px; @@ -2289,7 +2289,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__label { flex-shrink: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-secondary); } @@ -2312,7 +2312,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__title { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; text-transform: uppercase; letter-spacing: 0.5px; @@ -2320,7 +2320,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__summary { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; @@ -2385,13 +2385,13 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__legend-name { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); white-space: nowrap; } &__legend-val { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-secondary); font-variant-numeric: tabular-nums; font-weight: $font-weight-medium; @@ -2399,7 +2399,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__legend-pct { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; text-align: right; @@ -2424,7 +2424,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__empty { padding: $size-gap-2 $size-gap-3; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); font-style: italic; } @@ -2473,7 +2473,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); &__name { flex: 1; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-secondary); min-width: 0; @@ -2551,13 +2551,13 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__text { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-muted); } &__hint { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); opacity: 0.7; line-height: $line-height-relaxed; @@ -2617,7 +2617,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__name { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-primary); white-space: nowrap; @@ -2626,7 +2626,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__desc { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; @@ -2691,7 +2691,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__name { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-primary); white-space: nowrap; @@ -2713,7 +2713,7 @@ $nursery-scene-gutter: clamp(40px, 6vw, 80px); } &__desc { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-muted); line-height: $line-height-relaxed; white-space: nowrap; @@ -2864,7 +2864,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); } &__meta-tag { - font-size: $font-size-base; + font-size: var(--font-size-base); color: var(--color-text-muted); cursor: pointer; border-radius: $size-radius-sm; @@ -2883,14 +2883,14 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); } &__meta-dot { - font-size: $font-size-base; + font-size: var(--font-size-base); color: var(--color-text-muted); opacity: 0.35; user-select: none; } &__meta-input { - font-size: $font-size-base; + font-size: var(--font-size-base); max-width: 140px; } } @@ -2910,7 +2910,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); &__title { margin: 0 0 $size-gap-3; padding: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; line-height: $line-height-tight; letter-spacing: -0.01em; @@ -2941,24 +2941,24 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); min-height: 42px; padding: $size-gap-2 $size-gap-3; border-radius: $size-radius-lg; - font-size: $font-size-base; + font-size: var(--font-size-base); } .bitfun-nav-panel__inline-item.is-child { min-height: 38px; padding-left: calc(#{$size-gap-3} + 22px); - font-size: $font-size-sm; + font-size: var(--font-size-sm); } .bitfun-nav-panel__inline-empty { padding: $size-gap-4 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); } .bitfun-nav-panel__inline-action { min-height: 38px; padding: $size-gap-3 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); border-radius: $size-radius-lg; } } @@ -3062,7 +3062,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); } &__name { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); cursor: pointer; @@ -3080,7 +3080,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); } &__name-input { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; width: 100%; } @@ -3112,7 +3112,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); &__meta-value { flex: 1; min-width: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); cursor: pointer; padding: 1px $size-gap-1; @@ -3192,7 +3192,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); &__title { flex: 1; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-semibold; text-transform: uppercase; letter-spacing: 0.08em; @@ -3250,7 +3250,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); border-radius: $size-radius-base; background: transparent; color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); text-align: left; cursor: pointer; transition: @@ -3296,7 +3296,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); &__file { flex-shrink: 0; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-family: $font-family-mono, ui-monospace, monospace; color: var(--color-text-muted); } @@ -3305,7 +3305,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); // ── Empty / loading states ──────────────────────────────────────────────────── .acp-empty { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); font-style: italic; padding: $size-gap-4 0; @@ -3346,7 +3346,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); &__title { flex: 1; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); overflow: hidden; @@ -3369,7 +3369,7 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); &__error { margin: 0 0 $size-gap-3; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-danger-600, #e11d48); line-height: $line-height-relaxed; } diff --git a/src/web-ui/src/app/scenes/session/ChatPane.scss b/src/web-ui/src/app/scenes/session/ChatPane.scss index d0244350..5f8c30d7 100644 --- a/src/web-ui/src/app/scenes/session/ChatPane.scss +++ b/src/web-ui/src/app/scenes/session/ChatPane.scss @@ -13,6 +13,8 @@ overflow: hidden; background: var(--color-bg-flowchat); position: relative; + font-family: var(--font-sans, var(--font-family-sans, inherit)); + font-size: var(--flowchat-font-size-base); } .bitfun-chat-pane__chat-container { diff --git a/src/web-ui/src/app/scenes/settings/SettingsNav.scss b/src/web-ui/src/app/scenes/settings/SettingsNav.scss index c6e554cd..4235eff7 100644 --- a/src/web-ui/src/app/scenes/settings/SettingsNav.scss +++ b/src/web-ui/src/app/scenes/settings/SettingsNav.scss @@ -24,7 +24,7 @@ } &__title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 600; color: var(--color-text-primary); white-space: nowrap; @@ -68,7 +68,7 @@ } &.search .search__input { - font-size: $font-size-sm; + font-size: var(--font-size-sm); &::placeholder { color: var(--color-text-disabled); @@ -100,7 +100,7 @@ color: var(--color-text-secondary); cursor: pointer; text-align: left; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; width: 100%; position: relative; @@ -145,7 +145,7 @@ &__search-empty { padding: $size-gap-3 $size-gap-3; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); text-align: center; } @@ -218,7 +218,7 @@ color: var(--color-text-secondary); cursor: pointer; text-align: left; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; width: 100%; position: relative; diff --git a/src/web-ui/src/app/scenes/shell/ShellNav.scss b/src/web-ui/src/app/scenes/shell/ShellNav.scss index 9ba41fff..07827ded 100644 --- a/src/web-ui/src/app/scenes/shell/ShellNav.scss +++ b/src/web-ui/src/app/scenes/shell/ShellNav.scss @@ -28,7 +28,7 @@ } &__title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 600; color: var(--color-text-primary); white-space: nowrap; @@ -79,7 +79,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__workspace-trigger-icon { @@ -112,7 +112,7 @@ color: var(--color-text-secondary); cursor: pointer; text-align: left; - font-size: $font-size-xs; + font-size: var(--font-size-xs); transition: color $motion-fast $easing-standard, background $motion-fast $easing-standard; @@ -223,7 +223,7 @@ color: var(--color-text-secondary); cursor: pointer; text-align: left; - font-size: $font-size-xs; + font-size: var(--font-size-xs); transition: color $motion-fast $easing-standard, background $motion-fast $easing-standard; @@ -260,7 +260,7 @@ border-radius: 8px; background: transparent; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: 500; cursor: pointer; transition: @@ -315,7 +315,7 @@ color: var(--color-text-secondary); cursor: pointer; text-align: left; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: 400; position: relative; transition: @@ -426,7 +426,7 @@ flex-shrink: 0; padding: 2px 5px; border-radius: 999px; - font-size: 10px; + font-size: var(--font-size-xxs); line-height: 1; color: var(--color-text-muted); background: color-mix(in srgb, var(--color-text-muted) 12%, transparent); @@ -436,7 +436,7 @@ flex-shrink: 0; padding: 2px 5px; border-radius: 999px; - font-size: 10px; + font-size: var(--font-size-xxs); line-height: 1; color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 14%, transparent); @@ -448,7 +448,7 @@ border: 1px dashed var(--border-subtle); border-radius: 10px; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: $line-height-relaxed; } } diff --git a/src/web-ui/src/app/scenes/skills/SkillsScene.scss b/src/web-ui/src/app/scenes/skills/SkillsScene.scss index 7a5dd1d8..cf44b704 100644 --- a/src/web-ui/src/app/scenes/skills/SkillsScene.scss +++ b/src/web-ui/src/app/scenes/skills/SkillsScene.scss @@ -114,7 +114,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); .skills-split__subtitle { margin: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); line-height: $line-height-relaxed; } @@ -166,7 +166,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); border: none; border-radius: $size-radius-base; @include btn-primary.btn-primary-surface-default; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; cursor: pointer; transition: @@ -213,7 +213,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); } .skills-split__section-title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); letter-spacing: -0.01em; @@ -221,7 +221,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); .skills-split__section-sub { flex: 1; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); a { @@ -466,7 +466,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); .skills-split__page-info { min-width: 52px; text-align: center; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); } @@ -491,7 +491,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); gap: $size-gap-3; min-height: 140px; padding: $size-gap-8 $size-gap-6; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); text-align: center; @@ -554,7 +554,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); border-radius: $size-radius-full; background: transparent; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; cursor: pointer; transition: @@ -664,7 +664,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); } .skills-split__row-name { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-primary); line-height: $line-height-tight; @@ -674,7 +674,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); } .skills-split__row-desc { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); opacity: 0.72; line-height: $line-height-relaxed; @@ -802,14 +802,14 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); &__path-hint, &__form-hint, &__validating { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); } &__validation { padding: $size-gap-2 $size-gap-3; border-radius: $size-radius-base; - font-size: $font-size-sm; + font-size: var(--font-size-sm); &.is-valid { background: rgba($color-success, 0.08); @@ -825,7 +825,7 @@ $skills-content-top: clamp(36px, 4.5vh, 48px); } &__validation-name { font-weight: $font-weight-medium; } - &__validation-desc { margin-top: 2px; font-size: $font-size-xs; opacity: 0.85; } + &__validation-desc { margin-top: 2px; font-size: var(--font-size-xs); opacity: 0.85; } &__validation-error { font-weight: $font-weight-medium; } &__modal-form { diff --git a/src/web-ui/src/app/scenes/skills/components/SkillCard.scss b/src/web-ui/src/app/scenes/skills/components/SkillCard.scss index f00c3fc3..d7761eea 100644 --- a/src/web-ui/src/app/scenes/skills/components/SkillCard.scss +++ b/src/web-ui/src/app/scenes/skills/components/SkillCard.scss @@ -152,7 +152,7 @@ margin: 0; padding: 0; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: $line-height-base; } diff --git a/src/web-ui/src/app/scenes/welcome/WelcomeScene.scss b/src/web-ui/src/app/scenes/welcome/WelcomeScene.scss index fe5385cc..36a08ed3 100644 --- a/src/web-ui/src/app/scenes/welcome/WelcomeScene.scss +++ b/src/web-ui/src/app/scenes/welcome/WelcomeScene.scss @@ -35,7 +35,7 @@ &__title { margin: 0; - font-size: $font-size-2xl; + font-size: var(--font-size-2xl); line-height: $line-height-tight; letter-spacing: -0.02em; color: var(--color-text-primary); @@ -43,7 +43,7 @@ } &__greeting-label { - font-size: $font-size-lg; + font-size: var(--font-size-lg); line-height: 1.5; color: var(--color-text-primary); margin: 0; @@ -76,7 +76,7 @@ display: flex; align-items: center; gap: $size-gap-1; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); font-weight: $font-weight-medium; text-transform: uppercase; @@ -98,7 +98,7 @@ border-radius: $size-radius-sm; background: transparent; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); cursor: pointer; transition: background $motion-fast $easing-standard, color $motion-fast $easing-standard; @@ -169,7 +169,7 @@ border: none; background: transparent; color: var(--color-text-secondary); - font-size: $font-size-base; + font-size: var(--font-size-base); cursor: pointer; text-align: left; transition: color $motion-fast $easing-standard; @@ -191,7 +191,7 @@ border: none; background: transparent; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); cursor: pointer; transition: color $motion-fast $easing-standard, background $motion-fast $easing-standard; @@ -259,18 +259,18 @@ overflow: hidden; text-overflow: ellipsis; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); } &__recent-host-sep { flex-shrink: 0; color: var(--color-text-muted); opacity: 0.6; - font-size: $font-size-sm; + font-size: var(--font-size-sm); } &__no-recent { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); margin: 0; padding: $size-gap-1 $size-gap-2; diff --git a/src/web-ui/src/app/styles/global.scss b/src/web-ui/src/app/styles/global.scss index 3692539b..87c23ff5 100644 --- a/src/web-ui/src/app/styles/global.scss +++ b/src/web-ui/src/app/styles/global.scss @@ -33,8 +33,8 @@ html { } body { - font-family: $font-family-sans; - font-size: $font-size-base; + font-family: var(--font-family-sans, #{$font-family-sans}); + font-size: var(--font-size-base, #{$font-size-base}); line-height: $line-height-base; color: var(--color-text-primary); background: var(--color-bg-primary); @@ -71,6 +71,19 @@ a:hover { border-radius: $size-radius-sm; } +/* Font preference: compact number stepper — avoid stacking global accent ring on the input */ +.font-pref-panel__number-input:focus, +.font-pref-panel__number-input:focus-visible { + outline: none; + outline-offset: 0; +} + +.font-pref-panel__flow-select:focus, +.font-pref-panel__flow-select:focus-visible { + outline: none; + outline-offset: 0; +} + /* Disabled state */ :disabled { opacity: $opacity-disabled; diff --git a/src/web-ui/src/component-library/components/Alert/Alert.scss b/src/web-ui/src/component-library/components/Alert/Alert.scss index b516c00f..3a9b8e97 100644 --- a/src/web-ui/src/component-library/components/Alert/Alert.scss +++ b/src/web-ui/src/component-library/components/Alert/Alert.scss @@ -90,20 +90,20 @@ } &__title { - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); font-weight: tokens.$font-weight-medium; line-height: tokens.$line-height-base; margin-bottom: 2px; } &__message { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); line-height: tokens.$line-height-base; } &__description { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); line-height: tokens.$line-height-base; margin-top: tokens.$size-gap-1; diff --git a/src/web-ui/src/component-library/components/Badge/Badge.scss b/src/web-ui/src/component-library/components/Badge/Badge.scss index e341c79a..8f93dd61 100644 --- a/src/web-ui/src/component-library/components/Badge/Badge.scss +++ b/src/web-ui/src/component-library/components/Badge/Badge.scss @@ -11,7 +11,7 @@ gap: 3px; padding: tokens.$badge-padding-y tokens.$badge-padding-x; border-radius: tokens.$badge-border-radius; - font-size: tokens.$badge-font-size; + font-size: var(--badge-font-size, #{tokens.$badge-font-size}); font-weight: tokens.$badge-font-weight; line-height: 1; border: none; diff --git a/src/web-ui/src/component-library/components/Checkbox/Checkbox.scss b/src/web-ui/src/component-library/components/Checkbox/Checkbox.scss index 5c9e9486..a449bfed 100644 --- a/src/web-ui/src/component-library/components/Checkbox/Checkbox.scss +++ b/src/web-ui/src/component-library/components/Checkbox/Checkbox.scss @@ -72,14 +72,14 @@ } &__label { - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); font-weight: tokens.$font-weight-medium; color: tokens.$color-text-primary; line-height: tokens.$line-height-base; } &__description { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: tokens.$color-text-muted; line-height: tokens.$line-height-base; } @@ -163,7 +163,7 @@ } .bitfun-checkbox__label { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); } .bitfun-checkbox__description { @@ -190,11 +190,11 @@ } .bitfun-checkbox__label { - font-size: tokens.$font-size-base; + font-size: var(--font-size-base); } .bitfun-checkbox__description { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); } } } diff --git a/src/web-ui/src/component-library/components/ConfirmDialog/ConfirmDialog.scss b/src/web-ui/src/component-library/components/ConfirmDialog/ConfirmDialog.scss index 48528706..9f2ff8a3 100644 --- a/src/web-ui/src/component-library/components/ConfirmDialog/ConfirmDialog.scss +++ b/src/web-ui/src/component-library/components/ConfirmDialog/ConfirmDialog.scss @@ -56,7 +56,7 @@ } &__title { - font-size: $font-size-lg; + font-size: var(--font-size-lg); font-weight: $font-weight-semibold; line-height: 1.35; letter-spacing: -0.01em; @@ -70,7 +70,7 @@ } &__message { - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: 1.55; color: var(--color-text-secondary); text-align: left; @@ -87,7 +87,7 @@ /** Lead line before bullet list (e.g. “This will:”) */ &__message-intro { margin: 0 0 $size-gap-3; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; line-height: 1.5; color: var(--color-text-primary); @@ -107,7 +107,7 @@ position: relative; margin: 0; padding-left: $size-gap-5; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: 1.55; color: var(--color-text-secondary); @@ -140,7 +140,7 @@ margin: 0; padding: 0; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-primary); white-space: pre-wrap; word-break: break-all; diff --git a/src/web-ui/src/component-library/components/FilterPill/FilterPill.scss b/src/web-ui/src/component-library/components/FilterPill/FilterPill.scss index 9696dbb4..81383355 100644 --- a/src/web-ui/src/component-library/components/FilterPill/FilterPill.scss +++ b/src/web-ui/src/component-library/components/FilterPill/FilterPill.scss @@ -18,7 +18,7 @@ border: 1px solid transparent; border-radius: 14px; color: var(--color-text-secondary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; font-family: $font-family-sans; cursor: pointer; diff --git a/src/web-ui/src/component-library/components/FlowChatCards/BaseToolCard/BaseToolCard.scss b/src/web-ui/src/component-library/components/FlowChatCards/BaseToolCard/BaseToolCard.scss index 287a840c..a5d6f2db 100644 --- a/src/web-ui/src/component-library/components/FlowChatCards/BaseToolCard/BaseToolCard.scss +++ b/src/web-ui/src/component-library/components/FlowChatCards/BaseToolCard/BaseToolCard.scss @@ -41,7 +41,7 @@ display: flex; align-items: center; gap: tokens.$size-gap-3; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); position: relative; z-index: 2; @@ -100,7 +100,7 @@ } &__name { - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); font-weight: tokens.$font-weight-semibold; color: tokens.$color-text-primary; margin-bottom: 2px; @@ -108,7 +108,7 @@ } &__description { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: tokens.$color-text-muted; line-height: 1.4; } @@ -175,7 +175,7 @@ } &__input-label { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-weight: tokens.$font-weight-semibold; color: tokens.$color-text-secondary; margin-bottom: tokens.$size-gap-2; @@ -194,7 +194,7 @@ pre { margin: 0; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: tokens.$color-text-secondary; font-family: tokens.$font-family-mono; line-height: 1.5; @@ -232,7 +232,7 @@ } &__result-label { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-weight: tokens.$font-weight-semibold; color: tokens.$color-text-secondary; margin-bottom: tokens.$size-gap-2; @@ -253,7 +253,7 @@ pre { margin: 0; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: tokens.$color-text-secondary; font-family: tokens.$font-family-mono; line-height: 1.5; @@ -284,7 +284,7 @@ } &__error-message { - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); color: tokens.$color-text-secondary; line-height: tokens.$line-height-base; flex: 1; diff --git a/src/web-ui/src/component-library/components/FlowChatCards/ContextCompressionCard/ContextCompressionCard.scss b/src/web-ui/src/component-library/components/FlowChatCards/ContextCompressionCard/ContextCompressionCard.scss index 634c63b4..f6d0393f 100644 --- a/src/web-ui/src/component-library/components/FlowChatCards/ContextCompressionCard/ContextCompressionCard.scss +++ b/src/web-ui/src/component-library/components/FlowChatCards/ContextCompressionCard/ContextCompressionCard.scss @@ -68,14 +68,14 @@ .context-compression-card__action { color: tokens.$color-text-secondary; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-weight: tokens.$font-weight-medium; flex-shrink: 0; } .context-compression-card__tokens { color: tokens.$color-text-primary; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-weight: tokens.$font-weight-medium; font-family: tokens.$font-family-mono; flex-shrink: 1; @@ -137,7 +137,7 @@ align-items: center; justify-content: space-between; padding: tokens.$size-gap-2 0; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); color: tokens.$color-text-secondary; &:first-child { @@ -157,7 +157,7 @@ .context-compression-card__simple-duration { color: tokens.$color-text-muted; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-family: tokens.$font-family-mono; } @@ -169,7 +169,7 @@ .context-compression-card__simple-savings { color: tokens.$color-success; font-weight: tokens.$font-weight-semibold; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); } @@ -184,7 +184,7 @@ z-index: 2; span { - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); font-weight: tokens.$font-weight-medium; color: tokens.$color-text-primary; } diff --git a/src/web-ui/src/component-library/components/FlowChatCards/SearchCard/SearchCard.scss b/src/web-ui/src/component-library/components/FlowChatCards/SearchCard/SearchCard.scss index fd4a215c..c6929265 100644 --- a/src/web-ui/src/component-library/components/FlowChatCards/SearchCard/SearchCard.scss +++ b/src/web-ui/src/component-library/components/FlowChatCards/SearchCard/SearchCard.scss @@ -49,14 +49,14 @@ .search-card__action { color: tokens.$color-text-secondary; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-weight: tokens.$font-weight-medium; flex-shrink: 0; } .search-card__pattern { color: tokens.$color-text-primary; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-weight: tokens.$font-weight-medium; font-family: tokens.$font-family-mono; flex-shrink: 1; @@ -122,7 +122,7 @@ display: flex; align-items: center; gap: tokens.$size-gap-2; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); } .search-card__label { @@ -158,14 +158,14 @@ } .search-card__stat-value { - font-size: tokens.$font-size-xl; + font-size: var(--font-size-xl); font-weight: tokens.$font-weight-bold; font-family: tokens.$font-family-mono; color: tokens.$color-text-primary; } .search-card__stat-label { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: tokens.$color-text-muted; } @@ -183,7 +183,7 @@ border: 1px solid tokens.$border-base; border-radius: tokens.$size-radius-base; color: tokens.$color-text-secondary; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); font-weight: tokens.$font-weight-medium; cursor: pointer; transition: all tokens.$motion-base tokens.$easing-standard; @@ -237,7 +237,7 @@ .search-card__file-name { flex: 1; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); color: tokens.$color-text-primary; font-family: tokens.$font-family-mono; overflow: hidden; @@ -246,7 +246,7 @@ } .search-card__file-count { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: tokens.$color-text-muted; background: tokens.$element-bg-soft; padding: 2px 6px; @@ -259,7 +259,7 @@ padding: tokens.$size-gap-4; text-align: center; color: tokens.$color-text-muted; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); background: tokens.$element-bg-base; border: 1px solid tokens.$border-base; border-radius: tokens.$size-radius-base; diff --git a/src/web-ui/src/component-library/components/FlowChatCards/SnapshotCard/SnapshotCard.scss b/src/web-ui/src/component-library/components/FlowChatCards/SnapshotCard/SnapshotCard.scss index 9693a13f..7c76c504 100644 --- a/src/web-ui/src/component-library/components/FlowChatCards/SnapshotCard/SnapshotCard.scss +++ b/src/web-ui/src/component-library/components/FlowChatCards/SnapshotCard/SnapshotCard.scss @@ -83,14 +83,14 @@ .snapshot-card__action { color: tokens.$color-text-secondary; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-weight: tokens.$font-weight-medium; flex-shrink: 0; } .snapshot-card__filename { color: tokens.$color-text-primary; - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); font-weight: tokens.$font-weight-medium; flex-shrink: 1; min-width: 0; @@ -241,7 +241,7 @@ display: flex; align-items: center; gap: tokens.$size-gap-2; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); } .snapshot-card__label { @@ -275,13 +275,13 @@ } .snapshot-card__stat-value { - font-size: tokens.$font-size-lg; + font-size: var(--font-size-lg); font-weight: tokens.$font-weight-bold; font-family: tokens.$font-family-mono; } .snapshot-card__stat-label { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: tokens.$color-text-muted; } @@ -334,7 +334,7 @@ border: 1px solid rgba(59, 130, 246, 0.3); border-radius: tokens.$size-radius-base; color: tokens.$color-info; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); } .snapshot-card__processing-icon { @@ -350,7 +350,7 @@ border: 1px solid rgba(239, 68, 68, 0.3); border-radius: tokens.$size-radius-base; color: tokens.$color-error; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); } diff --git a/src/web-ui/src/component-library/components/FlowChatCards/_shared-styles.scss b/src/web-ui/src/component-library/components/FlowChatCards/_shared-styles.scss index 29e9161d..cc605829 100644 --- a/src/web-ui/src/component-library/components/FlowChatCards/_shared-styles.scss +++ b/src/web-ui/src/component-library/components/FlowChatCards/_shared-styles.scss @@ -71,7 +71,7 @@ padding: tokens.$size-gap-2 tokens.$size-gap-4; border: 1px solid tokens.$border-base; border-radius: tokens.$size-radius-base; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); font-weight: tokens.$font-weight-medium; cursor: pointer; transition: all tokens.$motion-base tokens.$easing-standard; diff --git a/src/web-ui/src/component-library/components/Search/Search.scss b/src/web-ui/src/component-library/components/Search/Search.scss index f01f5e72..43b3405e 100644 --- a/src/web-ui/src/component-library/components/Search/Search.scss +++ b/src/web-ui/src/component-library/components/Search/Search.scss @@ -70,7 +70,7 @@ box-shadow: none !important; background: transparent; color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-family: $font-family-sans; line-height: $line-height-base; padding: 0; @@ -150,7 +150,7 @@ border-radius: $size-radius-sm; background: transparent; color: var(--color-accent-500); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; font-family: $font-family-sans; cursor: pointer; @@ -193,7 +193,7 @@ &__error-message { margin-top: $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-error); display: flex; align-items: center; @@ -209,7 +209,7 @@ } .search__input { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } .search__icon, @@ -230,7 +230,7 @@ .search__button { padding: $size-gap-1 $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); } } @@ -242,7 +242,7 @@ } .search__input { - font-size: $font-size-base; + font-size: var(--font-size-base); } .search__icon, @@ -263,7 +263,7 @@ .search__button { padding: $size-gap-2 $size-gap-5; - font-size: $font-size-base; + font-size: var(--font-size-base); } } diff --git a/src/web-ui/src/component-library/components/Switch/Switch.scss b/src/web-ui/src/component-library/components/Switch/Switch.scss index b861560f..d9f0ca5e 100644 --- a/src/web-ui/src/component-library/components/Switch/Switch.scss +++ b/src/web-ui/src/component-library/components/Switch/Switch.scss @@ -134,14 +134,14 @@ } &__label { - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); font-weight: tokens.$font-weight-medium; color: var(--color-text-primary, tokens.$color-text-primary); line-height: tokens.$line-height-base; } &__description { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted, tokens.$color-text-muted); line-height: tokens.$line-height-base; } @@ -172,7 +172,7 @@ } .bitfun-switch__label { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); } .bitfun-switch__description { @@ -209,11 +209,11 @@ } .bitfun-switch__label { - font-size: tokens.$font-size-base; + font-size: var(--font-size-base); } .bitfun-switch__description { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); } } } diff --git a/src/web-ui/src/component-library/components/Tabs/Tabs.scss b/src/web-ui/src/component-library/components/Tabs/Tabs.scss index f86e0f45..d28c6151 100644 --- a/src/web-ui/src/component-library/components/Tabs/Tabs.scss +++ b/src/web-ui/src/component-library/components/Tabs/Tabs.scss @@ -27,7 +27,7 @@ justify-content: center; gap: 6px; padding: tokens.$size-gap-2 tokens.$size-gap-3; - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); font-weight: tokens.$font-weight-medium; color: var(--color-text-secondary); cursor: pointer; diff --git a/src/web-ui/src/component-library/components/Tag/Tag.scss b/src/web-ui/src/component-library/components/Tag/Tag.scss index 3c06f924..673d0f57 100644 --- a/src/web-ui/src/component-library/components/Tag/Tag.scss +++ b/src/web-ui/src/component-library/components/Tag/Tag.scss @@ -11,18 +11,18 @@ position: relative; &--small { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); padding: 2px tokens.$size-gap-2; gap: tokens.$size-gap-1; } &--medium { - font-size: tokens.$font-size-xs; + font-size: var(--font-size-xs); padding: tokens.$size-gap-1 tokens.$size-gap-3; } &--large { - font-size: tokens.$font-size-sm; + font-size: var(--font-size-sm); padding: tokens.$size-gap-2 tokens.$size-gap-4; } diff --git a/src/web-ui/src/component-library/styles/tokens.scss b/src/web-ui/src/component-library/styles/tokens.scss index 699e3f4d..5abd0997 100644 --- a/src/web-ui/src/component-library/styles/tokens.scss +++ b/src/web-ui/src/component-library/styles/tokens.scss @@ -301,14 +301,14 @@ $font-weight-bold: 600; // Optimized: use 600 instead of 700; Bold font removed $font-size-xxs: 10px; $font-size-2xs: 11px; $font-size-xs: 12px; -$font-size-sm: 14px; -$font-size-base: 15px; -$font-size-lg: 16px; -$font-size-xl: 18px; -$font-size-2xl: 20px; -$font-size-3xl: 24px; -$font-size-4xl: 30px; -$font-size-5xl: 36px; +$font-size-sm: 13px; +$font-size-base: 14px; +$font-size-lg: 15px; +$font-size-xl: 16px; +$font-size-2xl: 18px; +$font-size-3xl: 22px; +$font-size-4xl: 26px; +$font-size-5xl: 32px; $line-height-tight: 1.2; $line-height-base: 1.5; @@ -403,7 +403,7 @@ $modal-backdrop: rgba(0, 0, 0, 0.85); $badge-border-radius: $size-radius-sm; $badge-padding-x: $size-gap-2; $badge-padding-y: 2px; -$badge-font-size: $font-size-xs; +$badge-font-size: var(--font-size-xs); $badge-font-weight: $font-weight-medium; $badge-neutral-bg: $element-bg-base; @@ -659,7 +659,7 @@ $badge-info-text: $color-info; justify-content: center; padding: $badge-padding-y $badge-padding-x; border-radius: $badge-border-radius; - font-size: $badge-font-size; + font-size: var(--badge-font-size, #{$badge-font-size}); font-weight: $badge-font-weight; line-height: 1; border: none; @@ -933,6 +933,19 @@ $badge-info-text: $color-info; --font-size-3xl: #{$font-size-3xl}; --font-size-4xl: #{$font-size-4xl}; --font-size-5xl: #{$font-size-5xl}; + + /* Flow chat: mirrors UI scale until font preference overwrites (independent mode). */ + --flowchat-font-size-xxs: var(--font-size-xxs); + --flowchat-font-size-2xs: var(--font-size-2xs); + --flowchat-font-size-xs: var(--font-size-xs); + --flowchat-font-size-sm: var(--font-size-sm); + --flowchat-font-size-base: var(--font-size-base); + --flowchat-font-size-lg: var(--font-size-lg); + --flowchat-font-size-xl: var(--font-size-xl); + --flowchat-font-size-2xl: var(--font-size-2xl); + --flowchat-font-size-3xl: var(--font-size-3xl); + --flowchat-font-size-4xl: var(--font-size-4xl); + --flowchat-font-size-5xl: var(--font-size-5xl); --line-height-tight: #{$line-height-tight}; --line-height-base: #{$line-height-base}; diff --git a/src/web-ui/src/flow_chat/components/ChatEmptyState.scss b/src/web-ui/src/flow_chat/components/ChatEmptyState.scss index e236483d..be6c4cc9 100644 --- a/src/web-ui/src/flow_chat/components/ChatEmptyState.scss +++ b/src/web-ui/src/flow_chat/components/ChatEmptyState.scss @@ -59,13 +59,13 @@ p { margin: 0; - font-size: $font-size-2xl; + font-size: var(--flowchat-font-size-2xl); color: var(--color-text-secondary); font-weight: $font-weight-normal; line-height: $line-height-relaxed; &:first-child { - font-size: $font-size-3xl; + font-size: var(--flowchat-font-size-3xl); font-weight: $font-weight-semibold; color: var(--color-text-primary); letter-spacing: -0.02em; @@ -134,7 +134,7 @@ p { margin: 0 0 $size-gap-3; - font-size: $font-size-2xl; + font-size: var(--flowchat-font-size-2xl); color: var(--color-text-secondary); line-height: $line-height-relaxed; font-weight: $font-weight-normal; @@ -146,7 +146,7 @@ } &__hint { - font-size: $font-size-xl; + font-size: var(--flowchat-font-size-xl); color: var(--color-text-muted); font-style: italic; } @@ -160,7 +160,7 @@ p { margin: 0; - font-size: $font-size-xl; + font-size: var(--flowchat-font-size-xl); color: var(--color-text-secondary); line-height: 1.7; font-weight: $font-weight-normal; @@ -169,7 +169,7 @@ &-hint { margin-top: $size-gap-4; padding: $size-gap-3 $size-gap-4; - font-size: $font-size-lg; + font-size: var(--flowchat-font-size-lg); color: var(--color-text-muted); font-style: italic; background: var(--element-bg-subtle); diff --git a/src/web-ui/src/flow_chat/components/ChatInput.scss b/src/web-ui/src/flow_chat/components/ChatInput.scss index 64760e95..b250a71c 100644 --- a/src/web-ui/src/flow_chat/components/ChatInput.scss +++ b/src/web-ui/src/flow_chat/components/ChatInput.scss @@ -133,7 +133,7 @@ min-height: 24px !important; max-height: 24px !important; max-width: 100%; - font-size: 14px; + font-size: var(--flowchat-font-size-base); line-height: 24px; overflow: hidden; padding: 0 !important; @@ -145,7 +145,7 @@ display: block; color: var(--color-text-primary); opacity: 0.6; - font-size: 14px; + font-size: var(--flowchat-font-size-base); line-height: 24px; text-align: center; width: 100%; @@ -160,7 +160,7 @@ justify-content: center; gap: 6px; width: 100%; - font-size: 13px; + font-size: var(--flowchat-font-size-sm); line-height: 24px; color: var(--color-text-muted); opacity: 0.62; @@ -230,7 +230,7 @@ display: inline-block; padding: 0 4px; color: var(--color-text-secondary); - font-size: 12px; + font-size: var(--flowchat-font-size-xs); font-weight: 500; letter-spacing: 0.01em; background: transparent; @@ -243,7 +243,7 @@ align-items: center; flex-shrink: 0; gap: 4px; - font-size: 13px; + font-size: var(--flowchat-font-size-sm); line-height: 24px; color: var(--color-text-muted); opacity: 0.72; @@ -413,7 +413,7 @@ } &__target-switcher-label { - font-size: 10px; + font-size: var(--flowchat-font-size-xxs); color: var(--color-text-muted); font-weight: 400; padding: 2px 8px 2px 0; @@ -431,7 +431,7 @@ border: none; background: transparent; color: var(--color-text-muted); - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); font-weight: 400; border-radius: 5px; cursor: pointer; @@ -456,7 +456,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: 10px; + font-size: var(--flowchat-font-size-xxs); font-weight: 400; opacity: 0.65; @@ -601,7 +601,7 @@ padding: 2px 4px 2px 10px; border-radius: 999px; border: none; - font-size: 10px; + font-size: var(--flowchat-font-size-xxs); font-weight: 500; letter-spacing: 0.02em; color: var(--color-text-secondary); @@ -650,7 +650,7 @@ &__agent-boost-empty { padding: 12px 14px; - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); color: var(--color-text-tertiary); text-align: center; line-height: 1.35; @@ -679,7 +679,7 @@ margin: 0; padding: 8px 12px; background: transparent; - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); color: var(--color-text-secondary); cursor: pointer; user-select: none; @@ -725,7 +725,7 @@ margin: 0; padding: 8px 12px; background: transparent; - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); color: var(--color-text-secondary); cursor: pointer; user-select: none; @@ -809,7 +809,7 @@ justify-content: center; gap: 8px; padding: 14px 12px; - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); color: var(--color-text-muted); } @@ -843,7 +843,7 @@ padding: 5px 8px; border-radius: 4px; background: transparent; - font-size: 12px; + font-size: var(--flowchat-font-size-xs); color: var(--color-text-primary); cursor: pointer; user-select: none; @@ -876,7 +876,7 @@ padding: 8px 10px 10px; border-top: 1px solid var(--border-subtle); background: transparent; - font-size: 10px; + font-size: var(--flowchat-font-size-xxs); font-weight: 500; color: rgba(120, 160, 255, 0.95); cursor: pointer; @@ -902,7 +902,7 @@ } &__mode-pending-indicator { - font-size: 9px; + font-size: var(--flowchat-font-size-xxs); color: rgba(251, 146, 60, 0.9); margin-left: 4px; display: inline-flex; @@ -940,7 +940,7 @@ &__mode-option { padding: 7px 12px; - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); color: var(--color-text-secondary); cursor: pointer; transition: all 0.15s ease; @@ -966,7 +966,7 @@ &::after { content: ' (Pending)'; - font-size: 9px; + font-size: var(--flowchat-font-size-xxs); opacity: 0.8; } } @@ -999,7 +999,7 @@ &__mode-divider-text { padding: 0 8px; - font-size: 9px; + font-size: var(--flowchat-font-size-xxs); color: var(--color-text-muted); white-space: nowrap; font-weight: 500; @@ -1012,7 +1012,7 @@ &__mode-submenu-trigger { padding: 7px 12px; - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); color: var(--color-text-secondary); cursor: pointer; transition: all 0.15s ease; @@ -1044,7 +1044,7 @@ } &__mode-submenu-active-name { - font-size: 10px; + font-size: var(--flowchat-font-size-xxs); color: rgba(140, 180, 255, 0.9); font-weight: 500; margin-left: auto; @@ -1056,7 +1056,7 @@ } &__mode-submenu-dots { - font-size: 10px; + font-size: var(--flowchat-font-size-xxs); color: var(--color-text-tertiary); margin-left: auto; letter-spacing: 1px; @@ -1067,7 +1067,7 @@ .bitfun-chat-input__mode-option { padding-left: 24px; - font-size: 10px; + font-size: var(--flowchat-font-size-xxs); &:hover:not(&--disabled) { background: rgba(255, 255, 255, 0.04); @@ -1089,7 +1089,7 @@ border-radius: 3px; background: var(--color-warning-bg); color: var(--color-warning); - font-size: 8px; + font-size: var(--flowchat-font-size-xxs); font-weight: 600; letter-spacing: 0.5px; margin-left: 6px; @@ -1137,7 +1137,7 @@ justify-content: space-between; padding: 8px 12px; border-bottom: 1px solid var(--border-subtle); - font-size: 10px; + font-size: var(--flowchat-font-size-xxs); font-weight: 500; color: var(--color-text-muted); text-transform: uppercase; @@ -1145,7 +1145,7 @@ } &__slash-command-hint { - font-size: 9px; + font-size: var(--flowchat-font-size-xxs); color: var(--color-text-tertiary); font-weight: 400; text-transform: none; @@ -1199,7 +1199,7 @@ } &__slash-command-name { - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); font-weight: 500; color: rgba(120, 160, 255, 0.9); font-family: var(--font-mono); @@ -1207,13 +1207,13 @@ } &__slash-command-label { - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); color: var(--color-text-secondary); flex: 1; } &__slash-command-current { - font-size: 9px; + font-size: var(--flowchat-font-size-xxs); padding: 2px 5px; border-radius: 3px; background: rgba(100, 140, 255, 0.15); @@ -1224,7 +1224,7 @@ &__slash-command-empty { padding: 16px 12px; text-align: center; - font-size: 11px; + font-size: var(--flowchat-font-size-2xs); color: var(--color-text-tertiary); } @@ -1424,7 +1424,7 @@ display: inline-flex; align-items: center; justify-content: center; - font-size: 8px; + font-size: var(--flowchat-font-size-xxs); font-weight: 700; line-height: 1; box-shadow: 0 0 0 1px rgba(18, 18, 28, 0.85); diff --git a/src/web-ui/src/flow_chat/components/CurrentSessionTitle.scss b/src/web-ui/src/flow_chat/components/CurrentSessionTitle.scss index 173134e0..744e0b84 100644 --- a/src/web-ui/src/flow_chat/components/CurrentSessionTitle.scss +++ b/src/web-ui/src/flow_chat/components/CurrentSessionTitle.scss @@ -17,7 +17,7 @@ position: relative; &__text { - font-size: $font-size-base; + font-size: var(--flowchat-font-size-base); font-weight: $font-weight-medium; color: var(--color-text-primary); white-space: nowrap; diff --git a/src/web-ui/src/flow_chat/components/FlowTextBlock.scss b/src/web-ui/src/flow_chat/components/FlowTextBlock.scss index 4d8e99fe..1102a832 100644 --- a/src/web-ui/src/flow_chat/components/FlowTextBlock.scss +++ b/src/web-ui/src/flow_chat/components/FlowTextBlock.scss @@ -7,7 +7,7 @@ /* Chat: slightly roomier reading measure than generic markdown preview */ .markdown-renderer { - font-size: 0.9375rem; + font-size: 0.9375em; line-height: 1.65; letter-spacing: 0.01em; } @@ -38,7 +38,7 @@ } .markdown-renderer .code-block-lang { - font-size: 0.625rem; + font-size: var(--flowchat-font-size-xxs); line-height: 1.2; } diff --git a/src/web-ui/src/flow_chat/components/RichTextInput.scss b/src/web-ui/src/flow_chat/components/RichTextInput.scss index 9200ded3..dccb87f8 100644 --- a/src/web-ui/src/flow_chat/components/RichTextInput.scss +++ b/src/web-ui/src/flow_chat/components/RichTextInput.scss @@ -11,7 +11,7 @@ border: none !important; outline: none !important; color: var(--color-text-primary); - font-size: 14px; + font-size: var(--flowchat-font-size-base); line-height: $line-height-base; padding: 0; vertical-align: top; @@ -72,7 +72,7 @@ background: rgba(99, 102, 241, 0.1); border: 1px dashed rgba(99, 102, 241, 0.35); border-radius: 6px; - font-size: $font-size-sm; + font-size: var(--flowchat-font-size-sm); font-weight: 500; color: var(--color-accent-400); cursor: pointer; @@ -117,7 +117,7 @@ background: rgba(96, 165, 250, 0.12); border: none; border-radius: 10px; - font-size: $font-size-sm; + font-size: var(--flowchat-font-size-sm); font-weight: 500; color: rgba(96, 165, 250, 0.95); cursor: default; @@ -208,7 +208,7 @@ background: transparent; color: currentColor; opacity: 0.6; - font-size: 18px; + font-size: var(--flowchat-font-size-2xl); line-height: 1; cursor: pointer; border-radius: 50%; diff --git a/src/web-ui/src/flow_chat/components/UserMessage.css b/src/web-ui/src/flow_chat/components/UserMessage.css index ca47de80..dbc15862 100644 --- a/src/web-ui/src/flow_chat/components/UserMessage.css +++ b/src/web-ui/src/flow_chat/components/UserMessage.css @@ -13,7 +13,7 @@ padding: 3px 10px; margin: 0 3px; border-radius: 12px; - font-size: 0.875rem; + font-size: 0.875em; font-weight: 500; line-height: 1.4; border: 1px solid; @@ -78,7 +78,7 @@ } .message-timestamp { - font-size: 0.75rem; + font-size: 0.75em; color: var(--color-text-tertiary, #9ca3af); } diff --git a/src/web-ui/src/flow_chat/components/UserMessage.scss b/src/web-ui/src/flow_chat/components/UserMessage.scss index b5a7badc..06ca65db 100644 --- a/src/web-ui/src/flow_chat/components/UserMessage.scss +++ b/src/web-ui/src/flow_chat/components/UserMessage.scss @@ -49,7 +49,7 @@ color: var(--color-text-primary); position: relative; z-index: 1; - font-size: 1rem; + font-size: 1em; user-select: text; } @@ -66,7 +66,7 @@ } .message-timestamp { - font-size: 0.75rem; + font-size: 0.75em; color: var(--color-text-muted); font-weight: 400; } @@ -86,7 +86,7 @@ margin: 0 0.25rem; border-radius: 0.375rem; border: 1px solid; - font-size: 0.875rem; + font-size: 0.875em; font-weight: 500; vertical-align: middle; white-space: nowrap; diff --git a/src/web-ui/src/flow_chat/components/modern/FlowChatHeader.scss b/src/web-ui/src/flow_chat/components/modern/FlowChatHeader.scss index 846dd480..5dbf3475 100644 --- a/src/web-ui/src/flow_chat/components/modern/FlowChatHeader.scss +++ b/src/web-ui/src/flow_chat/components/modern/FlowChatHeader.scss @@ -96,7 +96,7 @@ gap: $size-gap-2; padding: $size-gap-2 $size-gap-3; border-bottom: 1px solid var(--border-base); - font-size: $font-size-xs; + font-size: var(--flowchat-font-size-xs); color: var(--color-text-secondary); } @@ -139,7 +139,7 @@ border-radius: 999px; background: color-mix(in srgb, var(--element-bg-soft) 82%, transparent); color: var(--color-text-secondary); - font-size: $font-size-xs; + font-size: var(--flowchat-font-size-xs); line-height: 1; white-space: nowrap; } @@ -147,7 +147,7 @@ &__turn-list-title { min-width: 0; flex: 1; - font-size: $font-size-sm; + font-size: var(--flowchat-font-size-sm); color: inherit; white-space: nowrap; overflow: hidden; @@ -175,14 +175,14 @@ border-radius: 999px; background: color-mix(in srgb, var(--element-bg-soft) 82%, transparent); color: var(--color-text-secondary); - font-size: $font-size-xs; + font-size: var(--flowchat-font-size-xs); line-height: 1; white-space: nowrap; } &__message-text { min-width: 0; - font-size: $font-size-sm; + font-size: var(--flowchat-font-size-sm); color: var(--color-text-primary); white-space: nowrap; overflow: hidden; diff --git a/src/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.scss b/src/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.scss index 3fe63174..e26d34f3 100644 --- a/src/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.scss +++ b/src/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.scss @@ -2,6 +2,11 @@ * Modern FlowChat container styles. */ +.modern-flowchat-container.flow-chat-typography { + font-family: var(--font-sans, var(--font-family-sans, inherit)); + font-size: var(--flowchat-font-size-base); +} + .modern-flowchat-container { width: 100%; height: 100%; diff --git a/src/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.tsx b/src/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.tsx index 371eab6f..01e9a7ef 100644 --- a/src/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.tsx +++ b/src/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.tsx @@ -215,7 +215,7 @@ export const ModernFlowChatContainer: React.FC = ( return ( -
+
label:not(.bitfun-checkbox):not(.bitfun-radio-label) { display: block; margin-bottom: $size-gap-2; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-secondary); } @@ -897,7 +897,7 @@ border: 1px solid var(--border-base, rgba(255, 255, 255, 0.14)); border-radius: var(--size-radius-sm, 6px); color: var(--color-text-primary, #e8e8e8); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-family: $font-family-sans; transition: all var(--motion-base, 0.3s) var(--easing-standard, cubic-bezier(0.4, 0, 0.2, 1)); min-height: 36px; @@ -1356,7 +1356,7 @@ display: flex; align-items: center; cursor: pointer; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); padding: $size-gap-2 $size-gap-3; border-radius: $size-radius-sm; @@ -1399,7 +1399,7 @@ border: 1px solid var(--border-base); > label { - font-size: $font-size-xs !important; + font-size: var(--font-size-xs) !important; color: var(--color-text-secondary) !important; margin-bottom: $size-gap-3; display: block; @@ -1434,7 +1434,7 @@ border-radius: $size-radius-sm; margin-top: $size-gap-2; color: var(--color-warning); - font-size: $font-size-sm; + font-size: var(--font-size-sm); svg { flex-shrink: 0; @@ -1446,7 +1446,7 @@ &__field-hint { display: block; color: var(--color-text-secondary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); margin-bottom: $size-gap-2; line-height: 1.5; } @@ -1530,13 +1530,13 @@ } &__provider-name { - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); } &__provider-description { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); line-height: 1.4; } @@ -1568,7 +1568,7 @@ gap: 4px; margin-top: auto; padding-top: $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-accent-500); text-decoration: none; transition: color $motion-base $easing-standard; @@ -1585,7 +1585,7 @@ gap: $size-gap-4; margin: $size-gap-6 0; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); &::before, &::after { @@ -1625,14 +1625,14 @@ } &__custom-option-title { - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); margin-bottom: 4px; } &__custom-option-description { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); } @@ -1653,7 +1653,7 @@ border: none; border-radius: $size-radius-sm; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); cursor: pointer; transition: all $motion-base $easing-standard; @@ -1702,11 +1702,11 @@ } &__title { - font-size: $font-size-lg; + font-size: var(--font-size-lg); } &__subtitle { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } @@ -1722,7 +1722,7 @@ &__tab { padding: $size-gap-2 $size-gap-3; - font-size: $font-size-xs; + font-size: var(--font-size-xs); gap: $size-gap-1; svg { @@ -1754,7 +1754,7 @@ &__category-tab { padding: 5px $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); height: 30px; } @@ -1774,11 +1774,11 @@ } &__item-name { - font-size: $font-size-sm; + font-size: var(--font-size-sm); } &__item-description { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__item-badges { @@ -1812,7 +1812,7 @@ &__action-btn { padding: $size-gap-2 $size-gap-3; - font-size: $font-size-xs; + font-size: var(--font-size-xs); svg { width: 14px; @@ -1833,13 +1833,13 @@ margin-bottom: $size-gap-3; > label:not(.bitfun-checkbox):not(.bitfun-radio-label) { - font-size: $font-size-xs; + font-size: var(--font-size-xs); margin-bottom: $size-gap-1; } > input, > select, > textarea { padding: $size-gap-2 $size-gap-3; - font-size: $font-size-sm; + font-size: var(--font-size-sm); } } diff --git a/src/web-ui/src/infrastructure/config/components/AIRulesMemoryConfig.scss b/src/web-ui/src/infrastructure/config/components/AIRulesMemoryConfig.scss index 6bbde327..84f55070 100644 --- a/src/web-ui/src/infrastructure/config/components/AIRulesMemoryConfig.scss +++ b/src/web-ui/src/infrastructure/config/components/AIRulesMemoryConfig.scss @@ -45,7 +45,7 @@ flex-shrink: 0; padding: 1px 7px; border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; white-space: nowrap; background: var(--element-bg-medium); @@ -98,13 +98,13 @@ } &__details-field { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); line-height: $line-height-relaxed; } &__details-label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-muted); margin-right: $size-gap-2; @@ -115,7 +115,7 @@ background: var(--element-bg-medium); border-radius: $size-radius-sm; font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-accent-500); } @@ -132,7 +132,7 @@ border: 1px solid var(--border-subtle); border-radius: $size-radius-sm; font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-primary); line-height: $line-height-relaxed; white-space: pre-wrap; @@ -142,7 +142,7 @@ } &__details-meta { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); padding-top: $size-gap-3; border-top: 1px solid var(--border-subtle); @@ -161,7 +161,7 @@ margin-bottom: $size-gap-3; h3 { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); } @@ -224,7 +224,7 @@ flex-shrink: 0; padding: 1px 7px; border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; white-space: nowrap; border: 1px solid transparent; @@ -242,7 +242,7 @@ flex-direction: column; gap: $size-gap-1; label { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-secondary); } diff --git a/src/web-ui/src/infrastructure/config/components/BasicsConfig.scss b/src/web-ui/src/infrastructure/config/components/BasicsConfig.scss index fc322f48..4567ffa5 100644 --- a/src/web-ui/src/infrastructure/config/components/BasicsConfig.scss +++ b/src/web-ui/src/infrastructure/config/components/BasicsConfig.scss @@ -58,13 +58,13 @@ } &__language-native { - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); } &__language-english { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); } @@ -121,14 +121,14 @@ &__theme-option-name { color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; line-height: 1.3; } &__theme-option-desc { color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: 1.3; white-space: nowrap; overflow: hidden; @@ -197,13 +197,13 @@ } &__name { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); } &__description { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); line-height: 1.3; display: -webkit-box; @@ -330,7 +330,7 @@ } &__name { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__description { @@ -796,7 +796,7 @@ border: 1px dashed var(--border-base); border-radius: $size-radius-sm; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); } &__inline-alert { diff --git a/src/web-ui/src/infrastructure/config/components/BasicsConfig.tsx b/src/web-ui/src/infrastructure/config/components/BasicsConfig.tsx index 8515444c..4947a093 100644 --- a/src/web-ui/src/infrastructure/config/components/BasicsConfig.tsx +++ b/src/web-ui/src/infrastructure/config/components/BasicsConfig.tsx @@ -1,4 +1,5 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { FontPreferencePanel } from '@/infrastructure/font-preference'; import { useTranslation } from 'react-i18next'; import { FolderOpen } from 'lucide-react'; import { @@ -856,6 +857,7 @@ const BasicsConfig: React.FC = () => { + diff --git a/src/web-ui/src/infrastructure/config/components/DebugConfig.scss b/src/web-ui/src/infrastructure/config/components/DebugConfig.scss index d10389cb..b106ae8f 100644 --- a/src/web-ui/src/infrastructure/config/components/DebugConfig.scss +++ b/src/web-ui/src/infrastructure/config/components/DebugConfig.scss @@ -117,7 +117,7 @@ } &__template-name { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-primary); white-space: nowrap; @@ -149,7 +149,7 @@ } &__template-label { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-secondary); } @@ -171,7 +171,7 @@ } &__template-note { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); line-height: $line-height-relaxed; } diff --git a/src/web-ui/src/infrastructure/config/components/DefaultModelConfig.scss b/src/web-ui/src/infrastructure/config/components/DefaultModelConfig.scss index a484f9ec..cccb4b04 100644 --- a/src/web-ui/src/infrastructure/config/components/DefaultModelConfig.scss +++ b/src/web-ui/src/infrastructure/config/components/DefaultModelConfig.scss @@ -8,7 +8,7 @@ &__optional-label { margin-left: 4px; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-normal; opacity: 0.75; } @@ -128,7 +128,7 @@ } &__slot-label { - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); } @@ -137,7 +137,7 @@ display: inline-flex; align-items: center; padding: 2px 8px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; border-radius: $size-radius-sm; background: rgba(var(--color-success-rgb, 34, 197, 94), 0.15); @@ -151,14 +151,14 @@ } &__slot-description { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); line-height: 1.5; margin: 0; } &__slot-hint { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); margin: 0; font-style: italic; @@ -277,7 +277,7 @@ display: flex; align-items: center; gap: $size-gap-2; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); @@ -288,7 +288,7 @@ } &__capability-status { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; @@ -297,7 +297,7 @@ } &__capability-description { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); line-height: 1.4; margin: 0; @@ -320,7 +320,7 @@ border: none; cursor: pointer; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; transition: all $motion-base $easing-standard; border-radius: $size-radius-sm; @@ -357,14 +357,14 @@ } &__override-title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); margin: 0 0 $size-gap-1 0; } &__override-description { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); margin: 0 0 $size-gap-3 0; } @@ -383,7 +383,7 @@ &__override-name { flex: 0 0 140px; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-primary); white-space: nowrap; @@ -415,7 +415,7 @@ p { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: 1.5; } } @@ -432,7 +432,7 @@ p { margin-top: $size-gap-4; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); } } } @@ -468,11 +468,11 @@ } &__slot-label { - font-size: $font-size-sm; + font-size: var(--font-size-sm); } &__slot-description { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__capability-grid { @@ -492,7 +492,7 @@ &__override-name { flex: none; - font-size: $font-size-xs; + font-size: var(--font-size-xs); } } } diff --git a/src/web-ui/src/infrastructure/config/components/EditorConfig.scss b/src/web-ui/src/infrastructure/config/components/EditorConfig.scss index f51a065a..0552f462 100644 --- a/src/web-ui/src/infrastructure/config/components/EditorConfig.scss +++ b/src/web-ui/src/infrastructure/config/components/EditorConfig.scss @@ -16,7 +16,7 @@ } &__saving { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); white-space: nowrap; } diff --git a/src/web-ui/src/infrastructure/config/components/McpToolsConfig.scss b/src/web-ui/src/infrastructure/config/components/McpToolsConfig.scss index 92899941..08ef0ce7 100644 --- a/src/web-ui/src/infrastructure/config/components/McpToolsConfig.scss +++ b/src/web-ui/src/infrastructure/config/components/McpToolsConfig.scss @@ -14,7 +14,7 @@ &__json-editor-header { h3 { margin: 0 0 $size-gap-1; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); } @@ -22,14 +22,14 @@ &__json-hint { margin: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); line-height: $line-height-relaxed; } &__json-textarea { font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: 1.6; } @@ -45,7 +45,7 @@ h4 { margin: 0 0 $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-muted); text-transform: uppercase; @@ -60,7 +60,7 @@ h5 { margin: 0 0 $size-gap-1; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-secondary); } @@ -72,7 +72,7 @@ border: 1px solid var(--border-subtle); border-radius: $size-radius-sm; font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-primary); line-height: 1.6; white-space: pre-wrap; @@ -88,7 +88,7 @@ flex-shrink: 0; padding: 1px 7px; border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; white-space: nowrap; border: 1px solid transparent; @@ -142,13 +142,13 @@ } &__server-detail-label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); } &__server-detail-value { font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); word-break: break-all; } diff --git a/src/web-ui/src/infrastructure/config/components/ModelSelectionRadio.scss b/src/web-ui/src/infrastructure/config/components/ModelSelectionRadio.scss index d77ef08f..c1cac589 100644 --- a/src/web-ui/src/infrastructure/config/components/ModelSelectionRadio.scss +++ b/src/web-ui/src/infrastructure/config/components/ModelSelectionRadio.scss @@ -24,7 +24,7 @@ .model-selection-radio__option { padding: $size-gap-1 $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); } .model-selection-radio__dropdown { @@ -37,7 +37,7 @@ .model-selection-radio__option { padding: $size-gap-2 $size-gap-3; - font-size: $font-size-sm; + font-size: var(--font-size-sm); } .model-selection-radio__dropdown { @@ -121,7 +121,7 @@ &__hint { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); font-weight: $font-weight-normal; diff --git a/src/web-ui/src/infrastructure/config/components/SkillsConfig.scss b/src/web-ui/src/infrastructure/config/components/SkillsConfig.scss index d4754949..4304b01d 100644 --- a/src/web-ui/src/infrastructure/config/components/SkillsConfig.scss +++ b/src/web-ui/src/infrastructure/config/components/SkillsConfig.scss @@ -13,12 +13,12 @@ } &__path-hint { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); } &__validating { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); font-style: italic; } @@ -26,7 +26,7 @@ &__validation { padding: $size-gap-2 $size-gap-3; border-radius: $size-radius-base; - font-size: $font-size-sm; + font-size: var(--font-size-sm); &.is-valid { background: rgba($color-success, 0.08); @@ -46,7 +46,7 @@ } &__validation-desc { - font-size: $font-size-xs; + font-size: var(--font-size-xs); opacity: 0.8; margin-top: 2px; } @@ -56,13 +56,13 @@ } &__form-hint { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); } &__path-value { font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); word-break: break-all; } @@ -91,7 +91,7 @@ rgba(255, 255, 255, 0.02) 100% ); color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-relaxed; } @@ -188,7 +188,7 @@ } &__market-item-name { - font-size: $font-size-lg; + font-size: var(--font-size-lg); font-weight: $font-weight-semibold; color: var(--color-text-primary); line-height: $line-height-tight; @@ -200,7 +200,7 @@ gap: 4px; padding: 2px 8px; border-radius: $size-radius-full; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; border: 1px solid var(--border-subtle); background: var(--element-bg-soft); @@ -214,7 +214,7 @@ } &__market-item-description { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); line-height: $line-height-relaxed; margin-bottom: $size-gap-3; @@ -238,7 +238,7 @@ max-width: 100%; padding: 2px 10px; border-radius: $size-radius-full; - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: 1.35; border: 1px solid var(--border-subtle); background: var(--element-bg-soft); @@ -261,7 +261,7 @@ flex-shrink: 0; padding: 2px 10px; border-radius: $size-radius-full; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-muted); border: 1px solid var(--border-subtle); @@ -379,7 +379,7 @@ } &__market-item-name { - font-size: $font-size-base; + font-size: var(--font-size-base); } &__market-item-description { diff --git a/src/web-ui/src/infrastructure/config/components/common/ConfigCollectionItem.scss b/src/web-ui/src/infrastructure/config/components/common/ConfigCollectionItem.scss index 40ae3828..995da76a 100644 --- a/src/web-ui/src/infrastructure/config/components/common/ConfigCollectionItem.scss +++ b/src/web-ui/src/infrastructure/config/components/common/ConfigCollectionItem.scss @@ -60,7 +60,7 @@ flex-shrink: 0; padding: 1px 7px; border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; white-space: nowrap; background: var(--element-bg-medium); @@ -132,7 +132,7 @@ gap: $size-gap-3; padding: $size-gap-6 $size-gap-4; color: var(--color-text-muted); - font-size: $font-size-sm; + font-size: var(--font-size-sm); p { margin: 0; @@ -155,7 +155,7 @@ h3 { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); } @@ -177,13 +177,13 @@ // ─── details inner blocks ────────────────────────────────────────────────────── .bitfun-collection-details__field { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); line-height: $line-height-relaxed; } .bitfun-collection-details__label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-muted); margin-bottom: $size-gap-1; @@ -196,7 +196,7 @@ border: 1px solid var(--border-subtle); border-radius: $size-radius-sm; font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-primary); line-height: $line-height-relaxed; white-space: pre-wrap; @@ -206,7 +206,7 @@ } .bitfun-collection-details__meta { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); padding-top: $size-gap-3; border-top: 1px solid var(--border-subtle); @@ -217,7 +217,7 @@ background: var(--element-bg-medium); border-radius: $size-radius-sm; font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-accent-500); } diff --git a/src/web-ui/src/infrastructure/config/components/common/ConfigPageLayout.scss b/src/web-ui/src/infrastructure/config/components/common/ConfigPageLayout.scss index 5f1cb327..1bd595c3 100644 --- a/src/web-ui/src/infrastructure/config/components/common/ConfigPageLayout.scss +++ b/src/web-ui/src/infrastructure/config/components/common/ConfigPageLayout.scss @@ -65,6 +65,14 @@ flex: 1; } +.bitfun-config-page-section__title-row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: var(--size-gap-2, 8px); + min-width: 0; +} + .bitfun-config-page-section__title { margin: 0; font-size: var(--font-size-base); @@ -119,7 +127,8 @@ gap: var(--size-gap-2, 8px); .bitfun-config-page-row__control { - justify-content: stretch; + justify-content: flex-start; + align-items: stretch; justify-self: stretch; } } diff --git a/src/web-ui/src/infrastructure/config/components/common/ConfigPageLayout.tsx b/src/web-ui/src/infrastructure/config/components/common/ConfigPageLayout.tsx index 05efb15a..0a2113dd 100644 --- a/src/web-ui/src/infrastructure/config/components/common/ConfigPageLayout.tsx +++ b/src/web-ui/src/infrastructure/config/components/common/ConfigPageLayout.tsx @@ -47,6 +47,8 @@ export const ConfigPageContent: React.FC = ({ export interface ConfigPageSectionProps { title: string; + /** Renders inline after the title (e.g. status badge). */ + titleSuffix?: React.ReactNode; description?: React.ReactNode; extra?: React.ReactNode; children: React.ReactNode; @@ -55,6 +57,7 @@ export interface ConfigPageSectionProps { export const ConfigPageSection: React.FC = ({ title, + titleSuffix, description, extra, children, @@ -64,7 +67,10 @@ export const ConfigPageSection: React.FC = ({
-

{title}

+
+

{title}

+ {titleSuffix} +
{description && (

{description}

)} diff --git a/src/web-ui/src/infrastructure/font-preference/components/FontPreferencePanel.scss b/src/web-ui/src/infrastructure/font-preference/components/FontPreferencePanel.scss new file mode 100644 index 00000000..65c75830 --- /dev/null +++ b/src/web-ui/src/infrastructure/font-preference/components/FontPreferencePanel.scss @@ -0,0 +1,365 @@ +@use '../../../component-library/styles/tokens.scss' as *; +@use '../../../component-library/styles/btn-primary-tokens.scss' as btn-primary; + +.font-pref-panel { + /* 界面字体:多行区块,标题与说明之间略松一点 */ + &__row--ui.bitfun-config-page-row--multiline { + gap: $size-gap-3; + + .bitfun-config-page-row__description { + max-width: 52ch; + } + } + + /* 对话:左右单行,左侧说明区偏宽、右侧控件区保证最小宽度 */ + &__row--flow-chat.bitfun-config-page-row:not(.bitfun-config-page-row--multiline) { + --row-grid-cols: minmax(0, 8fr) minmax(220px, 4fr); + } + + &__ui-size { + display: flex; + flex-direction: column; + gap: $size-gap-3; + width: 100%; + min-width: 0; + flex: 1 1 auto; + align-self: stretch; + } + + &__level-buttons { + display: flex; + flex-wrap: nowrap; + gap: $size-gap-2; + flex-shrink: 0; + } + + &__ui-control-row { + display: flex; + align-items: center; + gap: $size-gap-3; + flex-wrap: nowrap; + width: 100%; + min-width: 0; + overflow-x: auto; + scrollbar-width: thin; + padding-bottom: 2px; + } + + &__flow-chat { + display: flex; + flex-direction: column; + align-items: stretch; + gap: $size-gap-2; + width: 100%; + min-width: 0; + } + + &__flow-chat-line { + display: flex; + justify-content: flex-end; + width: 100%; + } + + &__flow-chat-panel { + display: flex; + align-items: center; + justify-content: space-between; + gap: $size-gap-3; + width: 100%; + box-sizing: border-box; + padding: $size-gap-2 $size-gap-3; + border: 1px solid var(--border-base); + border-radius: $size-radius-sm; + background: var(--bg-secondary); + } + + &__flow-chat-panel-label { + font-size: var(--font-size-xs); + color: var(--text-secondary); + flex-shrink: 0; + } + + &__flow-chat-picker { + display: flex; + align-items: center; + gap: $size-gap-2; + min-width: 0; + margin-left: auto; + } + + &__flow-select { + height: 32px; + min-width: 5.5rem; + max-width: 100%; + padding: 0 $size-gap-3; + border: 1px solid var(--border-base); + border-radius: $size-radius-sm; + background: var(--bg-primary); + color: var(--text-primary); + font-size: var(--font-size-sm); + font-family: var(--font-sans, var(--font-family-sans)); + cursor: pointer; + outline: none; + + &:focus, + &:focus-visible { + outline: none !important; + outline-offset: 0 !important; + box-shadow: none !important; + border-color: var(--border-strong); + } + } + + &__level-btn { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 36px; + padding: $size-gap-2 $size-gap-3; + font-size: var(--font-size-sm); + font-family: var(--font-sans, var(--font-family-sans)); + background: transparent; + border: 1px solid var(--border-base); + border-radius: $size-radius-sm; + color: var(--text-secondary); + cursor: pointer; + transition: background $motion-fast $easing-standard, + border-color $motion-fast $easing-standard, + color $motion-fast $easing-standard, + box-shadow $motion-fast $easing-standard; + white-space: nowrap; + + &:hover:not(:disabled):not(&--active) { + background: var(--element-bg-subtle); + border-color: var(--border-strong); + color: var(--text-primary); + } + + &--active { + @include btn-primary.btn-primary-surface-default; + border-color: var(--btn-primary-border, transparent); + font-weight: $font-weight-semibold; + box-shadow: var(--btn-primary-shadow, none); + + &:hover:not(:disabled) { + @include btn-primary.btn-primary-surface-hover; + border-color: var(--btn-primary-hover-border, transparent); + box-shadow: var(--btn-primary-hover-shadow, none); + } + } + } + + &__level-label { + display: block; + line-height: 1.15; + font-weight: inherit; + color: inherit; + } + + &__custom-row { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: $size-gap-2; + + &--capsule { + flex-wrap: nowrap; + margin-left: auto; + align-items: center; + gap: $size-gap-2; + padding: 4px 4px 4px $size-gap-3; + border: 1px solid var(--border-strong); + border-radius: 999px; + background: var(--bg-secondary); + box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06); + } + + &--active { + .font-pref-panel__custom-label { + color: var(--text-primary); + } + } + + &--capsule.font-pref-panel__custom-row--active { + @include btn-primary.btn-primary-surface-default; + border-color: var(--btn-primary-border, transparent); + box-shadow: var(--btn-primary-shadow, none); + + .font-pref-panel__custom-label, + .font-pref-panel__custom-unit { + color: var(--btn-primary-color, var(--text-primary)); + opacity: 0.95; + } + + .font-pref-panel__stepper { + border-color: color-mix(in srgb, var(--btn-primary-color, #fff) 22%, transparent); + } + + .font-pref-panel__step-btn { + color: var(--btn-primary-color, var(--text-primary)); + + &:hover:not(:disabled) { + background: color-mix(in srgb, var(--btn-primary-color, #fff) 14%, transparent); + color: var(--btn-primary-color, var(--text-primary)); + } + } + + .font-pref-panel__number-input { + background: color-mix(in srgb, var(--btn-primary-bg, #000) 12%, transparent); + color: var(--btn-primary-color, var(--text-primary)); + border-left-color: color-mix(in srgb, var(--btn-primary-color, #fff) 22%, transparent); + border-right-color: color-mix(in srgb, var(--btn-primary-color, #fff) 22%, transparent); + } + + .font-pref-panel__number-input--readonly { + background: color-mix(in srgb, var(--btn-primary-color, #fff) 8%, transparent); + color: var(--btn-primary-color, var(--text-primary)); + opacity: 0.92; + } + } + } + + &__custom-label { + font-size: var(--font-size-sm); + color: var(--text-secondary); + flex-shrink: 0; + } + + &__stepper { + display: flex; + align-items: center; + gap: 0; + border: 1px solid var(--border-base); + border-radius: $size-radius-sm; + overflow: hidden; + width: fit-content; + + &:focus-within { + outline: none !important; + outline-offset: 0 !important; + box-shadow: none !important; + } + } + + &__custom-unit { + font-size: var(--font-size-xs); + color: var(--text-muted); + } + + &__step-btn { + display: flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; + background: transparent; + border: none; + color: var(--text-secondary); + cursor: pointer; + font-size: var(--font-size-base); + transition: background $motion-fast $easing-standard; + flex-shrink: 0; + + &:hover:not(:disabled) { + background: var(--element-bg-subtle); + color: var(--text-primary); + } + + &:disabled { + opacity: 0.4; + cursor: not-allowed; + } + } + + &__number-input { + width: 56px; + height: 28px; + padding: 0 $size-gap-2; + border: none; + border-left: 1px solid var(--border-base); + border-right: 1px solid var(--border-base); + background: var(--bg-primary); + color: var(--text-primary); + font-size: var(--font-size-sm); + text-align: center; + outline: none !important; + outline-offset: 0 !important; + appearance: textfield; + + &:focus, + &:focus-visible { + outline: none !important; + outline-offset: 0 !important; + box-shadow: none !important; + } + + &::-webkit-outer-spin-button, + &::-webkit-inner-spin-button { + appearance: none; + margin: 0; + } + + &:disabled { + opacity: 0.4; + cursor: not-allowed; + } + + &--readonly { + background: var(--bg-secondary); + color: var(--text-secondary); + cursor: pointer; + } + + &--error { + border-left-color: var(--color-semantic-error); + border-right-color: var(--color-semantic-error); + color: var(--color-semantic-error); + } + } + + &__error { + font-size: var(--font-size-xs); + color: var(--color-semantic-error); + width: 100%; + } + + &__custom-hint { + width: 100%; + font-size: var(--font-size-xs); + color: var(--text-muted); + line-height: 1.4; + } + + &__preview { + width: 100%; + box-sizing: border-box; + margin-top: $size-gap-2; + padding: $size-gap-3 $size-gap-4; + background: var(--bg-secondary); + border: 1px solid var(--border-subtle); + border-radius: $size-radius-sm; + color: var(--text-secondary); + line-height: 1.6; + word-wrap: break-word; + transition: font-size $motion-base $easing-standard; + } + + &__reset-btn { + margin-left: auto; + padding: $size-gap-2 $size-gap-4; + font-size: var(--font-size-sm); + font-family: var(--font-sans, var(--font-family-sans)); + background: transparent; + border: 1px solid var(--border-base); + border-radius: $size-radius-sm; + color: var(--text-secondary); + cursor: pointer; + transition: all $motion-fast $easing-standard; + + &:hover { + background: var(--element-bg-subtle); + border-color: var(--border-strong); + color: var(--text-primary); + } + } +} diff --git a/src/web-ui/src/infrastructure/font-preference/components/FontPreferencePanel.tsx b/src/web-ui/src/infrastructure/font-preference/components/FontPreferencePanel.tsx new file mode 100644 index 00000000..d590bf00 --- /dev/null +++ b/src/web-ui/src/infrastructure/font-preference/components/FontPreferencePanel.tsx @@ -0,0 +1,257 @@ +import React, { useId, useState, useCallback, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Badge, Switch } from '@/component-library'; +import { ConfigPageRow, ConfigPageSection } from '@/infrastructure/config/components/common'; +import { useFontPreference } from '../hooks/useFontPreference'; +import { FontSizeLevel, UI_FONT_SIZE_PRESETS } from '../types'; +import './FontPreferencePanel.scss'; + +const UI_LEVELS: FontSizeLevel[] = ['compact', 'small', 'default', 'medium', 'large']; +const FLOW_CHAT_PX_OPTIONS = [12, 13, 14, 15, 16, 17, 18, 19, 20]; + +export function FontPreferencePanel() { + const { t } = useTranslation('settings/basics'); + const flowChatBaselineLabelId = useId(); + const { preference, setUiSize, setFlowChatFont, reset } = useFontPreference(); + + const { level, customPx } = preference.uiSize; + const [customInput, setCustomInput] = useState(String(customPx ?? 14)); + const [fcBaseInput, setFcBaseInput] = useState(String(preference.flowChat.basePx ?? 14)); + const [customError, setCustomError] = useState(null); + + useEffect(() => { + if (preference.flowChat.mode === 'independent') { + setFcBaseInput(String(preference.flowChat.basePx ?? 14)); + } + }, [preference.flowChat.mode, preference.flowChat.basePx]); + + /** Legacy "sync" mode removed from UI: normalize to lift (UI +1). */ + useEffect(() => { + if (preference.flowChat.mode === 'sync') { + void setFlowChatFont('lift'); + } + }, [preference.flowChat.mode, setFlowChatFont]); + + const handleLevelClick = useCallback(async (l: FontSizeLevel) => { + if (l === 'custom') { + const px = parseInt(customInput, 10); + if (isNaN(px) || px < 12 || px > 20) { + await setUiSize('custom', 14); + setCustomInput('14'); + } else { + await setUiSize('custom', px); + } + } else { + await setUiSize(l); + } + setCustomError(null); + }, [customInput, setUiSize]); + + const handleCustomInputChange = (e: React.ChangeEvent) => { + const raw = e.target.value; + setCustomInput(raw); + const px = parseInt(raw, 10); + if (isNaN(px) || px < 12 || px > 20) { + setCustomError(t('appearance.fontSize.customPxOutOfRange')); + } else { + setCustomError(null); + void setUiSize('custom', px); + } + }; + + const handleCustomStep = (delta: number) => { + const current = parseInt(customInput, 10); + const next = Math.max(12, Math.min(20, (isNaN(current) ? 14 : current) + delta)); + setCustomInput(String(next)); + setCustomError(null); + void setUiSize('custom', next); + }; + + const handleReset = async () => { + await reset(); + setCustomInput('14'); + setFcBaseInput('14'); + setCustomError(null); + }; + + const previewBasePx = level === 'custom' + ? (parseInt(customInput, 10) || 14) + : parseInt(UI_FONT_SIZE_PRESETS[level].base, 10); + const uiCustomActive = level === 'custom'; + const uiDisplayPx = uiCustomActive ? customInput : String(previewBasePx); + + const fcIndependent = preference.flowChat.mode === 'independent'; + const flowChatSelectValue = (() => { + const n = parseInt(fcBaseInput, 10); + return n >= 12 && n <= 20 ? String(n) : '14'; + })(); + + const handleFlowChatCustomToggle = (enabled: boolean) => { + if (enabled) { + const px = parseInt(fcBaseInput, 10); + const v = isNaN(px) || px < 12 || px > 20 ? 14 : px; + setFcBaseInput(String(v)); + void setFlowChatFont('independent', v); + } else { + void setFlowChatFont('lift'); + } + }; + + const handleFlowChatPxSelect = (e: React.ChangeEvent) => { + const v = parseInt(e.target.value, 10); + setFcBaseInput(String(v)); + void setFlowChatFont('independent', v); + }; + + return ( + {t('appearance.fontSize.betaBadge')}} + description={t('appearance.fontSize.hint')} + > + {/* UI Font Size */} + +
+
+
+ {UI_LEVELS.map((l) => ( + + ))} +
+ +
+ + {t('appearance.fontSize.levels.custom')} + +
+ + void handleLevelClick('custom')} + aria-readonly={!uiCustomActive} + aria-invalid={!!customError} + /> + +
+ px +
+
+ {customError && ( + {customError} + )} + + {/* Live preview */} +
+ {t('appearance.fontSize.previewText')} +
+
+
+ + {/* Flow chat font scale */} + +
+
+ handleFlowChatCustomToggle(e.target.checked)} + label={t('appearance.fontSize.flowChatCustomToggle')} + /> +
+ {fcIndependent && ( +
+ + {t('appearance.fontSize.flowChatBaselinePicker')} + +
+ +
+
+ )} +
+
+ + {/* Reset */} + + + +
+ ); +} diff --git a/src/web-ui/src/infrastructure/font-preference/core/FontPreferenceService.ts b/src/web-ui/src/infrastructure/font-preference/core/FontPreferenceService.ts new file mode 100644 index 00000000..25d579f6 --- /dev/null +++ b/src/web-ui/src/infrastructure/font-preference/core/FontPreferenceService.ts @@ -0,0 +1,216 @@ + +import { configAPI } from '@/infrastructure/api'; +import { createLogger } from '@/shared/utils/logger'; +import { + FontPreference, + FontPreferenceEvent, + FontPreferenceEventListener, + FontPreferenceEventType, + FlowChatFontMode, + FontSizeLevel, + FontSizeTokens, + UiFontSizePreference, + DEFAULT_FONT_PREFERENCE, + resolveFontSizeTokens, + resolveFlowChatFontSizeTokens, +} from '../types'; + +const log = createLogger('FontPreferenceService'); + +const CONFIG_KEY = 'font'; + +export class FontPreferenceService { + private preference: FontPreference = { ...DEFAULT_FONT_PREFERENCE }; + private listeners: Map> = new Map(); + /** Only register theme hook once (initialize may run from main + settings). */ + private themeSyncRegistered = false; + + // ---- Lifecycle ---- + + async initialize(): Promise { + try { + const saved = await configAPI.getConfig(CONFIG_KEY, { skipRetryOnNotFound: true }) as FontPreference | undefined; + if (saved) { + this.preference = this.mergeWithDefaults(saved); + } + } catch { + // Config not found — use defaults + } + this.applyPreference(this.preference); + + if (!this.themeSyncRegistered) { + this.themeSyncRegistered = true; + const { themeService } = await import('@/infrastructure/theme'); + themeService.on('theme:after-change', () => { + this.applyPreference(this.preference); + }); + } + + log.info('Font preference initialized', { + level: this.preference.uiSize.level, + flowChat: this.preference.flowChat.mode, + }); + } + + // ---- Read ---- + + getPreference(): FontPreference { + return { ...this.preference }; + } + + getDefaultPreference(): FontPreference { + return { ...DEFAULT_FONT_PREFERENCE }; + } + + // ---- Write ---- + + async setPreference(partial: Partial): Promise { + const previous = { ...this.preference }; + const merged = this.mergeWithDefaults({ ...this.preference, ...partial }); + + this.emit({ type: 'font:before-change', preference: merged, previousPreference: previous, timestamp: Date.now() }); + + this.preference = merged; + this.applyPreference(merged); + + this.emit({ type: 'font:after-change', preference: merged, previousPreference: previous, timestamp: Date.now() }); + + try { + await configAPI.setConfig(CONFIG_KEY, merged); + } catch (error) { + log.error('Failed to persist font preference', error); + } + } + + async setUiSize(level: FontSizeLevel, customPx?: number): Promise { + const uiSize: UiFontSizePreference = level === 'custom' + ? { level, customPx: Math.max(12, Math.min(20, customPx ?? 14)) } + : { level }; + await this.setPreference({ uiSize }); + } + + async setFlowChatFont(mode: FlowChatFontMode, basePx?: number): Promise { + if (mode === 'independent') { + await this.setPreference({ + flowChat: { mode, basePx: Math.max(12, Math.min(20, Math.round(basePx ?? 14))) }, + }); + return; + } + await this.setPreference({ flowChat: { mode } }); + } + + async reset(): Promise { + await this.setPreference(DEFAULT_FONT_PREFERENCE); + } + + // ---- CSS Application ---- + + applyPreference(pref: FontPreference): void { + const root = document.documentElement; + const tokens = resolveFontSizeTokens(pref.uiSize); + + // Apply all UI font-size tokens — overrides tokens.scss :root defaults + (Object.entries(tokens) as [string, string][]).forEach(([key, value]) => { + root.style.setProperty(`--font-size-${key}`, value); + }); + + this.applyExtraFontSizeTokens(root, tokens); + + const flowTokens = resolveFlowChatFontSizeTokens(pref); + (Object.entries(flowTokens) as [string, string][]).forEach(([key, value]) => { + root.style.setProperty(`--flowchat-font-size-${key}`, value); + }); + this.applyFlowChatExtraFontSizeTokens(root, flowTokens); + + // Drive body font-size so elements using `inherit` cascade to the new base size. + // This is the broadest single-point fix for SCSS components that compiled their + // font-size to literal px at build time (e.g. font-size: 14px). + document.body.style.fontSize = tokens.base; + + log.debug('Font preference applied', { level: pref.uiSize.level }); + } + + // ---- Events ---- + + on(type: FontPreferenceEventType, listener: FontPreferenceEventListener): () => void { + if (!this.listeners.has(type)) { + this.listeners.set(type, new Set()); + } + this.listeners.get(type)!.add(listener); + return () => { + this.listeners.get(type)?.delete(listener); + }; + } + + off(type: FontPreferenceEventType, listener: FontPreferenceEventListener): void { + this.listeners.get(type)?.delete(listener); + } + + /** Smaller steps used by some SCSS (xxs / 2xs); badge uses xs scale. */ + private applyExtraFontSizeTokens(root: HTMLElement, tokens: FontSizeTokens): void { + const xsPx = parseInt(tokens.xs, 10); + if (!Number.isNaN(xsPx)) { + const twoXs = Math.max(8, xsPx - 1); + const xxs = Math.max(7, xsPx - 2); + root.style.setProperty('--font-size-2xs', `${twoXs}px`); + root.style.setProperty('--font-size-xxs', `${xxs}px`); + } + root.style.setProperty('--badge-font-size', tokens.xs); + } + + private applyFlowChatExtraFontSizeTokens(root: HTMLElement, tokens: FontSizeTokens): void { + const xsPx = parseInt(tokens.xs, 10); + if (!Number.isNaN(xsPx)) { + const twoXs = Math.max(8, xsPx - 1); + const xxs = Math.max(7, xsPx - 2); + root.style.setProperty('--flowchat-font-size-2xs', `${twoXs}px`); + root.style.setProperty('--flowchat-font-size-xxs', `${xxs}px`); + } + } + + private emit(event: FontPreferenceEvent): void { + const listeners = this.listeners.get(event.type); + if (!listeners) return; + listeners.forEach(listener => { + try { + void listener(event); + } catch (error) { + log.error('Font preference event listener error', { type: event.type, error }); + } + }); + } + + // ---- Helpers ---- + + private mergeWithDefaults(raw: Partial): FontPreference { + const def = DEFAULT_FONT_PREFERENCE; + return { + uiSize: { + level: raw.uiSize?.level ?? def.uiSize.level, + customPx: raw.uiSize?.customPx, + }, + flowChat: this.mergeFlowChatPreference(raw.flowChat), + }; + } + + private mergeFlowChatPreference( + raw: Partial | undefined, + ): FontPreference['flowChat'] { + const def = DEFAULT_FONT_PREFERENCE.flowChat; + if (!raw || raw.mode === undefined) { + return { ...def }; + } + if (raw.mode === 'sync' || raw.mode === 'lift') { + return { mode: raw.mode }; + } + if (raw.mode === 'independent') { + const basePx = typeof raw.basePx === 'number' + ? Math.max(12, Math.min(20, Math.round(raw.basePx))) + : 14; + return { mode: 'independent', basePx }; + } + return { ...def }; + } +} + +export const fontPreferenceService = new FontPreferenceService(); diff --git a/src/web-ui/src/infrastructure/font-preference/hooks/useFontPreference.ts b/src/web-ui/src/infrastructure/font-preference/hooks/useFontPreference.ts new file mode 100644 index 00000000..87f5ee98 --- /dev/null +++ b/src/web-ui/src/infrastructure/font-preference/hooks/useFontPreference.ts @@ -0,0 +1,53 @@ + +import { useEffect } from 'react'; +import { useFontPreferenceStore } from '../store/fontPreferenceStore'; +import { FontSizeLevel } from '../types'; + +export function useFontPreference() { + const { + preference, + initialized, + loading, + error, + initialize, + setUiSize, + setFlowChatFont, + reset, + } = useFontPreferenceStore(); + + useEffect(() => { + if (!initialized && !loading) { + initialize(); + } + }, [initialized, loading, initialize]); + + return { + preference, + loading, + error, + setUiSize, + setFlowChatFont, + reset, + }; +} + +export function useUiFontSize() { + return useFontPreferenceStore(s => ({ + uiSize: s.preference.uiSize, + setUiSize: s.setUiSize, + })); +} + +/** Convenience: return the current UI base font size level label (for display). */ +export function useFontSizeLevelLabel(): string { + const level = useFontPreferenceStore(s => s.preference.uiSize.level); + const labels: Record = { + compact: 'Compact', + small: 'Small', + default: 'Default', + medium: 'Medium', + large: 'Large', + custom: 'Custom', + }; + return labels[level] ?? labels.default; +} diff --git a/src/web-ui/src/infrastructure/font-preference/index.ts b/src/web-ui/src/infrastructure/font-preference/index.ts new file mode 100644 index 00000000..8d839d25 --- /dev/null +++ b/src/web-ui/src/infrastructure/font-preference/index.ts @@ -0,0 +1,18 @@ +// Types and constants +export * from './types'; + +// Core service +export { FontPreferenceService, fontPreferenceService } from './core/FontPreferenceService'; + +// State +export { useFontPreferenceStore } from './store/fontPreferenceStore'; + +// UI Components +export { FontPreferencePanel } from './components/FontPreferencePanel'; + +// React hooks +export { + useFontPreference, + useUiFontSize, + useFontSizeLevelLabel, +} from './hooks/useFontPreference'; diff --git a/src/web-ui/src/infrastructure/font-preference/store/fontPreferenceStore.ts b/src/web-ui/src/infrastructure/font-preference/store/fontPreferenceStore.ts new file mode 100644 index 00000000..0128bf0f --- /dev/null +++ b/src/web-ui/src/infrastructure/font-preference/store/fontPreferenceStore.ts @@ -0,0 +1,81 @@ + +import { create } from 'zustand'; +import { createLogger } from '@/shared/utils/logger'; +import { FontPreference, FontSizeLevel, FlowChatFontMode, DEFAULT_FONT_PREFERENCE } from '../types'; +import { fontPreferenceService } from '../core/FontPreferenceService'; + +const log = createLogger('FontPreferenceStore'); + +interface FontPreferenceState { + preference: FontPreference; + initialized: boolean; + loading: boolean; + error: string | null; + + initialize: () => Promise; + setUiSize: (level: FontSizeLevel, customPx?: number) => Promise; + setFlowChatFont: (mode: FlowChatFontMode, basePx?: number) => Promise; + reset: () => Promise; +} + +export const useFontPreferenceStore = create((set, get) => ({ + preference: { ...DEFAULT_FONT_PREFERENCE }, + initialized: false, + loading: false, + error: null, + + initialize: async () => { + if (get().initialized || get().loading) return; + set({ loading: true, error: null }); + try { + // Subscribe to service events so store stays in sync + fontPreferenceService.on('font:after-change', (event) => { + set({ preference: event.preference }); + }); + + await fontPreferenceService.initialize(); + + set({ + preference: fontPreferenceService.getPreference(), + initialized: true, + loading: false, + }); + } catch (error) { + log.error('Failed to initialize font preference', error); + set({ + loading: false, + error: error instanceof Error ? error.message : 'Failed to initialize font preference', + }); + } + }, + + setUiSize: async (level: FontSizeLevel, customPx?: number) => { + set({ error: null }); + try { + await fontPreferenceService.setUiSize(level, customPx); + } catch (error) { + log.error('Failed to set UI font size', { level, customPx, error }); + set({ error: error instanceof Error ? error.message : 'Failed to set UI font size' }); + } + }, + + setFlowChatFont: async (mode: FlowChatFontMode, basePx?: number) => { + set({ error: null }); + try { + await fontPreferenceService.setFlowChatFont(mode, basePx); + } catch (error) { + log.error('Failed to set flow chat font', { mode, basePx, error }); + set({ error: error instanceof Error ? error.message : 'Failed to set flow chat font' }); + } + }, + + reset: async () => { + set({ error: null }); + try { + await fontPreferenceService.reset(); + } catch (error) { + log.error('Failed to reset font preference', error); + set({ error: error instanceof Error ? error.message : 'Failed to reset font preference' }); + } + }, +})); diff --git a/src/web-ui/src/infrastructure/font-preference/types/index.ts b/src/web-ui/src/infrastructure/font-preference/types/index.ts new file mode 100644 index 00000000..29392f2a --- /dev/null +++ b/src/web-ui/src/infrastructure/font-preference/types/index.ts @@ -0,0 +1,117 @@ + +export type FontSizeLevel = 'compact' | 'small' | 'default' | 'medium' | 'large' | 'custom'; + +export interface UiFontSizePreference { + level: FontSizeLevel; + /** Only used when level === 'custom'. Range: 12–20. */ + customPx?: number; +} + +export type FlowChatFontMode = 'sync' | 'lift' | 'independent'; + +/** + * Flow chat typographic scale vs global UI: + * - `sync`: same tokens as UI + * - `lift`: UI baseline + 1px (cap 20), default + * - `independent`: custom baseline px + */ +export interface FlowChatFontSizePreference { + mode: FlowChatFontMode; + /** When `mode === 'independent'`, baseline px (12–20) for the flow-chat token ladder. */ + basePx?: number; +} + +export interface FontPreference { + uiSize: UiFontSizePreference; + /** Conversation / flow chat panel font scale (separate from global UI). */ + flowChat: FlowChatFontSizePreference; +} + +export interface FontSizeTokens { + xs: string; + sm: string; + base: string; + lg: string; + xl: string; + '2xl': string; + '3xl': string; + '4xl': string; + '5xl': string; +} + +export type FontSizeLevelPresets = Record, FontSizeTokens>; + +/** UI baseline (px) for each preset level. Default = 14. */ +export const PRESET_UI_BASE_PX: Record, number> = { + compact: 12, + small: 13, + default: 14, + medium: 15, + large: 16, +}; + +/** + * Derive font size tokens from a custom base px value. + * Other steps are calculated relative to base with fixed offsets. + */ +export function deriveFontSizeTokens(basePx: number): FontSizeTokens { + const b = Math.max(12, Math.min(20, basePx)); + return { + xs: `${b - 2}px`, + sm: `${b - 1}px`, + base: `${b}px`, + lg: `${b + 1}px`, + xl: `${b + 2}px`, + '2xl': `${b + 4}px`, + '3xl': `${b + 8}px`, + '4xl': `${b + 12}px`, + '5xl': `${b + 18}px`, + }; +} + +/** Preset levels share the same formula as custom UI size (deriveFontSizeTokens). */ +export const UI_FONT_SIZE_PRESETS: FontSizeLevelPresets = { + compact: deriveFontSizeTokens(PRESET_UI_BASE_PX.compact), + small: deriveFontSizeTokens(PRESET_UI_BASE_PX.small), + default: deriveFontSizeTokens(PRESET_UI_BASE_PX.default), + medium: deriveFontSizeTokens(PRESET_UI_BASE_PX.medium), + large: deriveFontSizeTokens(PRESET_UI_BASE_PX.large), +}; + +export function resolveFontSizeTokens(uiSize: UiFontSizePreference): FontSizeTokens { + if (uiSize.level === 'custom') { + return deriveFontSizeTokens(uiSize.customPx ?? 14); + } + return UI_FONT_SIZE_PRESETS[uiSize.level]; +} + +export function resolveFlowChatFontSizeTokens(pref: FontPreference): FontSizeTokens { + if (pref.flowChat.mode === 'independent') { + return deriveFontSizeTokens(pref.flowChat.basePx ?? 14); + } + if (pref.flowChat.mode === 'lift') { + const ui = resolveFontSizeTokens(pref.uiSize); + const uiBase = parseInt(ui.base, 10); + const bumped = Number.isNaN(uiBase) ? 15 : Math.min(20, uiBase + 1); + return deriveFontSizeTokens(bumped); + } + return resolveFontSizeTokens(pref.uiSize); +} + +export const DEFAULT_FONT_PREFERENCE: FontPreference = { + uiSize: { level: 'default' }, + flowChat: { mode: 'lift' }, +}; + +// ---- Events ---- + +export type FontPreferenceEventType = 'font:before-change' | 'font:after-change'; + +export interface FontPreferenceEvent { + type: FontPreferenceEventType; + preference: FontPreference; + previousPreference?: FontPreference; + timestamp: number; +} + +export type FontPreferenceEventListener = (event: FontPreferenceEvent) => void | Promise; diff --git a/src/web-ui/src/infrastructure/theme/presets/china-night-theme.ts b/src/web-ui/src/infrastructure/theme/presets/china-night-theme.ts index 7e7a2460..63d8353a 100644 --- a/src/web-ui/src/infrastructure/theme/presets/china-night-theme.ts +++ b/src/web-ui/src/infrastructure/theme/presets/china-night-theme.ts @@ -198,14 +198,14 @@ export const bitfunChinaNightTheme: ThemeConfig = { size: { xs: '12px', - sm: '14px', - base: '15px', - lg: '16px', - xl: '18px', - '2xl': '20px', - '3xl': '24px', - '4xl': '30px', - '5xl': '36px', + sm: '13px', + base: '14px', + lg: '15px', + xl: '16px', + '2xl': '18px', + '3xl': '22px', + '4xl': '26px', + '5xl': '32px', }, lineHeight: { diff --git a/src/web-ui/src/infrastructure/theme/presets/china-style-theme.ts b/src/web-ui/src/infrastructure/theme/presets/china-style-theme.ts index ca3dbccd..52a32866 100644 --- a/src/web-ui/src/infrastructure/theme/presets/china-style-theme.ts +++ b/src/web-ui/src/infrastructure/theme/presets/china-style-theme.ts @@ -196,14 +196,14 @@ export const bitfunChinaStyleTheme: ThemeConfig = { size: { xs: '12px', - sm: '14px', - base: '15px', - lg: '16px', - xl: '18px', - '2xl': '20px', - '3xl': '24px', - '4xl': '30px', - '5xl': '36px', + sm: '13px', + base: '14px', + lg: '15px', + xl: '16px', + '2xl': '18px', + '3xl': '22px', + '4xl': '26px', + '5xl': '32px', }, lineHeight: { diff --git a/src/web-ui/src/infrastructure/theme/presets/cyber-theme.ts b/src/web-ui/src/infrastructure/theme/presets/cyber-theme.ts index adc81f22..3f36734c 100644 --- a/src/web-ui/src/infrastructure/theme/presets/cyber-theme.ts +++ b/src/web-ui/src/infrastructure/theme/presets/cyber-theme.ts @@ -203,12 +203,12 @@ export const bitfunCyberTheme: ThemeConfig = { xs: '12px', sm: '13px', base: '14px', - lg: '16px', - xl: '18px', - '2xl': '20px', - '3xl': '24px', - '4xl': '30px', - '5xl': '36px', + lg: '15px', + xl: '16px', + '2xl': '18px', + '3xl': '22px', + '4xl': '26px', + '5xl': '32px', }, lineHeight: { diff --git a/src/web-ui/src/infrastructure/theme/presets/dark-theme.ts b/src/web-ui/src/infrastructure/theme/presets/dark-theme.ts index c0effd55..d3ce330a 100644 --- a/src/web-ui/src/infrastructure/theme/presets/dark-theme.ts +++ b/src/web-ui/src/infrastructure/theme/presets/dark-theme.ts @@ -203,14 +203,14 @@ export const bitfunDarkTheme: ThemeConfig = { size: { xs: '12px', - sm: '14px', - base: '15px', - lg: '16px', - xl: '18px', - '2xl': '20px', - '3xl': '24px', - '4xl': '30px', - '5xl': '36px', + sm: '13px', + base: '14px', + lg: '15px', + xl: '16px', + '2xl': '18px', + '3xl': '22px', + '4xl': '26px', + '5xl': '32px', }, lineHeight: { diff --git a/src/web-ui/src/infrastructure/theme/presets/light-theme.ts b/src/web-ui/src/infrastructure/theme/presets/light-theme.ts index aeb7fa84..e1551615 100644 --- a/src/web-ui/src/infrastructure/theme/presets/light-theme.ts +++ b/src/web-ui/src/infrastructure/theme/presets/light-theme.ts @@ -210,14 +210,14 @@ export const bitfunLightTheme: ThemeConfig = { size: { xs: '12px', - sm: '14px', - base: '15px', - lg: '16px', - xl: '18px', - '2xl': '20px', - '3xl': '24px', - '4xl': '30px', - '5xl': '36px', + sm: '13px', + base: '14px', + lg: '15px', + xl: '16px', + '2xl': '18px', + '3xl': '22px', + '4xl': '26px', + '5xl': '32px', }, lineHeight: { diff --git a/src/web-ui/src/infrastructure/theme/presets/midnight-theme.ts b/src/web-ui/src/infrastructure/theme/presets/midnight-theme.ts index f8d36d17..b2bbfcb8 100644 --- a/src/web-ui/src/infrastructure/theme/presets/midnight-theme.ts +++ b/src/web-ui/src/infrastructure/theme/presets/midnight-theme.ts @@ -198,14 +198,14 @@ export const bitfunMidnightTheme: ThemeConfig = { size: { xs: '12px', - sm: '14px', - base: '15px', - lg: '16px', - xl: '18px', - '2xl': '20px', - '3xl': '24px', - '4xl': '30px', - '5xl': '36px', + sm: '13px', + base: '14px', + lg: '15px', + xl: '16px', + '2xl': '18px', + '3xl': '22px', + '4xl': '26px', + '5xl': '32px', }, lineHeight: { diff --git a/src/web-ui/src/infrastructure/theme/presets/slate-theme.ts b/src/web-ui/src/infrastructure/theme/presets/slate-theme.ts index 3e602a8b..d46976f1 100644 --- a/src/web-ui/src/infrastructure/theme/presets/slate-theme.ts +++ b/src/web-ui/src/infrastructure/theme/presets/slate-theme.ts @@ -206,14 +206,14 @@ export const bitfunSlateTheme: ThemeConfig = { size: { xs: '12px', - sm: '14px', - base: '15px', - lg: '16px', - xl: '18px', - '2xl': '20px', - '3xl': '24px', - '4xl': '30px', - '5xl': '36px', + sm: '13px', + base: '14px', + lg: '15px', + xl: '16px', + '2xl': '18px', + '3xl': '22px', + '4xl': '26px', + '5xl': '32px', }, lineHeight: { diff --git a/src/web-ui/src/locales/en-US/settings/basics.json b/src/web-ui/src/locales/en-US/settings/basics.json index aaebc1b7..e3029643 100644 --- a/src/web-ui/src/locales/en-US/settings/basics.json +++ b/src/web-ui/src/locales/en-US/settings/basics.json @@ -44,6 +44,34 @@ "name": "Slate", "description": "Slate gray geometric theme - Deep immersion, high contrast grayscale aesthetics" } + }, + "fontSize": { + "betaBadge": "Beta", + "title": "Font Size", + "hint": "Adjust font size for the UI and chat area (editor font is configured in the editor settings).", + "uiSizeLabel": "UI Font", + "uiSizeHint": "Controls font size across navigation, panels, settings, and all other UI elements.", + "levels": { + "compact": "Compact", + "small": "Small", + "default": "Default", + "medium": "Medium", + "large": "Large", + "custom": "Custom" + }, + "customPxLabel": "Custom size (12–20 px)", + "customPxPlaceholder": "14", + "customPxOutOfRange": "Please enter an integer between 12 and 20", + "resetButton": "Reset to Default", + "previewText": "BitFun is an AI-driven programming environment. The quick brown fox jumps over the lazy dog.", + "flowChatLabel": "Chat area", + "flowChatHint": "When off, chat uses UI +1 px and tracks UI presets. Turn on to open a panel and pick a baseline size (12–20 px) from the list.", + "flowChatCustomToggle": "Custom chat font size", + "flowChatBaselinePicker": "Baseline size", + "flowChatPxOption": "{{n}} px", + "flowChatBaseLabel": "Chat baseline size", + "flowChatBaselinePicker": "Baseline size", + "flowChatPxOption": "{{n}} px" } }, "launchAtLogin": { diff --git a/src/web-ui/src/locales/zh-CN/settings/basics.json b/src/web-ui/src/locales/zh-CN/settings/basics.json index ab2bb1ea..e7d6549f 100644 --- a/src/web-ui/src/locales/zh-CN/settings/basics.json +++ b/src/web-ui/src/locales/zh-CN/settings/basics.json @@ -44,6 +44,34 @@ "name": "石板灰", "description": "石板灰几何主题 - 极深沉浸,高对比度灰度美学" } + }, + "fontSize": { + "betaBadge": "Beta", + "title": "字体大小", + "hint": "调整界面与对话区域的字体大小(编辑器字号在编辑器设置中配置)。", + "uiSizeLabel": "界面字体", + "uiSizeHint": "调整导航、面板、设置等所有界面元素的字体大小。", + "levels": { + "compact": "紧凑", + "small": "小", + "default": "默认", + "medium": "中等", + "large": "大", + "custom": "自定义" + }, + "customPxLabel": "自定义大小(12–20 px)", + "customPxPlaceholder": "14", + "customPxOutOfRange": "请输入 12–20 之间的整数", + "resetButton": "恢复默认", + "previewText": "BitFun 是一个由 AI 驱动的编程环境。The quick brown fox jumps over the lazy dog.", + "flowChatLabel": "对话区域", + "flowChatHint": "关闭时对话区域比界面大 1 px,并随界面档位变化。开启后在下方展开面板,从列表中选择基准字号(12–20 px)。", + "flowChatCustomToggle": "自定义对话字号", + "flowChatBaselinePicker": "基准字号", + "flowChatPxOption": "{{n}} px", + "flowChatBaseLabel": "对话基准字号", + "flowChatBaselinePicker": "基准字号", + "flowChatPxOption": "{{n}} px" } }, "launchAtLogin": { diff --git a/src/web-ui/src/main.tsx b/src/web-ui/src/main.tsx index 5990482d..b21567c2 100644 --- a/src/web-ui/src/main.tsx +++ b/src/web-ui/src/main.tsx @@ -238,7 +238,12 @@ async function initializeApp() { const { themeService } = await import('./infrastructure/theme'); await themeService.initialize(); log.info('Theme system initialized'); - + + // Apply saved UI / flow-chat font tokens (theme sets typography first; this overrides). + const { fontPreferenceService } = await import('./infrastructure/font-preference'); + await fontPreferenceService.initialize(); + log.info('Font preference initialized at startup'); + // Preload editor configuration. const { configManager } = await import('./infrastructure/config'); await configManager.getConfig('editor'); diff --git a/src/web-ui/src/shared/context-menu-system/components/ui/ContextMenu.scss b/src/web-ui/src/shared/context-menu-system/components/ui/ContextMenu.scss index 63ea308f..48c62f6c 100644 --- a/src/web-ui/src/shared/context-menu-system/components/ui/ContextMenu.scss +++ b/src/web-ui/src/shared/context-menu-system/components/ui/ContextMenu.scss @@ -28,7 +28,7 @@ pointer-events: none; font-family: var(--font-family-sans); - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: 1.4; :root[data-theme-type='light'] & { diff --git a/src/web-ui/src/shared/context-system/components/ContextCard/ContextCard.scss b/src/web-ui/src/shared/context-system/components/ContextCard/ContextCard.scss index e06ef803..f92b85d9 100644 --- a/src/web-ui/src/shared/context-system/components/ContextCard/ContextCard.scss +++ b/src/web-ui/src/shared/context-system/components/ContextCard/ContextCard.scss @@ -106,7 +106,7 @@ } &__title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-primary); display: flex; @@ -120,7 +120,7 @@ } &__subtitle { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); display: flex; align-items: center; @@ -219,7 +219,7 @@ align-items: center; gap: $size-gap-1; padding: $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); border-radius: $size-radius-sm; margin-top: $size-gap-2; @@ -281,7 +281,7 @@ } .bitfun-context-card__title { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } .bitfun-context-card__preview, diff --git a/src/web-ui/src/shared/context-system/components/ContextList/ContextList.scss b/src/web-ui/src/shared/context-system/components/ContextList/ContextList.scss index 2d8042c4..ce3123ea 100644 --- a/src/web-ui/src/shared/context-system/components/ContextList/ContextList.scss +++ b/src/web-ui/src/shared/context-system/components/ContextList/ContextList.scss @@ -23,7 +23,7 @@ display: flex; align-items: center; gap: $size-gap-2; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-secondary); } @@ -48,7 +48,7 @@ align-items: center; gap: $size-gap-1; padding: 4px 8px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-muted); background: transparent; @@ -106,14 +106,14 @@ } &__empty-text { - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-medium; color: var(--color-text-muted); margin: 0 0 $size-gap-1; } &__empty-hint { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-disabled); margin: 0; max-width: 300px; diff --git a/src/web-ui/src/shared/context-system/drag-drop/ContextDropZone.scss b/src/web-ui/src/shared/context-system/drag-drop/ContextDropZone.scss index 0fe3def1..399eb614 100644 --- a/src/web-ui/src/shared/context-system/drag-drop/ContextDropZone.scss +++ b/src/web-ui/src/shared/context-system/drag-drop/ContextDropZone.scss @@ -63,7 +63,7 @@ } &__text { - font-size: $font-size-lg; + font-size: var(--font-size-lg); font-weight: $font-weight-semibold; color: var(--color-accent-500); text-align: center; diff --git a/src/web-ui/src/shared/notification-system/components/LoadingNotification.scss b/src/web-ui/src/shared/notification-system/components/LoadingNotification.scss index ce020e4c..e9552d7e 100644 --- a/src/web-ui/src/shared/notification-system/components/LoadingNotification.scss +++ b/src/web-ui/src/shared/notification-system/components/LoadingNotification.scss @@ -75,7 +75,7 @@ } &__title { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-primary); margin-bottom: 2px; diff --git a/src/web-ui/src/shared/notification-system/components/NotificationCenter.scss b/src/web-ui/src/shared/notification-system/components/NotificationCenter.scss index 50e459e0..22d5491a 100644 --- a/src/web-ui/src/shared/notification-system/components/NotificationCenter.scss +++ b/src/web-ui/src/shared/notification-system/components/NotificationCenter.scss @@ -26,7 +26,7 @@ } &__title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-primary); margin: 0; @@ -90,7 +90,7 @@ background: transparent; border: none; border-bottom: 2px solid transparent; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-secondary); cursor: pointer; @@ -137,7 +137,7 @@ } &__empty-text { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); } @@ -277,7 +277,7 @@ } &__item-title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-primary); line-height: 1.4; @@ -297,7 +297,7 @@ } &__item-message { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); line-height: 1.45; margin-bottom: 2px; @@ -498,7 +498,7 @@ } &__active-task-title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-primary); overflow: hidden; @@ -517,7 +517,7 @@ } &__active-task-message { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); overflow: hidden; text-overflow: ellipsis; @@ -572,7 +572,7 @@ } &__active-loading-title { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-primary); overflow: hidden; @@ -581,7 +581,7 @@ } &__active-loading-message { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); overflow: hidden; text-overflow: ellipsis; diff --git a/src/web-ui/src/shared/notification-system/components/NotificationItem.scss b/src/web-ui/src/shared/notification-system/components/NotificationItem.scss index e65b5e6a..e6deb44f 100644 --- a/src/web-ui/src/shared/notification-system/components/NotificationItem.scss +++ b/src/web-ui/src/shared/notification-system/components/NotificationItem.scss @@ -69,14 +69,14 @@ } &__title { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-primary); line-height: 1.3; } &__message { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); line-height: 1.4; word-break: break-word; diff --git a/src/web-ui/src/shared/notification-system/components/ProgressNotification.scss b/src/web-ui/src/shared/notification-system/components/ProgressNotification.scss index de43c283..94162358 100644 --- a/src/web-ui/src/shared/notification-system/components/ProgressNotification.scss +++ b/src/web-ui/src/shared/notification-system/components/ProgressNotification.scss @@ -91,14 +91,14 @@ } &__title { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: var(--color-text-primary); line-height: 1.3; } &__percentage { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; color: #ca8a04; font-variant-numeric: tabular-nums; diff --git a/src/web-ui/src/tools/editor/components/CodeEditor.scss b/src/web-ui/src/tools/editor/components/CodeEditor.scss index e2e4664f..d1fc7945 100644 --- a/src/web-ui/src/tools/editor/components/CodeEditor.scss +++ b/src/web-ui/src/tools/editor/components/CodeEditor.scss @@ -56,7 +56,7 @@ $_editor-padding-desktop: 32px; &__loading-text { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); font-family: $font-family-mono; animation: code-editor-pulse $motion-slow ease-in-out infinite; @@ -85,7 +85,7 @@ $_editor-padding-desktop: 32px; &__error-message { margin: 0 0 $size-gap-3 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); font-family: $font-family-mono; } @@ -96,7 +96,7 @@ $_editor-padding-desktop: 32px; border: 1px dashed var(--color-text-muted); border-radius: $size-radius-sm; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-mono; cursor: pointer; transition: all $motion-base $easing-standard; @@ -163,7 +163,7 @@ $_editor-padding-desktop: 32px; color: var(--color-bg-primary); padding: $size-gap-2 $size-gap-4; border-radius: $size-radius-base; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; font-family: $font-family-mono; box-shadow: $glow-shadow-blue; @@ -277,7 +277,7 @@ $_editor-padding-desktop: 32px; &__loading-text, &__error-message { - font-size: $font-size-xs; + font-size: var(--font-size-xs); max-width: 300px; } diff --git a/src/web-ui/src/tools/editor/components/DiffEditor.scss b/src/web-ui/src/tools/editor/components/DiffEditor.scss index c0af3ed6..e964310a 100644 --- a/src/web-ui/src/tools/editor/components/DiffEditor.scss +++ b/src/web-ui/src/tools/editor/components/DiffEditor.scss @@ -39,7 +39,7 @@ $_diff-error-max-width: 400px; align-items: center; gap: $size-gap-4; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-family: $font-family-mono; } @@ -53,7 +53,7 @@ $_diff-error-max-width: 400px; font-weight: $font-weight-semibold; padding: 2px 6px; border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); &--add { color: #3fb950; @@ -71,13 +71,13 @@ $_diff-error-max-width: 400px; &__changes-count { font-weight: $font-weight-medium; color: var(--color-text-secondary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__file-path { color: var(--color-text-muted); font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__actions { @@ -96,7 +96,7 @@ $_diff-error-max-width: 400px; border: 1px solid $border-base; border-radius: $size-radius-base; color: var(--color-text-secondary); - font-size: $font-size-lg; + font-size: var(--font-size-lg); line-height: 1; cursor: pointer; transition: all $motion-base $easing-standard; @@ -194,7 +194,7 @@ $_diff-error-max-width: 400px; &__message { color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; margin: 0; line-height: $line-height-relaxed; @@ -202,7 +202,7 @@ $_diff-error-max-width: 400px; &__path { color: var(--color-text-tertiary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-mono; margin: 0; max-width: 100%; @@ -503,7 +503,7 @@ $_diff-error-max-width: 400px; max-width: 280px; &__message { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__path { diff --git a/src/web-ui/src/tools/editor/components/ImageViewer.scss b/src/web-ui/src/tools/editor/components/ImageViewer.scss index 50614bb6..b3a6478d 100644 --- a/src/web-ui/src/tools/editor/components/ImageViewer.scss +++ b/src/web-ui/src/tools/editor/components/ImageViewer.scss @@ -40,7 +40,7 @@ display: flex; align-items: center; gap: $size-gap-3; - font-size: $font-size-sm; + font-size: var(--font-size-sm); flex: 1; min-width: 0; } @@ -55,7 +55,7 @@ &__dimensions, &__filesize { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); white-space: nowrap; } @@ -101,7 +101,7 @@ width: auto; min-width: 40px; padding: 0 $size-gap-1; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; } } diff --git a/src/web-ui/src/tools/editor/components/MarkdownEditor.scss b/src/web-ui/src/tools/editor/components/MarkdownEditor.scss index 100ba539..ce3594dd 100644 --- a/src/web-ui/src/tools/editor/components/MarkdownEditor.scss +++ b/src/web-ui/src/tools/editor/components/MarkdownEditor.scss @@ -36,7 +36,7 @@ p { margin: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: $line-height-relaxed; } } @@ -100,7 +100,7 @@ p { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); } @@ -111,7 +111,7 @@ border: 1px solid $button-border-default; border-radius: $size-radius-base; cursor: pointer; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; transition: all $motion-base $easing-standard; backdrop-filter: blur(8px); @@ -140,7 +140,7 @@ color: var(--color-text-secondary); font-family: $font-family-sans; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-relaxed; h1, h2, h3, h4, h5, h6 { @@ -157,7 +157,7 @@ } h1 { - font-size: $font-size-3xl; + font-size: var(--font-size-3xl); color: var(--color-text-primary); border-bottom: 1px solid var(--border-subtle, #{$border-subtle}); padding-bottom: $size-gap-3; @@ -166,15 +166,15 @@ } h2 { - font-size: $font-size-2xl; + font-size: var(--font-size-2xl); border-bottom: 1px solid var(--border-subtle, #{$border-subtle}); padding-bottom: $size-gap-2; } - h3 { font-size: $font-size-xl; } - h4 { font-size: $font-size-lg; } - h5 { font-size: $font-size-base; } - h6 { font-size: $font-size-sm; } + h3 { font-size: var(--font-size-xl); } + h4 { font-size: var(--font-size-lg); } + h5 { font-size: var(--font-size-base); } + h6 { font-size: var(--font-size-sm); } p { margin-top: 0; diff --git a/src/web-ui/src/tools/editor/meditor/components/EditArea.scss b/src/web-ui/src/tools/editor/meditor/components/EditArea.scss index 54f2895a..90f658b9 100644 --- a/src/web-ui/src/tools/editor/meditor/components/EditArea.scss +++ b/src/web-ui/src/tools/editor/meditor/components/EditArea.scss @@ -9,7 +9,7 @@ box-shadow: none !important; resize: none; font-family: $font-family-mono; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-relaxed; background: transparent; color: inherit; diff --git a/src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss b/src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss index 329f5a83..70d56231 100644 --- a/src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss +++ b/src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss @@ -16,7 +16,7 @@ min-height: 100%; outline: none; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-relaxed; /* blockId lives on
itself — do not use paragraph chrome (padding + radius + hover fill) on hr */ @@ -37,7 +37,7 @@ > p.is-empty { position: relative; - min-height: calc(#{$font-size-sm} * #{$line-height-relaxed}); + min-height: calc(var(--font-size-sm) * var(--line-height-relaxed)); } > p.is-empty::before { @@ -45,7 +45,7 @@ color: var(--color-text-disabled); float: left; height: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); letter-spacing: normal; white-space: nowrap; opacity: 0; @@ -85,29 +85,29 @@ } h1 { - font-size: $font-size-3xl; + font-size: var(--font-size-3xl); color: var(--color-text-primary); text-align: center; } h2 { - font-size: $font-size-2xl; + font-size: var(--font-size-2xl); } h3 { - font-size: $font-size-xl; + font-size: var(--font-size-xl); } h4 { - font-size: $font-size-lg; + font-size: var(--font-size-lg); } h5 { - font-size: $font-size-base; + font-size: var(--font-size-base); } h6 { - font-size: $font-size-sm; + font-size: var(--font-size-sm); letter-spacing: 0.02em; text-transform: uppercase; } @@ -515,7 +515,7 @@ } .bitfun-input { - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: 1.35; } } @@ -543,7 +543,7 @@ border-radius: 999px; background: color-mix(in srgb, var(--color-text-muted) 14%, transparent); color: var(--color-text-muted); - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-medium; letter-spacing: 0.02em; white-space: nowrap; @@ -613,7 +613,7 @@ .m-editor-inline-ai__section-title { margin: $size-gap-2 0 6px; color: var(--color-text-muted); - font-size: $font-size-xxs; + font-size: var(--font-size-xxs); font-weight: $font-weight-medium; letter-spacing: 0.02em; opacity: 0.72; @@ -635,7 +635,7 @@ border-radius: 8px; background: transparent; color: var(--color-text-primary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: 1.35; cursor: pointer; text-align: left; @@ -656,7 +656,7 @@ .m-editor-inline-ai__quick-action--primary { font-weight: $font-weight-semibold; - font-size: $font-size-sm; + font-size: var(--font-size-sm); } .m-editor-inline-ai__quick-action-icon { @@ -679,7 +679,7 @@ border: none; background: transparent; color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); cursor: pointer; &:hover { @@ -711,14 +711,14 @@ } .m-editor-inline-ai-preview__title { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); font-weight: $font-weight-medium; color: var(--color-accent-500); letter-spacing: 0.02em; } .m-editor-inline-ai-preview__status { - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--color-text-disabled); white-space: nowrap; } @@ -728,7 +728,7 @@ position: relative; color: inherit; padding-left: $size-gap-3; - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: 1.45; } @@ -769,7 +769,7 @@ .m-editor-inline-ai-rendered__loading { margin-bottom: $size-gap-2; color: var(--color-text-disabled); - font-size: $font-size-xs; + font-size: var(--font-size-xs); } .m-editor-inline-ai-rendered__content { @@ -800,16 +800,16 @@ } .m-editor-inline-ai-rendered__content.markdown-body h1 { - font-size: $font-size-lg; + font-size: var(--font-size-lg); text-align: left; } .m-editor-inline-ai-rendered__content.markdown-body h2 { - font-size: $font-size-base; + font-size: var(--font-size-base); } .m-editor-inline-ai-rendered__content.markdown-body h3 { - font-size: $font-size-sm; + font-size: var(--font-size-sm); } .m-editor-inline-ai-rendered__content.markdown-body p { @@ -820,7 +820,7 @@ margin: 0 0 6px; padding: var(--flowchat-md-bq-padding); font-style: italic; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); color: var(--flowchat-md-bq-fg); background: var(--flowchat-md-bq-bg); border-left: 3px solid var(--flowchat-md-bq-border); @@ -831,7 +831,7 @@ .m-editor-inline-ai-rendered__content.markdown-body pre { margin: 0 0 6px; padding: 8px 10px; - font-size: $font-size-2xs; + font-size: var(--font-size-2xs); line-height: 1.45; font-family: var(--flowchat-md-code-font-mono); color: var(--flowchat-md-pre-code-fg); @@ -900,7 +900,7 @@ .m-editor-inline-ai-preview__placeholder { color: inherit; - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: 1.45; padding: 4px 6px; } @@ -917,14 +917,14 @@ gap: 4px; min-height: 28px; padding: 4px 12px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); border-radius: 999px; } .m-editor-inline-ai__error { margin-top: $size-gap-2; color: var(--color-error); - font-size: $font-size-xs; + font-size: var(--font-size-xs); } .m-editor-render-only-block, @@ -947,7 +947,7 @@ .m-editor-raw-html-block__label, .m-editor-raw-html-inline__label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-semibold; letter-spacing: 0.02em; text-transform: uppercase; @@ -957,7 +957,7 @@ .m-editor-raw-html-inline__source { margin: 0; font-family: var(--flowchat-md-code-font-mono); - font-size: $font-size-xs; + font-size: var(--font-size-xs); white-space: pre-wrap; word-break: break-word; } @@ -994,7 +994,7 @@ .m-editor-raw-html-block__textarea { margin: 0; font-family: var(--flowchat-md-code-font-mono); - font-size: $font-size-sm; + font-size: var(--font-size-sm); display: block; width: 100%; min-height: 180px; @@ -1056,7 +1056,7 @@ display: none; margin: 0; font-family: var(--flowchat-md-code-font-mono); - font-size: $font-size-sm; + font-size: var(--font-size-sm); white-space: pre-wrap; word-break: break-word; border: 1px solid color-mix(in srgb, var(--color-text-primary) 12%, transparent); @@ -1151,7 +1151,7 @@ display: block; list-style: none; color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; outline: none; } @@ -1208,7 +1208,7 @@ border: none; background: transparent; color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; outline: none; } diff --git a/src/web-ui/src/tools/file-system/components/FileSearchResults.scss b/src/web-ui/src/tools/file-system/components/FileSearchResults.scss index 09d4d66c..2857423d 100644 --- a/src/web-ui/src/tools/file-system/components/FileSearchResults.scss +++ b/src/web-ui/src/tools/file-system/components/FileSearchResults.scss @@ -31,7 +31,7 @@ $_icon-size: 16px; } &-hint { - font-size: $font-size-xs; + font-size: var(--font-size-xs); opacity: 0.7; margin-top: $size-gap-2; } @@ -45,7 +45,7 @@ $_icon-size: 16px; } .bitfun-search-results__count { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); font-weight: $font-weight-medium; } @@ -105,7 +105,7 @@ $_icon-size: 16px; } &-name { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: inherit; @include mixins.text-ellipsis; @@ -113,7 +113,7 @@ $_icon-size: 16px; } &-path { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); opacity: 0.6; @include mixins.text-ellipsis; @@ -146,7 +146,7 @@ $_icon-size: 16px; } &-toggle-count { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; line-height: 1; } @@ -196,7 +196,7 @@ $_icon-size: 16px; &-line { flex-shrink: 0; width: 40px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); font-family: $font-family-mono; opacity: 0.6; @@ -210,7 +210,7 @@ $_icon-size: 16px; code { display: block; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-mono; color: var(--color-text-secondary); white-space: pre-wrap; @@ -241,7 +241,7 @@ $_icon-size: 16px; border-top: 1px solid $border-base; background: var(--element-bg-subtle); color: var(--color-text-muted); - font-size: $font-size-xs; + font-size: var(--font-size-xs); cursor: pointer; transition: all $motion-base $easing-standard; user-select: none; diff --git a/src/web-ui/src/tools/file-system/styles/FileExplorer.scss b/src/web-ui/src/tools/file-system/styles/FileExplorer.scss index ccc2781a..dca8a1b2 100644 --- a/src/web-ui/src/tools/file-system/styles/FileExplorer.scss +++ b/src/web-ui/src/tools/file-system/styles/FileExplorer.scss @@ -336,7 +336,7 @@ $_indent-width: 8px; .bitfun-file-explorer__node-name { flex: 1; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-normal; @include mixins.text-ellipsis; position: relative; @@ -380,7 +380,7 @@ $_indent-width: 8px; } .bitfun-input { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-primary); font-weight: $font-weight-medium; border: none !important; @@ -400,7 +400,7 @@ $_indent-width: 8px; } .bitfun-file-explorer__node-size { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); opacity: 0.7; flex-shrink: 0; @@ -409,7 +409,7 @@ $_indent-width: 8px; } .bitfun-file-explorer__node-modified { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); opacity: 0.7; flex-shrink: 0; @@ -448,7 +448,7 @@ $_indent-width: 8px; } .bitfun-file-explorer__node-name { - font-size: $font-size-base; + font-size: var(--font-size-base); } .bitfun-file-explorer__node-size, diff --git a/src/web-ui/src/tools/git/components/CreateBranchDialog/CreateBranchDialog.scss b/src/web-ui/src/tools/git/components/CreateBranchDialog/CreateBranchDialog.scss index e0d4b9b5..47944ecd 100644 --- a/src/web-ui/src/tools/git/components/CreateBranchDialog/CreateBranchDialog.scss +++ b/src/web-ui/src/tools/git/components/CreateBranchDialog/CreateBranchDialog.scss @@ -37,7 +37,7 @@ } &__title { - font-size: $font-size-lg; + font-size: var(--font-size-lg); font-weight: $font-weight-semibold; color: var(--color-text-primary); } @@ -82,7 +82,7 @@ display: flex; align-items: center; gap: $size-gap-2; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); font-weight: $font-weight-medium; @@ -93,7 +93,7 @@ &__base-value { font-family: $font-family-mono; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-primary); font-weight: $font-weight-medium; padding: 2px 8px; @@ -115,7 +115,7 @@ } &__label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-secondary); display: flex; @@ -135,7 +135,7 @@ border-radius: $size-radius-sm; color: var(--color-text-primary); font-family: $font-family-mono; - font-size: $font-size-sm; + font-size: var(--font-size-sm); transition: all $motion-base $easing-standard; &:focus { @@ -174,12 +174,12 @@ border: 1px solid rgba(239, 68, 68, 0.25); border-radius: $size-radius-sm; color: #ef4444; - font-size: $font-size-xs; + font-size: var(--font-size-xs); animation: bitfun-create-branch-dialog-shake 0.4s ease-in-out; } &__hint { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); line-height: 1.6; @@ -229,7 +229,7 @@ &__shortcuts { margin-top: $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); text-align: center; diff --git a/src/web-ui/src/tools/git/components/GitDiffEditor/GitDiffEditor.scss b/src/web-ui/src/tools/git/components/GitDiffEditor/GitDiffEditor.scss index a431f04b..e6d62378 100644 --- a/src/web-ui/src/tools/git/components/GitDiffEditor/GitDiffEditor.scss +++ b/src/web-ui/src/tools/git/components/GitDiffEditor/GitDiffEditor.scss @@ -26,7 +26,7 @@ $_diff-padding-desktop: 32px; border-radius: 0; border-bottom: 1px solid rgba(239, 68, 68, 0.5); color: var(--color-error); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; font-family: $font-family-mono; animation: git-diff-editor-error-slide-in 0.3s ease-out; @@ -220,7 +220,7 @@ $_diff-padding-desktop: 32px; border: 1px solid rgba(255, 255, 255, 0.1); border-radius: $size-radius-base; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-family: $font-family-mono; z-index: $z-overlay; animation: git-diff-editor-fade-in 0.2s ease-out; @@ -245,7 +245,7 @@ $_diff-padding-desktop: 32px; animation: git-diff-editor-fade-in 0.2s ease-out; p { - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-medium; font-family: $font-family-mono; color: var(--color-text-primary); @@ -315,7 +315,7 @@ $_diff-padding-desktop: 32px; } &__completed-title { - font-size: $font-size-2xl; + font-size: var(--font-size-2xl); font-weight: $font-weight-semibold; font-family: $font-family-mono; color: var(--color-text-primary); @@ -330,14 +330,14 @@ $_diff-padding-desktop: 32px; animation: git-diff-editor-slide-up 0.4s ease-out 0.2s both; .git-diff-editor__file-path { - font-size: $font-size-base; + font-size: var(--font-size-base); font-family: $font-family-mono; color: var(--color-text-muted); } } &__result-text { - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-medium; font-family: $font-family-mono; margin-top: $size-gap-3; @@ -438,7 +438,7 @@ $_diff-padding-desktop: 32px; } &__completed-title { - font-size: $font-size-xl; + font-size: var(--font-size-xl); } &__spinner { diff --git a/src/web-ui/src/tools/git/components/GitDiffView/GitDiffView.scss b/src/web-ui/src/tools/git/components/GitDiffView/GitDiffView.scss index 878105cb..2e18fae0 100644 --- a/src/web-ui/src/tools/git/components/GitDiffView/GitDiffView.scss +++ b/src/web-ui/src/tools/git/components/GitDiffView/GitDiffView.scss @@ -59,7 +59,7 @@ $opacity-high: 0.8 !default; background: transparent; color: var(--color-text-secondary); border: none; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-sans; font-weight: $font-weight-medium; cursor: pointer; @@ -85,7 +85,7 @@ $opacity-high: 0.8 !default; display: flex; align-items: center; gap: $size-gap-1-5; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); } @@ -110,7 +110,7 @@ $opacity-high: 0.8 !default; border: 1px solid $border-base; border-radius: $size-radius-sm; color: var(--color-text-secondary); - font-size: $font-size-xs; + font-size: var(--font-size-xs); cursor: pointer; transition: all $motion-base $easing-standard; @@ -151,14 +151,14 @@ $opacity-high: 0.8 !default; } h3 { - font-size: $font-size-lg; + font-size: var(--font-size-lg); font-weight: $font-weight-medium; margin-bottom: $size-gap-2; color: var(--color-text-primary); } p { - font-size: $font-size-sm; + font-size: var(--font-size-sm); opacity: $opacity-high; } } @@ -211,7 +211,7 @@ $opacity-high: 0.8 !default; &__file-path { font-family: $font-family-mono; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-primary); font-weight: $font-weight-normal; white-space: nowrap; @@ -229,7 +229,7 @@ $opacity-high: 0.8 !default; &__file-status { padding: 2px $size-gap-2; border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; font-family: $font-family-mono; color: var(--color-text-muted); @@ -259,7 +259,7 @@ $opacity-high: 0.8 !default; display: flex; align-items: center; gap: $size-gap-3; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-mono; font-weight: $font-weight-medium; flex-shrink: 0; @@ -291,7 +291,7 @@ $opacity-high: 0.8 !default; padding: 0; background: var(--color-bg-primary); font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); line-height: 1.6; overflow-x: auto; border-top: 1px solid $border-base; @@ -400,7 +400,7 @@ $opacity-high: 0.8 !default; } &__dialog-title { - font-size: $font-size-xl; + font-size: var(--font-size-xl); font-weight: $font-weight-semibold; color: var(--color-text-primary); } @@ -431,7 +431,7 @@ $opacity-high: 0.8 !default; border: 1px solid var(--color-error-border); border-radius: $size-radius-base; color: var(--color-error); - font-size: $font-size-sm; + font-size: var(--font-size-sm); animation: bitfun-git-diff-view-shake 0.4s ease-in-out; } @@ -448,7 +448,7 @@ $opacity-high: 0.8 !default; } &__form-label { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); font-weight: $font-weight-medium; } @@ -461,7 +461,7 @@ $opacity-high: 0.8 !default; border-radius: $size-radius-base; color: var(--color-text-primary); font-family: $font-family-mono; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: 1.6; resize: vertical; transition: all $motion-base $easing-standard; @@ -499,7 +499,7 @@ $opacity-high: 0.8 !default; display: flex; align-items: center; gap: $size-gap-2; - font-size: $font-size-sm; + font-size: var(--font-size-sm); } &__ai-info-label { @@ -509,7 +509,7 @@ $opacity-high: 0.8 !default; &__ai-info-badge { padding: 2px 8px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-accent-500); background: rgba(96, 165, 250, 0.15); @@ -521,7 +521,7 @@ $opacity-high: 0.8 !default; &__ai-info-value { color: var(--color-text-primary); font-family: $font-family-mono; - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__ai-confidence { @@ -546,7 +546,7 @@ $opacity-high: 0.8 !default; } &__ai-confidence-text { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); font-weight: $font-weight-medium; } @@ -561,7 +561,7 @@ $opacity-high: 0.8 !default; border: 1px solid var(--color-warning-border); border-radius: $size-radius-base; color: var(--color-warning); - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__form-checkbox { @@ -577,7 +577,7 @@ $opacity-high: 0.8 !default; } label { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); cursor: pointer; } @@ -598,7 +598,7 @@ $opacity-high: 0.8 !default; background: $element-bg-base; border-radius: $size-radius-base; margin-bottom: $size-gap-4; - font-size: $font-size-sm; + font-size: var(--font-size-sm); strong { color: var(--color-text-primary); diff --git a/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.scss b/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.scss index b3d1f151..de4d0f95 100644 --- a/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.scss +++ b/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.scss @@ -30,7 +30,7 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; h3 { margin: 0; - font-size: $font-size-lg; + font-size: var(--font-size-lg); font-weight: $font-weight-semibold; color: var(--color-text-primary); } @@ -47,7 +47,7 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; align-items: center; gap: $size-gap-2; padding: $size-gap-2 $size-gap-4; - font-size: $font-size-xs; + font-size: var(--font-size-xs); position: relative; &--success { @@ -70,7 +70,7 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; cursor: pointer; padding: 0 $size-gap-2; margin-left: auto; - font-size: $font-size-xl; + font-size: var(--font-size-xl); line-height: 1; opacity: $opacity-secondary; transition: opacity $motion-fast $easing-standard; @@ -108,13 +108,13 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; display: flex; align-items: center; gap: $size-gap-2; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-primary); } &__form-description { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); margin-top: -$size-gap-1; } @@ -125,7 +125,7 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; border: 1px solid $border-base; border-radius: $size-radius-base; color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-family: $font-family-mono; transition: all $motion-base $easing-standard; @@ -151,7 +151,7 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; border: 1px solid $border-base; border-radius: $size-radius-base; color: var(--color-text-primary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); cursor: pointer; transition: all $motion-base $easing-standard; @@ -181,7 +181,7 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; label { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-primary); cursor: pointer; user-select: none; @@ -206,14 +206,14 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; } &__section-title { - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); margin: 0; } &__section-description { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); margin-top: $size-gap-1; } @@ -242,7 +242,7 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; } &__config-key { - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-medium; color: var(--color-text-primary); margin-bottom: $size-gap-1; @@ -250,7 +250,7 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; } &__config-value { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-secondary); font-family: $font-family-mono; white-space: nowrap; @@ -276,14 +276,14 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; color: var(--color-text-secondary); h3 { - font-size: $font-size-lg; + font-size: var(--font-size-lg); font-weight: $font-weight-medium; margin: $size-gap-4 0 $size-gap-2 0; color: var(--color-text-primary); } p { - font-size: $font-size-sm; + font-size: var(--font-size-sm); margin-bottom: $size-gap-4; } } @@ -293,7 +293,7 @@ $border-subtle: rgba(255, 255, 255, 0.06) !default; } &__error-message { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-error); margin-bottom: $size-gap-4; } diff --git a/src/web-ui/src/tools/lsp/components/LspPluginList/LspPluginList.scss b/src/web-ui/src/tools/lsp/components/LspPluginList/LspPluginList.scss index 6cd27e39..8ad39eb3 100644 --- a/src/web-ui/src/tools/lsp/components/LspPluginList/LspPluginList.scss +++ b/src/web-ui/src/tools/lsp/components/LspPluginList/LspPluginList.scss @@ -39,7 +39,7 @@ p { margin: 0; color: var(--color-text-secondary); - font-size: $font-size-sm; + font-size: var(--font-size-sm); } svg { @@ -47,7 +47,7 @@ } .hint { - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-text-muted); } @@ -82,7 +82,7 @@ h3 { margin: 0; - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); } @@ -179,7 +179,7 @@ } &__name { - font-size: $font-size-base; + font-size: var(--font-size-base); font-weight: $font-weight-semibold; color: var(--color-text-primary); white-space: nowrap; @@ -188,7 +188,7 @@ } &__version { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-mono; color: var(--color-text-muted); flex-shrink: 0; @@ -207,7 +207,7 @@ background: var(--color-accent-100); color: var(--color-accent-500); border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-mono; font-weight: $font-weight-medium; white-space: nowrap; @@ -216,7 +216,7 @@ &__badge-more { padding: 4px $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-muted); } @@ -238,13 +238,13 @@ &__description { margin: 0; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-secondary); line-height: $line-height-relaxed; } &__label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-muted); text-transform: uppercase; @@ -252,7 +252,7 @@ } &__value { - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-primary); } @@ -267,7 +267,7 @@ background: $element-bg-soft; border: none; border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-mono; color: var(--color-text-primary); transition: all $motion-fast $easing-standard; @@ -291,7 +291,7 @@ background: var(--color-accent-100); border: none; border-radius: $size-radius-sm; - font-size: $font-size-xs; + font-size: var(--font-size-xs); color: var(--color-accent-500); svg { @@ -351,7 +351,7 @@ } p { - font-size: $font-size-sm; + font-size: var(--font-size-sm); } } @@ -360,7 +360,7 @@ margin-bottom: $size-gap-3; h3 { - font-size: $font-size-sm; + font-size: var(--font-size-sm); } } @@ -386,11 +386,11 @@ } &__name { - font-size: $font-size-sm; + font-size: var(--font-size-sm); } &__version { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__badges { @@ -403,15 +403,15 @@ } &__description { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__label { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__value { - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__tags { @@ -420,7 +420,7 @@ &__tag { padding: 3px 6px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__capabilities { @@ -429,7 +429,7 @@ &__capability { padding: 3px 6px; - font-size: $font-size-xs; + font-size: var(--font-size-xs); } &__actions { diff --git a/src/web-ui/src/tools/lsp/components/ReferencesPanel/ReferencesPanel.scss b/src/web-ui/src/tools/lsp/components/ReferencesPanel/ReferencesPanel.scss index 361821b8..c98e48e7 100644 --- a/src/web-ui/src/tools/lsp/components/ReferencesPanel/ReferencesPanel.scss +++ b/src/web-ui/src/tools/lsp/components/ReferencesPanel/ReferencesPanel.scss @@ -36,7 +36,7 @@ pointer-events: all; font-family: $font-family-sans; - font-size: $font-size-sm; + font-size: var(--font-size-sm); line-height: $line-height-base; opacity: 0; @@ -69,7 +69,7 @@ display: flex; align-items: center; gap: $size-gap-2; - font-size: $font-size-sm; + font-size: var(--font-size-sm); font-weight: $font-weight-semibold; color: var(--color-text-secondary); @@ -80,7 +80,7 @@ .references-panel__count { margin-left: $size-gap-2; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-normal; color: var(--color-text-muted); } @@ -123,7 +123,7 @@ .references-panel__empty { padding: $size-gap-8 $size-gap-4; text-align: center; - font-size: $font-size-sm; + font-size: var(--font-size-sm); color: var(--color-text-muted); } @@ -160,7 +160,7 @@ .references-panel__file-path { flex: 1; min-width: 0; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-weight: $font-weight-medium; color: var(--color-text-secondary); white-space: nowrap; @@ -250,7 +250,7 @@ .references-panel__reference-preview { flex: 1; - font-size: $font-size-xs; + font-size: var(--font-size-xs); font-family: $font-family-mono; color: var(--color-text-secondary); line-height: $line-height-base; @@ -270,7 +270,7 @@ @media (max-width: 768px) { .references-panel { min-width: 280px; - font-size: $font-size-lg; + font-size: var(--font-size-lg); } .references-panel__reference-item {