大家好,歡迎來到 Day 2!在昨天,我們用 Clean Architecture 和「功能優先」的原則,為專案搭建了一個穩固、專業的骨架。今天,我們要為這個骨架注入靈魂,賦予它獨一無二的個性。我們要做的,就是將「Crew Up!」的設計規範,轉化為一個真實、可用的 設計系統 (Design System)。
一個設計系統,遠不止是選幾個好看的顏色。它是一套規則、一套原則,更是設計師與工程師之間溝通的共同語言。它能確保無論 App 如何擴展,使用者體驗始終保持高度的一致性。今天,我們將深入探討設計系統的「道」與「術」。
在動手之前,我們先來探討一個重要問題:為什麼要投入時間做設計系統?這就是設計系統的「道」。
一致性 (Consistency): 這是最直接的好處。從按鈕、字體到卡片間距,統一的規範能確保 App 的每個角落都給人相同的品牌感受,提供流暢且可預測的使用者體驗。
效率 (Efficiency): 預先定義好可重用的顏色、樣式和元件,未來開發新頁面將不再是從零開始,而是像「堆樂高」一樣,快速組合、搭建,效率呈指數級提升。
溝通 (Communication): 設計系統為團隊提供了一套共享的詞彙。當設計師說「用 Heading3 樣式」時,工程師能精準地知道是哪一個 TextStyle,減少了大量的溝通成本與誤解。
可維護性 (Maintainability): 當需要調整品牌色彩或字體時,只需要修改設計系統的核心檔案,整個 App 的視覺效果就會同步更新,避免了遺漏和不一致的問題。
可擴展性 (Scalability): 隨著專案成長,新的設計需求會不斷出現。一個好的設計系統能夠輕鬆地擴展,而不會破壞現有的視覺一致性。
為了有系統地建立我們的設計系統,我們將借鑒一個非常經典的理念:原子設計 (Atomic Design)。這個理念幫助我們理解設計系統的「術」。
原子 (Atoms): 構成我們 UI 最基礎的元素,無法再被拆分。這就是我們今天的目標。 例如:顏色、字體樣式、間距單位、圓角與陰影。
分子 (Molecules): 由數個原子組成的簡單 UI 元件。例如:一個包含標籤和圖示的輸入框。
組織 (Organisms): 由分子和原子組成的更複雜、獨立的區塊。例如:一個完整的活動卡片 (Activity Card)。
模板 (Templates): 頁面的骨架,定義了內容的結構和佈局。
頁面 (Pages): 具體的實例,展示真實的內容和狀態。
理解了背後的哲學,現在讓我們開始動手,根據您的精確設計稿,實踐設計系統的「術」,打造構成我們 App 風格的最基本「原子」。
我們將定義所有色階,並為常用的顏色提供語意化的別名:
// 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;
}
在設計系統中,字體的選擇直接影響到使用者體驗的品質。對於 Crew Up! 這樣的社交應用,我們需要考慮可讀性、一致性和跨平台相容性。
為什麼選擇原生字體?
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,
);
}
我們將定義所有間距單位,建立一個基於4的倍數的間距系統。這是現代設計系統的最佳實踐,確保視覺的一致性和可預測性。
為什麼基於4?
// 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;
}
我們將定義所有圓角和陰影的樣式:
// 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;
}
最後,我們更新 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 元件能夠保持一致與高效開發的基石。
更重要的是,我們建立了:
完整的設計系統架構:從顏色到字體,從間距到陰影,每個設計元素都有明確的定義和規範。
基於4的設計原則:所有間距和字體大小都遵循4的倍數,確保視覺一致性和開發效率。
原生字體策略:使用平台原生字體,提供最佳的使用者體驗和效能。
可擴展的設計系統:新的設計需求能夠輕鬆地整合到現有系統中。
明天,我們將以今天的成果為基礎,開始組合我們的第一個「分子」一個可重用的按鈕元件,並探討如何設計一個優雅的元件。
期待與您在 Day 3 相見!