Spaces:
Sleeping
Sleeping
|
Download docs/design.md from minchun/II_SpectraEngine: direct link, hf CLI and curl.
- Browser
- Download file 19.7 kB
-
https://huggingface.co/spaces/minchun/II_SpectraEngine/resolve/main/docs/design.md
- Command line
-
hf download hf://spaces/minchun/II_SpectraEngine/docs/design.md
-
curl -L -o design.md https://huggingface.co/spaces/minchun/II_SpectraEngine/resolve/main/docs/design.md
19.7 kB
| version: 1.3 | |
| project: SpectraEngine(譯彩紛呈 II 分析引擎) | |
| brand: 致理科技大學應日系 鄧老師委託案 | |
| last_updated: 2026-08-12 | |
| source: assets/app.css(E4 抽出前為 app_agent.py 內嵌 _CUSTOM_CSS 常數) | |
| colors: | |
| light: | |
| bg: "#f3f8fd" | |
| surface: "#ffffff" | |
| surface2: "#eef5fc" | |
| surface3: "#ffffff" | |
| surface3-border: "#e2e8f0" | |
| border: "rgba(2,132,199,.16)" | |
| border-hover: "rgba(2,132,199,.35)" | |
| border-strong: "rgba(2,132,199,.30)" | |
| divider: "#a9cbe8" | |
| thead-bg: "#d8e8f6" | |
| bubble-bg: "#ffffff" | |
| input-border: "#7fb0d9" | |
| accent: "#0284c7" | |
| accent-strong: "#0369a1" | |
| accent2: "#4f46e5" | |
| accent2-strong: "#4338ca" | |
| accent3: "#9333ea" | |
| text: "#1e293b" | |
| text-soft: "#334155" | |
| text-muted: "#475569" | |
| text-subtle: "#64748b" | |
| success: "#047857" | |
| warn: "#b45309" | |
| user-bubble-bg: "#dcfce7" | |
| user-bubble-border: "#86efac" | |
| user-bubble-text: "#166534" | |
| dark: | |
| bg: "#0b1424" | |
| surface: "#172136" | |
| surface2: "#1b2740" | |
| surface3: "#1e293b" | |
| surface3-border: "#334155" | |
| border: "rgba(14,165,233,.11)" | |
| border-hover: "rgba(14,165,233,.30)" | |
| border-strong: "rgba(148,163,184,.28)" | |
| divider: "rgba(148,163,184,.18)" | |
| thead-bg: "#1e2a42" | |
| bubble-bg: "#172136" | |
| input-border: "rgba(14,165,233,.15)" | |
| accent: "#0ea5e9" | |
| accent-strong: "#38bdf8" | |
| accent2: "#818cf8" | |
| accent2-strong: "#a5b4fc" | |
| accent3: "#c084fc" | |
| text: "#e2e8f0" | |
| text-soft: "#cbd5e1" | |
| text-muted: "#94a3b8" | |
| text-subtle: "#475569" | |
| success: "#34d399" | |
| warn: "#fbbf24" | |
| user-bubble-bg: "rgba(34,197,94,.18)" | |
| user-bubble-border: "rgba(34,197,94,.42)" | |
| user-bubble-text: "#bbf7d0" | |
| primary-cta-gradient: "linear-gradient(135deg, #0284c7 0%, #4f46e5 100%)" | |
| accent-gradient: "linear-gradient(100deg, var(--c-accent) 10%, var(--c-accent2) 90%)" | |
| heading-gradient: "linear-gradient(120deg, var(--c-accent-strong) 0%, var(--c-accent2) 55%, var(--c-accent3) 100%)" | |
| typography: | |
| fontFamily: | |
| ui: "Inter, Noto Sans TC, system-ui, sans-serif" | |
| mono: "JetBrains Mono, monospace" | |
| heading-latin: "Crimson Pro" | |
| heading-zh: "Noto Sans TC" | |
| unit: rem | |
| remBase: "16px" | |
| base: | |
| fontSize: "0.875rem" | |
| cssVar: "--font-size-base" | |
| note: "全站內文字級唯一來源,任何內文字級改動一律引用這個變數,不手寫 rem 數值" | |
| scale: | |
| display-lg: "2.1rem" | |
| display-md: "1.8rem" | |
| display-sm: "1.6rem" | |
| title-lg: "1.4rem" | |
| title-md: "1.25rem" | |
| title-sm: "1.15rem" | |
| body-lg: "1.05rem" | |
| body-base: "var(--font-size-base)" | |
| caption: "0.78rem" | |
| badge: "0.70rem" | |
| step-pill: "0.62rem" | |
| rounded: | |
| sm: "4px" | |
| md: "9px" | |
| lg: "10px" | |
| xl: "12px" | |
| card: "14px" | |
| card-lg: "16px" | |
| pill: "20px" | |
| shadow: | |
| card: "0 4px 16px rgba(15,23,42,.18)" | |
| card-hover: "0 16px 40px rgba(79,70,229,.35)" | |
| card-hover-strong: "0 20px 46px rgba(79,70,229,.45)" | |
| overlay: "0 16px 50px rgba(15,23,42,.20)" | |
| drawer: "4px 0 24px rgba(15,23,42,.28)" | |
| layout: | |
| columns: "nav-col : chat-col : canvas-col = 2 : 3 : 7(gr.Column scale)" | |
| nav-col-width: "220px(收合 60px,@media min-width:901px 才套用收合樣式)" | |
| chat-col-min-width: "280px" | |
| canvas-col-min-width: "380px" | |
| homepage-max-width: "50rem" | |
| base-padding: "16px(nav-col/輸入框基準,20px canvas 內容區)" | |
| # SpectraEngine 設計系統 | |
| > 本文件包含兩層:YAML front matter 為機器可讀的 design tokens(供 AI agent 或 Stitch 等工具直接使用);Markdown 本文記錄「為什麼」與人的判斷準則。實作以 `assets/app.css` 為準——這份 CSS 原本內嵌在 `app_agent.py`,2026-08-05(E4)抽成獨立檔案,改用 `app.launch(css_paths=...)` 載入。 | |
| --- | |
| ## 專案定位 | |
| `SpectraEngine`(譯彩紛呈 II 分析引擎)是一套針對重譯文本語言特徵的量化分析平台,技術上是 Python + Gradio 單頁研究工具,服務對象是進行重譯研究的學術使用者(大學教師、研究生)。介面分兩種截然不同的使用情境,視覺語言刻意分兩派: | |
| - **對話區**(左側導覽+對話串+輸入框):參考 **AI-Native UI** 風格——訊息泡泡、打字中三點跳動動畫、串流文字顯示,對應報告撰寫等待期間的載入體感需求。介面語彙上參考 Claude.ai/ChatGPT 網頁版的排版與操作體驗。 | |
| - **結果分頁**(表格/圖表區):參考 **Data-Dense Dashboard** 風格——多圖表/資料表並存、緊湊排版、最大化資訊密度,對應 75 項指標表格與 4 種統計圖表的呈現需求。 | |
| 兩種風格共用同一套色彩與間距 token,差異只在密度與動效,不是兩套獨立設計系統。 | |
| --- | |
| ## 配色 | |
| 雙主題(淺色/深色)系統,經 WCAG AA 對比度驗算(叫 ui-ux-pro-max skill 對執行中實機量測,非套用通則):淺色模式主要文字對比度約 7.24–14.63:1、深色模式約 7.87–14.78:1,9 個關鍵文字元素全數通過 AA。 | |
| **配色決策原則:本次改版不重新設計配色**——業主原本版本已建立完整雙主題 token(sky + indigo + slate 系),驗算品質良好,只在使用場景上做微調,不更換色相。 | |
| ### 一般強調色 vs 加強強調色 | |
| 淺色模式的一般強調色 `#0284c7`(accent)用於一般大小的內文文字時,對比度 4.09:1 略低於 WCAG AA 的 4.5:1 門檻,但用於按鈕/圖示/大字等允許 3:1 門檻的地方完全合格。系統另外準備了 `accent-strong`(`#0369a1`,5.93:1)供小字/連結專用。**兩者不能混用**:一般強調色用在按鈕/圖示/大字,加強強調色用在小字/連結文字。 | |
| ### 底色體系:三層(2026-08-12 新增) | |
| 業主回報「純黑或純白背景面積很大,整個視覺壓力也變大」。量過之後確認抱怨的來源不只對話欄:淺色的頁面底 `#f8fafc` 幾乎等於白,而真正的大面積純白是 `--c-surface`(表格資料列與所有 Gradio 區塊);深色則是 `#020617` 近乎純黑。 | |
| 改成三層結構,淺色與深色共用同一套邏輯: | |
| | 層 | Token | 淺色 | 深色 | 鋪在哪 | | |
| | :--- | :--- | :--- | :--- | :--- | | |
| | 底 | `--c-bg` | `#f3f8fd` | `#0b1424` | 頁面、canvas、導覽列、對話欄 | | |
| | 浮起物 | `--c-bubble-bg` | `#ffffff` | `#172136` | 對話氣泡,比底亮一階 | | |
| | 資料紙張 | `--c-surface` | `#ffffff` | `#172136` | 表格資料列、卡片、輸入框、Gradio 區塊 | | |
| 兩個判斷準則: | |
| - **淺色的資料紙張維持純白**,不跟著染藍。75 項指標表格是資料密集區,白底的可讀性優先於「消滅所有純白」;染藍的是它下面那層底,白色表格因此變成浮在淡藍上的紙張,層次比原本白疊白更清楚。 | |
| - **氣泡比底亮一階、浮在上面**,深淺一致。深色本來就是這個關係(原 `#0d1526` 浮在 `#020617` 上),這輪讓淺色跟上,兩個主題不再各講各的。近白區間的填色差本來就只有一階,邊界靠細線邊框補(見下)。 | |
| ### 邊界與分隔線:兩級線條(2026-08-12 新增) | |
| WCAG 1.4.11 對「UI 元件與圖形物件的邊界」要求 3:1,這條在淺色模式一直沒被滿足:`--c-border`(`rgba(2,132,199,.16)`)疊在白/近白底上只有約 1.2:1,區塊外框、水平分界線、表格框線在淺色模式等於看不見(深色模式當初已針對 `.app-header`、欄邊框、標題底線個別補成 `rgba(148,163,184,.28)`,淺色端從沒補)。業主 2026-08-12 回報「淺色版看不清楚區塊的顏色」即為此。 | |
| 線條因此分兩級,新增元件時二選一,不要再直接用 `--c-border` 畫可見邊界: | |
| | Token | 用途 | 淺色 | 深色 | | |
| | :--- | :--- | :--- | :--- | | |
| | `--c-border-strong` | 結構線:區塊外框、欄位分隔、頂部列底線、標題底線、`hr`、表格外框與表頭分界 | `rgba(2,132,199,.30)`(= `button.secondary` 的邊框色,對底約 1.46:1) | `rgba(148,163,184,.28)` | | |
| | `--c-divider` | 細線:表格資料列之間這種密集重複的線 | `#a9cbe8` | `rgba(148,163,184,.18)` | | |
| | `--c-bubble-border` | 對話氣泡邊框(獨立一級,兩個主題實測對齊 1.61:1) | `#a9cbe8` | `rgba(148,163,184,.26)` | | |
| | `--c-input-border` | 輸入框邊界 | `#7fb0d9`(約 2.0:1) | `rgba(14,165,233,.15)` | | |
| 密集重複的線刻意不拉到 3:1:整張資料表如果每一條線都是結構線強度,會變成網格紙、反而更難讀,1.4.11 的門檻也只針對「識別元件所必需」的邊界。 | |
| **淺色線條一律走 sky 相,不用中性灰藍。** 中間版本曾用 `#a3aebd`/`#b6c0cd`(同樣的亮度級距、但偏灰),配上淡藍底會顯灰顯髒,業主明確要求「維持亮麗的淺藍」。換色相時**亮度級距不動**,手感才不會又跑掉。 | |
| **結構線最終落在 1.46:1,是連續三輪往柔和方向調的結果,已明確離開 1.4.11 的 3:1 門檻。** 沿革:`#7c8798`(3.64:1,符合規範)→ 業主嫌太搶眼改 `#a3aebd`(2.25:1)→ 嫌偏灰改 sky 相 `#6ba3d6`(2.3:1)→ 業主指定「跟『重新選擇研究情境』按鈕的邊框同一個色」,定案 `rgba(2,132,199,.30)`。 | |
| 這是業主拍板的視覺取捨,不是疏忽:**線條顏色從此與 `button.secondary` 共用同一個值**,全站次要邊界只有一個來源,改一處全站跟著走。文字對比完全不受影響,仍全數通過 AA。日後若無障礙稽核要求嚴格達標,把這個 token 換成同色相但更深的 sky 值即可,19 處線條會一起跟上。 | |
| `--c-border` 本身維持原值,因為它同時餵給 `--block-border-color` 與 `--border-color-primary` 兩個 Gradio 原生元件變數,改動會牽連一整批沒盤點過的元件。 | |
| ### 對話氣泡(2026-08-12 更新) | |
| 淺色氣泡原本是白底無框,疊在對話欄底 `#f8fafc` 上只有 1.07:1。定案改成 **填色+淡邊框**:底色 `--c-bubble-bg`(淺色 `#ffffff`、深色 `#172136`),外加 1px `--c-bubble-border`。氣泡比欄底亮一階、浮在上面(見上方「底色體系」)。 | |
| 邊框比結構線明顯,因為填色差只有一階(白氣泡疊 `#f3f8fd` 只有 1.07:1),邊界全靠它。**「深淺一致」是用量測對齊的,不是兩邊各挑一個看起來順眼的值**:淺色 `#a9cbe8` 疊白 1.69:1、深色 `rgba(148,163,184,.26)` 疊 `#172136` 1.61:1。 | |
| 這裡踩過一次坑值得記下來:中間版本讓氣泡邊框共用 `--c-divider`,淺色值卻是對著「深色結構線那一級(alpha `.28`)」挑的,而深色 `--c-divider` 其實是更淡的 `.18`——結果深色氣泡邊框只有 1.37:1、淺色 1.61:1,兩個主題看起來不一樣。**跨主題要對齊的視覺元素,就給它自己的 token,不要借用剛好數值接近的鄰居。** | |
| 可見邊界畫在內層 `.md`,不是外層 `.message`(量測時要認這層)。使用者訊息與 AI 訊息共用同一層,目前兩側同款氣泡、只靠左右對齊區分,是 2026-08-12 業主確認過的現況。 | |
| ### 漸層文字與漸層背景的已知踩坑 | |
| `background: linear-gradient(...)` 簡寫在這版瀏覽器會把 `background-image` 這個子屬性解析成空值(實測用 devtools 讀 `getPropertyValue('background-image')` 回傳空字串),視覺上等於文字消失。**規則:漸層一律寫 `background-image: linear-gradient(...)` 這個子屬性本身,不用 `background` 簡寫**。全站三處漸層文字/按鈕(`.app-header .title-line`、`.homepage-hero h1`、CTA 按鈕)都遵守這條。 | |
| 判斷漸層文字的 WCAG 對比度時,不能用 `getComputedStyle().color`(漸層文字用 `-webkit-text-fill-color:transparent`,會讀到透明),要用截圖取樣實際渲染像素計算。 | |
| --- | |
| ## 字體 | |
| - **英文/數字**:Crimson Pro(學術感、研究工具調性),標題與強調數字用 | |
| - **中文本文**:Noto Sans TC(維持業主原設定;Stitch 等工具的字體庫多為西文導向、不含中文字體,中西混搭是人工判斷後的決定,非工具庫建議) | |
| - **UI 介面文字**:Inter(Gradio 主題 `font=` 設定,中文 fallback 到 Noto Sans TC) | |
| - **等寬/資料**:JetBrains Mono(指標數值、程式碼片段) | |
| ### 字級規範 | |
| 全站基礎內文字級統一 `0.875rem`(14px),**唯一來源是 CSS 變數 `--font-size-base`,任何內文字級改動都要引用這個變數,不允許手寫 rem 數值**(2026-07-24 曾經手寫 `.88rem` 被業主當場糾正,需求文件第十一節的既有規範)。標題、步驟列 pill、小徽章這類刻意做出層級差異的地方例外,可以有自己的固定字級(見 YAML `typography.scale`)。 | |
| --- | |
| ## 造型與間距 | |
| - **圓角**:卡片類 14–16px、按鈕/輸入框 9–10px、徽章/pill 20px(全圓) | |
| - **陰影**:僅用在懸浮/強調狀態(卡片 hover、彈窗、抽屜),靜態卡片不加陰影——2026-07-23 業主實機回饋「原本的強調色外框+大範圍陰影+漸層底色讓卡片像浮起來的彈窗」,改成扁平化:外框、陰影、底色拿掉,只留圓角與內距維持呼吸空間;彈出動畫保留(負責「這塊剛出現」的狀態提示,跟視覺重量無關) | |
| - **版面比例**:三欄式工作區 `nav-col : chat-col : canvas-col = 2 : 3 : 7`,寬螢幕滿版貼齊左右邊界(不做置中留白),首頁例外維持 `max-width: 50rem` 置中,避免寬螢幕上被拉滿版 | |
| - **結果頁內容順序**:標題 → 圖表/表格 → 下載按鈕,六個結果頁一致(2026-08-12 業主要求把「語言指標分析」的下載從頁面頂部改回最下方,統一順序) | |
| - **表單欄位不包卡片**(2026-08-12):語料說明表單的欄位一律「小標題+內容直接攤開」,不要 Gradio 自動包的白色 `.form` 卡片。Gradio 這層卡片是兩件事疊起來的——`.form` 出框線、內層 `.block`/`fieldset` 出白底與內距——兩層都要清掉才會消失。內距清掉之後欄位左緣自然對齊小標題與下方表格。另外 `.form` 的 `align-items` 要改 `flex-start`:預設的 `stretch` 會把每個欄位的高度鎖成整列高度,而那個列高不含欄位標籤,radio 這種「標籤在上、選項在下」的元件會被裁掉一截 | |
| - **欄位標籤只有一種樣式**(2026-08-12):`.7rem`/`700`/`--c-text-muted`。這是 Gradio 給文字欄位標籤的既有值,不是另訂的字級,所以不套 `--font-size-base`(標籤比內文小一階是這張表單本來的層級設計)。radio 的 `fieldset` 標籤走 Gradio 另一條規則、預設是一般大小的深色字,要另外對齊,否則同一張表單裡兩種欄位的標籤長得不一樣 | |
| - **表格不自己出捲軸**(2026-08-12):dataframe 的內部容器一律 `scrollbar-width: none`。Gradio 預設 `max-height: 500px` + `overflow-y: auto`,列多時捲軸會佔掉 10px 版面寬度,表格因此比外框窄一截,右側露出一條空白帶,看起來像最後一欄被切掉(業主回報過)。滾輪/觸控/鍵盤照常可捲。**不要改用移除 `max-height` 的做法**:這個表格是虛擬捲動,靠自身捲動位置決定渲染哪些列,移除後會變成「保留整表高度卻只渲染 1 列」的空表。也**不要用 `::-webkit-scrollbar`**:Gradio 在該元件設了標準屬性 `scrollbar-width`/`scrollbar-color`,Chrome 見到標準屬性就會忽略 legacy 偽元素 | |
| - **導覽列末項**:「使用說明」固定在左側導覽列最後一項(技術執行紀錄下方,用分隔線隔開),與分析進度無關、全程可見;它是下載動作不是頁面,不參與導覽列的 active 狀態 | |
| - **基準留白**:導覽列與輸入框四邊留白 16px 為基準,其餘區塊(對話氣泡、Canvas 內容區)對齊同一基準線,避免同一頁面出現兩種留白邏輯 | |
| --- | |
| ## 圖示 | |
| Heroicons outline 風格 SVG,24×24、`stroke-width="1.75"`、`fill="none"`,手繪 path(非套件逐點對照)。業主明確否決沿用專案既有的 emoji 慣例。 | |
| **新增導覽圖示時要量「實際上色範圍」,不能只看 viewBox。** 所有圖示的 viewBox 都是 24×24、容器都是 22px,但畫出來的大小取決於 path 撐到哪裡。現有導覽圖示的上色範圍多落在 18×16 附近(`folder`/`chat-bubble`/`table-cells` 皆是),2026-08-12 新增的 `book-open` 初版只有 16×15,肉眼看得出比別人小一圈、卻不容易指出原因,是截圖逐一量非背景像素才確認。新增圖示畫完後量一次,對齊 18×16 這個量體。 | |
| ### AI 頭像(2026-08-12 新增) | |
| AI 訊息左側的頭像是 28px 圓形,紫→藍漸層底+白色四角星(sparkle),漸層與標題字共用同一條 heading-gradient。 | |
| 實作分工是刻意的:**漸層畫在 CSS 的 `.avatar-container`,SVG 檔(`assets/icons/ai-avatar.svg`)只放白色 glyph**。原因是 `gr.Chatbot(avatar_images=...)` 是 Python 端參數,同一個檔案沒辦法隨明暗主題換色;把漸層交給 CSS 才吃得到 `--c-accent-strong / --c-accent2 / --c-accent3` 這組會跟著主題切換的 token。白色圖形疊在任一主題的漸層上都夠亮。頭像寬高固定並設 `flex: none`,避免重蹈「圖示被 flex 壓縮」的舊坑。 | |
| glyph 規格與其他導覽圖示不同,另立一套:**兩顆星都是實心 `fill`、不描邊**,path 撐到接近滿版(大星 x3.9–17.1/y2.2–17.2、小星 x15.3–21.5/y13.6–20.7),`img` 內距 3px,圖案在 28px 圓內的可用範圍 22px。實心與放大要一起做才有效——只縮內距是把細線稿放大,只放大 path 又會被內距框住。 | |
| 深色模式處理:`gr.Button(icon=...)` 在這版 Gradio 渲染成 `<img>` 標籤而非行內 `<svg>`,CSS `currentColor` 對它無效,因此淺色版固定 stroke 顏色,深色模式改用 `filter: grayscale(1) invert(1) brightness(1.55) contrast(.85)` 反相逼近深色版文字色,不另外準備第二份深色 SVG 檔案。需要 `currentColor` 正常運作(例如收合鈕、明暗切換鈕這類不需要 Python `.click()` 的裝飾性圖示)則改用 `gr.HTML()` 內嵌行內 SVG。 | |
| --- | |
| ## 動效 | |
| - 對話訊息串流顯示、打字中三點跳動動畫(AI-Native UI 語彙) | |
| - 運算中狀態用轉圈動畫,避免使用 Gradio 預設的 `.generating` 呼吸藍框(視覺上與本站的呼吸動畫語彙衝突,需求文件已列為既有修正項) | |
| - 手機抽屜/確認彈窗用 `transform` 位移或 overlay 淡入,不做過度炫技的轉場 | |
| --- | |
| ## 已知技術限制(設計時務必納入考量) | |
| - **沒有測試套件**,任何視覺改動都要手動走一次流程驗證,純美感/主觀判斷的改動先截圖給業主看過再定案 | |
| - Gradio 6 的 CSS pipeline 會自動幫 `css=`/`css_paths=` 內的所有選擇器加上 `.gradio-container .contain` 前綴,`:root` 選擇器包進 `@media` 區塊後永遠無法命中;系統深色模式的 token 覆寫因此改放在 `app.launch(head=...)` 注入的獨立 `<style>`(見 `_DARK_MODE_HEAD_CSS`),繞過這個轉換管線 | |
| - 部分 Gradio 原生元件(`gr.Column(visible=False)` 等)在特定時序下會有可見性狀態的非直覺行為,改版面配置前建議先查 `app_agent.py` 裡累積的相關踩坑註解,避免重踩 | |
| --- | |
| *本文件為本次 UI/UX 改版團隊(吳千卉)依既有實作彙整,非全新設計提案。配色與整體風格方向延續業主原有版本,未來調整請同步更新本文件與 `assets/app.css`,保持兩者一致。* | |