diff --git a/app/lib/core/widgets/section_header.dart b/app/lib/core/widgets/section_header.dart new file mode 100644 index 0000000..94e4873 --- /dev/null +++ b/app/lib/core/widgets/section_header.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; + +/// A bold section title with a short accent underline beneath its left edge — the +/// Grimmory-style marker for "a new block starts here" that replaces a divider line. +/// For a titled card use [SectionCard] instead; this is for a bare block of content +/// (a chart, a row of tiles, a list) that isn't wrapped in a card of its own. +class SectionHeader extends StatelessWidget { + const SectionHeader({required this.title, this.trailing, super.key}); + + final String title; + final Widget? trailing; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + title, + style: theme.textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w800), + ), + const SizedBox(height: 6), + Container( + width: 28, + height: 3, + decoration: BoxDecoration( + color: theme.colorScheme.primary, + borderRadius: BorderRadius.circular(2), + ), + ), + ], + ), + ), + ?trailing, + ], + ); + } +} diff --git a/app/lib/core/widgets/tile_carousel.dart b/app/lib/core/widgets/tile_carousel.dart new file mode 100644 index 0000000..19f0dfc --- /dev/null +++ b/app/lib/core/widgets/tile_carousel.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +/// A horizontally scrolling row of tiles — the Grimmory-style carousel, used on the +/// dashboard in place of a [Wrap] of [StatTile]s so a long row of metrics scrolls +/// instead of wrapping onto a second, uneven line. +class TileCarousel extends StatelessWidget { + const TileCarousel({required this.children, super.key}); + + final List children; + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: IntrinsicHeight( + child: Row( + children: [ + for (var i = 0; i < children.length; i++) ...[ + if (i > 0) const SizedBox(width: 12), + children[i], + ], + ], + ), + ), + ); + } +}