From 438644ef037289bd3b3aead626a7ed547c125844 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Thu, 28 May 2026 11:40:51 +0300 Subject: [PATCH] feat(theme): SqlEditorChrome tokens for SQL workspaces (#60) Add toolbar decoration helper, brightness-aware accent glow, and widget tests for imported editor colors; wire PG/MySQL toolbars to theme tokens. --- .../main_screen/sql_editor_chrome.dart | 47 +++++++++++--- lib/features/mysql/mysql_sql_workspace.dart | 6 +- .../postgresql/postgres_sql_workspace.dart | 6 +- .../main_screen/sql_editor_chrome_test.dart | 65 +++++++++++++++++++ 4 files changed, 107 insertions(+), 17 deletions(-) diff --git a/lib/features/main_screen/sql_editor_chrome.dart b/lib/features/main_screen/sql_editor_chrome.dart index 6be04c0c..7dcd62db 100644 --- a/lib/features/main_screen/sql_editor_chrome.dart +++ b/lib/features/main_screen/sql_editor_chrome.dart @@ -10,24 +10,49 @@ class SqlEditorChrome extends StatelessWidget { final Widget child; - static const double _outerRadius = 14; - static const double _innerRadius = 10; + static const double outerRadius = 14; + static const double innerRadius = 10; + + /// Accent glow strength; slightly softer on light themes. + static double chromeGlowAlpha(Brightness brightness) => + brightness == Brightness.light ? 0.08 : 0.1; + + static double inlineGlowAlpha(Brightness brightness) => + brightness == Brightness.light ? 0.05 : 0.07; + + /// Toolbar strip above SQL editor (Postgres/MySQL workspaces). + static material.BoxDecoration sqlToolbarDecoration( + BuildContext context, + ) { + final workbench = context.workbench; + return material.BoxDecoration( + color: workbench.surface.withValues(alpha: 0.85), + border: material.Border( + bottom: material.BorderSide( + color: workbench.borderSubtle.withValues(alpha: 0.35), + ), + ), + ); + } /// Decoration for compact SQL fields (dialogs) from theme tokens. static material.BoxDecoration inlineFieldDecoration( QueryaEditorTheme editor, - QueryaWorkbenchTheme workbench, - ) { + QueryaWorkbenchTheme workbench, { + Brightness brightness = Brightness.dark, + }) { final border = editor.widgetBorder ?? workbench.borderSubtle; return material.BoxDecoration( color: editor.background, - borderRadius: material.BorderRadius.circular(_innerRadius), + borderRadius: material.BorderRadius.circular(innerRadius), border: material.Border.all( color: border.withValues(alpha: 0.45), ), boxShadow: [ material.BoxShadow( - color: workbench.accent.withValues(alpha: 0.07), + color: workbench.accent.withValues( + alpha: inlineGlowAlpha(brightness), + ), blurRadius: 18, offset: const material.Offset(0, 6), ), @@ -41,6 +66,7 @@ class SqlEditorChrome extends StatelessWidget { return inlineFieldDecoration( context.editorTheme, context.workbench, + brightness: Theme.of(context).brightness, ); } @@ -48,12 +74,15 @@ class SqlEditorChrome extends StatelessWidget { Widget build(BuildContext context) { final editor = context.editorTheme; final workbench = context.workbench; + final brightness = Theme.of(context).brightness; final border = editor.widgetBorder ?? workbench.borderSubtle; - final glow = workbench.accent.withValues(alpha: 0.1); + final glow = workbench.accent.withValues( + alpha: chromeGlowAlpha(brightness), + ); return material.Container( decoration: material.BoxDecoration( - borderRadius: material.BorderRadius.circular(_outerRadius), + borderRadius: material.BorderRadius.circular(outerRadius), boxShadow: [ material.BoxShadow( color: glow, @@ -66,7 +95,7 @@ class SqlEditorChrome extends StatelessWidget { child: material.Container( decoration: material.BoxDecoration( color: editor.background, - borderRadius: material.BorderRadius.circular(_outerRadius), + borderRadius: material.BorderRadius.circular(outerRadius), border: material.Border.all( color: border.withValues(alpha: 0.5), ), diff --git a/lib/features/mysql/mysql_sql_workspace.dart b/lib/features/mysql/mysql_sql_workspace.dart index 4fcc70fc..42386bdc 100644 --- a/lib/features/mysql/mysql_sql_workspace.dart +++ b/lib/features/mysql/mysql_sql_workspace.dart @@ -10,6 +10,7 @@ import 'package:querya_desktop/features/settings/preferences_dialog.dart'; import 'package:querya_desktop/features/settings/sql_statement_timeout_dropdown.dart'; import 'package:querya_desktop/features/main_screen/query_editor_tab.dart'; import 'package:querya_desktop/features/main_screen/results_tab.dart'; +import 'package:querya_desktop/features/main_screen/sql_editor_chrome.dart'; import 'package:querya_desktop/features/main_screen/sql_query_history_dialog.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; @@ -345,13 +346,10 @@ class _MysqlSqlToolbar extends material.StatelessWidget { @override material.Widget build(material.BuildContext context) { - final theme = Theme.of(context); final accent = context.workbench.accent; return material.Container( padding: const material.EdgeInsets.symmetric(horizontal: 12, vertical: 8), - decoration: material.BoxDecoration( - color: theme.colorScheme.muted.withValues(alpha: 0.6), - ), + decoration: SqlEditorChrome.sqlToolbarDecoration(context), child: material.Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: material.MainAxisSize.min, diff --git a/lib/features/postgresql/postgres_sql_workspace.dart b/lib/features/postgresql/postgres_sql_workspace.dart index 20df05f8..f870a4c7 100644 --- a/lib/features/postgresql/postgres_sql_workspace.dart +++ b/lib/features/postgresql/postgres_sql_workspace.dart @@ -14,6 +14,7 @@ import 'package:querya_desktop/features/settings/preferences_dialog.dart'; import 'package:querya_desktop/features/settings/sql_statement_timeout_dropdown.dart'; import 'package:querya_desktop/features/main_screen/query_editor_tab.dart'; import 'package:querya_desktop/features/main_screen/results_tab.dart'; +import 'package:querya_desktop/features/main_screen/sql_editor_chrome.dart'; import 'package:querya_desktop/features/main_screen/sql_query_history_dialog.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; @@ -518,13 +519,10 @@ class _SqlToolbar extends material.StatelessWidget { @override material.Widget build(material.BuildContext context) { - final theme = Theme.of(context); final accent = context.workbench.accent; return material.Container( padding: const material.EdgeInsets.symmetric(horizontal: 12, vertical: 8), - decoration: material.BoxDecoration( - color: theme.colorScheme.muted.withValues(alpha: 0.6), - ), + decoration: SqlEditorChrome.sqlToolbarDecoration(context), child: material.Column( crossAxisAlignment: material.CrossAxisAlignment.stretch, mainAxisSize: material.MainAxisSize.min, diff --git a/test/features/main_screen/sql_editor_chrome_test.dart b/test/features/main_screen/sql_editor_chrome_test.dart index c8aaa5fc..42887469 100644 --- a/test/features/main_screen/sql_editor_chrome_test.dart +++ b/test/features/main_screen/sql_editor_chrome_test.dart @@ -1,9 +1,14 @@ +import 'package:flutter/material.dart' as material; import 'package:flutter_test/flutter_test.dart'; +import 'package:querya_desktop/core/theme/parser/querya_theme_from_vscode.dart'; import 'package:querya_desktop/core/theme/querya_editor_theme.dart'; +import 'package:querya_desktop/core/theme/querya_theme.dart'; import 'package:querya_desktop/core/theme/querya_workbench_theme.dart'; import 'package:querya_desktop/features/main_screen/sql_editor_chrome.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart'; +import '../../support/querya_theme_test_shell.dart'; + void main() { group('SqlEditorChrome.inlineFieldDecoration', () { test('uses editor background and workbench accent glow', () { @@ -66,9 +71,69 @@ void main() { final deco = SqlEditorChrome.inlineFieldDecoration( editor, QueryaWorkbenchTheme.lightDefault, + brightness: Brightness.light, ); final border = deco.border as Border; expect(border.top.color, const Color(0xFFFF0000).withValues(alpha: 0.45)); + expect( + deco.boxShadow!.single.color, + QueryaWorkbenchTheme.lightDefault.accent.withValues(alpha: 0.05), + ); + }); + }); + + group('SqlEditorChrome widget', () { + testWidgets('applies imported editor background and border', (tester) async { + final queryaTheme = buildQueryaThemeFromVsCodeColors( + brightness: Brightness.dark, + colors: const { + 'editor.background': '#aabbcc', + 'editorWidget.border': '#112233', + 'focusBorder': '#00ffee', + }, + fallback: QueryaTheme.darkDefault, + ); + + await tester.pumpWidget( + queryaThemeTestShell( + data: queryaTheme, + child: const material.SizedBox( + width: 320, + height: 200, + child: SqlEditorChrome( + child: material.SizedBox.expand(), + ), + ), + ), + ); + await tester.pump(); + + final containers = tester.widgetList( + find.descendant( + of: find.byType(SqlEditorChrome), + matching: find.byType(material.Container), + ), + ); + + final inner = containers.firstWhere((c) { + final d = c.decoration; + return d is material.BoxDecoration && + d.color == const Color(0xFFAABBCC); + }); + final border = (inner.decoration! as material.BoxDecoration).border as Border; + expect( + border.top.color, + const Color(0xFF112233).withValues(alpha: 0.5), + ); + + final outerGlow = containers + .map((c) => c.decoration) + .whereType() + .expand((d) => d.boxShadow ?? const []) + .map((s) => s.color) + .whereType() + .firstWhere((c) => c == const Color(0xFF00FFEE).withValues(alpha: 0.1)); + expect(outerGlow, const Color(0xFF00FFEE).withValues(alpha: 0.1)); }); }); }