iT邦幫忙

2025 iThome 鐵人賽

DAY 2
0

大家好,歡迎來到 Day 2!在昨天,我們用 Clean Architecture 和「功能優先」的原則,為專案搭建了一個穩固、專業的骨架。今天,我們要為這個骨架注入靈魂,賦予它獨一無二的個性。我們要做的,就是將「Crew Up!」的設計規範,轉化為一個真實、可用的 設計系統 (Design System)

一個設計系統,遠不止是選幾個好看的顏色。它是一套規則、一套原則,更是設計師與工程師之間溝通的共同語言。它能確保無論 App 如何擴展,使用者體驗始終保持高度的一致性。今天,我們將深入探討設計系統的「道」與「術」。

設計系統的「道」 - 為什麼我們需要它?

在動手之前,我們先來探討一個重要問題:為什麼要投入時間做設計系統?這就是設計系統的「道」。

  1. 一致性 (Consistency): 這是最直接的好處。從按鈕、字體到卡片間距,統一的規範能確保 App 的每個角落都給人相同的品牌感受,提供流暢且可預測的使用者體驗。

  2. 效率 (Efficiency): 預先定義好可重用的顏色、樣式和元件,未來開發新頁面將不再是從零開始,而是像「堆樂高」一樣,快速組合、搭建,效率呈指數級提升。

  3. 溝通 (Communication): 設計系統為團隊提供了一套共享的詞彙。當設計師說「用 Heading3 樣式」時,工程師能精準地知道是哪一個 TextStyle,減少了大量的溝通成本與誤解。

  4. 可維護性 (Maintainability): 當需要調整品牌色彩或字體時,只需要修改設計系統的核心檔案,整個 App 的視覺效果就會同步更新,避免了遺漏和不一致的問題。

  5. 可擴展性 (Scalability): 隨著專案成長,新的設計需求會不斷出現。一個好的設計系統能夠輕鬆地擴展,而不會破壞現有的視覺一致性。

原子設計 (Atomic Design) 的哲學

為了有系統地建立我們的設計系統,我們將借鑒一個非常經典的理念:原子設計 (Atomic Design)。這個理念幫助我們理解設計系統的「術」。

  • 原子 (Atoms): 構成我們 UI 最基礎的元素,無法再被拆分。這就是我們今天的目標。 例如:顏色、字體樣式、間距單位、圓角與陰影。

  • 分子 (Molecules): 由數個原子組成的簡單 UI 元件。例如:一個包含標籤和圖示的輸入框。

  • 組織 (Organisms): 由分子和原子組成的更複雜、獨立的區塊。例如:一個完整的活動卡片 (Activity Card)。

  • 模板 (Templates): 頁面的骨架,定義了內容的結構和佈局。

  • 頁面 (Pages): 具體的實例,展示真實的內容和狀態。

動手時間:設計系統的「術」 - 打造 Crew Up! 的「原子」

理解了背後的哲學,現在讓我們開始動手,根據您的精確設計稿,實踐設計系統的「術」,打造構成我們 App 風格的最基本「原子」。

1. 顏色系統 (Color System) - 根據設計規範

我們將定義所有色階,並為常用的顏色提供語意化的別名:

// lib/app/config/theme/app_colors.dart
class AppColors {
  AppColors._();

  // 基礎顏色
  static const Color orange700 = Color(0xFFC64508);
  static const Color blue500 = Color(0xFF5090A7);
  static const Color neutral50 = Color(0xFFFAFAFA);
  static const Color neutral950 = Color(0xFF0A0A0A);

  // 功能顏色別名
  static const Color actionPrimary = orange700;
  static const Color actionSecondary = blue500;
  static const Color textPrimary = neutral950;
  static const Color surfaceBackground = neutral50;
}

2. 字體排印系統 (Typography System) - 原生字體的智慧選擇

在設計系統中,字體的選擇直接影響到使用者體驗的品質。對於 Crew Up! 這樣的社交應用,我們需要考慮可讀性一致性跨平台相容性

為什麼選擇原生字體?

  1. 最佳的可讀性:原生字體經過各平台精心優化,在不同螢幕密度下都能提供最佳的顯示效果
  2. 一致的體驗:使用者對原生字體已經熟悉,能提供更自然的閱讀體驗
  3. 效能優勢:無需額外的字體檔案,減少 App 大小,提升載入速度
  4. 維護簡便:不需要管理字體檔案,避免字體載入失敗的問題

Flutter 原生字體策略:

我們將定義所有字體階層,並使用正確的顏色別名:

// lib/app/config/theme/app_typography.dart
class AppTypography {
  AppTypography._();

  // 字體大小
  static const double fontSizeXXS = 10.0;
  static const double fontSizeXS = 14.0;
  static const double fontSizeSM = 16.0;
  static const double fontSizeMD = 24.0;
  static const double fontSizeLG = 20.0;
  static const double fontSizeXL = 28.0;

  // 標題樣式
  static const TextStyle heading1 = TextStyle(
    fontSize: fontSizeXL,
    fontWeight: FontWeight.w700,
    color: AppColors.textPrimary,
  );

  // 正文樣式
  static const TextStyle body1 = TextStyle(
    fontSize: fontSizeMD,
    fontWeight: FontWeight.w400,
    color: AppColors.textPrimary,
  );
}

3. 間距系統 (Spacing System) - 基於4的設計原則

我們將定義所有間距單位,建立一個基於4的倍數的間距系統。這是現代設計系統的最佳實踐,確保視覺的一致性和可預測性。

為什麼基於4?

  1. 視覺一致性:4的倍數能確保元素之間的對齊更加精確
  2. 開發效率:開發者能快速計算和預測間距
  3. 響應式設計:在不同螢幕尺寸下都能保持良好的比例
  4. 設計系統標準:符合 Material Design、iOS Human Interface Guidelines 等主流設計系統
// lib/app/config/theme/app_spacing.dart
class AppSpacing {
  AppSpacing._();

  // 基礎間距值 - 基於4的倍數
  static const double xxs = 4.0;
  static const double xs = 8.0;
  static const double s = 16.0;
  static const double m = 24.0;
  static const double l = 32.0;
  static const double xl = 40.0;

  // 功能間距別名
  static const double pageMargin = m;
  static const double cardPadding = m;
  static const double buttonPadding = s;
}

4. 圓角與陰影系統 (Radius & Shadow System) - 根據設計規範

我們將定義所有圓角和陰影的樣式:

// lib/app/config/theme/app_radius.dart
class AppRadius {
  AppRadius._();

  // 圓角值
  static const double radiusXS = 8.0;
  static const double radiusS = 12.0;
  static const double radiusM = 16.0;

  // 元件專用圓角
  static const BorderRadius cardRadius = BorderRadius.all(Radius.circular(radiusM));
  static const BorderRadius buttonRadius = BorderRadius.all(Radius.circular(radiusS));
}

// lib/app/config/theme/app_shadows.dart
class AppShadows {
  AppShadows._();

  // 陰影定義
  static const List<BoxShadow> shadowS = [
    BoxShadow(
      color: Color.fromRGBO(0, 0, 0, 0.07),
      blurRadius: 8,
      offset: Offset(0, 2),
    ),
  ];

  // 元件專用陰影
  static const List<BoxShadow> cardShadow = shadowS;
}

5. 整合到 App 主題

最後,我們更新 app_theme.dart,將新的顏色和字體原子整合進 ThemeData:

// lib/app/config/theme/app_theme.dart
class AppTheme {
  AppTheme._();

  static ThemeData get lightTheme {
    return ThemeData(
      primaryColor: AppColors.actionPrimary,
      scaffoldBackgroundColor: AppColors.surfaceBackground,
      textTheme: const TextTheme(
        headline1: AppTypography.heading1,
        bodyText1: AppTypography.body1,
      ),
      appBarTheme: const AppBarTheme(
        backgroundColor: AppColors.surfaceWhite,
        foregroundColor: AppColors.textPrimary,
      ),
      cardTheme: CardTheme(
        shape: AppRadius.cardRadius,
        color: AppColors.surfaceWhite,
      ),
    );
  }
}

結語與下一步

恭喜!今天我們完成了一項極其重要的工程。我們將分散的設計規範,系統性地轉化為了程式碼中可重用、可管理的「原子」。

我們的 App 現在擁有了與您的設計稿完全一致的視覺基因。這份前期工作看似繁瑣,卻是未來所有 UI 元件能夠保持一致與高效開發的基石。

更重要的是,我們建立了:

  1. 完整的設計系統架構:從顏色到字體,從間距到陰影,每個設計元素都有明確的定義和規範。

  2. 基於4的設計原則:所有間距和字體大小都遵循4的倍數,確保視覺一致性和開發效率。

  3. 原生字體策略:使用平台原生字體,提供最佳的使用者體驗和效能。

  4. 可擴展的設計系統:新的設計需求能夠輕鬆地整合到現有系統中。

明天,我們將以今天的成果為基礎,開始組合我們的第一個「分子」一個可重用的按鈕元件,並探討如何設計一個優雅的元件。

期待與您在 Day 3 相見!


📋 相關資源

📝 專案資訊

  • 專案名稱: Crew Up!
  • 開發日誌: Day 2 - 設計系統的哲學與實作
  • 文章日期: 2025-09-16
  • 技術棧: Flutter 3.8+, Dart 3.8+, Riverpod 2.6+, Clean Architecture

上一篇
Day 1 - 專案啟動與架構選型
下一篇
Day 3 - 元件的藝術:打造類型安全、高效能的 Flutter UI 分子
系列文
我的 Flutter 進化論:30 天打造「Crew Up!」的架構之旅11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言