feat(nav): discoverable sidebar — instant tooltips, shortcuts made visible, pinnable rail
Some checks are pending
Security / Security check (push) Waiting to run

The icon-only rail forced first-time users to guess (usertest:
Senior, a11y, UX personas). Three changes:
- Nav tooltips appear instantly and carry the page shortcut
  (Cmd+1..9, Ctrl on non-mac — Ctrl activators added); expanded
  labels show the same hint. Explicit button semantics for
  screen readers on every destination.
- A visible 'Search & commands' row above the footer opens the
  existing Cmd+K palette, which nothing in the UI advertised.
- Settings -> Appearance gains 'Keep the navigation expanded':
  pins the rail with permanent labels (persisted preference).
Footer strip and pillar toggle made overflow-safe for the
animating rail; responsive test scrolls the by-design scrollable
destinations list.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-07-17 23:36:33 +02:00
parent ca01fd2ec0
commit c436e12601
11 changed files with 364 additions and 30 deletions

View file

@ -48,7 +48,13 @@ void main() {
await tester.pump(const Duration(milliseconds: 100));
for (final id in _destinations) {
await tester.tap(find.byKey(ValueKey('sidebar-item-$id')));
// The destinations list scrolls by design: at 600-px-high
// windows the rail (destinations + search row + footer)
// exceeds the viewport, so bring the item into view first.
final item = find.byKey(ValueKey('sidebar-item-$id'));
await tester.scrollUntilVisible(item, 40,
scrollable: find.byType(Scrollable).first);
await tester.tap(item);
await tester.pump(const Duration(milliseconds: 400));
expect(
tester.takeException(),

View file

@ -41,6 +41,12 @@ void main() {
testWidgets(
'sidebar destination Y positions are stable across rail expansion',
(tester) async {
// Desktop-sized surface: the rail carries 8 destinations plus
// the search row and footer the 600-px default viewport
// scrolls the last destination out of the ListView.
tester.view.physicalSize = const Size(1280, 900);
tester.view.devicePixelRatio = 1.0;
addTearDown(tester.view.reset);
// Collapsed (default).
await tester.pumpWidget(
const StudioApp(