Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions docs/ui-kit.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,17 +207,19 @@ Canonical labels and roles from the review:
| several related buttons side by side with gaps | `QueryaButtonGroup` |
| shadcn / material `IconButton`, private `_TreeIconButton` | `QueryaIconButton` (with tooltip) |
| `InkWell` / `GestureDetector` around an icon or text | `QueryaButton` or `QueryaIconButton` |
| private `_ActionButton`, `_SmallActionButton`, `_ToolbarButton` | `QueryaButton` |
| show-password eye pasted in forms | one password field widget |
| private `_ActionButton`, `_SmallActionButton`, `_ToolbarButton` (gone) | `QueryaButton` |
| show-password eye pasted in forms | `QueryaIconButton` (one password field widget stays open in #1445) |

### Guards (landing with #1339)
### Guards

| Test | Forbids |
|------|---------|
| `no_shadcn_buttons_test.dart` | `PrimaryButton`, `OutlineButton`, `GhostButton`, `DestructiveButton`, `SecondaryButton`, `LinkButton`, `ButtonSize`, `ButtonDensity` outside an allow-list |
| `no_raw_material_buttons_test.dart` | `IconButton`, `TextButton`, `ElevatedButton`, `OutlinedButton`, `FilledButton` |
| `no_ad_hoc_button_classes_test.dart` | a `*Button` class outside `lib/shared/widgets/`; a button-like `InkWell` / `GestureDetector` outside the kit |
| `button_literals_test.dart` | `waitDuration: Duration(...)` literals, `BorderRadius.circular(n)` on a kit control |
All four live in `test/guards/button_standard_guards_test.dart`:

| Guard | Forbids |
|-------|---------|
| shadcn button types | `PrimaryButton`, `OutlineButton`, `GhostButton`, `DestructiveButton`, `SecondaryButton`, `LinkButton`, `ButtonSize`, `ButtonDensity` in `lib/` |
| raw Material buttons | `IconButton`, `TextButton`, `ElevatedButton`, `OutlinedButton`, `FilledButton` in `lib/` |
| button classes | a `*Button` class outside `lib/shared/widgets/` (allow-list: `ThemePickerButton`, `TableEditModeButton`, follow-up #1445) |
| tooltip delay | `waitDuration: Duration(...)` literals; use `kQueryaTooltipWait` |

## Design tokens

Expand Down
18 changes: 8 additions & 10 deletions lib/features/connections/forms/connection_auth_section.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart' as material;
import 'package:querya_desktop/core/ui/querya_control_tokens.dart';
import 'package:querya_desktop/features/connections/remove_saved_password_option.dart';
import 'package:querya_desktop/shared/widgets/widgets.dart';

Expand Down Expand Up @@ -77,17 +78,14 @@ class _ConnectionAuthSectionState extends material.State<ConnectionAuthSection>
top: 0,
bottom: 0,
child: material.Center(
child: material.IconButton(
icon: material.Icon(
_showPassword
child: QueryaIconButton(
icon: material.Icon(_showPassword
? material.Icons.visibility_off
: material.Icons.visibility,
size: 20,
),
onPressed: () => setState(() => _showPassword = !_showPassword),
padding: material.EdgeInsets.zero,
constraints: const material.BoxConstraints(),
),
: material.Icons.visibility),
tooltip: _showPassword ? 'Hide password' : 'Show password',
size: QueryaControlSize.sm,
onPressed: () => setState(() => _showPassword = !_showPassword),
),
),
),
],
Expand Down
18 changes: 6 additions & 12 deletions lib/features/connections/sqlite_connection_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -364,18 +364,12 @@ class _SqliteConnectionFormContentState
),
).small(),
),
material.IconButton(
icon: material.Icon(
material.Icons.close,
size: 18,
color: theme.mutedForeground,
),
onPressed: _dismissResult,
style: material.IconButton.styleFrom(
minimumSize: const material.Size(28, 28),
padding: material.EdgeInsets.zero,
),
),
QueryaIconButton(
icon: const material.Icon(material.Icons.close),
tooltip: 'Dismiss',
size: QueryaControlSize.sm,
onPressed: _dismissResult,
),
],
),
),
Expand Down
33 changes: 12 additions & 21 deletions lib/features/main_screen/querya_window_title_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart' as material;
import 'package:querya_desktop/core/layout/ui_scale.dart';
import 'package:querya_desktop/core/storage/local_db.dart';
import 'package:querya_desktop/core/theme/querya_theme_scope.dart';
import 'package:querya_desktop/core/ui/querya_control_tokens.dart';
import 'package:querya_desktop/features/connections/driver_manager_dialog.dart';
import 'package:querya_desktop/core/actions/querya_command_host.dart';
import 'package:querya_desktop/features/command_palette/command_palette_dialog.dart';
Expand All @@ -17,6 +18,7 @@ import 'package:querya_desktop/features/updater/update_available_badge.dart';
import 'package:querya_desktop/features/updater/update_controller.dart';
import 'package:querya_desktop/features/updater/update_dialog.dart';
import 'package:querya_desktop/core/actions/sql_editor_actions.dart';
import 'package:querya_desktop/shared/widgets/querya_icon_button.dart';
import 'package:querya_desktop/shared/widgets/querya_text.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart' hide TextExtension;

Expand Down Expand Up @@ -126,28 +128,17 @@ class QueryaWindowTitleBar extends StatelessWidget {
const Text('Querya').semiBold().small(),
const Gap(12),
if (onToggleSidebar != null) ...[
material.Tooltip(
message:
'Toggle Sidebar (${Platform.isMacOS ? "Cmd+B" : "Ctrl+B"})',
child: material.IconButton(
key: const Key('title_bar_toggle_sidebar_button'),
icon: material.Icon(
isSidebarVisible
? material.Icons.view_sidebar_rounded
: material.Icons.view_sidebar_outlined,
size: 16,
color: isSidebarVisible
? Theme.of(context).colorScheme.foreground
: wb.mutedForeground,
),
splashRadius: 14,
padding: const material.EdgeInsets.all(4),
constraints: const material.BoxConstraints(
minWidth: 26,
minHeight: 26,
),
onPressed: onToggleSidebar,
QueryaIconButton(
key: const Key('title_bar_toggle_sidebar_button'),
icon: material.Icon(
isSidebarVisible
? material.Icons.view_sidebar_rounded
: material.Icons.view_sidebar_outlined,
),
tooltip:
'Toggle Sidebar (${Platform.isMacOS ? "Cmd+B" : "Ctrl+B"})',
size: QueryaControlSize.sm,
onPressed: onToggleSidebar,
),
const Gap(12),
] else
Expand Down
61 changes: 7 additions & 54 deletions lib/features/mongodb/mongo_collections_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,11 @@ class _CollectionRow extends StatelessWidget {
const material.EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
children: [
_ActionButton(
QueryaButton.secondary(
label: 'View',
icon: material.Icons.visibility_rounded,
color: context.semanticPalette.success,
onTap: onView,
size: QueryaControlSize.sm,
onPressed: onView,
),
const Gap(16),
Expanded(
Expand All @@ -440,11 +440,12 @@ class _CollectionRow extends StatelessWidget {
width: 100,
child: Text(_formatSize(collection.size)).muted().small(),
),
_ActionButton(
QueryaButton.secondary(
label: 'Del',
icon: material.Icons.delete_rounded,
color: context.semanticPalette.destructive,
onTap: onDrop,
size: QueryaControlSize.sm,
tone: QueryaButtonTone.destructive,
onPressed: onDrop,
),
],
),
Expand All @@ -466,54 +467,6 @@ class _CollectionRow extends StatelessWidget {
}
}

class _ActionButton extends StatelessWidget {
const _ActionButton({
required this.label,
required this.icon,
required this.color,
required this.onTap,
});

final String label;
final material.IconData icon;
final Color color;
final VoidCallback onTap;

@override
Widget build(BuildContext context) {
return material.Material(
color: Colors.transparent,
child: material.InkWell(
onTap: onTap,
borderRadius: material.BorderRadius.circular(6),
child: material.Container(
padding:
const material.EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: material.BoxDecoration(
color: color.withValues(alpha: 0.14),
borderRadius: material.BorderRadius.circular(6),
),
child: Row(
mainAxisSize: material.MainAxisSize.min,
children: [
material.Icon(icon, size: 14, color: color),
const Gap(5),
Text(
label,
style: material.TextStyle(
color: color,
fontSize: 12,
fontWeight: material.FontWeight.w500,
),
),
],
),
),
),
);
}
}

// ─── Data model ──────────────────────────────────────────────────────────────

class _CollectionInfo {
Expand Down
61 changes: 7 additions & 54 deletions lib/features/mongodb/mongo_databases_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -390,11 +390,11 @@ class _DatabaseRow extends StatelessWidget {
const material.EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
children: [
_ActionButton(
QueryaButton.secondary(
label: 'View',
icon: material.Icons.visibility_rounded,
color: context.semanticPalette.success,
onTap: onView,
size: QueryaControlSize.sm,
onPressed: onView,
),
const Gap(16),
Expanded(
Expand All @@ -413,11 +413,12 @@ class _DatabaseRow extends StatelessWidget {
width: 120,
child: Text(_formatSize(database.sizeOnDisk)).muted().small(),
),
_ActionButton(
QueryaButton.secondary(
label: 'Del',
icon: material.Icons.delete_rounded,
color: context.semanticPalette.destructive,
onTap: onDrop,
size: QueryaControlSize.sm,
tone: QueryaButtonTone.destructive,
onPressed: onDrop,
),
],
),
Expand All @@ -439,54 +440,6 @@ class _DatabaseRow extends StatelessWidget {
}
}

class _ActionButton extends StatelessWidget {
const _ActionButton({
required this.label,
required this.icon,
required this.color,
required this.onTap,
});

final String label;
final material.IconData icon;
final Color color;
final VoidCallback onTap;

@override
Widget build(BuildContext context) {
return material.Material(
color: Colors.transparent,
child: material.InkWell(
onTap: onTap,
borderRadius: material.BorderRadius.circular(6),
child: material.Container(
padding:
const material.EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: material.BoxDecoration(
color: color.withValues(alpha: 0.14),
borderRadius: material.BorderRadius.circular(6),
),
child: Row(
mainAxisSize: material.MainAxisSize.min,
children: [
material.Icon(icon, size: 14, color: color),
const Gap(5),
Text(
label,
style: material.TextStyle(
color: color,
fontSize: 12,
fontWeight: material.FontWeight.w500,
),
),
],
),
),
),
);
}
}

// ─── Data models ─────────────────────────────────────────────────────────────

class _DatabaseInfo {
Expand Down
Loading
Loading