Skip to content

Commit 8fe8091

Browse files
authored
refactor(hig): hero icons, link buttons, spacing sweep (#993)
* refactor(hero-icons): SF Symbols hierarchical rendering with Dynamic Type largeTitle * refactor(buttons): tertiary actions use .link / .borderless instead of .plain + manual tint * refactor(spacing): sweep 5pt-grid magic numbers (5, 14) to 8pt-grid (4, 6, 12); add cancelAction to ConnectionForm Cancel button * docs(changelog): note HIG phase 5 polish
1 parent 5b0f92b commit 8fe8091

19 files changed

Lines changed: 40 additions & 24 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Changed
1111

12+
- HIG polish (phase 5): nine hero icons (empty / success / error / Pro feature gate states across Onboarding, Feedback, Export Success, Import Success, Import Error, Query Success, Main editor empty state) move from hardcoded `.system(size: 40-64)` to a Dynamic-Type-aware combination of `.font(.largeTitle).imageScale(.large).symbolRenderingMode(.hierarchical)`, so they scale with the user's accessibility text-size setting and gain the canonical SF Symbols depth treatment. Five `.plain`-button-as-link callsites (Fetch All in the status bar, Show All / Hide All in the column visibility popover, Skip in onboarding, Close in the feedback success state) move to `.buttonStyle(.link)` or `.borderless`. Spacing sweep across 8 files normalises 5pt-grid magic numbers (`spacing: 5`, `spacing: 14`, `padding(.horizontal, 5)`) onto Apple's 8pt grid (`spacing: 4`, `spacing: 12`, `padding(.horizontal, 6)`). The Connection Form's Cancel button gains `.keyboardShortcut(.cancelAction)` so Esc dismisses correctly.
1213
- HIG list & window cleanup (phase 4): three small refactors that align inline list affordances with the rest of the codebase. `SlowQueryListView` (the collapsible "Slow Queries" panel in the Server Dashboard) drops a hand-rolled `Button { chevron }` + `ScrollView` + `LazyVStack` and uses a real `DisclosureGroup` + `List`, so VoiceOver gets the disclosure semantics and keyboard handling for free, and the orange-on-red error pill in its header switches to the warning-triangle convention introduced in phase 3. `ColumnVisibilityPopover` (the column show/hide popover) replaces its `ScrollView` + `LazyVStack` with a native `List`, gaining row hover, separators, and the standard list keyboard-navigation it was missing; the "Show All" / "Hide All" buttons in its header switch from `.plain` + manual accent foreground to `.buttonStyle(.link)`. `JSONViewerWindowController` deletes its hand-coded UserDefaults size persistence and uses the `NSWindow.applyAutosaveName` helper that every other imperative window in the project already uses; window position is now remembered too, not just size.
1314
- HIG pattern refactors (phase 3): five callsites migrate off bespoke implementations onto native primitives. `ResultTabBar` (the `.plain`-button strip in the results pane) gains hover states, accent-tint selection, and a `.bar` material background that matches macOS Sequoia inline tab patterns. `ConnectionSwitcherPopover` drops its manual `selectedIndex: Int` plus per-row `isHighlighted` color flipping and uses native `List(selection:)` for keyboard navigation, focus chrome, and scroll-into-view. The Welcome window's `+` and "new group" buttons replace a custom `@State isHovering` background with `.buttonStyle(.bordered).controlSize(.large)`. Eight inline form validation banners (URL parsing, plugin install, pgpass permissions, jump-host test, license activation, etc.) move from raw `.foregroundStyle(.systemRed)` text to a semantic `Label("...", systemImage: "exclamationmark.triangle.fill").foregroundStyle(.systemOrange)` pattern matching Apple's form-warning convention. Four sheets (Create Database, Create Tag, Export Options, Pagination Settings popover) are rebuilt on `Form { Section { ... } }.formStyle(.grouped)` with `LabeledContent` rows instead of hand-laid `VStack` + caption-styled labels + `roundedBorder` TextFields.
1415
- HIG component extraction (phase 2): introduces three reusable components — `TypeBadge`, `ProBadge`, and `ColorPaletteView` — replacing five duplicated open-coded variants across the UI. The column-type pill (previously hand-written in three places with hardcoded 9pt fonts and no accessibility labels) becomes one Dynamic-Type-aware `TypeBadge` that announces "Type: VARCHAR" to VoiceOver. The "PRO" pill standardises on a Capsule shape with `.caption2.bold()` and a "Pro feature" accessibility label. The connection / tag / group color pickers (three near-duplicate `HStack`-of-circles) collapse into one `ColorPaletteView` with `.compact` and `.regular` size variants. The toolbar `TagBadgeView` switches to a saturated tint background with white text for proper Increase Contrast support, replacing the same-hue text + 0.2-opacity-fill pattern that failed AA contrast for several preset tags.

TablePro/Views/AIChat/AIChatMessageView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ private struct TypingIndicatorView: View {
196196
@State private var animating = false
197197

198198
var body: some View {
199-
HStack(spacing: 5) {
199+
HStack(spacing: 4) {
200200
ForEach(0..<3, id: \.self) { index in
201201
Circle()
202202
.fill(Color(nsColor: .tertiaryLabelColor))

TablePro/Views/Components/ProFeatureGate.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ struct ProFeatureGateModifier: ViewModifier {
4040

4141
VStack(spacing: 12) {
4242
Image(systemName: feature.systemImage)
43-
.font(.system(size: 40))
43+
.font(.largeTitle)
44+
.imageScale(.large)
45+
.symbolRenderingMode(.hierarchical)
4446
.foregroundStyle(.secondary)
4547

4648
switch access {

TablePro/Views/Components/TypeBadge.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct TypeBadge: View {
1818
Text(label)
1919
.font(.caption2.weight(.medium))
2020
.foregroundStyle(.tertiary)
21-
.padding(.horizontal, 5)
21+
.padding(.horizontal, 6)
2222
.padding(.vertical, 1)
2323
.background(.quaternary, in: Capsule())
2424
.accessibilityLabel(Text("Type: \(accessibilityDescription ?? label)"))

TablePro/Views/Connection/ConnectionFormView+Footer.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ extension ConnectionFormView {
5454
Button("Cancel") {
5555
dismiss()
5656
}
57+
.keyboardShortcut(.cancelAction)
5758

5859
if isNew {
5960
Button(String(localized: "Save")) {

TablePro/Views/Connection/OnboardingContentView.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ struct OnboardingContentView: View {
150150
private var getStartedPage: some View {
151151
VStack(spacing: 16) {
152152
Image(systemName: "checkmark.circle.fill")
153-
.font(.system(size: 48))
153+
.font(.largeTitle)
154+
.imageScale(.large)
155+
.symbolRenderingMode(.hierarchical)
154156
.foregroundStyle(Color(nsColor: .systemGreen))
155157

156158
Text("You're all set!")
@@ -170,8 +172,7 @@ struct OnboardingContentView: View {
170172
Button("Skip") {
171173
completeOnboarding()
172174
}
173-
.buttonStyle(.plain)
174-
.foregroundStyle(.secondary)
175+
.buttonStyle(.link)
175176
.opacity(currentPage == 2 ? 0 : 1)
176177
.frame(minWidth: 110, alignment: .leading)
177178

TablePro/Views/Connection/WelcomeLeftPanel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ struct KeyboardHint: View {
130130
HStack(spacing: 4) {
131131
Text(keys)
132132
.font(.system(.caption, design: .monospaced))
133-
.padding(.horizontal, 5)
133+
.padding(.horizontal, 6)
134134
.padding(.vertical, 2)
135135
.background(
136136
RoundedRectangle(cornerRadius: 3)

TablePro/Views/Editor/QuerySuccessView.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ struct QuerySuccessView: View {
1919

2020
// Success icon
2121
Image(systemName: "checkmark.circle.fill")
22-
.font(.system(size: 64))
22+
.font(.largeTitle)
23+
.imageScale(.large)
24+
.symbolRenderingMode(.hierarchical)
2325
.foregroundStyle(Color(nsColor: .systemGreen))
2426

2527
// Success message

TablePro/Views/Export/ExportSuccessView.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ struct ExportSuccessView: View {
2424
VStack(spacing: 20) {
2525
// Success icon
2626
Image(systemName: "checkmark.circle.fill")
27-
.font(.system(size: 48))
27+
.font(.largeTitle)
28+
.imageScale(.large)
29+
.symbolRenderingMode(.hierarchical)
2830
.foregroundStyle(Color(nsColor: .systemGreen))
2931

3032
// Title and message

TablePro/Views/Feedback/FeedbackView.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,9 @@ struct FeedbackView: View {
277277
Spacer()
278278

279279
Image(systemName: "checkmark.circle.fill")
280-
.font(.system(size: 44))
280+
.font(.largeTitle)
281+
.imageScale(.large)
282+
.symbolRenderingMode(.hierarchical)
281283
.foregroundStyle(Color(nsColor: .systemGreen))
282284

283285
Text("Feedback submitted!")
@@ -303,8 +305,7 @@ struct FeedbackView: View {
303305
NSApp.keyWindow?.close()
304306
}
305307
.font(.subheadline)
306-
.buttonStyle(.plain)
307-
.foregroundStyle(.secondary)
308+
.buttonStyle(.borderless)
308309
}
309310

310311
Spacer()

0 commit comments

Comments
 (0)