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 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 = [ ...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, ); } }