halkyon/packages/halkyon_ui/README.md
Tizian 「ティツィアーン」 45fd6595e1
feat(ui,learn,todo,train,meditate): a wave in the app's colour over the navigation bar
The developer's choice of 7 Nov 2026 (the mockup's variant E): a tap on
another destination sends a radial glow in the app's colour over the bar
from that destination's centre, solid to 35 % of its radius and gone at
70 %, growing to cover the bar (cubic(.2, .7, .2, 1)) while it fades from
half its strength in dark mode and a third in light, over 1.2 s, behind
the destinations and clipped to the bar. None for the destination already
chosen, none with animations off, and none for a tab changed without a
tap (a link, back): the wave answers the finger. The destination chosen
takes the app's colour, its indicator tinted 22 % with it, without
Material's ripple or the indicator growing; the bar's top corners are
rounded, 20 dp, the screen showing through them.

Each app gives the frame its colour (NavigationFrame's accent, from
PaletteColor): Learn's purple, its icon's last colour, Todo's strawberry,
Train's carrot and Meditate's fern, their screens' wash.

For trying it on a phone, a debug build's Settings has a section
Navigation bar (debug), halkyon_ui's NavigationBarDebugSection, switching
live, in memory alone: the variant (A Material only, C the wave with
Material's fill, E without it, F without the indicator too), the wave's
time (0.7 to 2 s) and the corners (0 to 28 dp). Release builds never read
it and show shippingNavigationBarStyle, the debug section's start: to
remove it, delete the section from the four Settings screens and
debugNavigationBarStyle, and let effectiveNavigationBarStyle return the
shipping style.

Whats-New: Tapping a tab sends a soft wave in the app's colour across the navigation bar, now with rounded corners.
Whats-New-De: Ein Tipp auf einen Tab schickt eine sanfte Welle in der Farbe der App über die Navigationsleiste, jetzt mit abgerundeten Ecken.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-08 11:48:37 +01:00

97 lines
4.4 KiB
Markdown

# halkyon_ui
Halkyon's look, shared by its apps (Learn, Todo, Train): one theme around the
kingfisher's cobalt and copper, the bundled Noto Sans, Material 3's window
sizes, and the widgets every app's screens are built of, with their texts in
British English, American English and German.
Written as the apps are: Dart 3.13's primary constructors, Material from
`package:material_ui` (never `package:flutter/material.dart`), Lucide icons,
LeanCode's lints.
## What it holds
- **Theme** (`lib/src/theme/`): `appTheme(brightness, extensions: …)`, Material
3 with hand-written light and dark schemes (primary cobalt, tertiary copper,
cobalt-tinted neutrals), Material 3 Expressive's 64 dp navigation bar, flat
app bars, floating snack bars; `Brand`; `ThemeExtras`, the status colours
Material has no role for (`Theme.of(context).extras`); `PaletteColor`, the
20 colours a person can give content, each with a text colour held to WCAG
AA by a test; `FittedSnackBars`.
- **Fonts**: Noto Sans for Latin, Greek and Cyrillic, every weight in one
variable file, as `appFontFamily` (`packages/halkyon_ui/Noto Sans`). Chinese,
Japanese and Korean fall back to `Noto Sans JP`, `SC`, `TC` and `KR`, which
an app bundles itself if it needs them (`appFontFallbackFor` puts a
language's own first).
- **Layout** (`lib/src/layout/`): `WindowSize` (`context.windowSize`) and
`readableContentMaxWidth`.
- **Widgets** (`lib/src/widget/`): `showAdaptiveSheet` with `SheetScaffold`;
`TopGradient`, `ScreenTint`, `ScreenColor`, `TintFrame`, `FramedScreen`
and `TabVisibility`; `FlushNavigationBar`, and `NavigationFrame`, every
app's frame around its tabs (the rail with the app's icon, the bar flush
with the foot with a fade above it, its rounded top corners and the
wave in the app's colour a tap sends over it, `shippingNavigationBarStyle`,
switched live in a debug build's `NavigationBarDebugSection`, a tick on every choice, a status such as a recording under way above
the bar), whichever router drives it;
`AppLoadingIndicator`, `ButtonLoadingIndicator`, `AppRefreshIndicator`;
`SectionCard`, `SliverCentered`, `EmptyListMessage`, `CountBadge`,
`TitleWithKicker`, `CollapsingRow`, `ScrollHidingFab`, `Shimmer` and `SkeletonBox`, `liftWhileDragged`,
`ReorderToggle`, `ReorderGrip`; `ChevronField`, `requiredDecoration`,
`FieldInfoButton`, `CountStepper`, `PaletteColorPicker`, `TextLimits` with
`nearLimitCounter`; `confirmDestructiveAction`, `showUndoSnackBar`,
`showMoreInfoSheet`; `FoundById`; `KeyboardBackOnResume`; `BrandWordmark`
and `LaunchScreen`, which take the app's word and icon.
What belongs to one app stays in it: its own colours (an extension passed to
`appTheme`), routes, repositories, editors and texts.
## Using it in an app
Depend on it by path, within the repository's workspace (an app's packages sit in
`apps/<app>/`), so a change to the package and to the apps using it is one commit:
```yaml
dependencies:
halkyon_ui:
path: ../../../packages/halkyon_ui
```
Then set the app up as `example/lib/main.dart` does:
```dart
MaterialApp(
theme: appTheme(Brightness.light, extensions: [MyColors.light]),
darkTheme: appTheme(Brightness.dark, extensions: [MyColors.dark]),
localizationsDelegates: const [
AppLocalizations.delegate,
HalkyonUiLocalizations.delegate,
// material_ui's: flutter_localizations' serve only the SDK's Material.
...GlobalMaterialLocalizations.delegates,
],
supportedLocales: AppLocalizations.supportedLocales,
builder: (context, child) => FittedSnackBars(child: child!),
…
);
```
and call `registerFontLicenses()` at start. An app bundling the CJK fonts
declares them in its own `pubspec.yaml` under exactly the names
`appFontFallback` lists (no `packages/` prefix) and registers their licence
itself.
## Texts
`lib/l10n/halkyon_ui_en.arb` is the template (British English, also the
fallback); `halkyon_ui_de.arb` German, informal "du"; `halkyon_ui_en_US.arb`
only what American English spells differently; `halkyon_ui_en_GB.arb` empty. A
new text goes into the template and German together (`test/l10n/` fails
otherwise). `flutter pub get` writes `lib/l10n/halkyon_ui_localizations*.dart`,
which are committed and never edited or
formatted by hand.
## Checks
From the workspace root: `dart analyze --fatal-infos`; then `flutter test` in
`packages/halkyon_ui` and in `packages/halkyon_ui/example`, whose tests check
what only an app sees (the font under the name an app finds it by, its
licence).