feat(ui,learn): the navigation bar in the colour of the screen in view
The developer's review of 8 Nov 2026: the bar follows the screen in view
rather than one colour per app, so a Todo project of its own colour gives
the bar that colour while it shows. The wave, the chosen destination's
icon and label and its indicator take ScreenTint.color, the colour the
screen in view claims through its TopGradient; the frame's accent, the
app's colour, stays only for the moment before any screen claims one,
since ScreenTint itself starts at cobalt, which would be wrong for Todo,
Train and Meditate. Learn's tabs claim cobalt, their wash, so its bar is
cobalt there now, not purple.
A colour changing on the same tab (a project opening) passes into the
next over 300 ms, at once with animations off. A wave paints in that
colour as it goes: it starts in the colour of the screen being left, as
the arriving one claims its own only once it shows, a frame later, and
passes into it with the rest of the bar.
A person's colours may be light, so the chosen destination's colour is
made legible (readableTone, halkyon_ui): a palette colour starts from its
own text tone as Todo's dates take it (its outline in light mode, its
fill in dark), any other colour from itself, then darkens towards black
in light mode and lightens towards white in dark, only until it reads at
4.5:1 on the bar and on its indicator. Every palette colour is tested in
both themes, on the neutral and the tinted surface. This also lifts
Learn's label, which read at about 3:1.
The debug section gains Bar surface, neutral or tinted: tinted mixes 6 %
of the screen's colour into the bar's own surface in light mode and 8 %
in dark, changing with it. Neutral by default, and in the shipping style.
Whats-New: The navigation bar takes the colour of the screen you're on, such as a project's own.
Whats-New-De: Die Navigationsleiste nimmt die Farbe des Bildschirms an, auf dem du bist, etwa die eines Projekts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 01:12:08 +01:00
|
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
|
|
import 'package:halkyon_ui/halkyon_ui.dart';
|
|
|
|
|
|
import 'package:material_ui/material_ui.dart';
|
|
|
|
|
|
|
|
|
|
|
|
import '../support/test_app.dart';
|
|
|
|
|
|
|
|
|
|
|
|
/// The navigation bar takes the colour of the screen in view (the
|
|
|
|
|
|
/// developer's review, 8 Nov 2026): a project of its own colour colours the
|
|
|
|
|
|
/// bar while it shows, the app's colour before any screen claims one, every
|
|
|
|
|
|
/// tone legible on the bar in both themes.
|
|
|
|
|
|
void main() {
|
|
|
|
|
|
/// A 1 × 1 PNG, the app's icon in these tests.
|
|
|
|
|
|
final icon = MemoryImage(
|
|
|
|
|
|
Uint8List.fromList(const [
|
|
|
|
|
|
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, //
|
|
|
|
|
|
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
|
|
|
|
|
|
0x08, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x15, 0xC4, 0x89, 0x00, 0x00, 0x00,
|
|
|
|
|
|
0x0B, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9C, 0x63, 0x60, 0x00, 0x02, 0x00,
|
|
|
|
|
|
0x00, 0x05, 0x00, 0x01, 0x7A, 0x5E, 0xAB, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
|
0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82,
|
|
|
|
|
|
]),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
final accent = PaletteColor.strawberry.background;
|
|
|
|
|
|
|
|
|
|
|
|
/// The frame around [child] on a phone, in [brightness].
|
|
|
|
|
|
Future<void> show(
|
|
|
|
|
|
WidgetTester tester,
|
|
|
|
|
|
Widget child, {
|
|
|
|
|
|
Brightness brightness = Brightness.light,
|
|
|
|
|
|
bool disableAnimations = false,
|
|
|
|
|
|
}) async {
|
|
|
|
|
|
tester.view.physicalSize = const Size(400, 800);
|
|
|
|
|
|
tester.view.devicePixelRatio = 1;
|
|
|
|
|
|
addTearDown(tester.view.reset);
|
|
|
|
|
|
await tester.pumpWidget(
|
|
|
|
|
|
testApp(
|
|
|
|
|
|
brightness: brightness,
|
|
|
|
|
|
Builder(
|
|
|
|
|
|
builder: (context) => MediaQuery(
|
|
|
|
|
|
data: MediaQuery.of(
|
|
|
|
|
|
context,
|
|
|
|
|
|
).copyWith(disableAnimations: disableAnimations),
|
|
|
|
|
|
child: NavigationFrame(
|
|
|
|
|
|
appName: 'Halkyon Test',
|
|
|
|
|
|
icon: icon,
|
|
|
|
|
|
accent: accent,
|
|
|
|
|
|
selectedIndex: 0,
|
|
|
|
|
|
onSelected: (_) {},
|
|
|
|
|
|
destinations: const [
|
|
|
|
|
|
(label: 'Home', icon: Icon(Icons.home), selectedIcon: null),
|
|
|
|
|
|
(label: 'Maps', icon: Icon(Icons.map), selectedIcon: null),
|
|
|
|
|
|
],
|
|
|
|
|
|
child: child,
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// A screen claiming [color] while it shows.
|
|
|
|
|
|
Widget screen(Color color) => TopGradient(
|
|
|
|
|
|
color: color,
|
|
|
|
|
|
background: Colors.white,
|
|
|
|
|
|
child: const SizedBox.expand(),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
Color? chosenIcon(WidgetTester tester) =>
|
|
|
|
|
|
IconTheme.of(tester.element(find.byIcon(Icons.home))).color;
|
|
|
|
|
|
Color? indicator(WidgetTester tester) =>
|
|
|
|
|
|
tester.widget<NavigationBar>(find.byType(NavigationBar)).indicatorColor;
|
|
|
|
|
|
Color barSurface(WidgetTester tester) => tester
|
|
|
|
|
|
.widget<ColoredBox>(
|
|
|
|
|
|
find
|
|
|
|
|
|
.descendant(
|
|
|
|
|
|
of: find.byKey(FlushNavigationBar.barKey),
|
|
|
|
|
|
matching: find.byType(ColoredBox),
|
|
|
|
|
|
)
|
|
|
|
|
|
.first,
|
|
|
|
|
|
)
|
|
|
|
|
|
.color;
|
|
|
|
|
|
Color legible(WidgetTester tester, Color color) {
|
|
|
|
|
|
final theme = Theme.of(tester.element(find.byType(NavigationBar)));
|
|
|
|
|
|
final surface = barSurface(tester);
|
|
|
|
|
|
return readableTone(
|
|
|
|
|
|
color,
|
|
|
|
|
|
brightness: theme.brightness,
|
|
|
|
|
|
on: [surface, Color.alphaBlend(color.withValues(alpha: 0.22), surface)],
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
testWidgets("before a screen claims a colour, the bar takes the app's", (
|
|
|
|
|
|
tester,
|
|
|
|
|
|
) async {
|
|
|
|
|
|
await show(tester, const SizedBox.expand());
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
|
|
expect(indicator(tester), accent.withValues(alpha: 0.22));
|
|
|
|
|
|
expect(chosenIcon(tester), legible(tester, accent));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
testWidgets('the bar takes the colour the screen in view claims, and '
|
|
|
|
|
|
'changes with it over 300 ms', (tester) async {
|
|
|
|
|
|
final project = PaletteColor.ocean.background;
|
|
|
|
|
|
await show(tester, screen(project));
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
expect(indicator(tester), project.withValues(alpha: 0.22));
|
|
|
|
|
|
expect(chosenIcon(tester), legible(tester, project));
|
|
|
|
|
|
|
|
|
|
|
|
// Another project opens on the same tab.
|
|
|
|
|
|
final other = PaletteColor.olive.background;
|
|
|
|
|
|
await show(tester, screen(other));
|
|
|
|
|
|
await tester.pump();
|
|
|
|
|
|
await tester.pump(const Duration(milliseconds: 150));
|
|
|
|
|
|
expect(
|
|
|
|
|
|
indicator(tester),
|
|
|
|
|
|
isNot(
|
|
|
|
|
|
anyOf(project.withValues(alpha: 0.22), other.withValues(alpha: 0.22)),
|
|
|
|
|
|
),
|
|
|
|
|
|
reason: 'half way',
|
|
|
|
|
|
);
|
|
|
|
|
|
await tester.pump(const Duration(milliseconds: 200));
|
|
|
|
|
|
expect(indicator(tester), other.withValues(alpha: 0.22));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
testWidgets('with animations off, the colour changes at once', (
|
|
|
|
|
|
tester,
|
|
|
|
|
|
) async {
|
|
|
|
|
|
await show(tester, screen(PaletteColor.ocean.background));
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
final other = PaletteColor.olive.background;
|
|
|
|
|
|
await show(tester, screen(other), disableAnimations: true);
|
|
|
|
|
|
await tester.pump();
|
|
|
|
|
|
await tester.pump();
|
|
|
|
|
|
expect(indicator(tester), other.withValues(alpha: 0.22));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
group('every palette colour is legible on the bar', () {
|
|
|
|
|
|
final byLuminance = [...PaletteColor.values]
|
|
|
|
|
|
..sort(
|
|
|
|
|
|
(a, b) => a.background.computeLuminance().compareTo(
|
|
|
|
|
|
b.background.computeLuminance(),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
final lightest = byLuminance.last;
|
|
|
|
|
|
final darkest = byLuminance.first;
|
|
|
|
|
|
|
|
|
|
|
|
for (final brightness in Brightness.values) {
|
refactor(ui,learn,todo,train,meditate): the navigation bar's one look, the debug section gone
The developer decided on 8 Nov 2026, after trying the variants on the
phone: the wave in the colour of the screen in view, without Material's
ripple, the indicator kept and there at once, a 1.2 s wave, top corners
of 20 dp, the bar's own neutral surface. Learn's bar stays cobalt, the
colour its tabs wash in, rather than its icon's purple.
So the bar has one look: FlushNavigationBar.waveDuration and
cornerRadius are constants, and the debug section goes from the four
Settings screens with what it switched (NavigationBarDebugSection,
debugNavigationBarStyle, effectiveNavigationBarStyle, the style record
and the variants A, C and F, the speeds, the corners and the tinted
surface). Their tests go too; those stating the look kept stay. Learn's
sign-out helper no longer has to scroll past the section.
ADR 0030's amendment of D60, the halkyon_ui README and Learn's
AGENTS.md record the decision and the alternatives set aside.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 11:40:35 +01:00
|
|
|
|
testWidgets('in the $brightness theme: the lightest '
|
|
|
|
|
|
'(${lightest.name}), the darkest (${darkest.name}) and every other', (
|
|
|
|
|
|
tester,
|
|
|
|
|
|
) async {
|
|
|
|
|
|
for (final color in [lightest, darkest, ...PaletteColor.values]) {
|
|
|
|
|
|
await show(tester, screen(color.background), brightness: brightness);
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
final tone = chosenIcon(tester)!;
|
|
|
|
|
|
final surface = barSurface(tester);
|
|
|
|
|
|
final onIndicator = Color.alphaBlend(
|
|
|
|
|
|
color.background.withValues(alpha: 0.22),
|
|
|
|
|
|
surface,
|
|
|
|
|
|
);
|
|
|
|
|
|
expect(
|
|
|
|
|
|
TopGradient.contrast(tone, surface),
|
|
|
|
|
|
greaterThanOrEqualTo(4.5),
|
|
|
|
|
|
reason: '${color.name} on the bar',
|
|
|
|
|
|
);
|
|
|
|
|
|
expect(
|
|
|
|
|
|
TopGradient.contrast(tone, onIndicator),
|
|
|
|
|
|
greaterThanOrEqualTo(4.5),
|
|
|
|
|
|
reason: '${color.name} on its indicator',
|
|
|
|
|
|
);
|
|
|
|
|
|
final label = find.text('Home');
|
|
|
|
|
|
expect(
|
|
|
|
|
|
tester.widget<Text>(label).style?.color ??
|
|
|
|
|
|
DefaultTextStyle.of(tester.element(label)).style.color,
|
|
|
|
|
|
tone,
|
|
|
|
|
|
reason: '${color.name}: the label as the icon',
|
feat(ui,learn): the navigation bar in the colour of the screen in view
The developer's review of 8 Nov 2026: the bar follows the screen in view
rather than one colour per app, so a Todo project of its own colour gives
the bar that colour while it shows. The wave, the chosen destination's
icon and label and its indicator take ScreenTint.color, the colour the
screen in view claims through its TopGradient; the frame's accent, the
app's colour, stays only for the moment before any screen claims one,
since ScreenTint itself starts at cobalt, which would be wrong for Todo,
Train and Meditate. Learn's tabs claim cobalt, their wash, so its bar is
cobalt there now, not purple.
A colour changing on the same tab (a project opening) passes into the
next over 300 ms, at once with animations off. A wave paints in that
colour as it goes: it starts in the colour of the screen being left, as
the arriving one claims its own only once it shows, a frame later, and
passes into it with the rest of the bar.
A person's colours may be light, so the chosen destination's colour is
made legible (readableTone, halkyon_ui): a palette colour starts from its
own text tone as Todo's dates take it (its outline in light mode, its
fill in dark), any other colour from itself, then darkens towards black
in light mode and lightens towards white in dark, only until it reads at
4.5:1 on the bar and on its indicator. Every palette colour is tested in
both themes, on the neutral and the tinted surface. This also lifts
Learn's label, which read at about 3:1.
The debug section gains Bar surface, neutral or tinted: tinted mixes 6 %
of the screen's colour into the bar's own surface in light mode and 8 %
in dark, changing with it. Neutral by default, and in the shipping style.
Whats-New: The navigation bar takes the colour of the screen you're on, such as a project's own.
Whats-New-De: Die Navigationsleiste nimmt die Farbe des Bildschirms an, auf dem du bist, etwa die eines Projekts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 01:12:08 +01:00
|
|
|
|
);
|
refactor(ui,learn,todo,train,meditate): the navigation bar's one look, the debug section gone
The developer decided on 8 Nov 2026, after trying the variants on the
phone: the wave in the colour of the screen in view, without Material's
ripple, the indicator kept and there at once, a 1.2 s wave, top corners
of 20 dp, the bar's own neutral surface. Learn's bar stays cobalt, the
colour its tabs wash in, rather than its icon's purple.
So the bar has one look: FlushNavigationBar.waveDuration and
cornerRadius are constants, and the debug section goes from the four
Settings screens with what it switched (NavigationBarDebugSection,
debugNavigationBarStyle, effectiveNavigationBarStyle, the style record
and the variants A, C and F, the speeds, the corners and the tinted
surface). Their tests go too; those stating the look kept stay. Learn's
sign-out helper no longer has to scroll past the section.
ADR 0030's amendment of D60, the halkyon_ui README and Learn's
AGENTS.md record the decision and the alternatives set aside.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 11:40:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
});
|
feat(ui,learn): the navigation bar in the colour of the screen in view
The developer's review of 8 Nov 2026: the bar follows the screen in view
rather than one colour per app, so a Todo project of its own colour gives
the bar that colour while it shows. The wave, the chosen destination's
icon and label and its indicator take ScreenTint.color, the colour the
screen in view claims through its TopGradient; the frame's accent, the
app's colour, stays only for the moment before any screen claims one,
since ScreenTint itself starts at cobalt, which would be wrong for Todo,
Train and Meditate. Learn's tabs claim cobalt, their wash, so its bar is
cobalt there now, not purple.
A colour changing on the same tab (a project opening) passes into the
next over 300 ms, at once with animations off. A wave paints in that
colour as it goes: it starts in the colour of the screen being left, as
the arriving one claims its own only once it shows, a frame later, and
passes into it with the rest of the bar.
A person's colours may be light, so the chosen destination's colour is
made legible (readableTone, halkyon_ui): a palette colour starts from its
own text tone as Todo's dates take it (its outline in light mode, its
fill in dark), any other colour from itself, then darkens towards black
in light mode and lightens towards white in dark, only until it reads at
4.5:1 on the bar and on its indicator. Every palette colour is tested in
both themes, on the neutral and the tinted surface. This also lifts
Learn's label, which read at about 3:1.
The debug section gains Bar surface, neutral or tinted: tinted mixes 6 %
of the screen's colour into the bar's own surface in light mode and 8 %
in dark, changing with it. Neutral by default, and in the shipping style.
Whats-New: The navigation bar takes the colour of the screen you're on, such as a project's own.
Whats-New-De: Die Navigationsleiste nimmt die Farbe des Bildschirms an, auf dem du bist, etwa die eines Projekts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 01:12:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
testWidgets("a colour legible already keeps the palette's own text tone: "
|
|
|
|
|
|
'its outline in light mode, its fill in dark', (tester) async {
|
|
|
|
|
|
const light = Color(0xFFF3F3F3);
|
|
|
|
|
|
const dark = Color(0xFF1A1B24);
|
|
|
|
|
|
expect(
|
|
|
|
|
|
readableTone(
|
|
|
|
|
|
PaletteColor.cobalt.background,
|
|
|
|
|
|
brightness: Brightness.light,
|
|
|
|
|
|
on: [light],
|
|
|
|
|
|
),
|
|
|
|
|
|
PaletteColor.cobalt.outline,
|
|
|
|
|
|
);
|
|
|
|
|
|
expect(
|
|
|
|
|
|
readableTone(
|
|
|
|
|
|
PaletteColor.purple.background,
|
|
|
|
|
|
brightness: Brightness.dark,
|
|
|
|
|
|
on: [dark],
|
|
|
|
|
|
),
|
|
|
|
|
|
PaletteColor.purple.background,
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
refactor(ui,learn,todo,train,meditate): the navigation bar's one look, the debug section gone
The developer decided on 8 Nov 2026, after trying the variants on the
phone: the wave in the colour of the screen in view, without Material's
ripple, the indicator kept and there at once, a 1.2 s wave, top corners
of 20 dp, the bar's own neutral surface. Learn's bar stays cobalt, the
colour its tabs wash in, rather than its icon's purple.
So the bar has one look: FlushNavigationBar.waveDuration and
cornerRadius are constants, and the debug section goes from the four
Settings screens with what it switched (NavigationBarDebugSection,
debugNavigationBarStyle, effectiveNavigationBarStyle, the style record
and the variants A, C and F, the speeds, the corners and the tinted
surface). Their tests go too; those stating the look kept stay. Learn's
sign-out helper no longer has to scroll past the section.
ADR 0030's amendment of D60, the halkyon_ui README and Learn's
AGENTS.md record the decision and the alternatives set aside.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 11:40:35 +01:00
|
|
|
|
testWidgets("the bar's surface is the theme's own, whatever the screen's "
|
|
|
|
|
|
'colour, light and dark', (tester) async {
|
feat(ui,learn): the navigation bar in the colour of the screen in view
The developer's review of 8 Nov 2026: the bar follows the screen in view
rather than one colour per app, so a Todo project of its own colour gives
the bar that colour while it shows. The wave, the chosen destination's
icon and label and its indicator take ScreenTint.color, the colour the
screen in view claims through its TopGradient; the frame's accent, the
app's colour, stays only for the moment before any screen claims one,
since ScreenTint itself starts at cobalt, which would be wrong for Todo,
Train and Meditate. Learn's tabs claim cobalt, their wash, so its bar is
cobalt there now, not purple.
A colour changing on the same tab (a project opening) passes into the
next over 300 ms, at once with animations off. A wave paints in that
colour as it goes: it starts in the colour of the screen being left, as
the arriving one claims its own only once it shows, a frame later, and
passes into it with the rest of the bar.
A person's colours may be light, so the chosen destination's colour is
made legible (readableTone, halkyon_ui): a palette colour starts from its
own text tone as Todo's dates take it (its outline in light mode, its
fill in dark), any other colour from itself, then darkens towards black
in light mode and lightens towards white in dark, only until it reads at
4.5:1 on the bar and on its indicator. Every palette colour is tested in
both themes, on the neutral and the tinted surface. This also lifts
Learn's label, which read at about 3:1.
The debug section gains Bar surface, neutral or tinted: tinted mixes 6 %
of the screen's colour into the bar's own surface in light mode and 8 %
in dark, changing with it. Neutral by default, and in the shipping style.
Whats-New: The navigation bar takes the colour of the screen you're on, such as a project's own.
Whats-New-De: Die Navigationsleiste nimmt die Farbe des Bildschirms an, auf dem du bist, etwa die eines Projekts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 01:12:08 +01:00
|
|
|
|
final project = PaletteColor.ocean.background;
|
|
|
|
|
|
for (final brightness in Brightness.values) {
|
|
|
|
|
|
await show(tester, screen(project), brightness: brightness);
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
expect(
|
|
|
|
|
|
barSurface(tester),
|
refactor(ui,learn,todo,train,meditate): the navigation bar's one look, the debug section gone
The developer decided on 8 Nov 2026, after trying the variants on the
phone: the wave in the colour of the screen in view, without Material's
ripple, the indicator kept and there at once, a 1.2 s wave, top corners
of 20 dp, the bar's own neutral surface. Learn's bar stays cobalt, the
colour its tabs wash in, rather than its icon's purple.
So the bar has one look: FlushNavigationBar.waveDuration and
cornerRadius are constants, and the debug section goes from the four
Settings screens with what it switched (NavigationBarDebugSection,
debugNavigationBarStyle, effectiveNavigationBarStyle, the style record
and the variants A, C and F, the speeds, the corners and the tinted
surface). Their tests go too; those stating the look kept stay. Learn's
sign-out helper no longer has to scroll past the section.
ADR 0030's amendment of D60, the halkyon_ui README and Learn's
AGENTS.md record the decision and the alternatives set aside.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 11:40:35 +01:00
|
|
|
|
Theme.of(
|
|
|
|
|
|
tester.element(find.byType(NavigationBar)),
|
|
|
|
|
|
).colorScheme.surfaceContainer,
|
feat(ui,learn): the navigation bar in the colour of the screen in view
The developer's review of 8 Nov 2026: the bar follows the screen in view
rather than one colour per app, so a Todo project of its own colour gives
the bar that colour while it shows. The wave, the chosen destination's
icon and label and its indicator take ScreenTint.color, the colour the
screen in view claims through its TopGradient; the frame's accent, the
app's colour, stays only for the moment before any screen claims one,
since ScreenTint itself starts at cobalt, which would be wrong for Todo,
Train and Meditate. Learn's tabs claim cobalt, their wash, so its bar is
cobalt there now, not purple.
A colour changing on the same tab (a project opening) passes into the
next over 300 ms, at once with animations off. A wave paints in that
colour as it goes: it starts in the colour of the screen being left, as
the arriving one claims its own only once it shows, a frame later, and
passes into it with the rest of the bar.
A person's colours may be light, so the chosen destination's colour is
made legible (readableTone, halkyon_ui): a palette colour starts from its
own text tone as Todo's dates take it (its outline in light mode, its
fill in dark), any other colour from itself, then darkens towards black
in light mode and lightens towards white in dark, only until it reads at
4.5:1 on the bar and on its indicator. Every palette colour is tested in
both themes, on the neutral and the tinted surface. This also lifts
Learn's label, which read at about 3:1.
The debug section gains Bar surface, neutral or tinted: tinted mixes 6 %
of the screen's colour into the bar's own surface in light mode and 8 %
in dark, changing with it. Neutral by default, and in the shipping style.
Whats-New: The navigation bar takes the colour of the screen you're on, such as a project's own.
Whats-New-De: Die Navigationsleiste nimmt die Farbe des Bildschirms an, auf dem du bist, etwa die eines Projekts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 01:12:08 +01:00
|
|
|
|
reason: '$brightness',
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|