diff --git a/Cotabby/UI/CustomRulesEditor.swift b/Cotabby/UI/CustomRulesEditor.swift index d7ef67b7..442f6263 100644 --- a/Cotabby/UI/CustomRulesEditor.swift +++ b/Cotabby/UI/CustomRulesEditor.swift @@ -9,6 +9,11 @@ import SwiftUI struct CustomRulesEditor: View { @ObservedObject var suggestionSettings: SuggestionSettingsModel + /// When false, the editor drops its own "Rules" title so an enclosing `Section("Rules")` can + /// supply the heading without duplicating it. The Clear control stays in place either way. + /// Defaults to true so standalone uses (e.g. onboarding) keep their inline title. + var showsTitleHeader: Bool = true + @State private var inputText: String = "" private var rules: [String] { suggestionSettings.customRules } @@ -27,17 +32,21 @@ struct CustomRulesEditor: View { var body: some View { VStack(alignment: .leading, spacing: 14) { - HStack { - Text("Rules") - .font(.system(size: 13, weight: .medium)) - Spacer() - if canClear { - Button("Clear") { - suggestionSettings.clearRules() + if showsTitleHeader || canClear { + HStack { + if showsTitleHeader { + Text("Rules") + .font(.system(size: 13, weight: .medium)) + } + Spacer() + if canClear { + Button("Clear") { + suggestionSettings.clearRules() + } + .buttonStyle(.plain) + .font(.system(size: 12)) + .foregroundStyle(.secondary) } - .buttonStyle(.plain) - .font(.system(size: 12)) - .foregroundStyle(.secondary) } } diff --git a/Cotabby/UI/LanguageTagsEditor.swift b/Cotabby/UI/LanguageTagsEditor.swift index e0fe002d..ca23454a 100644 --- a/Cotabby/UI/LanguageTagsEditor.swift +++ b/Cotabby/UI/LanguageTagsEditor.swift @@ -8,6 +8,11 @@ import SwiftUI struct LanguageTagsEditor: View { @ObservedObject var suggestionSettings: SuggestionSettingsModel + /// When false, the editor drops its own "Languages" title so an enclosing `Section("Languages")` + /// can supply the heading without duplicating it. The Clear control stays in place either way. + /// Defaults to true so standalone uses (e.g. onboarding) keep their inline title. + var showsTitleHeader: Bool = true + @State private var inputText: String = "" private var languages: [String] { suggestionSettings.responseLanguages } @@ -26,17 +31,21 @@ struct LanguageTagsEditor: View { var body: some View { VStack(alignment: .leading, spacing: 14) { - HStack { - Text("Languages") - .font(.system(size: 13, weight: .medium)) - Spacer() - if canClear { - Button("Clear") { - suggestionSettings.clearLanguages() + if showsTitleHeader || canClear { + HStack { + if showsTitleHeader { + Text("Languages") + .font(.system(size: 13, weight: .medium)) + } + Spacer() + if canClear { + Button("Clear") { + suggestionSettings.clearLanguages() + } + .buttonStyle(.plain) + .font(.system(size: 12)) + .foregroundStyle(.secondary) } - .buttonStyle(.plain) - .font(.system(size: 12)) - .foregroundStyle(.secondary) } } diff --git a/Cotabby/UI/Settings/Panes/AppsPaneView.swift b/Cotabby/UI/Settings/Panes/AppsPaneView.swift index 79267359..7e7a839a 100644 --- a/Cotabby/UI/Settings/Panes/AppsPaneView.swift +++ b/Cotabby/UI/Settings/Panes/AppsPaneView.swift @@ -13,7 +13,7 @@ struct AppsPaneView: View { var body: some View { SettingsPaneScaffold { - Section("Apps") { + Section("Disabled Apps") { Text("Cotabby won't autocomplete in these apps. Add an app you can't disable from the " + "menu bar, like a launcher that closes the moment it loses focus.") .font(.caption) diff --git a/Cotabby/UI/Settings/Panes/GeneralPaneView.swift b/Cotabby/UI/Settings/Panes/GeneralPaneView.swift index 996c668d..52ce2ac0 100644 --- a/Cotabby/UI/Settings/Panes/GeneralPaneView.swift +++ b/Cotabby/UI/Settings/Panes/GeneralPaneView.swift @@ -14,7 +14,7 @@ struct GeneralPaneView: View { var body: some View { SettingsPaneScaffold { - Section { + Section("Status") { Toggle("Enable Globally", isOn: globallyEnabledBinding) // Fast Mode is the most user-facing performance lever, so it gets prime real @@ -92,7 +92,7 @@ struct GeneralPaneView: View { } } - Section { + Section("Help") { LabeledContent("Onboarding") { Button("Open Welcome Guide") { onShowWelcome() diff --git a/Cotabby/UI/Settings/Panes/ShortcutsPaneView.swift b/Cotabby/UI/Settings/Panes/ShortcutsPaneView.swift index 221ced6e..756ed134 100644 --- a/Cotabby/UI/Settings/Panes/ShortcutsPaneView.swift +++ b/Cotabby/UI/Settings/Panes/ShortcutsPaneView.swift @@ -13,9 +13,11 @@ struct ShortcutsPaneView: View { var body: some View { SettingsPaneScaffold { - Section("Shortcuts") { + Section("Mode") { AcceptanceModePickerView(suggestionSettings: suggestionSettings) + } + Section("Keys") { LabeledContent("Accept Word") { KeybindRow( label: suggestionSettings.acceptanceKeyLabel, diff --git a/Cotabby/UI/Settings/Panes/WritingPaneView.swift b/Cotabby/UI/Settings/Panes/WritingPaneView.swift index 43882978..1465740d 100644 --- a/Cotabby/UI/Settings/Panes/WritingPaneView.swift +++ b/Cotabby/UI/Settings/Panes/WritingPaneView.swift @@ -10,7 +10,7 @@ struct WritingPaneView: View { var body: some View { SettingsPaneScaffold { - Section("Writing") { + Section("Length") { Picker("Length", selection: selectedWordCountPresetBinding) { ForEach(SuggestionWordCountPreset.allCases) { preset in Text(preset.displayLabel).tag(preset) @@ -19,10 +19,13 @@ struct WritingPaneView: View { } Section("Profile") { - VStack(alignment: .leading, spacing: 24) { - Text("This information is passed to the AI to help personalize your completions.") + VStack(alignment: .leading, spacing: 16) { + // The caption introduces all three personalization inputs (name, languages, + // rules) since each is passed to the AI, even though they live in separate cards. + Text("Your name, languages, and rules are passed to the AI to help personalize your completions.") .font(.caption) .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) VStack(alignment: .leading, spacing: 8) { Text("Name") @@ -34,12 +37,20 @@ struct WritingPaneView: View { )) .textFieldStyle(.roundedBorder) } + } + .padding(.vertical, 6) + } - LanguageTagsEditor(suggestionSettings: suggestionSettings) + // The editors suppress their own titles here so the Section headers ("Languages"/"Rules") + // carry the heading, matching the explicit-header pattern used across the pane. + Section("Languages") { + LanguageTagsEditor(suggestionSettings: suggestionSettings, showsTitleHeader: false) + .padding(.vertical, 6) + } - CustomRulesEditor(suggestionSettings: suggestionSettings) - } - .padding(.vertical, 10) + Section("Rules") { + CustomRulesEditor(suggestionSettings: suggestionSettings, showsTitleHeader: false) + .padding(.vertical, 6) } } }