From cfa5031398bee4aecbb2cb0d7b9e4b43de65bd22 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sat, 10 Oct 2026 12:12:45 +0300 Subject: [PATCH 1/2] fix(results): the Grid / Groupings / Charts tabs size by their labels The strip sat in a 240 x 32 box. A tab row is taller than 32 (8 px padding on both sides plus a 2 px focus border), so the tabs were clipped, and at a larger UI or text scale 'Groupings' ran into its neighbours. QueryaTabStrip gets dense (4 px vertical padding) and the strip is no longer boxed. The chart type strip (Bar / Line / Pie) had the same fixed 260 x 32 box and gets the same fix. A test lays the tabs out at 1.0, 1.3 and 1.6 text scale and checks they do not overlap. --- .../results/charts/quick_chart_view.dart | 25 +++++----- lib/features/workspace/results_tab.dart | 18 +++---- lib/shared/widgets/querya_tab_strip.dart | 7 ++- test/features/workspace/results_tab_test.dart | 47 ++++++++++++++++++- 4 files changed, 72 insertions(+), 25 deletions(-) diff --git a/lib/features/results/charts/quick_chart_view.dart b/lib/features/results/charts/quick_chart_view.dart index f875efb1..07ff4772 100644 --- a/lib/features/results/charts/quick_chart_view.dart +++ b/lib/features/results/charts/quick_chart_view.dart @@ -295,20 +295,17 @@ class _QuickChartViewState extends material.State { runSpacing: 8, crossAxisAlignment: material.WrapCrossAlignment.center, children: [ - material.SizedBox( - height: 32, - width: 260, - child: QueryaTabStrip( - labels: const ['Bar', 'Line', 'Pie'], - selectedIndex: QuickChartType.values.indexOf(_type), - onSelected: (i) => setState(() { - _type = QuickChartType.values[i]; - _topN = _type == QuickChartType.pie - ? ChartData.pieTopN - : ChartData.defaultTopN; - _hoveredSlice = null; - }), - ), + QueryaTabStrip( + dense: true, + labels: const ['Bar', 'Line', 'Pie'], + selectedIndex: QuickChartType.values.indexOf(_type), + onSelected: (i) => setState(() { + _type = QuickChartType.values[i]; + _topN = _type == QuickChartType.pie + ? ChartData.pieTopN + : ChartData.defaultTopN; + _hoveredSlice = null; + }), ), const material.SizedBox(width: 12), Text(_xLabel), diff --git a/lib/features/workspace/results_tab.dart b/lib/features/workspace/results_tab.dart index bf5f2327..e8f84a9e 100644 --- a/lib/features/workspace/results_tab.dart +++ b/lib/features/workspace/results_tab.dart @@ -404,15 +404,15 @@ class _ResultsTabState extends material.State { mainAxisSize: material.MainAxisSize.min, children: [ // Grid / Groupings View Selector - material.SizedBox( - height: 32, - width: 240, - child: QueryaTabStrip( - labels: const ['Grid', 'Groupings', 'Charts'], - selectedIndex: ResultViewMode.values.indexOf(_viewMode), - onSelected: (i) => - setState(() => _viewMode = ResultViewMode.values[i]), - ), + // Sized by its labels: a fixed box clipped the tabs and + // let "Groupings" run into its neighbours at larger UI + // scales. + QueryaTabStrip( + dense: true, + labels: const ['Grid', 'Groupings', 'Charts'], + selectedIndex: ResultViewMode.values.indexOf(_viewMode), + onSelected: (i) => + setState(() => _viewMode = ResultViewMode.values[i]), ), const Gap(10), Text( diff --git a/lib/shared/widgets/querya_tab_strip.dart b/lib/shared/widgets/querya_tab_strip.dart index a451b07f..be8d83df 100644 --- a/lib/shared/widgets/querya_tab_strip.dart +++ b/lib/shared/widgets/querya_tab_strip.dart @@ -25,6 +25,7 @@ class QueryaTabStrip extends material.StatefulWidget { this.onAdd, this.canClose, this.scrollController, + this.dense = false, }) : assert(labels.length > 0); final List labels; @@ -35,6 +36,10 @@ class QueryaTabStrip extends material.StatefulWidget { final bool Function(int index)? canClose; final material.ScrollController? scrollController; + /// Tighter vertical padding for toolbars: the strip is as tall as a dense + /// icon button instead of a full tab row. + final bool dense; + @override material.State createState() => QueryaTabStripState(); } @@ -268,7 +273,7 @@ class QueryaTabStripState extends material.State curve: context.motionCurve(QueryaMotion.enter), padding: material.EdgeInsets.symmetric( horizontal: showClose ? 10 : 12, - vertical: 8, + vertical: widget.dense ? 4 : 8, ), decoration: material.BoxDecoration( color: material.Colors.transparent, diff --git a/test/features/workspace/results_tab_test.dart b/test/features/workspace/results_tab_test.dart index 901d11db..5b925229 100644 --- a/test/features/workspace/results_tab_test.dart +++ b/test/features/workspace/results_tab_test.dart @@ -1343,5 +1343,50 @@ void main() { expect(tester.takeException(), isNull); }); }); -} + group('result view tabs', () { + testWidgets( + 'Grid, Groupings and Charts sit side by side at any text scale', + (tester) async { + for (final scale in [1.0, 1.3, 1.6]) { + await tester.pumpWidget( + material.MediaQuery( + data: material.MediaQueryData( + size: const material.Size(900, 500), + textScaler: material.TextScaler.linear(scale), + ), + child: resultsShell( + child: material.Scaffold( + body: material.SizedBox( + width: 900, + height: 500, + child: ResultsTab( + columns: const ['id', 'name'], + rows: const [ + ['1', 'Alice'], + ], + ), + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + + final grid = + tester.getRect(find.byKey(const material.ValueKey('querya_tab_Grid'))); + final groupings = tester.getRect( + find.byKey(const material.ValueKey('querya_tab_Groupings'))); + final charts = tester.getRect( + find.byKey(const material.ValueKey('querya_tab_Charts'))); + + expect(grid.right, lessThanOrEqualTo(groupings.left), reason: 'x$scale'); + expect(groupings.right, lessThanOrEqualTo(charts.left), + reason: 'x$scale'); + // The tabs are as tall as their own content: nothing is clipped by a + // box that is shorter than them. + expect(tester.takeException(), isNull, reason: 'x$scale'); + } + }); + }); +} From 429a73eea667076a6220eea9f839876cce08eb93 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sat, 10 Oct 2026 12:15:45 +0300 Subject: [PATCH 2/2] test(results): const widgets in the tab layout test --- test/features/workspace/results_tab_test.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/features/workspace/results_tab_test.dart b/test/features/workspace/results_tab_test.dart index 5b925229..b6a0df37 100644 --- a/test/features/workspace/results_tab_test.dart +++ b/test/features/workspace/results_tab_test.dart @@ -1356,13 +1356,13 @@ void main() { textScaler: material.TextScaler.linear(scale), ), child: resultsShell( - child: material.Scaffold( + child: const material.Scaffold( body: material.SizedBox( width: 900, height: 500, child: ResultsTab( - columns: const ['id', 'name'], - rows: const [ + columns: ['id', 'name'], + rows: [ ['1', 'Alice'], ], ),