From 9d49a9539b784ad8125d1f493f98a88e3038c835 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sat, 19 Sep 2026 15:31:26 +0300 Subject: [PATCH] =?UTF-8?q?feat(app):=20SectionHeader=20=D0=B8=20TileCarou?= =?UTF-8?q?sel=20=E2=80=94=20=D0=BE=D0=B1=D1=89=D0=B8=D0=B5=20=D0=B2=D0=B8?= =?UTF-8?q?=D0=B4=D0=B6=D0=B5=D1=82=D1=8B=20=D1=80=D0=B5=D0=B4=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D0=B9=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SectionHeader — заголовок блока с короткой акцентной полоской вместо разделителя. TileCarousel — горизонтальная прокрутка StatTile вместо Wrap, не требует общей высоты у детей. Оба без экрана-потребителя пока не влияют на вид приложения. --- app/lib/core/widgets/section_header.dart | 44 ++++++++++++++++++++++++ app/lib/core/widgets/tile_carousel.dart | 27 +++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 app/lib/core/widgets/section_header.dart create mode 100644 app/lib/core/widgets/tile_carousel.dart 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], + ], + ], + ), + ), + ); + } +}