Initial commit
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import 'dart:ui' show ImageFilter;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../providers/appearance_provider.dart';
|
||||
import '../theme/app_theme.dart';
|
||||
import 'window_chrome.dart';
|
||||
|
||||
|
||||
class AppSliverHeader extends ConsumerWidget {
|
||||
final String? title;
|
||||
final Widget? titleWidget;
|
||||
final Widget? leading;
|
||||
final bool automaticallyImplyLeading;
|
||||
final List<Widget> actions;
|
||||
final PreferredSizeWidget? bottom;
|
||||
final double? expandedHeight;
|
||||
final double? toolbarHeight;
|
||||
|
||||
const AppSliverHeader({
|
||||
super.key,
|
||||
this.title,
|
||||
this.titleWidget,
|
||||
this.leading,
|
||||
this.automaticallyImplyLeading = true,
|
||||
this.actions = const [],
|
||||
this.bottom,
|
||||
this.expandedHeight,
|
||||
this.toolbarHeight,
|
||||
}) : assert(
|
||||
title != null || titleWidget != null,
|
||||
'AppSliverHeader requires either title or titleWidget',
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final mode =
|
||||
ref.watch(appearanceProvider).value?.headerMode ?? HeaderMode.frosted;
|
||||
final isFrosted = mode == HeaderMode.frosted;
|
||||
final theme = Theme.of(context);
|
||||
final tokens = context.appTokens;
|
||||
final reserved = WindowChrome.reservedTrailingWidth(tokens);
|
||||
final effectiveActions = <Widget>[
|
||||
...actions,
|
||||
if (reserved > 0) SizedBox(width: reserved),
|
||||
];
|
||||
|
||||
return SliverAppBar(
|
||||
pinned: true,
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
toolbarHeight: toolbarHeight ?? kToolbarHeight,
|
||||
leading: leading,
|
||||
automaticallyImplyLeading: automaticallyImplyLeading,
|
||||
title:
|
||||
titleWidget ??
|
||||
(title != null
|
||||
? Text(
|
||||
title!,
|
||||
style: theme.textTheme.titleMedium,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)
|
||||
: null),
|
||||
actions: effectiveActions,
|
||||
bottom: bottom,
|
||||
expandedHeight: expandedHeight,
|
||||
backgroundColor: isFrosted
|
||||
? theme.colorScheme.surface.withValues(alpha: 0.7)
|
||||
: theme.colorScheme.surface,
|
||||
shape: isFrosted
|
||||
? Border(
|
||||
bottom: BorderSide(
|
||||
color: theme.colorScheme.onSurface.withValues(alpha: 0.08),
|
||||
width: 1,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
flexibleSpace: isFrosted
|
||||
? ClipRect(
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 18, sigmaY: 18),
|
||||
child: const SizedBox.expand(),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user