Mobile App — UI Design System & Consistency Guidelines
Purpose: This document defines the design rules for typography, spacing, buttons, layout, and component-based structures to enforce visual consistency across the Swopix application. It integrates Android (Material Design 3) and iOS (Apple HIG) developer best practices to eliminate UI fragmentation.
1. Android & Cross-Platform Best Practices
When building cross-platform Flutter applications targeting Android and iOS, developer design patterns should align with standard platform specifications.
1a. Density-Independent Pixels (dp) vs. Scale-Independent Pixels (sp)
- DP/Logical Pixels: Spacing, sizes, and padding must always be set in logical pixels (dp). Never hardcode physical pixel coordinates.
- SP (Typography Scaling): Text size must always be set in scale-independent pixels (
spor direct double values in Flutter which automatically scale based on the system's text scale factor). - Prohibition of Sizer for Spacing/Text: Do NOT use
.wor.hfrom thesizerpackage for padding, margins, or text size. Viewport-percentage styling scales uncontrollably, causing stretched components and unreadable text on tablets, foldables, and large screens. Use absolute logical pixels (e.g.,16,24) for spacing.
1b. Material Design 3 (M3) Specs for Android
- M3 Grid System: Built on a linear 8dp grid. All spacing, margins, and layout offsets should align with multiples of 8dp (
8,16,24,32,40,48,56,64). A secondary 4dp grid can be used for tight spacing inside dense components (like icon label gaps). - Touch Targets: The minimum touch target size for interactive elements on Android (M3 and WCAG 2.1 AA) is 48x48dp. Even if a visual asset is smaller (e.g., a 24dp icon), its clickable container must be padded to at least 48dp.
- Tonal Elevation: Material Design 3 replaces dark drop shadows with tonal overlays. Surfaces at higher elevations receive a colored overlay derived from the app's primary theme color rather than deep shadows.
2. Typography & Visual Hierarchy
Establishing a strong typographic hierarchy is critical to preventing screens from looking cluttered or flat.
2a. Material Design 3 Typography Scale
Use a unified typography scale to map text elements. Do not introduce arbitrary inline styles.
| M3 Role | App Token | Font Size | Weight | Line Height | Usage |
|---|---|---|---|---|---|
| Display Large | displayLarge | 57sp | Regular (400) | 1.1x | Large hero banners |
| Display Small | displaySmall | 36sp | Regular (400) | 1.2x | Onboarding titles |
| Headline Small | headlineSmall | 24sp | SemiBold (600) | 1.3x | Screen headers, modals |
| Title Large | titleLarge | 20sp | SemiBold (600) | 1.3x | App bar titles, card headers |
| Title Medium | titleMedium | 16sp | Medium (500) | 1.4x | Sub-sections, form labels |
| Title Small | titleSmall | 14sp | Medium (500) | 1.4x | List titles, small section heads |
| Body Large | bodyLarge | 16sp | Regular (400) | 1.5x | Primary reading copy, inputs |
| Body Medium | bodyMedium | 14sp | Regular (400) | 1.5x | Secondary descriptions |
| Body Small | bodySmall | 12sp | Regular (400) | 1.5x | Supporting metadata |
| Label Large | labelLarge | 14sp | Medium (500) | 1.4x | Button text, prominent chips |
| Label Small | labelSmall | 12sp | Medium (500) | 1.4x | Badges, navigation labels |
2b. Typographic Rules
- Minimum Font Size: No text in the app should go below 12sp for readability. Sizes of 7sp, 8sp, or 9sp fail accessibility criteria and are unreadable on high-density displays.
- Font Weight Hierarchy: Do not mix more than 2-3 weights on a single screen. Prefer
Regular (400)for body copy,Medium (500)for labels/buttons, andSemiBold (600)orBold (700)for headers. ProhibitExtraBold (800)orBlack (900)as they disrupt page hierarchy and look harsh. - Letter Spacing: Cap letter-spacing at
0.5pxfor small labels or badges. Body text must have zero extra letter spacing.
3. Spacing System (8dp Grid)
Spacing should never be arbitrary (e.g. 5, 7, 10, 13, 17, 21).
| Token | Size | Primary Usage |
|---|---|---|
space-1 | 4dp | Tight item spacing, icon + label gaps |
space-2 | 8dp | Chips/badges, heading to body text |
space-3 | 12dp | Horizontal list items spacing |
space-4 | 16dp | Default Screen Horizontal Padding |
space-5 | 20dp | Internal card layouts |
space-6 | 24dp | Between content sections |
space-8 | 32dp | Large hero element spacing |
space-10 | 40dp | Screen top/bottom padding offsets |
- Margins: Every screen must respect a 16dp horizontal margin on both sides. No components should touch the edge of the screen.
4. Components & Sizes
4a. Buttons
Buttons should be built as modular widgets. Do not hardcode button widths mid-screen.
- Width Rules:
- Full-Width (52dp Height): Belong exclusively at the bottom of the screen for primary CTAs (e.g., "Login", "Confirm", "Post Ad").
- Wrap-Content (44dp Height): Used inside lists, cards, and mid-screen buttons. They size dynamically with 16dp horizontal padding.
- Dual Action: Side-by-side buttons of equal width (split screen width minus 8dp spacing).
- Pressed Feedback: Every button (including custom widgets like
GradientButton) must implement pressed states. Use overlays (e.g. black with 10% opacity) or opacity scales (0.8) during click events.
4b. Text Fields
- Height: Standardized to 56dp (matching M3 Outlined/Filled specs) or 52dp with vertical padding of
14dpand horizontal padding of16dp. - Border Thickness: Default border should be
1dp. Focused and error borders must be2dpfor strong visual contrast.
4c. Cards
- Border Radius: Standardized to 12dp for all lists and grid cards. Avoid 16dp or 20dp corners to maintain modern, sleek outlines.
- Inner Padding: Standard card padding is 16dp all sides. Never use tight padding like 8dp or 10dp on main card layouts.
4d. Navigation
- Top App Bar: Height must be 64dp with centered or left-aligned titles (consistent throughout the app).
- Bottom Navigation Bar: Height must be 80dp (M3 guideline) with a pill-shaped selection indicator.
5. Component-Based Architecture Best Practices
Developer velocity and UI consistency depend on a strong component structure:
- Composition Over Inheritance: Assemble screens using small, single-purpose widgets.
- Stateless UI Presentation: Keep layout presentation widgets
Statelesswhere possible. Pass data and callbacks into them. - Themes over Hardcoding: Never hardcode color hex codes (e.g.,
Color(0xFF9CA3AF)) or style blocks inside text. Instead, refer toTheme.of(context).colorSchemeorAppTheme. - Isolate Responsive Widgets: Ensure that dynamic grids and layouts handle content scaling gracefully without breaking (use
LayoutBuilder).
6. Swopix Codebase Visual Gaps & Consistency Audit
Below is a detailed list of identified visual design inconsistencies, gaps, and issues in the current Swopix codebase that violate developer best practices.
6a. Typography Hierarchy & Weight Inconsistencies
- Font Sizes Below Readability Limit:
- listing_list_card_widget.dart: Uses
fontSize: 7for theFEATUREDlabel. 7sp is completely unreadable on high-density mobile screens. - listing_card_widget.dart: Uses
fontSize: 8forFEATUREDlabel. - listing_card_widget.dart: Uses
fontSize: 9for listing time-ago text. - main_shell.dart: Hardcodes
fontSize: 9for notification count. - my_listing_card.dart: Uses hardcoded
fontSize: 10.
- listing_list_card_widget.dart: Uses
- Inconsistent/Extreme Font Weights:
- boost_listing_screen.dart: Uses
FontWeight.w800(Extra Bold). This font weight is too heavy and breaks typographic rules. - listing_card_widget.dart: Uses
FontWeight.w900(Black/Heavy) for the smallFEATUREDbadge.
- boost_listing_screen.dart: Uses
- Local Overrides vs Centralized Theme:
- Multiple text styles are hardcoded with local
TextStyleblocks containing sizes/colors rather than relying onTheme.of(context).textTheme. For example:- boost_listing_screen.dart ->
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w800)
- boost_listing_screen.dart ->
- Multiple text styles are hardcoded with local
6b. Spacing & Margin Inconsistencies
- Use of Sizer for Padding & Margins:
- terms_conditions_screen.dart: Uses
EdgeInsets.only(left: 2.w)andleft: 17.w. - support_screen.dart: Uses
EdgeInsets.only(left: 17.w). - pricing_section_widget.dart: Uses
EdgeInsets.only(left: 4.w, top: 1.8.h). Impact: Viewport-percentage spacing causes layout drift on different screen aspect ratios.
- terms_conditions_screen.dart: Uses
- Arbitrary Margins (Non-multiples of 4):
- listing_card_widget.dart: Uses
padding: const EdgeInsets.fromLTRB(10, 8, 10, 8). 10px horizontal padding violates the 8dp grid spacing standard.
- listing_card_widget.dart: Uses
6c. Border Radius Discrepancies
- Cards Radius Inconsistency:
- listing_card_widget.dart: Uses
BorderRadius.circular(16). - listing_list_card_widget.dart: Uses
BorderRadius.circular(16). Impact: These cards conflict with Phase 3 instructions to standardize lists/grid card outlines to12px.
- listing_card_widget.dart: Uses
- Uneven Image Border Radii:
- listing_card_widget.dart: Top borders of listing images are clipped using
Radius.circular(15)inside a card container of16pxborder radius, creating an uneven visual frame.
- listing_card_widget.dart: Top borders of listing images are clipped using
6d. Touch Target Failures (Below 48x48dp)
- Toggles & Small Controls:
- Toggle controls (such as the view togglers in home screens) and icons inside badges (like listing stars or location pins) have small hitboxes that make them difficult to tap on mobile touchscreens.
- Buttons like
_ViewToggleButtonat 32x32px and category chips at 40px height do not meet Android's 48dp touch target standards.
7. Refactoring Checklist for Visual Consistency
When clean-up tasks are scheduled, verify:
- Replace sizer
.spvalues with standard scale-independent values. - Replace
.wand.hmargins/paddings with static logical dp values. - Up-scale all font sizes below
12spto12sp(AppTypography.labelSmall). - Normalize Card radii from
16pxdown to12px. - Set minimum heights of default inline buttons to
44dpand ensure they have a tactile pressed state. - Ensure all key interactive icons/buttons have an absolute minimum tap box of
48x48dp.