feat(ui): design token discipline, accessibility and i18n pass
- Replace all hardcoded Color literals outside lib/tema with theme tokens (new static brand palette in PluriWaveTokens); media notification uses the brand color instead of the Material default purple - Favorite button on station cards grows to a 48dp target and becomes an independent semantics node for screen readers (Semantics container fix) - All flutter_animate call sites route through the PluriAnimate reduced-motion gate (zero direct .animate() left) - Locale-aware short dates via intl DateFormat (new lib/l10n/formato_fechas.dart) replacing the hardcoded DD/MM/YYYY; proper plural messages for the favorites counter; example stream URL as a localized key - all 13 locales - Rounded shimmer placeholders matching card radii; shimmer loading state in search instead of a bare spinner; rounded icon variants unified in settings; bottom-sheet conventions on the custom station form - Fix latent debug crash: vacation editor read AppLocalizations in initState - 11 new tests (121 total green), flutter analyze clean
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../tema/pluriwave_theme.dart';
|
||||
import '../tema/pluriwave_tokens.dart';
|
||||
import 'pluri_glass_surface.dart';
|
||||
import 'pluri_icon.dart';
|
||||
|
||||
@@ -38,12 +39,14 @@ class PluriScreenHeader extends StatelessWidget {
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
const Color(0xFF20E6FF).withValues(alpha: 0.95),
|
||||
PluriWaveTokens.brightCyan.withValues(alpha: 0.95),
|
||||
t.electricMagenta,
|
||||
t.warmCoral,
|
||||
],
|
||||
),
|
||||
boxShadow: [BoxShadow(color: t.glowColor, blurRadius: 28, spreadRadius: 2)],
|
||||
boxShadow: [
|
||||
BoxShadow(color: t.glowColor, blurRadius: 28, spreadRadius: 2),
|
||||
],
|
||||
),
|
||||
child: Center(
|
||||
child: PluriIcon(
|
||||
@@ -117,14 +120,22 @@ class PluriScreenHeader extends StatelessWidget {
|
||||
Expanded(child: textBlock()),
|
||||
if (trailing != null) ...[
|
||||
const SizedBox(width: 12),
|
||||
ConstrainedBox(constraints: const BoxConstraints(maxWidth: 220), child: trailing!),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 220),
|
||||
child: trailing!,
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(t.spacingMd, t.spacingSm, t.spacingMd, t.spacingSm),
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
t.spacingMd,
|
||||
t.spacingSm,
|
||||
t.spacingMd,
|
||||
t.spacingSm,
|
||||
),
|
||||
child: PluriGlassSurface(
|
||||
borderRadius: BorderRadius.circular(t.radiusLg + 8),
|
||||
padding: EdgeInsets.symmetric(
|
||||
@@ -164,7 +175,10 @@ class PluriScreenHeader extends StatelessWidget {
|
||||
Positioned(
|
||||
right: -36,
|
||||
top: -42,
|
||||
child: _Orb(color: t.electricMagenta.withValues(alpha: 0.38), size: 128),
|
||||
child: _Orb(
|
||||
color: t.electricMagenta.withValues(alpha: 0.38),
|
||||
size: 128,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
@@ -182,7 +196,10 @@ class PluriScreenHeader extends StatelessWidget {
|
||||
Positioned(
|
||||
right: 44,
|
||||
bottom: -54,
|
||||
child: _Orb(color: const Color(0xFF20E6FF).withValues(alpha: 0.22), size: 116),
|
||||
child: _Orb(
|
||||
color: PluriWaveTokens.brightCyan.withValues(alpha: 0.22),
|
||||
size: 116,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(compact ? 2 : 4),
|
||||
@@ -195,7 +212,6 @@ class PluriScreenHeader extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PluriStatusPill extends StatelessWidget {
|
||||
const PluriStatusPill({
|
||||
super.key,
|
||||
@@ -232,7 +248,9 @@ class PluriStatusPill extends StatelessWidget {
|
||||
label,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(fontWeight: FontWeight.w800),
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.labelMedium?.copyWith(fontWeight: FontWeight.w800),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -267,14 +285,26 @@ class PluriEmptyState extends StatelessWidget {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
PluriIcon(glyph: glyph, variant: PluriIconVariant.activeGlow, size: 58),
|
||||
PluriIcon(
|
||||
glyph: glyph,
|
||||
variant: PluriIconVariant.activeGlow,
|
||||
size: 58,
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
Text(title, textAlign: TextAlign.center, style: theme.textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w900)),
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
subtitle,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(color: theme.colorScheme.onSurface.withValues(alpha: 0.72)),
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.colorScheme.onSurface.withValues(alpha: 0.72),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user