Skip to content

Commit e87e02d

Browse files
mcintyre94claude
andcommitted
Improve Quick Actions sheet styling to match platform conventions
- Replace custom ZStack header with NavigationStack + navigationTitle + xmark toolbar button, matching the pattern used by other sheets - Remove divider between tab bar and content (was sandwiching input bar) - Add sheet design guidelines to CLAUDE.md covering form vs utility sheet patterns, transparent background pitfalls, and divider usage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c650a8b commit e87e02d

File tree

4 files changed

+23
-17
lines changed

4 files changed

+23
-17
lines changed

CLAUDE.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ The app runs on iPhone, iPad, and Mac (Designed for iPad). Keep all three in min
119119
- Run `mkdir -p /home/sprite/project` on first chat message if no project dir exists
120120
- Settings captions: when a setting needs an explanation, wrap the control and caption text together in a `VStack(alignment: .leading, spacing: 8)` inside the `Section`, with the caption styled `.font(.subheadline).foregroundStyle(.secondary)`.
121121

122+
### Sheet design
123+
124+
Two sheet patterns in use — match the right one:
125+
126+
- **Form sheets** (data entry, e.g. New Sprite, New Checkpoint): `NavigationStack` > `Form` > `.navigationTitle` + `.navigationBarTitleDisplayMode(.inline)` + `.toolbar` with text Cancel / action-name buttons (e.g. "Cancel" / "Create"). Keep text labels — they're more informative than icons for actions with consequences.
127+
- **Utility/panel sheets** (e.g. Quick Actions): `NavigationStack` > custom content > `.navigationTitle` + `.navigationBarTitleDisplayMode(.inline)` + `Image(systemName: "xmark")` in `.cancellationAction`. `TabView` is fine for tabs here. Note: if you ever need a transparent sheet background, `TabView` will block it — its UIKit-backed view hierarchy ignores SwiftUI `.background(.clear)` and would need replacing with a custom VStack + HStack tab bar.
128+
129+
Both sheet types use opaque `Color(.systemBackground)` throughout — do **not** use material/transparent backgrounds on sheets. Materials suit bars and floating elements (popovers, context menus), not sheets.
130+
131+
Avoid sandwiching a fixed element (e.g. input bar) between two `Divider`s. A divider above the input bar separating scrollable content from a fixed action area is standard; a second one below it is redundant.
132+
122133
## Testing
123134

124135
- Run unit tests after making changes to verify nothing is broken

Wisp/Views/QuickActions/BashQuickView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ struct BashQuickView: View {
5151
}
5252
.frame(maxWidth: .infinity, minHeight: 100, alignment: .topLeading)
5353
}
54+
.background(.clear)
5455
.defaultScrollAnchor(.bottom)
5556
.onChange(of: viewModel.output) {
5657
proxy.scrollTo("output", anchor: .bottom)

Wisp/Views/QuickActions/QuickActionsView.swift

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,20 @@ struct QuickActionsView: View {
1010
@State private var selectedTab = 0
1111

1212
var body: some View {
13-
VStack(spacing: 0) {
14-
headerBar
15-
Divider()
13+
NavigationStack {
1614
tabs
15+
.navigationTitle(selectedTab == 0 ? "Quick Chat" : "Bash")
16+
.navigationBarTitleDisplayMode(.inline)
17+
.toolbar {
18+
ToolbarItem(placement: .cancellationAction) {
19+
Button(action: handleDone) {
20+
Image(systemName: "xmark")
21+
}
22+
}
23+
}
1724
}
1825
}
1926

20-
private var headerBar: some View {
21-
ZStack(alignment: .center) {
22-
Text(selectedTab == 0 ? "Quick Chat" : "Bash")
23-
.font(.headline)
24-
HStack {
25-
Button("Done", action: handleDone)
26-
.padding(.leading)
27-
Spacer()
28-
}
29-
}
30-
.frame(height: 44)
31-
.background(.bar)
32-
}
33-
3427
private var tabs: some View {
3528
TabView(selection: $selectedTab) {
3629
QuickChatView(viewModel: viewModel.quickChatViewModel)

Wisp/Views/QuickActions/QuickChatView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct QuickChatView: View {
4141
}
4242
.frame(maxWidth: .infinity, alignment: .leading)
4343
}
44+
.background(.clear)
4445
.defaultScrollAnchor(.bottom)
4546
.onChange(of: viewModel.response) {
4647
proxy.scrollTo("response", anchor: .bottom)

0 commit comments

Comments
 (0)