Create reusable expandable toggle component for all settings sections with auto-expand on enable and consistent alignment

This commit is contained in:
Beingpax 2025-12-31 16:43:23 +05:45
parent c9d57e5b89
commit a6c47240e7
3 changed files with 55 additions and 68 deletions

View File

@ -29,6 +29,15 @@ struct ExpandableToggleSection<Content: View>: View {
} }
.toggleStyle(.switch) .toggleStyle(.switch)
.help(helpText) .help(helpText)
.onChange(of: isEnabled) { _, newValue in
if newValue {
withAnimation(.easeInOut(duration: 0.2)) {
isExpanded = true
}
} else {
isExpanded = false
}
}
if isEnabled { if isEnabled {
Spacer() Spacer()

View File

@ -67,7 +67,6 @@ struct ExperimentalFeaturesSection: View {
Spacer() Spacer()
} }
.padding(.leading, 16)
} }
} }
} }

View File

@ -25,6 +25,8 @@ struct SettingsView: View {
@State private var isCustomSoundsExpanded = false @State private var isCustomSoundsExpanded = false
@State private var isSystemMuteExpanded = false @State private var isSystemMuteExpanded = false
@State private var isClipboardRestoreExpanded = false @State private var isClipboardRestoreExpanded = false
@State private var isCustomCancelExpanded = false
@State private var isMiddleClickExpanded = false
var body: some View { var body: some View {
@ -136,81 +138,60 @@ struct SettingsView: View {
Divider() Divider()
// Custom Cancel Shortcut ExpandableToggleSection(
VStack(alignment: .leading, spacing: 12) { title: "Custom Cancel Shortcut",
HStack(spacing: 8) { helpText: "Shortcut for cancelling the current recording session. Default: double-tap Escape.",
Toggle(isOn: $isCustomCancelEnabled.animation()) { isEnabled: $isCustomCancelEnabled,
Text("Custom Cancel Shortcut") isExpanded: $isCustomCancelExpanded
} ) {
.toggleStyle(.switch) HStack(spacing: 12) {
.onChange(of: isCustomCancelEnabled) { _, newValue in Text("Cancel Shortcut")
if !newValue { .font(.system(size: 13, weight: .medium))
KeyboardShortcuts.setShortcut(nil, for: .cancelRecorder) .foregroundColor(.secondary)
}
} KeyboardShortcuts.Recorder(for: .cancelRecorder)
.controlSize(.small)
InfoTip(
title: "Dismiss Recording", Spacer()
message: "Shortcut for cancelling the current recording session. Default: double-tap Escape."
)
} }
}
if isCustomCancelEnabled { .onChange(of: isCustomCancelEnabled) { _, newValue in
HStack(spacing: 12) { if !newValue {
Text("Cancel Shortcut") KeyboardShortcuts.setShortcut(nil, for: .cancelRecorder)
.font(.system(size: 13, weight: .medium))
.foregroundColor(.secondary)
KeyboardShortcuts.Recorder(for: .cancelRecorder)
.controlSize(.small)
Spacer()
}
.padding(.leading, 16)
.transition(.opacity.combined(with: .move(edge: .top)))
} }
} }
Divider() Divider()
// Middle-Click Toggle ExpandableToggleSection(
VStack(alignment: .leading, spacing: 12) { title: "Enable Middle-Click Toggle",
helpText: "Use middle mouse button to toggle VoiceInk recording.",
isEnabled: $hotkeyManager.isMiddleClickToggleEnabled,
isExpanded: $isMiddleClickExpanded
) {
HStack(spacing: 8) { HStack(spacing: 8) {
Toggle("Enable Middle-Click Toggle", isOn: $hotkeyManager.isMiddleClickToggleEnabled) Text("Activation Delay")
.toggleStyle(.switch) .font(.system(size: 13, weight: .medium))
.foregroundColor(.secondary)
InfoTip( TextField("", value: $hotkeyManager.middleClickActivationDelay, formatter: {
title: "Middle-Click Toggle", let formatter = NumberFormatter()
message: "Use middle mouse button to toggle VoiceInk recording." formatter.numberStyle = .none
) formatter.minimum = 0
} return formatter
}())
.textFieldStyle(PlainTextFieldStyle())
.padding(EdgeInsets(top: 3, leading: 6, bottom: 3, trailing: 6))
.background(Color(NSColor.textBackgroundColor))
.cornerRadius(5)
.frame(width: 70)
if hotkeyManager.isMiddleClickToggleEnabled { Text("ms")
HStack(spacing: 8) { .foregroundColor(.secondary)
Text("Activation Delay")
.font(.system(size: 13, weight: .medium))
.foregroundColor(.secondary)
TextField("", value: $hotkeyManager.middleClickActivationDelay, formatter: { Spacer()
let formatter = NumberFormatter()
formatter.numberStyle = .none
formatter.minimum = 0
return formatter
}())
.textFieldStyle(PlainTextFieldStyle())
.padding(EdgeInsets(top: 3, leading: 6, bottom: 3, trailing: 6))
.background(Color(NSColor.textBackgroundColor))
.cornerRadius(5)
.frame(width: 70)
Text("ms")
.foregroundColor(.secondary)
Spacer()
}
.padding(.leading, 16)
} }
} }
} }
@ -261,7 +242,6 @@ struct SettingsView: View {
Spacer() Spacer()
} }
.padding(.leading, 16)
} }
Divider() Divider()
@ -289,7 +269,6 @@ struct SettingsView: View {
Spacer() Spacer()
} }
.padding(.leading, 16)
} }
} }