Files
buzz/mobile/lib/shared/widgets/mobile_tab_footer_backdrop.dart
klopez4212 4555899ab2 Polish mobile navigation and menus (#3486)
## Summary
- Add a shared footer fade behind the floating tabs on Home, Activity,
and Search.
- Use a shared anchored popover for Activity filters and section
actions, with working section move controls.
- Polish message grouping/press states and remove the initial Search
back button.
<img width="630" height="1368" alt="Screenshot 2026-07-29 at 08 49 37"
src="https://github.com/user-attachments/assets/9e787adf-0bb3-49c6-8224-5819e8cfb1ad"
/>

### Testing
- `flutter analyze`
- `flutter test`
- Release build installed and checked on a connected iPhone

### Screenshots
A real-device Activity baseline showing the original solid footer is
attached in a PR comment. The updated review build was checked on the
connected iPhone.

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
2026-07-29 16:10:51 +01:00

62 lines
1.8 KiB
Dart

import 'package:flutter/material.dart';
import '../theme/theme.dart';
/// Height of the floating mobile tab bar, excluding its bottom clearance.
const mobileTabBarHeight = 56.0;
/// Gap between the floating mobile tab bar and the bottom safe area.
const mobileTabBarBottomGap = Grid.twelve;
/// Returns the shared footer backdrop height, including the logical safe area.
double mobileTabFooterBackdropHeight(BuildContext context) =>
mobileTabBarHeight +
mobileTabBarBottomGap +
MediaQuery.paddingOf(context).bottom +
Grid.xl +
Grid.gutter;
/// Shared fade behind the floating mobile tab bar.
class MobileTabFooterBackdrop extends StatelessWidget {
/// Vertical extent of the backdrop in logical pixels.
final double height;
/// Gradient stop positions, from the transparent top to the opaque bottom.
final List<double> stops;
/// Surface-color alpha values paired with [stops].
final List<double> opacities;
/// Creates a footer backdrop with the required [height].
///
/// Override [stops] and [opacities] together to customize the gradient.
const MobileTabFooterBackdrop({
super.key,
required this.height,
this.stops = const [0, 0.5, 1],
this.opacities = const [0, 0.75, 1],
}) : assert(stops.length == opacities.length);
@override
Widget build(BuildContext context) {
final surface = context.colors.surface;
return SizedBox(
height: height,
width: double.infinity,
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: stops,
colors: [
for (final opacity in opacities)
surface.withValues(alpha: opacity),
],
),
),
),
);
}
}