Skip to content

[Refactor] Rediseño UI con Material Design 3 + Dynamic Color#110

Open
omartosca wants to merge 5 commits intojavikin:mainfrom
omartosca:claude/thirsty-boyd
Open

[Refactor] Rediseño UI con Material Design 3 + Dynamic Color#110
omartosca wants to merge 5 commits intojavikin:mainfrom
omartosca:claude/thirsty-boyd

Conversation

@omartosca
Copy link
Copy Markdown

@omartosca omartosca commented Mar 8, 2026

Summary

Migración completa del Design System de Umbral a Material Design 3 con soporte de Dynamic Color (Material You), manteniendo la paleta sage teal como fallback en Android < 12.

  • Fase 1 — Tema: Theme.kt con dynamicDarkColorScheme/dynamicLightColorScheme en API 31+; UmbralLightColorScheme y UmbralDarkColorScheme con lightColorScheme()/darkColorScheme() como fallback; Color.kt ampliado con todos los roles MD3
  • Fase 2 — Layout: UmbralTopBar y UmbralBottomBar migrados a TopAppBarDefaults y NavigationBarDefaults; UmbralButton mapeado a variantes MD3 nativas (Button, FilledTonalButton, OutlinedButton, TextButton); UmbralCard mapeado a ElevatedCard/OutlinedCard/Card
  • Fase 3-4 — Componentes: 13 componentes migrados — UmbralSnackbar, UmbralToast, UmbralSkeleton, UmbralBadge, UmbralAvatar, UmbralTag, EmptyStateIllustrations, ProfileCard, UmbralSwitch, UmbralCheckbox, UmbralIconButton, UmbralSurface, UmbralDivider
  • Fase 6 — Screens: StatsScreen y SettingsScreen — últimas referencias a Color(0xFF...) reemplazadas por colorScheme.tertiary / colorScheme.error

Patrón eliminado en todos los componentes:

// ❌ Antes — frágil, rompe Dynamic Color
val isDark = colorScheme.background == Color(0xFF151515)
color = if (isDark) DarkAccentPrimary else LightAccentPrimary

// ✅ Después — automático con Dynamic Color
color = MaterialTheme.colorScheme.primary

Los colores sin equivalente MD3 (DarkSuccess, LightWarning) se mantienen con isSystemInDarkTheme() — uso correcto de la API.

Test plan

  • Probar en emulador Android 12+: cambiar wallpaper y verificar que los colores de la app se adaptan (Dynamic Color activo)
  • Probar en emulador Android 11 (API 30): verificar que usa la paleta sage teal como fallback
  • Verificar light mode y dark mode en ambos casos
  • Correr ./gradlew test — sin regresiones (el cambio es visual/de theme)
  • Revisar ComponentCatalogScreen con dynamic color aplicado

- Rewrite README.md: update project status from pre-development to
  Beta, add gamification/notifications/Design System v2 features,
  add Build & Run instructions, complete tech stack table, update
  roadmap and contributions sections, define MIT license
- Update CLAUDE.md: remove outdated pre-development next steps,
  add Room v6 schema table (12 tables), update feature list with
  all implemented extras, update project structure tree, add
  current status and upcoming release steps
- Create AGENTS.md: portable AI agent guide with naming conventions,
  architecture overview, DB schema, module map, testing patterns,
  and what to avoid
- Create .claude/rules/: three focused rule files for agents
  (naming.md, architecture.md, testing.md) with code examples
- Theme.kt: enable dynamicDarkColorScheme/dynamicLightColorScheme on API 31+,
  keep sage teal palette as fallback for Android < 12
- UmbralTopBar: remove isSystemInDarkTheme + hardcoded color constants,
  use MaterialTheme.colorScheme.background
- UmbralButton: replace hardcoded Color(0xFF151515) contentColor with
  MaterialTheme.colorScheme.onPrimary for Primary variant
- UmbralCard: replace all hardcoded Dark/LightBackground* and Border*
  constants with MD3 colorScheme roles (surface, surfaceContainerHigh,
  outline, outlineVariant, primary)
- UmbralBottomBar: replace deprecated Divider with HorizontalDivider
Replace hardcoded color constants and fragile isDark checks across 13 components:

- UmbralSwitch: trackColor/thumbColor → colorScheme.primary/onPrimary/outline/onSurfaceVariant
- UmbralCheckbox: Color.White (in Canvas) → colorScheme.onPrimary captured in composable scope
- UmbralIconButton: Color(0xFF151515) → colorScheme.onPrimary; preview backgrounds → surfaceContainer
- UmbralSurface: Level0-3 elevation → colorScheme.background/surface/surfaceContainerHigh/surfaceContainerHighest
- UmbralDivider: DarkBorderDefault/LightBorderDefault → colorScheme.outlineVariant
- UmbralSnackbar: hacky isDark (background color comparison) → isSystemInDarkTheme(); DarkBackgroundElevated → surfaceContainerHigh; DarkTextPrimary → onSurface; DarkError → colorScheme.error
- UmbralToast: hacky isDark (surface color comparison) → surfaceContainerHigh + onSurface
- UmbralSkeleton: Color(0xFF252525/0xFFE8E8E8) → surfaceContainerHigh; Color(0xFF303030/0xFFF5F5F5) → surfaceContainerHighest
- UmbralBadge: isDark (background comparison) → isSystemInDarkTheme(); Default badge → colorScheme.primary/onPrimary; Error → colorScheme.error/onError; Neutral → surfaceVariant/onSurfaceVariant
- UmbralAvatar: DarkAccentPrimary/DarkSuccess/DarkTextTertiary → colorScheme.primary/tertiary/onSurfaceVariant
- UmbralTag: remove unused DarkAccentPrimary/LightAccentPrimary imports
- EmptyStateIllustrations: DarkAccentPrimary/DarkTextTertiary → colorScheme.primary/onSurfaceVariant
- ProfileCard (ActiveBadge): Color(0xFF4CAF50) → colorScheme.tertiary
- StatsScreen: PercentageChangeChip uses colorScheme.tertiary (positive)
  and colorScheme.error (negative) instead of Color(0xFF4CAF50/F44336)
- SettingsScreen: PermissionRow successColor uses colorScheme.tertiary
  instead of Color(0xFF4CAF50); remove unused Color import in both files

HomeScreen, ProfilesScreen, ProfileDetailScreen and all onboarding
screens were already clean — no changes needed.
@omartosca omartosca changed the title [Docs] Update documentation to reflect completed development state [Refactor] Rediseño UI con Material Design 3 + Dynamic Color Mar 8, 2026
- ThemeUtils: gradient/brush functions now read from MaterialTheme.colorScheme
  (background, surface, surfaceContainerHigh, primary, primaryContainer,
  outlineVariant) instead of hand-picking dark/light named constants
- ThemeUtils: accentDimmed(), dividerColor(), shimmerBrush(),
  surfaceColorAtElevation() all migrated to colorScheme roles
- UmbralCard legacy overloads: containerColor uses surfaceColorAtElevation()
  without isSystemInDarkTheme(); removed unused import
- WidgetTheme: Color(0xFFFFFFFF) → Color.White
- BlockingActivity: timer/streak icon tints and glow color use
  colorScheme.primary / colorScheme.tertiary
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant