Add KROW mobile release and paper design conventions documentation
- Introduced SKILL.md for KROW mobile release process detailing versioning, CHANGELOG management, GitHub Actions workflows, APK signing, and hotfix procedures. - Added SKILL.md for KROW paper design conventions covering design tokens, component patterns, screen structure, and naming rules to ensure visual consistency across design files.
This commit is contained in:
717
.agents/skills/krow-mobile-design-system/SKILL.md
Normal file
717
.agents/skills/krow-mobile-design-system/SKILL.md
Normal file
@@ -0,0 +1,717 @@
|
||||
---
|
||||
name: krow-mobile-design-system
|
||||
description: KROW mobile design system usage rules covering colors, typography, icons, spacing, and UI component patterns. Use this when implementing UI in KROW mobile features, matching POC designs to production, creating themed widgets, enforcing visual consistency, or reviewing UI code compliance. Prevents hardcoded values and ensures brand consistency across staff and client apps. Critical for maintaining immutable design tokens.
|
||||
---
|
||||
|
||||
# KROW Mobile Design System Usage
|
||||
|
||||
This skill defines mandatory standards for UI implementation using the shared `apps/mobile/packages/design_system`. All UI must consume design system tokens exclusively.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
- Implementing any UI in mobile features
|
||||
- Migrating POC/prototype designs to production
|
||||
- Creating new themed widgets or components
|
||||
- Reviewing UI code for design system compliance
|
||||
- Matching colors and typography from designs
|
||||
- Adding icons, spacing, or layout elements
|
||||
- Setting up theme configuration in apps
|
||||
- Refactoring UI code with hardcoded values
|
||||
|
||||
## Core Principle
|
||||
|
||||
**Design tokens (colors, typography, spacing) are IMMUTABLE and defined centrally.**
|
||||
|
||||
Features consume tokens but NEVER modify them. The design system maintains visual coherence across all apps.
|
||||
|
||||
## 1. Design System Ownership
|
||||
|
||||
### Centralized Authority
|
||||
|
||||
- `apps/mobile/packages/design_system` owns:
|
||||
- All brand assets
|
||||
- Colors and semantic color mappings
|
||||
- Typography and font configurations
|
||||
- Core UI components
|
||||
- Icons and images
|
||||
- Spacing, radius, elevation constants
|
||||
|
||||
### No Local Overrides
|
||||
|
||||
**✅ CORRECT:**
|
||||
```dart
|
||||
// Feature uses design system
|
||||
import 'package:design_system/design_system.dart';
|
||||
|
||||
Container(
|
||||
color: UiColors.background,
|
||||
padding: EdgeInsets.all(UiConstants.spacingL),
|
||||
child: Text(
|
||||
'Hello',
|
||||
style: UiTypography.display1m,
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
**❌ FORBIDDEN:**
|
||||
```dart
|
||||
// ❌ Custom colors in feature
|
||||
const myBlue = Color(0xFF1A2234);
|
||||
|
||||
// ❌ Custom text styles in feature
|
||||
const myStyle = TextStyle(fontSize: 24, fontWeight: FontWeight.bold);
|
||||
|
||||
// ❌ Theme overrides in feature
|
||||
Theme(
|
||||
data: ThemeData(primaryColor: Colors.blue),
|
||||
child: MyWidget(),
|
||||
)
|
||||
```
|
||||
|
||||
### Extension Policy
|
||||
|
||||
If a required style is missing:
|
||||
1. **FIRST:** Add it to `design_system` following existing patterns
|
||||
2. **THEN:** Use it in your feature
|
||||
|
||||
**DO NOT** create temporary workarounds with hardcoded values.
|
||||
|
||||
## 2. Package Structure
|
||||
|
||||
```
|
||||
apps/mobile/packages/design_system/
|
||||
├── lib/
|
||||
│ ├── src/
|
||||
│ │ ├── ui_colors.dart # Color tokens
|
||||
│ │ ├── ui_typography.dart # Text styles
|
||||
│ │ ├── ui_icons.dart # Icon exports
|
||||
│ │ ├── ui_constants.dart # Spacing, radius, elevation
|
||||
│ │ ├── ui_theme.dart # ThemeData factory
|
||||
│ │ └── widgets/ # Shared UI components
|
||||
│ │ ├── custom_button.dart
|
||||
│ │ └── custom_app_bar.dart
|
||||
│ └── design_system.dart # Public exports
|
||||
├── assets/
|
||||
│ ├── icons/
|
||||
│ ├── images/
|
||||
│ └── fonts/
|
||||
└── pubspec.yaml
|
||||
```
|
||||
|
||||
## 3. Colors Usage Rules
|
||||
|
||||
### Strict Protocol
|
||||
|
||||
**✅ DO:**
|
||||
```dart
|
||||
// Use UiColors for all color needs
|
||||
Container(color: UiColors.background)
|
||||
Text('Hello', style: TextStyle(color: UiColors.foreground))
|
||||
Icon(Icons.home, color: UiColors.primary)
|
||||
```
|
||||
|
||||
**❌ DON'T:**
|
||||
```dart
|
||||
// ❌ Hardcoded hex colors
|
||||
Container(color: Color(0xFF1A2234))
|
||||
|
||||
// ❌ Material color constants
|
||||
Container(color: Colors.blue)
|
||||
|
||||
// ❌ Opacity on hardcoded colors
|
||||
Container(color: Color(0xFF1A2234).withOpacity(0.5))
|
||||
```
|
||||
|
||||
### Available Color Categories
|
||||
|
||||
**Brand Colors:**
|
||||
- `UiColors.primary` - Main brand color
|
||||
- `UiColors.secondary` - Secondary brand color
|
||||
- `UiColors.accent` - Accent highlights
|
||||
|
||||
**Semantic Colors:**
|
||||
- `UiColors.background` - Page background
|
||||
- `UiColors.foreground` - Primary text color
|
||||
- `UiColors.card` - Card/container background
|
||||
- `UiColors.border` - Border colors
|
||||
- `UiColors.mutedForeground` - Secondary text
|
||||
|
||||
**Status Colors:**
|
||||
- `UiColors.success` - Success states
|
||||
- `UiColors.warning` - Warning states
|
||||
- `UiColors.error` - Error states
|
||||
- `UiColors.info` - Information states
|
||||
|
||||
### Color Matching from POCs
|
||||
|
||||
When migrating POC designs:
|
||||
|
||||
1. **Find closest match** in `UiColors`
|
||||
2. **Use existing color** even if slightly different
|
||||
3. **DO NOT add new colors** without design team approval
|
||||
|
||||
**Example Process:**
|
||||
```dart
|
||||
// POC has: Color(0xFF2C3E50)
|
||||
// Find closest: UiColors.background or UiColors.card
|
||||
// Use: UiColors.card
|
||||
|
||||
// POC has: Color(0xFF27AE60)
|
||||
// Find closest: UiColors.success
|
||||
// Use: UiColors.success
|
||||
```
|
||||
|
||||
### Theme Access
|
||||
|
||||
Colors can also be accessed via theme:
|
||||
```dart
|
||||
// Both are valid:
|
||||
Container(color: UiColors.primary)
|
||||
Container(color: Theme.of(context).colorScheme.primary)
|
||||
```
|
||||
|
||||
## 4. Typography Usage Rules
|
||||
|
||||
### Strict Protocol
|
||||
|
||||
**✅ DO:**
|
||||
```dart
|
||||
// Use UiTypography for all text
|
||||
Text('Title', style: UiTypography.display1m)
|
||||
Text('Body', style: UiTypography.body1r)
|
||||
Text('Label', style: UiTypography.caption1m)
|
||||
```
|
||||
|
||||
**❌ DON'T:**
|
||||
```dart
|
||||
// ❌ Custom TextStyle
|
||||
Text('Title', style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
))
|
||||
|
||||
// ❌ Manual font configuration
|
||||
Text('Body', style: TextStyle(
|
||||
fontFamily: 'Inter',
|
||||
fontSize: 16,
|
||||
))
|
||||
|
||||
// ❌ Modifying existing styles inline
|
||||
Text('Title', style: UiTypography.display1m.copyWith(
|
||||
fontSize: 28, // ← Don't override size
|
||||
))
|
||||
```
|
||||
|
||||
### Available Typography Styles
|
||||
|
||||
**Display Styles (Large Headers):**
|
||||
- `UiTypography.display1m` - Display Medium
|
||||
- `UiTypography.display1sb` - Display Semi-Bold
|
||||
- `UiTypography.display1b` - Display Bold
|
||||
|
||||
**Heading Styles:**
|
||||
- `UiTypography.heading1m` - H1 Medium
|
||||
- `UiTypography.heading1sb` - H1 Semi-Bold
|
||||
- `UiTypography.heading1b` - H1 Bold
|
||||
- `UiTypography.heading2m` - H2 Medium
|
||||
- `UiTypography.heading2sb` - H2 Semi-Bold
|
||||
|
||||
**Body Styles:**
|
||||
- `UiTypography.body1r` - Body Regular
|
||||
- `UiTypography.body1m` - Body Medium
|
||||
- `UiTypography.body1sb` - Body Semi-Bold
|
||||
- `UiTypography.body2r` - Body 2 Regular
|
||||
|
||||
**Caption/Label Styles:**
|
||||
- `UiTypography.caption1m` - Caption Medium
|
||||
- `UiTypography.caption1sb` - Caption Semi-Bold
|
||||
- `UiTypography.label1m` - Label Medium
|
||||
|
||||
### Allowed Customizations
|
||||
|
||||
**✅ ALLOWED (Color Only):**
|
||||
```dart
|
||||
// You MAY change color
|
||||
Text(
|
||||
'Title',
|
||||
style: UiTypography.display1m.copyWith(
|
||||
color: UiColors.error, // ← OK
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
**❌ FORBIDDEN (Size, Weight, Family):**
|
||||
```dart
|
||||
// ❌ Don't change size
|
||||
Text(
|
||||
'Title',
|
||||
style: UiTypography.display1m.copyWith(fontSize: 28),
|
||||
)
|
||||
|
||||
// ❌ Don't change weight
|
||||
Text(
|
||||
'Title',
|
||||
style: UiTypography.display1m.copyWith(fontWeight: FontWeight.w900),
|
||||
)
|
||||
|
||||
// ❌ Don't change family
|
||||
Text(
|
||||
'Title',
|
||||
style: UiTypography.display1m.copyWith(fontFamily: 'Roboto'),
|
||||
)
|
||||
```
|
||||
|
||||
### Typography Matching from POCs
|
||||
|
||||
When migrating:
|
||||
1. Identify text role (heading, body, caption)
|
||||
2. Find closest matching style in `UiTypography`
|
||||
3. Use existing style even if size/weight differs slightly
|
||||
|
||||
## 5. Icons Usage Rules
|
||||
|
||||
### Strict Protocol
|
||||
|
||||
**✅ DO:**
|
||||
```dart
|
||||
// Use UiIcons
|
||||
Icon(UiIcons.home)
|
||||
Icon(UiIcons.profile)
|
||||
Icon(UiIcons.chevronLeft)
|
||||
```
|
||||
|
||||
**❌ DON'T:**
|
||||
```dart
|
||||
// ❌ Direct icon library imports
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
Icon(LucideIcons.home)
|
||||
|
||||
// ❌ Font Awesome direct
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
FaIcon(FontAwesomeIcons.house)
|
||||
```
|
||||
|
||||
### Why Centralize Icons?
|
||||
|
||||
1. **Consistency:** Same icon for same action everywhere
|
||||
2. **Branding:** Unified icon set with consistent stroke weight
|
||||
3. **Swappability:** Change icon library in one place
|
||||
|
||||
### Icon Libraries
|
||||
|
||||
Design system uses:
|
||||
- `typedef _IconLib = LucideIcons;` (primary)
|
||||
- `typedef _IconLib2 = FontAwesomeIcons;` (secondary)
|
||||
|
||||
**Features MUST NOT import these directly.**
|
||||
|
||||
### Adding New Icons
|
||||
|
||||
If icon missing:
|
||||
1. Add to `ui_icons.dart`:
|
||||
```dart
|
||||
class UiIcons {
|
||||
static const home = _IconLib.home;
|
||||
static const newIcon = _IconLib.newIcon; // Add here
|
||||
}
|
||||
```
|
||||
2. Use in feature:
|
||||
```dart
|
||||
Icon(UiIcons.newIcon)
|
||||
```
|
||||
|
||||
## 6. Spacing & Layout Constants
|
||||
|
||||
### Strict Protocol
|
||||
|
||||
**✅ DO:**
|
||||
```dart
|
||||
// Use UiConstants for spacing
|
||||
Padding(padding: EdgeInsets.all(UiConstants.spacingL))
|
||||
SizedBox(height: UiConstants.spacingM)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.spacingL,
|
||||
vertical: UiConstants.spacingM,
|
||||
),
|
||||
)
|
||||
|
||||
// Use UiConstants for radius
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusM),
|
||||
),
|
||||
)
|
||||
|
||||
// Use UiConstants for elevation
|
||||
elevation: UiConstants.elevationLow
|
||||
```
|
||||
|
||||
**❌ DON'T:**
|
||||
```dart
|
||||
// ❌ Magic numbers
|
||||
Padding(padding: EdgeInsets.all(16.0))
|
||||
SizedBox(height: 24.0)
|
||||
BorderRadius.circular(8.0)
|
||||
elevation: 2.0
|
||||
```
|
||||
|
||||
### Available Constants
|
||||
|
||||
**Spacing:**
|
||||
```dart
|
||||
UiConstants.spacingXs // Extra small
|
||||
UiConstants.spacingS // Small
|
||||
UiConstants.spacingM // Medium
|
||||
UiConstants.spacingL // Large
|
||||
UiConstants.spacingXl // Extra large
|
||||
UiConstants.spacing2xl // 2x Extra large
|
||||
```
|
||||
|
||||
**Border Radius:**
|
||||
```dart
|
||||
UiConstants.radiusS // Small
|
||||
UiConstants.radiusM // Medium
|
||||
UiConstants.radiusL // Large
|
||||
UiConstants.radiusXl // Extra large
|
||||
UiConstants.radiusFull // Fully rounded
|
||||
```
|
||||
|
||||
**Elevation:**
|
||||
```dart
|
||||
UiConstants.elevationNone
|
||||
UiConstants.elevationLow
|
||||
UiConstants.elevationMedium
|
||||
UiConstants.elevationHigh
|
||||
```
|
||||
|
||||
## 7. Smart Widgets Usage
|
||||
|
||||
### When to Use
|
||||
|
||||
- **Prefer standard Flutter Material widgets** styled via theme
|
||||
- **Use design system widgets** for non-standard patterns
|
||||
- **Create new widgets** in design system if reused >3 features
|
||||
|
||||
### Navigation in Widgets
|
||||
|
||||
Widgets with navigation MUST use safe methods:
|
||||
|
||||
**✅ CORRECT:**
|
||||
```dart
|
||||
// In UiAppBar back button:
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_core/krow_core.dart';
|
||||
|
||||
IconButton(
|
||||
icon: Icon(UiIcons.chevronLeft),
|
||||
onPressed: () => Modular.to.popSafe(), // ← Safe pop
|
||||
)
|
||||
```
|
||||
|
||||
**❌ FORBIDDEN:**
|
||||
```dart
|
||||
// ❌ Direct Navigator
|
||||
IconButton(
|
||||
icon: Icon(UiIcons.chevronLeft),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
)
|
||||
|
||||
// ❌ Unsafe Modular
|
||||
IconButton(
|
||||
icon: Icon(UiIcons.chevronLeft),
|
||||
onPressed: () => Modular.to.pop(), // Can crash
|
||||
)
|
||||
```
|
||||
|
||||
### Composition Over Inheritance
|
||||
|
||||
**✅ CORRECT:**
|
||||
```dart
|
||||
// Compose standard widgets
|
||||
Container(
|
||||
padding: EdgeInsets.all(UiConstants.spacingL),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.card,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusM),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Title', style: UiTypography.heading1sb),
|
||||
SizedBox(height: UiConstants.spacingM),
|
||||
Text('Body', style: UiTypography.body1r),
|
||||
],
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
**❌ AVOID:**
|
||||
```dart
|
||||
// ❌ Deep custom widget hierarchies
|
||||
class CustomCard extends StatelessWidget {
|
||||
// Complex custom implementation
|
||||
}
|
||||
```
|
||||
|
||||
## 8. Theme Configuration
|
||||
|
||||
### App Setup
|
||||
|
||||
Apps initialize theme ONCE in root MaterialApp:
|
||||
|
||||
**✅ CORRECT:**
|
||||
```dart
|
||||
// apps/mobile/apps/staff/lib/app_widget.dart
|
||||
import 'package:design_system/design_system.dart';
|
||||
|
||||
class StaffApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp.router(
|
||||
theme: StaffTheme.light, // ← Design system theme
|
||||
darkTheme: StaffTheme.dark, // ← Optional dark mode
|
||||
themeMode: ThemeMode.system,
|
||||
// ...
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**❌ FORBIDDEN:**
|
||||
```dart
|
||||
// ❌ Custom theme in app
|
||||
MaterialApp.router(
|
||||
theme: ThemeData(
|
||||
primaryColor: Colors.blue, // ← NO!
|
||||
),
|
||||
)
|
||||
|
||||
// ❌ Theme override in feature
|
||||
Theme(
|
||||
data: ThemeData(...),
|
||||
child: MyFeatureWidget(),
|
||||
)
|
||||
```
|
||||
|
||||
### Accessing Theme
|
||||
|
||||
**Both methods valid:**
|
||||
```dart
|
||||
// Method 1: Direct design system import
|
||||
import 'package:design_system/design_system.dart';
|
||||
Text('Hello', style: UiTypography.body1r)
|
||||
|
||||
// Method 2: Via theme context
|
||||
Text('Hello', style: Theme.of(context).textTheme.bodyMedium)
|
||||
```
|
||||
|
||||
**Prefer Method 1** for explicit type safety.
|
||||
|
||||
## 9. POC → Production Workflow
|
||||
|
||||
### Step 1: Implement Structure (POC Matching)
|
||||
|
||||
Implement UI layout exactly matching POC:
|
||||
```dart
|
||||
// Temporary: Match POC visually
|
||||
Container(
|
||||
color: Color(0xFF1A2234), // ← POC color
|
||||
padding: EdgeInsets.all(16.0), // ← POC spacing
|
||||
child: Text(
|
||||
'Title',
|
||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), // ← POC style
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
**Purpose:** Ensure visual parity with POC before refactoring.
|
||||
|
||||
### Step 2: Architecture Refactor
|
||||
|
||||
Move to Clean Architecture:
|
||||
- Extract business logic to use cases
|
||||
- Move state management to BLoCs
|
||||
- Implement repository pattern
|
||||
- Use dependency injection
|
||||
|
||||
### Step 3: Design System Integration
|
||||
|
||||
Replace hardcoded values:
|
||||
```dart
|
||||
// Production: Design system tokens
|
||||
Container(
|
||||
color: UiColors.background, // ← Found closest match
|
||||
padding: EdgeInsets.all(UiConstants.spacingL), // ← Used constant
|
||||
child: Text(
|
||||
'Title',
|
||||
style: UiTypography.heading1sb, // ← Matched typography
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
**Color Matching:**
|
||||
- POC `#1A2234` → `UiColors.background`
|
||||
- POC `#3498DB` → `UiColors.primary`
|
||||
- POC `#27AE60` → `UiColors.success`
|
||||
|
||||
**Typography Matching:**
|
||||
- POC `24px bold` → `UiTypography.heading1sb`
|
||||
- POC `16px regular` → `UiTypography.body1r`
|
||||
- POC `14px medium` → `UiTypography.caption1m`
|
||||
|
||||
**Spacing Matching:**
|
||||
- POC `16px` → `UiConstants.spacingL`
|
||||
- POC `8px` → `UiConstants.spacingM`
|
||||
- POC `4px` → `UiConstants.spacingS`
|
||||
|
||||
## 10. Anti-Patterns & Common Mistakes
|
||||
|
||||
### ❌ Magic Numbers
|
||||
```dart
|
||||
// BAD
|
||||
EdgeInsets.all(12.0)
|
||||
SizedBox(height: 24.0)
|
||||
BorderRadius.circular(8.0)
|
||||
|
||||
// GOOD
|
||||
EdgeInsets.all(UiConstants.spacingM)
|
||||
SizedBox(height: UiConstants.spacingL)
|
||||
BorderRadius.circular(UiConstants.radiusM)
|
||||
```
|
||||
|
||||
### ❌ Local Themes
|
||||
```dart
|
||||
// BAD
|
||||
Theme(
|
||||
data: ThemeData(primaryColor: Colors.blue),
|
||||
child: MyWidget(),
|
||||
)
|
||||
|
||||
// GOOD
|
||||
// Use global theme defined in app
|
||||
```
|
||||
|
||||
### ❌ Hex Hunting
|
||||
```dart
|
||||
// BAD: Copy-paste from Figma
|
||||
Container(color: Color(0xFF3498DB))
|
||||
|
||||
// GOOD: Find matching design system color
|
||||
Container(color: UiColors.primary)
|
||||
```
|
||||
|
||||
### ❌ Direct Icon Library
|
||||
```dart
|
||||
// BAD
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
Icon(LucideIcons.home)
|
||||
|
||||
// GOOD
|
||||
Icon(UiIcons.home)
|
||||
```
|
||||
|
||||
### ❌ Custom Text Styles
|
||||
```dart
|
||||
// BAD
|
||||
Text('Title', style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Inter',
|
||||
))
|
||||
|
||||
// GOOD
|
||||
Text('Title', style: UiTypography.heading1sb)
|
||||
```
|
||||
|
||||
## 11. Design System Review Checklist
|
||||
|
||||
Before merging UI code:
|
||||
|
||||
### ✅ Design System Compliance
|
||||
- [ ] No hardcoded `Color(...)` or `0xFF...` hex values
|
||||
- [ ] No custom `TextStyle(...)` definitions
|
||||
- [ ] All spacing uses `UiConstants.spacing*`
|
||||
- [ ] All radius uses `UiConstants.radius*`
|
||||
- [ ] All elevation uses `UiConstants.elevation*`
|
||||
- [ ] All icons from `UiIcons`, not direct library imports
|
||||
- [ ] Theme consumed from design system, no local overrides
|
||||
- [ ] Layout matches POC intent using design system primitives
|
||||
|
||||
### ✅ Architecture Compliance
|
||||
- [ ] No business logic in widgets
|
||||
- [ ] State managed by BLoCs
|
||||
- [ ] Navigation uses Modular safe extensions
|
||||
- [ ] Localization used for all text (no hardcoded strings)
|
||||
- [ ] No direct Data Connect queries in widgets
|
||||
|
||||
### ✅ Code Quality
|
||||
- [ ] Widget build methods concise (<50 lines)
|
||||
- [ ] Complex widgets extracted to separate files
|
||||
- [ ] Meaningful widget names
|
||||
- [ ] Doc comments on reusable widgets
|
||||
|
||||
## 12. When to Extend Design System
|
||||
|
||||
### Add New Color
|
||||
**When:** New brand color approved by design team
|
||||
|
||||
**Process:**
|
||||
1. Add to `ui_colors.dart`:
|
||||
```dart
|
||||
class UiColors {
|
||||
static const myNewColor = Color(0xFF123456);
|
||||
}
|
||||
```
|
||||
2. Update theme if needed
|
||||
3. Use in features
|
||||
|
||||
### Add New Typography Style
|
||||
**When:** New text style pattern emerges across multiple features
|
||||
|
||||
**Process:**
|
||||
1. Add to `ui_typography.dart`:
|
||||
```dart
|
||||
class UiTypography {
|
||||
static const myNewStyle = TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontFamily: _fontFamily,
|
||||
);
|
||||
}
|
||||
```
|
||||
2. Use in features
|
||||
|
||||
### Add Shared Widget
|
||||
**When:** Widget reused in 3+ features
|
||||
|
||||
**Process:**
|
||||
1. Create in `lib/src/widgets/`:
|
||||
```dart
|
||||
// my_widget.dart
|
||||
class MyWidget extends StatelessWidget {
|
||||
// Implementation using design system tokens
|
||||
}
|
||||
```
|
||||
2. Export from `design_system.dart`
|
||||
3. Use across features
|
||||
|
||||
## Summary
|
||||
|
||||
**Core Rules:**
|
||||
1. **All colors from `UiColors`** - Zero hex codes in features
|
||||
2. **All typography from `UiTypography`** - Zero custom TextStyle
|
||||
3. **All spacing/radius/elevation from `UiConstants`** - Zero magic numbers
|
||||
4. **All icons from `UiIcons`** - Zero direct library imports
|
||||
5. **Theme defined once** in app entry point
|
||||
6. **POC → Production** requires design system integration step
|
||||
|
||||
**The Golden Rule:** Design system is immutable. Features adapt to the system, not the other way around.
|
||||
|
||||
When implementing UI:
|
||||
1. Import `package:design_system/design_system.dart`
|
||||
2. Use design system tokens exclusively
|
||||
3. Match POC intent with available tokens
|
||||
4. Request new tokens only when truly necessary
|
||||
5. Never create temporary hardcoded workarounds
|
||||
|
||||
Visual consistency is non-negotiable. Every pixel must come from the design system.
|
||||
Reference in New Issue
Block a user