fix(ajustes): inset row dividers and shrink icon/title/chevron
Tier 4 visual fidelity, audit S10/10.6/10.8/10.9 (t4 lines 514-516): GrupoAjustes' row divider now indents 47px instead of running full-bleed, FilaAjuste's leading icon drops from Material's 24px default to 21px, the row title is a local 14px override of cardTitle (14.5), and the chevron shrinks to 19px at 40% opacity instead of the 24px full-opacity default.
This commit is contained in:
@@ -34,7 +34,9 @@ class GrupoAjustes extends StatelessWidget {
|
|||||||
Text(titulo, style: type.eyebrowLabel),
|
Text(titulo, style: type.eyebrowLabel),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
for (var i = 0; i < filas.length; i++) ...[
|
for (var i = 0; i < filas.length; i++) ...[
|
||||||
if (i > 0) const Divider(height: 1),
|
// S10 (Tier 4 visual fidelity): the prototype insets its row
|
||||||
|
// divider by 47px (t4 line 516), not full-bleed.
|
||||||
|
if (i > 0) const Divider(height: 1, indent: 47),
|
||||||
filas[i],
|
filas[i],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -72,8 +74,14 @@ class FilaAjuste extends StatelessWidget {
|
|||||||
final valorActual = valor;
|
final valorActual = valor;
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
leading: Icon(icon),
|
// 10.6 (Tier 4 visual fidelity): the prototype's row icon is 21px (t4
|
||||||
title: Text(titulo, style: type.cardTitle),
|
// line 514), not Material's 24px default.
|
||||||
|
leading: Icon(icon, size: 21),
|
||||||
|
// 10.8 (Tier 4 visual fidelity): the prototype's row title is
|
||||||
|
// 14px/w700 (t4 line 514); cardTitle is 14.5/w700 — a one-off
|
||||||
|
// override, not a new PluriWaveTypography style (mirrors the
|
||||||
|
// precedent set for the ringing screen's station name, audit 9.7).
|
||||||
|
title: Text(titulo, style: type.cardTitle.copyWith(fontSize: 14)),
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@@ -88,7 +96,14 @@ class FilaAjuste extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
],
|
],
|
||||||
const Icon(Icons.chevron_right_rounded),
|
// 10.9 (Tier 4 visual fidelity): the prototype's chevron is 19px
|
||||||
|
// at 40% opacity (t4 lines 515-539), not Material's 24px
|
||||||
|
// full-opacity default.
|
||||||
|
Icon(
|
||||||
|
Icons.chevron_right_rounded,
|
||||||
|
size: 19,
|
||||||
|
color: const Color(0xFFF2F7FA).withValues(alpha: 0.4),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
|
|||||||
@@ -8,6 +8,24 @@ import 'package:pluriwave/tema/pluriwave_theme.dart';
|
|||||||
/// lines 512-539, 625 — "Voz clara", "Alta", "3 guardados", "Alfabético",
|
/// lines 512-539, 625 — "Voz clara", "Alta", "3 guardados", "Alfabético",
|
||||||
/// "7 · 84 MB", "Español", "Hoy, 08:12", "200 MB"). `FilaAjuste` used to
|
/// "7 · 84 MB", "Español", "Hoy, 08:12", "200 MB"). `FilaAjuste` used to
|
||||||
/// accept only `icon`/`titulo`/`onTap` — no value slot at all.
|
/// accept only `icon`/`titulo`/`onTap` — no value slot at all.
|
||||||
|
/// Pre-existing project constraint (see `pantalla_ajustes_test.dart`):
|
||||||
|
/// `PluriGlassSurface` paints a background over `ListTile`'s ink layer,
|
||||||
|
/// which Flutter flags as a warning-level assertion, not a correctness bug.
|
||||||
|
/// Only needed by the `GrupoAjustes` test below — the bare `FilaAjuste`
|
||||||
|
/// tests above never wrap a `ListTile` inside that surface.
|
||||||
|
void _suppressListTileInkAssertion() {
|
||||||
|
final original = FlutterError.onError;
|
||||||
|
FlutterError.onError = (details) {
|
||||||
|
if (details.exceptionAsString().contains(
|
||||||
|
'ListTile background color or ink splashes may be invisible',
|
||||||
|
)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
original?.call(details);
|
||||||
|
};
|
||||||
|
addTearDown(() => FlutterError.onError = original);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
Widget host(Widget child) {
|
Widget host(Widget child) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
@@ -49,4 +67,59 @@ void main() {
|
|||||||
expect(find.text('Info'), findsOneWidget);
|
expect(find.text('Info'), findsOneWidget);
|
||||||
expect(find.byIcon(Icons.chevron_right_rounded), findsOneWidget);
|
expect(find.byIcon(Icons.chevron_right_rounded), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'visual fidelity (audit 10.6/10.8/10.9): leading icon is 21px, the '
|
||||||
|
'title is 14px, and the chevron is 19px at 40% opacity (t4 lines '
|
||||||
|
'514-515)',
|
||||||
|
(tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
host(
|
||||||
|
FilaAjuste(
|
||||||
|
icon: Icons.equalizer_rounded,
|
||||||
|
titulo: 'Ecualizador base',
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final icon = tester.widget<Icon>(find.byIcon(Icons.equalizer_rounded));
|
||||||
|
expect(icon.size, 21);
|
||||||
|
|
||||||
|
final titulo = tester.widget<Text>(find.text('Ecualizador base'));
|
||||||
|
expect(titulo.style?.fontSize, 14);
|
||||||
|
|
||||||
|
final chevron = tester.widget<Icon>(
|
||||||
|
find.byIcon(Icons.chevron_right_rounded),
|
||||||
|
);
|
||||||
|
expect(chevron.size, 19);
|
||||||
|
expect(chevron.color, const Color(0xFFF2F7FA).withValues(alpha: 0.4));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'visual fidelity (audit S10): GrupoAjustes insets its row divider by '
|
||||||
|
'47px, not full-bleed (t4 line 516)',
|
||||||
|
(tester) async {
|
||||||
|
_suppressListTileInkAssertion();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
host(
|
||||||
|
GrupoAjustes(
|
||||||
|
titulo: 'AUDIO',
|
||||||
|
filas: [
|
||||||
|
FilaAjuste(
|
||||||
|
icon: Icons.equalizer_rounded,
|
||||||
|
titulo: 'Uno',
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
FilaAjuste(icon: Icons.hd_rounded, titulo: 'Dos', onTap: () {}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final divider = tester.widget<Divider>(find.byType(Divider));
|
||||||
|
expect(divider.indent, 47);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user