From 52abd16983f1e639c52f130f8a38dc0d951c9b54 Mon Sep 17 00:00:00 2001 From: Ayushya Amitabh Date: Mon, 5 Oct 2026 21:36:35 -0400 Subject: [PATCH] Floating bottom bar: use Android row (icon-only idle tabs) on iOS too Co-Authored-By: Claude Sonnet 5.5 --- .claude/context/styling.md | 4 +++- lib/widgets/noo/nav/noo_bottom_bar.dart | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.claude/context/styling.md b/.claude/context/styling.md index 743c4ad..4ec3b36 100644 --- a/.claude/context/styling.md +++ b/.claude/context/styling.md @@ -231,7 +231,9 @@ blocks are noted where they matter: don't confuse the two: this one is still non-blurred, just inset with a `line` border and `nooDialogShadow` (the app's one other shadow user - see that constant's doc comment) instead of edge to edge (no opacity/blur knob - either). The host `Scaffold` needs `extendBody: true` while it's active + either). `floating` ignores `NooNavStyle` and always uses the Android row + (icon-only idle tabs, sliding pill, 64px), so iOS matches Android there; + only the attached bar still has a distinct iOS row. The host `Scaffold` needs `extendBody: true` while it's active (`main.dart` already wires this off `SettingsController.bottomBarStyle`), which also means every tab's own scrollable list has to reserve enough bottom padding to clear the bar - nothing does that automatically once the diff --git a/lib/widgets/noo/nav/noo_bottom_bar.dart b/lib/widgets/noo/nav/noo_bottom_bar.dart index 61fbbd7..d4784aa 100644 --- a/lib/widgets/noo/nav/noo_bottom_bar.dart +++ b/lib/widgets/noo/nav/noo_bottom_bar.dart @@ -26,6 +26,9 @@ const double _kAndroidPillHeight = 32; /// 56x32 accent-soft pill that slides between tabs as selection moves, /// rather than popping in/out on the destination item itself. /// +/// [NooBottomBarStyle.floating] ignores [style] and always uses the Android +/// row below, so iOS gets the same icon-only idle tabs. +/// /// [barStyle] (user-configurable in Settings, Appearance) picks between /// that edge-to-edge [NooBottomBarStyle.attached] bar and /// [NooBottomBarStyle.floating] - inset 16px from both side edges, 28px @@ -75,7 +78,9 @@ class NooBottomBar extends StatelessWidget { /// scrollable body sharing the same `Scaffold` can reserve exactly this /// much clearance (see the class doc comment) instead of guessing. static double rowHeight(NooNavStyle style, NooBottomBarStyle barStyle) { - if (style == NooNavStyle.ios) return 50; + if (style == NooNavStyle.ios && barStyle != NooBottomBarStyle.floating) { + return 50; + } return barStyle == NooBottomBarStyle.floating ? 64 : 80; } @@ -86,8 +91,10 @@ class NooBottomBar extends StatelessWidget { @override Widget build(BuildContext context) { final colors = context.nooColors; - final ios = style == NooNavStyle.ios; final floating = barStyle == NooBottomBarStyle.floating; + // Floating always gets the Android row (icon-only idle tabs, sliding + // pill) - iOS's icon-over-label row doesn't fit a pill that short. + final ios = style == NooNavStyle.ios && !floating; final hasSearch = searchDestination != null && onSearchTap != null; // Attached folds Search into the row itself (last item); floating // gives it a separate satellite circle instead (built below), so the