Files
Kordant/tasks/shieldai-unified-restructure/35-android-design-system.md
2026-05-25 12:23:23 -04:00

6.4 KiB

35. Android App — Design System Components Matching Web Theme

meta: id: shieldai-unified-restructure-35 feature: shieldai-unified-restructure priority: P1 depends_on: [shieldai-unified-restructure-34] tags: [android, jetpack-compose, design-system, components, mobile]

objective:

  • Build a comprehensive set of reusable Jetpack Compose components that mirror the web app's UI primitives (Button, Card, Input, Badge, Modal, Toast) using the Android theme system from task 34. These should feel native to Android while maintaining visual consistency.

deliverables:

  • android/app/src/main/java/com/shieldai/android/ui/components/ — Component library:
    • ShieldButton.kt — Button component:
      • Variants: primary (filled), secondary (outlined), ghost (text), danger
      • Sizes: small, medium, large
      • States: enabled, disabled, loading (shows CircularProgressIndicator)
      • Icon support (leading/trailing)
    • ShieldCard.kt — Card container:
      • Gradient background matching web .gradient-card
      • Border with corner radius
      • Optional header and footer content slots
      • Click handling
    • ShieldTextField.kt — Text input:
      • Label, placeholder, error state, helper text
      • Password visibility toggle
      • Focus state styling
      • Validation support
    • ShieldBadge.kt — Status badge:
      • Variants: default, success, warning, error, info
      • Small rounded pill shape
      • Icon + text or text only
    • ShieldModal.kt — Modal bottom sheet / dialog:
      • ModalBottomSheet for mobile-appropriate presentation
      • Title, content, and action buttons
      • Swipe-to-dismiss
    • ShieldToast.kt — Toast / Snackbar:
      • Slide-up from bottom
      • Auto-dismiss after 3-4 seconds
      • Variants: success, error, warning, info
      • Action button support (e.g., "Undo")
    • ShieldAvatar.kt — User avatar:
      • Async image loading with Coil
      • Initials fallback
      • Sizes: small, medium, large
      • Online status indicator
    • ShieldProgressBar.kt — Progress indicator:
      • Linear progress bar with percentage
      • Color variants
    • ShieldEmptyState.kt — Empty state:
      • Icon, title, description, action button
    • ShieldSkeleton.kt — Skeleton loading:
      • Shimmer animation using Brush.linearGradient with infinite animation
      • Text line and rectangle shapes

steps:

  1. Create android/app/src/main/java/com/shieldai/android/ui/components/ directory.
  2. ShieldButton:
    • @Composable fun ShieldButton(...)
    • Primary: Button with containerColor = BrandPrimary
    • Secondary: OutlinedButton with borderColor = BrandPrimary
    • Ghost: TextButton with contentColor = BrandPrimary
    • Danger: Button with red gradient
    • Loading: wrap content in Box with CircularProgressIndicator overlay
    • Full-width: modifier = Modifier.fillMaxWidth()
  3. ShieldCard:
    • Card with custom colors using gradient brush background
    • border = BorderStroke(1.dp, BorderColor)
    • shape = MaterialTheme.shapes.large
    • Header/footer as optional @Composable slots
  4. ShieldTextField:
    • OutlinedTextField or TextField with custom colors
    • VisualTransformation for password toggle
    • Error state: red border and supporting text
    • KeyboardOptions for appropriate keyboard type per input
  5. ShieldBadge:
    • Surface with shape = RoundedCornerShape(50%)
    • Small padding, small text
    • Background color from semantic tokens
  6. ShieldModal:
    • ModalBottomSheet from Material3
    • Or AlertDialog for confirmation dialogs
    • SheetState management
  7. ShieldToast:
    • SnackbarHost with custom Snackbar composable
    • Scaffold provides SnackbarHostState
    • Show via scope.launch { snackbarHostState.showSnackbar(...) }
    • Custom colors per variant
  8. ShieldAvatar:
    • AsyncImage from Coil library
    • Fallback: Box with initials text on brand color circle
    • Status dot: small Canvas circle overlay
  9. ShieldProgressBar:
    • LinearProgressIndicator with custom trackColor and progressColor
    • Percentage text overlay
  10. ShieldEmptyState:
    • Column with icon (Image or Icon), title, description, optional ShieldButton
    • Centered alignment
  11. ShieldSkeleton:
  12. Create a preview composable showing all components in light and dark mode.

steps:

  • Unit: Each component renders correctly in Compose previews
  • Unit: ShieldButton click handler fires correctly
  • Unit: ShieldTextField validation shows error state
  • Unit: ShieldToast auto-dismisses after specified duration
  • Visual: All components match web app appearance in both color schemes
  • Visual: Components adapt to different font sizes (accessibility)

acceptance_criteria:

  • All 10 component types exist in ui/components/
  • Each component supports light and dark modes
  • Button supports all 4 styles, 3 sizes, and loading state
  • TextField supports validation, secure entry, and focus styling
  • Toast/Snackbar system can queue and auto-dismiss multiple messages
  • Card uses gradient background matching web theme
  • Skeleton has smooth shimmer animation
  • All components use theme tokens (no hardcoded colors)
  • Components adapt to accessibility font sizes

validation:

  • Open Compose preview for each component and verify appearance
  • Run app on emulator and navigate to component test screen
  • Toggle dark mode and verify all components shift colors
  • Enable large text in Accessibility settings and verify layouts don't break
  • Run ./gradlew test for unit tests

notes:

  • Compose previews are essential for component development. Use @Preview with both light and dark themes.
  • Use CompositionLocalProvider for theme overrides if needed (e.g., a section that needs inverted colors).
  • The shimmer animation in Compose uses rememberInfiniteTransition and Brush.linearGradient. This is the standard Android approach.
  • For image loading, Coil (io.coil-kt:coil-compose) is the standard. Add it to dependencies.
  • Keep components stateless where possible. State should be hoisted to parent composables or ViewModels.
  • Material3 ModalBottomSheet requires androidx.compose.material3:material3 version 1.2.0+. Ensure BOM includes it.