fix(escuchar,reproductor): add the section-heading token and screen 1-3 polish
Audit S7 plus the open items on screens 1-3. Escuchar gains the prototype's own 52px "now listening" eyebrow header (t4:53), which is structurally different from the 56px title row every other root uses (t4:325) -- the earlier wiring test asserted PluriRootHeader on all five roots, an over-broad premise now corrected to guard what actually holds: no AppBar, and the sleep-timer action still reachable.
This commit is contained in:
@@ -10,6 +10,7 @@ import 'package:pluriwave/estado/estado_radio.dart';
|
||||
import 'package:pluriwave/l10n/gen/app_localizations.dart';
|
||||
import 'package:pluriwave/modelos/emisora.dart';
|
||||
import 'package:pluriwave/pantallas/pantalla_inicio.dart';
|
||||
import 'package:pluriwave/widgets/pluri_root_header.dart';
|
||||
import 'package:pluriwave/widgets/visualizador_audio.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@@ -404,6 +405,299 @@ void main() {
|
||||
expect(texto.style?.color, const Color(0xFF21D4D9));
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'S7 visual fidelity: "Tus emisoras" uses the in-page section heading '
|
||||
'style (15/w800/ls-.2), not titleMedium(16)/w900',
|
||||
(tester) async {
|
||||
_setLargeSurfaceSize(tester);
|
||||
final favoritos = FakeServicioFavoritos();
|
||||
final estado = EstadoRadio(
|
||||
audio: FakeServicioAudio(),
|
||||
favoritos: favoritos,
|
||||
radio: FakeServicioRadio(),
|
||||
servicioEcualizador: FakeServicioEcualizador(),
|
||||
servicioGrabacion: FakeServicioGrabacionRadio(),
|
||||
resolverArchivoCustom: _archivoCustomVacio,
|
||||
iniciarAutomaticamente: false,
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
await tester.runAsync(estado.inicializar);
|
||||
await favoritos.agregar(emisoraDemo(uuid: 'f1', nombre: 'Favorita Uno'));
|
||||
await estado.cargarFavoritos();
|
||||
|
||||
await tester.pumpWidget(
|
||||
_conProviders(estado, _testApp(const PantallaInicio())),
|
||||
);
|
||||
await _pumpStableFrame(tester);
|
||||
|
||||
final texto = tester.widget<Text>(find.text('Tus emisoras'));
|
||||
expect(texto.style?.fontSize, 15, reason: 'prototype t4 line 80');
|
||||
expect(texto.style?.fontWeight, FontWeight.w800);
|
||||
expect(texto.style?.letterSpacing, -0.2);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'visual fidelity (audit 1.1): a full-bleed art/gradient/noise wash '
|
||||
'sits behind the whole screen, keyed so it can be found',
|
||||
(tester) async {
|
||||
_setLargeSurfaceSize(tester);
|
||||
final favoritos = FakeServicioFavoritos();
|
||||
final estado = EstadoRadio(
|
||||
audio: FakeServicioAudio(),
|
||||
favoritos: favoritos,
|
||||
radio: FakeServicioRadio(),
|
||||
servicioEcualizador: FakeServicioEcualizador(),
|
||||
servicioGrabacion: FakeServicioGrabacionRadio(),
|
||||
resolverArchivoCustom: _archivoCustomVacio,
|
||||
iniciarAutomaticamente: false,
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
await tester.runAsync(estado.inicializar);
|
||||
final sonando = emisoraDemo(uuid: 'f1', nombre: 'Favorita Uno');
|
||||
await favoritos.agregar(sonando);
|
||||
await estado.cargarFavoritos();
|
||||
await tester.runAsync(() => estado.reproducir(sonando));
|
||||
|
||||
await tester.pumpWidget(
|
||||
_conProviders(estado, _testApp(const PantallaInicio())),
|
||||
);
|
||||
await _pumpBounded(tester);
|
||||
|
||||
expect(
|
||||
find.byKey(const ValueKey('escuchar-background-art')),
|
||||
findsOneWidget,
|
||||
reason:
|
||||
'prototype t4 lines 49-51: full-bleed art at .5 opacity + a '
|
||||
'gradient + a noise texture',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'visual fidelity (audit 1.1): the background wash still renders with '
|
||||
'nothing playing (gradient/noise only, no station art to show)',
|
||||
(tester) async {
|
||||
_setLargeSurfaceSize(tester);
|
||||
final estado = EstadoRadio(
|
||||
audio: FakeServicioAudio(),
|
||||
favoritos: FakeServicioFavoritos(),
|
||||
radio: FakeServicioRadio(),
|
||||
servicioEcualizador: FakeServicioEcualizador(),
|
||||
servicioGrabacion: FakeServicioGrabacionRadio(),
|
||||
resolverArchivoCustom: _archivoCustomVacio,
|
||||
iniciarAutomaticamente: false,
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
await tester.runAsync(estado.inicializar);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_conProviders(estado, _testApp(const PantallaInicio())),
|
||||
);
|
||||
await _pumpStableFrame(tester);
|
||||
|
||||
expect(
|
||||
find.byKey(const ValueKey('escuchar-background-art')),
|
||||
findsOneWidget,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('visual fidelity (audit 1.2): Escuchar has its own 52px "Now '
|
||||
'listening" eyebrow header, not the shared 56px PluriRootHeader', (
|
||||
tester,
|
||||
) async {
|
||||
_setLargeSurfaceSize(tester);
|
||||
final estado = EstadoRadio(
|
||||
audio: FakeServicioAudio(),
|
||||
favoritos: FakeServicioFavoritos(),
|
||||
radio: FakeServicioRadio(),
|
||||
servicioEcualizador: FakeServicioEcualizador(),
|
||||
servicioGrabacion: FakeServicioGrabacionRadio(),
|
||||
resolverArchivoCustom: _archivoCustomVacio,
|
||||
iniciarAutomaticamente: false,
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
await tester.runAsync(estado.inicializar);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_conProviders(estado, _testApp(const PantallaInicio())),
|
||||
);
|
||||
await _pumpStableFrame(tester);
|
||||
|
||||
expect(find.byType(PluriRootHeader), findsNothing);
|
||||
expect(
|
||||
find.text('Escuchando ahora'),
|
||||
findsOneWidget,
|
||||
reason: 'prototype t4 line 53: "ESCUCHANDO AHORA"',
|
||||
);
|
||||
expect(find.byIcon(Icons.bedtime_outlined), findsOneWidget);
|
||||
|
||||
final cabeceras = tester
|
||||
.widgetList<SizedBox>(find.byType(SizedBox))
|
||||
.where((s) => s.height == 52);
|
||||
expect(cabeceras, isNotEmpty, reason: 'prototype t4 line 53: height:52px');
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
"visual fidelity (audit 1.2): the header's bedtime icon still opens "
|
||||
'the shared sleep-timer sheet',
|
||||
(tester) async {
|
||||
_setLargeSurfaceSize(tester);
|
||||
final estado = EstadoRadio(
|
||||
audio: FakeServicioAudio(),
|
||||
favoritos: FakeServicioFavoritos(),
|
||||
radio: FakeServicioRadio(),
|
||||
servicioEcualizador: FakeServicioEcualizador(),
|
||||
servicioGrabacion: FakeServicioGrabacionRadio(),
|
||||
resolverArchivoCustom: _archivoCustomVacio,
|
||||
iniciarAutomaticamente: false,
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
await tester.runAsync(estado.inicializar);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_conProviders(estado, _testApp(const PantallaInicio())),
|
||||
);
|
||||
await _pumpStableFrame(tester);
|
||||
|
||||
await tester.tap(find.byIcon(Icons.bedtime_outlined));
|
||||
await _pumpStableFrame(tester);
|
||||
|
||||
expect(find.byType(ActionChip), findsWidgets);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('visual fidelity (audit 1.5): the station name is 24/w800/ls-.5/'
|
||||
'height 1.12, not titleLarge(22) with no letter-spacing/height', (
|
||||
tester,
|
||||
) async {
|
||||
_setLargeSurfaceSize(tester);
|
||||
final favoritos = FakeServicioFavoritos();
|
||||
final estado = EstadoRadio(
|
||||
audio: FakeServicioAudio(),
|
||||
favoritos: favoritos,
|
||||
radio: FakeServicioRadio(),
|
||||
servicioEcualizador: FakeServicioEcualizador(),
|
||||
servicioGrabacion: FakeServicioGrabacionRadio(),
|
||||
resolverArchivoCustom: _archivoCustomVacio,
|
||||
iniciarAutomaticamente: false,
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
await tester.runAsync(estado.inicializar);
|
||||
// Deliberately NOT added to favoritos: the "Tus emisoras" grid also
|
||||
// renders a station's bare name, and this assertion targets the
|
||||
// hero's OWN station-name Text specifically -- a favorited station
|
||||
// with the same name would render twice and make `find.text` throw.
|
||||
final sonando = emisoraDemo(uuid: 'f1', nombre: 'Radio Horizonte');
|
||||
await tester.runAsync(() => estado.reproducir(sonando));
|
||||
|
||||
await tester.pumpWidget(
|
||||
_conProviders(estado, _testApp(const PantallaInicio())),
|
||||
);
|
||||
await _pumpBounded(tester);
|
||||
|
||||
final texto = tester.widget<Text>(find.text('Radio Horizonte'));
|
||||
expect(texto.style?.fontSize, 24, reason: 'prototype t4 line 60');
|
||||
expect(texto.style?.fontWeight, FontWeight.w800);
|
||||
expect(texto.style?.letterSpacing, -0.5);
|
||||
expect(texto.style?.height, 1.12);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'visual fidelity (audit 1.8): the hero play button is 72x72 with a '
|
||||
'38px icon, not 56x56 with a 28px icon',
|
||||
(tester) async {
|
||||
_setLargeSurfaceSize(tester);
|
||||
final favoritos = FakeServicioFavoritos();
|
||||
final estado = EstadoRadio(
|
||||
audio: FakeServicioAudio(),
|
||||
favoritos: favoritos,
|
||||
radio: FakeServicioRadio(),
|
||||
servicioEcualizador: FakeServicioEcualizador(),
|
||||
servicioGrabacion: FakeServicioGrabacionRadio(),
|
||||
resolverArchivoCustom: _archivoCustomVacio,
|
||||
iniciarAutomaticamente: false,
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
await tester.runAsync(estado.inicializar);
|
||||
final sonando = emisoraDemo(uuid: 'f1', nombre: 'Favorita Uno');
|
||||
await favoritos.agregar(sonando);
|
||||
await estado.cargarFavoritos();
|
||||
await tester.runAsync(() => estado.reproducir(sonando));
|
||||
|
||||
await tester.pumpWidget(
|
||||
_conProviders(estado, _testApp(const PantallaInicio())),
|
||||
);
|
||||
await _pumpBounded(tester);
|
||||
|
||||
final botones = tester
|
||||
.widgetList<SizedBox>(find.byType(SizedBox))
|
||||
.where((s) => s.width == 72 && s.height == 72);
|
||||
expect(botones, isNotEmpty, reason: 'prototype t4 line 73');
|
||||
|
||||
final iconos = tester
|
||||
.widgetList<Icon>(find.byType(Icon))
|
||||
.where(
|
||||
(i) =>
|
||||
i.icon == Icons.play_arrow_rounded ||
|
||||
i.icon == Icons.pause_rounded,
|
||||
);
|
||||
expect(iconos, isNotEmpty);
|
||||
expect(iconos.first.size, 38);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'visual fidelity (audit 1.9): the EQ/record/quality pill is centred, '
|
||||
'pill-shaped and uses expand_less at 17px -- not a left-aligned '
|
||||
'OutlinedButton with tune_rounded',
|
||||
(tester) async {
|
||||
_setLargeSurfaceSize(tester);
|
||||
final favoritos = FakeServicioFavoritos();
|
||||
final estado = EstadoRadio(
|
||||
audio: FakeServicioAudio(),
|
||||
favoritos: favoritos,
|
||||
radio: FakeServicioRadio(),
|
||||
servicioEcualizador: FakeServicioEcualizador(),
|
||||
servicioGrabacion: FakeServicioGrabacionRadio(),
|
||||
resolverArchivoCustom: _archivoCustomVacio,
|
||||
iniciarAutomaticamente: false,
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
await tester.runAsync(estado.inicializar);
|
||||
final sonando = emisoraDemo(uuid: 'f1', nombre: 'Favorita Uno');
|
||||
await favoritos.agregar(sonando);
|
||||
await estado.cargarFavoritos();
|
||||
await tester.runAsync(() => estado.reproducir(sonando));
|
||||
|
||||
await tester.pumpWidget(
|
||||
_conProviders(estado, _testApp(const PantallaInicio())),
|
||||
);
|
||||
await _pumpBounded(tester);
|
||||
|
||||
expect(find.byType(OutlinedButton), findsNothing);
|
||||
expect(
|
||||
find.byIcon(Icons.expand_less_rounded),
|
||||
findsOneWidget,
|
||||
reason: 'prototype t4 line 78: expand_less at 17px',
|
||||
);
|
||||
final icono = tester.widget<Icon>(find.byIcon(Icons.expand_less_rounded));
|
||||
expect(icono.size, 17);
|
||||
|
||||
final pildoras = tester
|
||||
.widgetList<DecoratedBox>(find.byType(DecoratedBox))
|
||||
.map((d) => d.decoration)
|
||||
.whereType<BoxDecoration>()
|
||||
.where((d) => d.borderRadius == BorderRadius.circular(999));
|
||||
expect(
|
||||
pildoras,
|
||||
isNotEmpty,
|
||||
reason: 'prototype t4 line 78: border-radius:999px pill',
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Mirrors the app.dart wiring: EstadoRadio owns the domain notifiers and
|
||||
|
||||
@@ -9,7 +9,10 @@ import 'package:pluriwave/l10n/gen/app_localizations.dart';
|
||||
import 'package:pluriwave/modelos/emisora.dart';
|
||||
import 'package:pluriwave/modelos/preset_ecualizador.dart';
|
||||
import 'package:pluriwave/pantallas/pantalla_reproductor.dart';
|
||||
import 'package:pluriwave/tema/pluriwave_tokens.dart';
|
||||
import 'package:pluriwave/widgets/ecualizador_widget.dart';
|
||||
import 'package:pluriwave/widgets/pluri_glass_surface.dart';
|
||||
import 'package:pluriwave/widgets/visualizador_audio.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
@@ -548,4 +551,157 @@ void main() {
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
group('Visual fidelity (screens 1-3 closing pass)', () {
|
||||
testWidgets('audit 2.1: the hero art is a fixed 246x246, not width*0.62', (
|
||||
tester,
|
||||
) async {
|
||||
final estado = crearEstado();
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await montarPantalla(tester, estado);
|
||||
|
||||
final sizedBox = tester.widget<SizedBox>(
|
||||
find.byKey(const Key('player-hero-art')),
|
||||
);
|
||||
expect(sizedBox.width, 246, reason: 'prototype t4 line 114');
|
||||
expect(sizedBox.height, 246);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'audit 2.2: a full-bleed backdrop sits behind the whole screen',
|
||||
(tester) async {
|
||||
const estacion = Emisora(
|
||||
uuid: 'demo-uuid',
|
||||
nombre: 'Radio Demo',
|
||||
url: 'https://stream.demo/radio',
|
||||
favicon: 'https://example.com/art.png',
|
||||
);
|
||||
final estado = crearEstado();
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await montarPantalla(tester, estado, estacion: estacion);
|
||||
|
||||
expect(
|
||||
find.byKey(const Key('player-background-art')),
|
||||
findsOneWidget,
|
||||
reason: 'prototype t4 lines 108-109: full-bleed blurred backdrop',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('audit 2.2: the backdrop still renders (gradient only) with no '
|
||||
'station art available', (tester) async {
|
||||
final estado = crearEstado();
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await montarPantalla(tester, estado);
|
||||
|
||||
expect(find.byKey(const Key('player-background-art')), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('audit 2.3: the title is 26/w800/ls-.5/height 1.15, not '
|
||||
'headlineSmall(24)/w700', (tester) async {
|
||||
final estado = crearEstado();
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await montarPantalla(tester, estado);
|
||||
|
||||
final texto = tester.widget<Text>(find.text(emisora.nombre));
|
||||
expect(texto.style?.fontSize, 26, reason: 'prototype t4 line 116');
|
||||
expect(texto.style?.fontWeight, FontWeight.w800);
|
||||
expect(texto.style?.letterSpacing, -0.5);
|
||||
expect(texto.style?.height, 1.15);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'audit 2.8: only the EQ propio tile is accented -- tinted brand '
|
||||
'background/border, the other three share a neutral opaque surface',
|
||||
(tester) async {
|
||||
final estado = crearEstado();
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await montarPantalla(tester, estado);
|
||||
|
||||
final eqDecoration =
|
||||
tester
|
||||
.widget<Container>(
|
||||
find
|
||||
.descendant(
|
||||
of: find.byKey(const Key('player-tool-eq')),
|
||||
matching: find.byType(Container),
|
||||
)
|
||||
.first,
|
||||
)
|
||||
.decoration
|
||||
as BoxDecoration;
|
||||
expect(
|
||||
eqDecoration.color,
|
||||
PluriWaveTokens.brand.withValues(alpha: 0.16),
|
||||
reason: 'prototype t4 line 133',
|
||||
);
|
||||
|
||||
final recordDecoration =
|
||||
tester
|
||||
.widget<Container>(
|
||||
find
|
||||
.descendant(
|
||||
of: find.byKey(const Key('player-tool-record')),
|
||||
matching: find.byType(Container),
|
||||
)
|
||||
.first,
|
||||
)
|
||||
.decoration
|
||||
as BoxDecoration;
|
||||
expect(
|
||||
recordDecoration.color,
|
||||
isNot(PluriWaveTokens.brand.withValues(alpha: 0.16)),
|
||||
reason: 'prototype t4 line 134: no explicit accent colour',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'audit 2.9: the transport row is not wrapped in a glass surface '
|
||||
'card',
|
||||
(tester) async {
|
||||
final estado = crearEstado();
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await montarPantalla(tester, estado);
|
||||
|
||||
expect(
|
||||
find.ancestor(
|
||||
of: find.byIcon(Icons.favorite_outline_rounded),
|
||||
matching: find.byType(PluriGlassSurface),
|
||||
),
|
||||
findsNothing,
|
||||
reason: 'prototype t4 lines 124-131: bare row, no glass card',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'audit 2.10: the visualizer is not wrapped in its own glass card',
|
||||
(tester) async {
|
||||
final estado = crearEstado();
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await montarPantalla(tester, estado);
|
||||
|
||||
final visualizador = find.byKey(const Key('player-visualizer'));
|
||||
expect(tester.widget(visualizador), isA<VisualizadorAudio>());
|
||||
expect(
|
||||
find.ancestor(
|
||||
of: visualizador,
|
||||
matching: find.byType(PluriGlassSurface),
|
||||
),
|
||||
findsNothing,
|
||||
reason:
|
||||
'prototype t4 lines 120-122: bars sit on the bare '
|
||||
'background',
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -102,8 +102,19 @@ void main() {
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'Escuchar draws its own PluriRootHeader with the tab title, no AppBar',
|
||||
'Escuchar is the documented header exception: a 52px "now listening" '
|
||||
'eyebrow instead of a PluriRootHeader title row, and still no AppBar',
|
||||
(tester) async {
|
||||
// The prototype gives Escuchar a STRUCTURALLY different header from
|
||||
// every other root (t4 line 53 vs line 325): 52px rather than 56, an
|
||||
// eyebrow at 15px/w800/55% opacity rather than a 23px title, and
|
||||
// trailing actions rather than a CTA. This test originally asserted
|
||||
// `PluriRootHeader` on all five roots — an over-broad premise, since
|
||||
// Escuchar's header was never a title row in the design.
|
||||
//
|
||||
// What still holds unconditionally, and is what this guards: no
|
||||
// AppBar anywhere (systemic item S1), and the sleep-timer action that
|
||||
// used to live in the removed global chrome is still reachable here.
|
||||
_suppressListTileInkAssertion();
|
||||
setLargeSurface(tester);
|
||||
final estado = crearEstadoRadio();
|
||||
@@ -112,9 +123,18 @@ void main() {
|
||||
await tester.pumpWidget(testApp(estado, const PantallaInicio()));
|
||||
await pumpStable(tester);
|
||||
|
||||
expect(find.byType(PluriRootHeader), findsOneWidget);
|
||||
expect(titleInHeader('Listen'), findsOneWidget);
|
||||
expect(find.byType(AppBar), findsNothing);
|
||||
expect(
|
||||
find.byType(PluriRootHeader),
|
||||
findsNothing,
|
||||
reason: 'Escuchar uses its own eyebrow header, not the shared one',
|
||||
);
|
||||
expect(find.text('Now listening'), findsOneWidget);
|
||||
expect(
|
||||
find.byIcon(Icons.bedtime_outlined),
|
||||
findsOneWidget,
|
||||
reason: 'the sleep-timer action survived the global AppBar removal',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -65,6 +65,20 @@ void main() {
|
||||
expect(type.eyebrowLabel.letterSpacing, 0.8);
|
||||
});
|
||||
|
||||
test(
|
||||
'S7 (visual fidelity): inPageSectionHeading is 15 / w800 / '
|
||||
'letter-spacing -0.2 -- the ADR-1 amendment adding a seventh style',
|
||||
() {
|
||||
expect(
|
||||
type.inPageSectionHeading.fontSize,
|
||||
15,
|
||||
reason: 'prototype t4 lines 80, 153, 164, 173',
|
||||
);
|
||||
expect(type.inPageSectionHeading.fontWeight, FontWeight.w800);
|
||||
expect(type.inPageSectionHeading.letterSpacing, -0.2);
|
||||
},
|
||||
);
|
||||
|
||||
test('S9 (Tier 1 visual fidelity): eyebrowLabel bakes in the prototype '
|
||||
"colour rgba(242,247,250,.42) — it used to carry no colour at all, "
|
||||
'so it rendered at full onSurface opacity', () {
|
||||
|
||||
Reference in New Issue
Block a user