iT邦幫忙

2025 iThome 鐵人賽

DAY 27
0
生成式 AI

左手藍圖,右手魔法:DDD 與 Vibe Coding 的開發協奏曲系列 第 27

Day 27: 【文件 #8】數據的畫布:用 Gemini 設計「圖表元件規格書」

  • 分享至 

  • xImage
  •  

安安,我是 ChiYu!

昨天,我們的 App 學會了「同理心」,能夠優雅地處理載入與錯誤,大幅提升了使用者體驗。至此,我們 App 的基礎建設與核心互動功能,都已相當完備。

現在,是時候兌現我們在《專案章程》中許下的最終承諾,實現我們 App 的核心價值主張了——「關聯性洞察」。

但是,圖表功能的開發,遠比一個簡單的按鈕要複雜得多。它涉及到數據的獲取、處理、整合與視覺化,稍有不慎,就可能陷入混亂。因此,在我們一頭熱地栽進去 Vibe Coding 之前,我們要重拾我們最强大的武器,再次回到 **「文件驅動開發 (DDD)」**的懷抱。

今天,我們將回頭重新設計文件,對於較為複雜的功能,為了避免AI天馬行空脫韁,還是建議回頭重新設計一份完整詳細的規格文件!我們將扮演一位「數據產品設計師」,與 Gemini 一同腦力激盪,為這個最複雜的功能,撰寫一份清晰、專業的**「圖表元件規格書」**。

Part 1:前端心法:為什麼複雜的功能更需要「文件先行」?

你可能會問:「我們不是已經有《使用者故事》了嗎?為什麼還要再寫一份文件?」

問得好!《使用者故事》告訴我們使用者想要 什麼 (What),但它並沒有告訴我們技術上該 如何實現 (How)。對於一個簡單的按鈕,這兩者之間的差距很小。但對於一個圖表元件,這個差距就非常巨大了:

  • 數據契約 (Data Contract):這個圖表元件,到底需要從外部接收什麼格式的數據才能運作?是兩個獨立的陣列,還是一個合併過的物件陣列?
  • 互動行為 (Interaction Behavior):使用者與圖表的互動有哪些?滑鼠移上去要顯示什麼?點擊圖例 (Legend) 會發生什麼事?
  • 邊界情況 (Edge Cases):如果沒有數據,圖表該顯示什麼?如果數據只有一天,又該如何呈現?

在動手寫 Code 前,先把這些問題用一份 **「技術規格書」**定義清楚,就像是在畫一張精密的「零件設計圖」。有了這張圖,我們接下來的 Vibe Coding 才能精準、高效,而不是一邊寫一邊猜。

Part 2:Vibe Coding 實戰:撰寫我們的「零件設計圖」

好了,理論武裝完畢!讓我們進入 gemini chat 模式,指揮 AI 為我們撰寫這份至關重要的規格書。

【魔法詠唱:設計圖表規格】

# 角色 (Role)
你是一位頂尖的數據產品設計師與資深前端架構師,精通數據視覺化、元件化開發與無障礙網頁設計 (a11y)。你最擅長的工作是將高階的商業需求,轉化為一份清晰、穩固、可執行、且具備卓越使用者體驗的前端元件技術規格書。

# 目標 (Objective)
請根據我提供的專案上下文,為我們的核心功能「關聯性洞察圖表」,設計一份專業、完整、且可直接交付給開發者執行的**「圖表元件技術規格書 (Chart Component Technical Specification)」**。這份文件將成為該元件開發的唯一真理來源。

# 上下文與關鍵資訊 (Context & Key Information)
* **核心價值主張**: 我們的 App 旨在「揭示個人行為與內在感受之間的微妙聯繫」(`@docs/PROJECT_CHARTER.md`)。
* **使用者故事**: 我們需要實現使用者故事 #5:「查看一個簡單的圖表,將我的心情趨勢與我完成的習慣並列視覺化」(`@docs/USER_STORIES.md`)。
* **可用數據源**: 我們可以透過 API 分別獲取 `moods` 和 `habits` 的日誌數據。
* **視覺風格**: 所有視覺設計(顏色、字體等)都必須嚴格遵循 `@docs/STYLE_GUIDE.md`。

# 產出格式與要求 (Your Task & Output Requirements)
**請生成一份專業的 Markdown 文件,並嚴格遵循以下大綱結構:**

### 1. **元件目標與使用者故事**
* 簡要重述此元件旨在解決的核心使用者問題,並直接引用相關的使用者故事。

### 2. **數據契約 (Data Contract / Props)**
* **架構理念**: 我們將採用「展示元件 (Presentational Component)」的設計模式。圖表元件本身**不應**負責合併或處理原始數據。它應該接收一個**已經處理好**的、單一的 `data` prop。
* **Props 定義**: 使用 Markdown 表格,清晰地定義此元件所需的所有 Props。
    | Prop 名稱 | 資料類型 | 是否必需 | 預設值 | 說明 |
    | :--- | :--- | :--- | :--- | :--- |
    | `data` | `Array<Object>` | 是 | `[]` | 經過處理後的圖表數據陣列。每個物件代表 X 軸上的一個點,應包含如 `{ date: 'YYYY-MM-DD', moodRating: number, completedHabits: Array<string> }` 的結構。 |
    | `isLoading` | `boolean` | 否 | `false` | 用於控制是否顯示載入狀態。 |

### 3. **核心功能與視覺呈現**
* 用條列式的方式,描述圖表的具體視覺元素:
    * **圖表類型**: 採用混合圖表 (Combo Chart)。
    * **心情趨勢**: 使用平滑的**折線圖 (Line Chart)** 呈現,線條顏色需使用風格指南中的主色 (`--color-primary`)。
    * **習慣完成**: 在有完成習慣的日期數據點上,疊加一個**散點 (Scatter Point)** 作為標記,顏色使用輔色 (`--color-accent`)。
    * **X 軸**: 代表**日期**,標籤應清晰易讀。
    * **Y 軸**: 代表**心情分數** (範圍 1-5)。
    * **圖例 (Legend)**: 需提供圖例,用以區分「心情趨勢」和「完成習慣」。
    * **響應式設計**: 描述在移動端等小螢幕上,圖表應如何調整以保持可讀性(例如:減少 X 軸標籤的顯示密度)。

### 4. **互動行為 (Interaction Behavior)**
* **滑鼠懸停 (Hover)**: 當滑鼠移到任一數據點上時,應顯示一個**工具提示 (Tooltip)**。Tooltip 需:
    * 顯示該點的詳細資訊:日期、心情分數、當日完成的所有習慣列表。
    * 其外觀(背景、字體、顏色)需符合風格指南。
* **圖例點擊**: 點擊圖例中的項目(如 "完成習慣"),應能切換(顯示/隱藏)對應數據系列在圖表上的可見性。

### 5. **狀態與邊界情況 (States & Edge Cases)**
* 定義在特殊情況下,元件的渲染內容:
    * **載入中 (`isLoading: true`)**: 元件區域應顯示一個**骨架屏 (Skeleton Screen)** 或載入指示器,而非空白。
    * **無數據/數據不足 (`data` 陣列長度 < 3)**: 元件區域應顯示一個設計過的提示訊息,例如:「持續記錄幾天,就能解鎖你的個人洞察報告!」

### 6. **無障礙設計 (Accessibility - a11y)**
* 定義為了讓所有使用者都能訪問圖表資訊所需滿足的條件:
    * **鍵盤導航**: 使用者應能使用鍵盤(如 Tab 鍵)遍歷圖表的各個數據點。
    * **ARIA 屬性**: 圖表的根 SVG 元素應包含適當的 `role` 和 `aria-label` 屬性。
    * **備用呈現**: 提供一個機制或隱藏的數據表格,讓螢幕閱讀器使用者也能獲取圖表的完整資訊。

### 7. **最終產出**
* 將以上所有內容,生成到 `docs/CHART_COMPONENT_SPEC.md` 檔案中。

Part 3:審核 AI 產出的「設計圖」

AI 完成操作後,讓我們來仔細品味一下這份由我們共同創作的、專業的「零件設計圖」。

【AI 生成文件範例】

# MindTrack - 關聯性洞察圖表元件技術規格書

- **文件版本**: 1.0
- **作者**: Gemini (數據產品設計師 / 前端架構師)

---

## 1. 元件目標與使用者故事

### 1.1. 核心目標

此元件的核心目標,是實現產品的關鍵價值主張:「**揭示個人行為與內在感受之間的微妙聯繫**」。它將透過數據視覺化的方式,將抽象的日誌數據轉化為使用者能輕易理解、並從中獲得洞察的圖形化介面,賦予使用者改善生活品質的知識與力量。

### 1.2. 使用者故事

本元件直接對應以下核心使用者故事:

> **作為一個**數據導向的使用者,
> **我希望能**看到一個簡單的圖表,將我的心情趨勢與我完成的習慣並列視覺化,
> **這樣我才能**開始識別我的行為與幸福感之間有意義的模式。

---

## 2. 數據契約 (Data Contract / Props)

### 2.1. 架構理念

本圖表將作為一個純粹的**「展示元件 (Presentational Component)」**。它自身不包含任何數據獲取或處理的業務邏輯。其所有渲染內容,完全由外部傳入的 `props` 決定。這種設計確保了元件的高度可複用性與可測試性。

### 2.2. Props 定義

| Prop 名稱   | 資料類型        | 是否必需 | 預設值  | 說明                                                                                                                                                             |
| :---------- | :-------------- | :------- | :------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data`      | `Array<Object>` | **是**   | `[]`    | 經過上層邏輯處理後的圖表數據陣列。每個物件代表 X 軸上的一個數據點,其結構應為:<br>`{ date: 'YYYY-MM-DD', moodRating: number, completedHabits: Array<string> }` |
| `isLoading` | `boolean`       | 否       | `false` | 用於控制元件是否應顯示為「載入中」狀態。當為 `true` 時,圖表內容將被載入指示器取代。                                                                     |

---

## 3. 核心功能與視覺呈現

所有視覺元素(顏色、字體等)的選擇,都必須嚴格遵循 `STYLE_GUIDE.md` 中的定義。

-   **圖表類型**: 採用**混合圖表 (Combo Chart)**,在同一個座標系中呈現兩種不同的數據系列。

-   **心情趨勢**: 
    -   應使用平滑的**折線圖 (Line Chart)** 來呈現,以展示數據的連續性與趨勢。
    -   線條顏色應使用風格指南中的主色 `var(--primary-color)`。
    -   線條下方可選用同色系的漸層區域填充,以增強視覺效果。

-   **習慣完成**:
    -   在 `completedHabits` 陣列**不為空**的日期數據點上,疊加一個**散點 (Scatter Point)** 作為視覺標記。
    -   散點顏色應使用風格指南中的輔色/強調色 `var(--accent-color)`,以使其足夠醒目。

-   **X 軸 (X-Axis)**:
    -   代表**日期**,應從左至右按時間順序排列。
    -   標籤應清晰易讀,格式建議為 `MM/DD`。

-   **Y 軸 (Y-Axis)**:
    -   代表**心情分數**,範圍為 1 至 5。
    -   應顯示至少三個主要刻度標籤(例如:低、中、高),以輔助使用者快速定位。

-   **圖例 (Legend)**:
    -   必須提供圖例,用以清晰地區分「心情趨勢」折線和「完成習慣」散點。
    -   圖例應放置在圖表下方或右上角,不應遮擋圖表主要內容。

-   **響應式設計 (Responsive Design)**:
    -   在移動端等小螢幕設備上,圖表必須能自動縮放以適應容器寬度。
    -   為避免 X 軸標籤因空間不足而重疊,應實作標籤顯示密度自動調整邏輯(例如:從顯示每天,變為每隔一天或每週顯示一個標籤)。

---

## 4. 互動行為 (Interaction Behavior)

-   **滑鼠懸停/觸控 (Hover/Touch)**:
    -   當使用者的指標(滑鼠或手指)懸停在任一數據點(折線上的節點)上時,必須顯示一個**工具提示 (Tooltip)**。
    -   **Tooltip 內容**: 應清晰地展示該數據點的詳細資訊,至少包含:
        1.  完整日期 (例如: `2025年9月8日`)
        2.  當日心情分數 (例如: `心情: 4/5`)
        3.  當日完成的所有習慣列表 (如果 `completedHabits` 陣列不為空)。
    -   **Tooltip 外觀**: 其背景色、字體、顏色等所有樣式,均需符合 `STYLE_GUIDE.md` 的規範。

-   **圖例點擊 (Legend Click)**:
    -   圖例中的項目應是可點擊的。
    -   點擊圖例中的任一項(例如「完成習慣」),應能切換(顯示/隱藏)該數據系列在圖表上的可見性。
    -   此互動讓使用者可以專注於單一數據系列進行分析。

---

## 5. 狀態與邊界情況 (States & Edge Cases)

元件必須能夠優雅地處理以下幾種情況:

-   **載入中 (`isLoading: true`)**:
    -   當 `isLoading` prop 為 `true` 時,元件的內容區域不應顯示空白。
    -   應顯示一個符合整體設計風格的**骨架屏 (Skeleton Screen)** 或**載入指示器 (Loading Spinner)**,向使用者傳達「正在準備你的洞察報告...」的狀態。

-   **無數據/數據不足 (`data.length < 3`)**:
    -   當傳入的 `data` 陣列長度不足以形成有意義的趨勢時(建議閾值為 3 個數據點),不應渲染一個空的座標軸。
    -   應在元件區域的正中央,顯示一個經過設計的、友好的提示訊息,例如:
        > **「持續記錄幾天,就能解鎖你的個人洞察報告!」**

---

## 6. 無障礙設計 (Accessibility - a11y)

為確保所有使用者(包括使用輔助技術的使用者)都能平等地獲取圖表資訊,本元件必須滿足以下 WCAG 標準:

-   **鍵盤導航 (Keyboard Navigation)**:
    -   使用者必須能使用 `Tab` 鍵將焦點移入圖表元件。
    -   當焦點在圖表上時,必須能使用方向鍵(`←` / `→`)在各個數據點之間遍歷,且每個被遍歷到的數據點都應能觸發其對應的 Tooltip 顯示。

-   **ARIA 屬性**: 
    -   圖表的根 `<svg>` 元素必須包含 `role="img"` 和一個內容豐富的 `aria-label`,例如:`aria-label="一張從 [開始日期] 到 [結束日期] 的心情與習慣關聯圖表。"`。
    -   每個可互動的數據點(或其所屬的 `<g>` 元素)都應有自己的 `role` 和 `aria-label`,用以描述其數據值,例如:`aria-label="9月8日,心情分數為 4 分,完成習慣 2 個。"`。

-   **備用呈現 (Alternative Presentation)**:
    -   必須提供一種讓螢幕閱讀器 (Screen Reader) 使用者能夠線性地、完整地理解圖表數據的機制。
    -   **推薦方案**: 在元件內部,提供一個**視覺上隱藏** (visually-hidden) 的數據表格 (`<table>`),其內容與圖表所呈現的數據完全對應。這能確保圖表資訊對所有使用者都是 100% 可訪問的。

Part 4:提交我們的「設計圖」

  • Commit 訊息: docs(frontend): Create chart component specification
  • Commit & Push

結語:從「想法」到「可執行的計畫」

再次恭喜!今天,我們又一次實踐了「文件驅動開發」的核心精神。我們沒有直接衝進複雜的圖表程式碼中,而是先退一步,將一個模糊的「想法」,轉化為了一份清晰、具體、可執行的「技術規格」。

有了這份精密的「零件設計圖」,我們接下來的開發工作將會變得無比順暢。明天,我們將正式拿起工具,嚴格依據今天的這份規格書,指揮 AI 和 Chart.js,將這幅數據的畫布,變成真實、可互動的前端程式碼!


上一篇
Day 26: 【前端 #7】用戶體驗的最後一哩路:優雅地處理載入與錯誤
系列文
左手藍圖,右手魔法:DDD 與 Vibe Coding 的開發協奏曲27
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言