Files
buzz/mobile/lib/shared/widgets/mobile_tab_footer_backdrop.dart
ff0b7982f1 Polish mobile top navigation (#4778)
## Summary

- Polish mobile Home, Activity, Search, and Settings navigation chrome.
- Add progressive Buzz gradients/frost, aligned theme colors, dividers,
typography, and section spacing.
- Refine Search and Settings motion, including automatic keyboard focus
on search activation.

<img width="630" height="1368"
alt="C78FA3CE-F2B3-45F2-B9F5-7EA7500778CC"
src="https://github.com/user-attachments/assets/5935514b-d894-4010-80dd-a938363fee93"
/>
<img width="630" height="1368"
alt="5C058A73-1879-476A-881C-531ACC256D84"
src="https://github.com/user-attachments/assets/5266c841-17ee-49e8-9841-b06d84f4195f"
/>
<img width="630" height="1368"
alt="3F50ADB7-9BDA-4A8D-A81E-20560C3B9EA6"
src="https://github.com/user-attachments/assets/f615f61e-9e96-4bce-b261-ae5ec54db872"
/>
<img width="630" height="1368"
alt="35ECE741-01F3-4B79-80C5-1DDD447121A7"
src="https://github.com/user-attachments/assets/b5145186-9884-44eb-8ebc-f3303831c0a4"
/>

## Validation


- `flutter analyze`
- Focused Home, Activity, Channels, Search, theme, and footer widget
tests
- Full pre-push checks, including mobile tests, desktop checks, and
Tauri checks
- On-device iPhone review during the visual polish pass

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: npub1glqcqfjxdens59scl477pmejh8lht4hqkhx0y4w38jxr6e6w6y2sm29y4e <47c18026466e670a1618fd7de0ef32b9ff75d6e0b5ccf255d13c8c3d674ed115@buzz.block.builderlab.xyz>
Signed-off-by: Code Reviewer <037593536284cf40e221c96c931e9877d4166d54f6bb84e5341a86d7fd5d05a4@buzz.block.builderlab.xyz>
Signed-off-by: Kenny Lopez <klopez4212@gmail.com>
Co-authored-by: npub1glqcqfjxdens59scl477pmejh8lht4hqkhx0y4w38jxr6e6w6y2sm29y4e <47c18026466e670a1618fd7de0ef32b9ff75d6e0b5ccf255d13c8c3d674ed115@buzz.block.builderlab.xyz>
Co-authored-by: Code Reviewer <037593536284cf40e221c96c931e9877d4166d54f6bb84e5341a86d7fd5d05a4@buzz.block.builderlab.xyz>
2026-08-05 19:01:20 +01:00

87 lines
2.7 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;
/// Fixed visual height of the shared footer fade behind the floating tab bar.
double mobileTabFooterBackdropHeight(BuildContext _) => 180;
/// Builds the shared transparent-to-surface footer fade.
///
/// Kept separate from [MobileTabFooterBackdrop] so floating controls such as
/// the channel composer can paint the exact same fade behind their own content.
LinearGradient mobileTabFooterBackdropGradient(
BuildContext context, {
List<double> stops = const [0, 0.18, 0.38, 0.6, 0.8, 1],
List<double> opacities = const [0, 0.03, 0.12, 0.34, 0.7, 1],
Color? tint,
double tintBlend = 0,
}) {
assert(stops.length == opacities.length);
assert(tintBlend >= 0 && tintBlend <= 1);
final surface = Color.lerp(context.colors.surface, tint, tintBlend)!;
return LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: stops,
colors: [
for (final opacity in opacities) surface.withValues(alpha: opacity),
],
);
}
/// 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;
/// Optional color blended into the surface before opacity is applied.
final Color? tint;
/// Amount of [tint] mixed into the surface, from 0 to 1.
final double tintBlend;
/// 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.18, 0.38, 0.6, 0.8, 1],
this.opacities = const [0, 0.03, 0.12, 0.34, 0.7, 1],
this.tint,
this.tintBlend = 0,
}) : assert(stops.length == opacities.length),
assert(tintBlend >= 0 && tintBlend <= 1);
@override
Widget build(BuildContext context) {
return SizedBox(
height: height,
width: double.infinity,
child: DecoratedBox(
decoration: BoxDecoration(
gradient: mobileTabFooterBackdropGradient(
context,
stops: stops,
opacities: opacities,
tint: tint,
tintBlend: tintBlend,
),
),
),
);
}
}