6.4 KiB
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
- Gradient background matching web
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:ModalBottomSheetfor 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.linearGradientwith infinite animation - Text line and rectangle shapes
- Shimmer animation using
steps:
- Create
android/app/src/main/java/com/shieldai/android/ui/components/directory. - ShieldButton:
@Composable fun ShieldButton(...)- Primary:
ButtonwithcontainerColor = BrandPrimary - Secondary:
OutlinedButtonwithborderColor = BrandPrimary - Ghost:
TextButtonwithcontentColor = BrandPrimary - Danger:
Buttonwith red gradient - Loading: wrap content in
BoxwithCircularProgressIndicatoroverlay - Full-width:
modifier = Modifier.fillMaxWidth()
- ShieldCard:
Cardwith customcolorsusing gradient brush backgroundborder = BorderStroke(1.dp, BorderColor)shape = MaterialTheme.shapes.large- Header/footer as optional
@Composableslots
- ShieldTextField:
OutlinedTextFieldorTextFieldwith custom colorsVisualTransformationfor password toggle- Error state: red border and supporting text
KeyboardOptionsfor appropriate keyboard type per input
- ShieldBadge:
Surfacewithshape = RoundedCornerShape(50%)- Small padding, small text
- Background color from semantic tokens
- ShieldModal:
ModalBottomSheetfrom Material3- Or
AlertDialogfor confirmation dialogs SheetStatemanagement
- ShieldToast:
SnackbarHostwith customSnackbarcomposableScaffoldprovidesSnackbarHostState- Show via
scope.launch { snackbarHostState.showSnackbar(...) } - Custom colors per variant
- ShieldAvatar:
AsyncImagefrom Coil library- Fallback:
Boxwith initials text on brand color circle - Status dot: small
Canvascircle overlay
- ShieldProgressBar:
LinearProgressIndicatorwith customtrackColorandprogressColor- Percentage text overlay
- ShieldEmptyState:
Columnwith icon (ImageorIcon), title, description, optionalShieldButton- Centered alignment
- ShieldSkeleton:
Brush.linearGradientwith animated offset usingrememberInfiniteTransition- Apply as background to
Boxshapes - Reference: https://developer.android.com/jetpack/compose/animation/shimmer
- 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 testfor unit tests
notes:
- Compose previews are essential for component development. Use
@Previewwith both light and dark themes. - Use
CompositionLocalProviderfor theme overrides if needed (e.g., a section that needs inverted colors). - The shimmer animation in Compose uses
rememberInfiniteTransitionandBrush.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
ModalBottomSheetrequiresandroidx.compose.material3:material3version 1.2.0+. Ensure BOM includes it.