feat(app): SectionHeader и TileCarousel — общие виджеты редизайна

SectionHeader — заголовок блока с короткой акцентной полоской вместо
разделителя. TileCarousel — горизонтальная прокрутка StatTile вместо
Wrap, не требует общей высоты у детей. Оба без экрана-потребителя пока
не влияют на вид приложения.
This commit is contained in:
Dmitry
2026-09-19 15:31:26 +03:00
parent bea239ba2d
commit 9d49a9539b
2 changed files with 71 additions and 0 deletions
+44
View File
@@ -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,
],
);
}
}
+27
View File
@@ -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<Widget> 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],
],
],
),
),
);
}
}