refactor
Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
4f46304a5b
commit
4190c95b84
@ -64,7 +64,7 @@ struct ClockSettingsView: View {
|
||||
SettingsNavigationRow(
|
||||
title: String(localized: "settings.debug.icon_generator.title", defaultValue: "Icon Generator"),
|
||||
subtitle: String(localized: "settings.debug.icon_generator.subtitle", defaultValue: "Generate and save app icon"),
|
||||
backgroundColor: AppSurface.primary
|
||||
backgroundColor: .clear
|
||||
) {
|
||||
IconGeneratorView(config: .noiseClock, appName: "TheNoiseClock")
|
||||
}
|
||||
@ -72,7 +72,7 @@ struct ClockSettingsView: View {
|
||||
SettingsNavigationRow(
|
||||
title: String(localized: "settings.debug.branding_preview.title", defaultValue: "Branding Preview"),
|
||||
subtitle: String(localized: "settings.debug.branding_preview.subtitle", defaultValue: "Preview icon and launch screen"),
|
||||
backgroundColor: AppSurface.primary
|
||||
backgroundColor: .clear
|
||||
) {
|
||||
BrandingPreviewView(
|
||||
iconConfig: .noiseClock,
|
||||
@ -82,27 +82,26 @@ struct ClockSettingsView: View {
|
||||
}
|
||||
|
||||
if let onResetOnboarding {
|
||||
Divider()
|
||||
.background(AppBorder.subtle)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
Button {
|
||||
onResetOnboarding()
|
||||
} label: {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: Design.Spacing.xxSmall) {
|
||||
Text(String(localized: "settings.debug.reset_onboarding.title", defaultValue: "Reset Onboarding"))
|
||||
.typography(.body)
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
Text(String(localized: "settings.debug.reset_onboarding.subtitle", defaultValue: "Show onboarding screens again on next launch"))
|
||||
.typography(.caption)
|
||||
.foregroundStyle(AppTextColors.secondary)
|
||||
SettingsCardRow(verticalPadding: Design.Spacing.medium) {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: Design.Spacing.xxSmall) {
|
||||
Text(String(localized: "settings.debug.reset_onboarding.title", defaultValue: "Reset Onboarding"))
|
||||
.typography(.body)
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
Text(String(localized: "settings.debug.reset_onboarding.subtitle", defaultValue: "Show onboarding screens again on next launch"))
|
||||
.typography(.caption)
|
||||
.foregroundStyle(AppTextColors.secondary)
|
||||
}
|
||||
Spacer()
|
||||
Image(systemName: "arrow.counterclockwise")
|
||||
.foregroundStyle(AppAccent.primary)
|
||||
}
|
||||
Spacer()
|
||||
Image(systemName: "arrow.counterclockwise")
|
||||
.foregroundStyle(AppAccent.primary)
|
||||
}
|
||||
.padding(Design.Spacing.medium)
|
||||
.background(AppSurface.primary)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
|
||||
@ -34,10 +34,7 @@ struct AdvancedAppearanceSection: View {
|
||||
)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.advanced_appearance.randomize_color.title", defaultValue: "Randomize Color"),
|
||||
@ -46,10 +43,7 @@ struct AdvancedAppearanceSection: View {
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsSlider(
|
||||
title: String(localized: "settings.advanced_appearance.glow.title", defaultValue: "Glow"),
|
||||
@ -61,10 +55,7 @@ struct AdvancedAppearanceSection: View {
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsSlider(
|
||||
title: String(localized: "settings.advanced_appearance.clock_opacity.title", defaultValue: "Clock Opacity"),
|
||||
|
||||
@ -30,24 +30,18 @@ struct AdvancedDisplaySection: View {
|
||||
.accessibilityIdentifier("settings.keepAwake.toggle")
|
||||
|
||||
if style.autoBrightness {
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
HStack {
|
||||
Text(String(localized: "settings.advanced_display.current_brightness", defaultValue: "Current Brightness"))
|
||||
.font(.subheadline.weight(.medium))
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
Spacer()
|
||||
SettingsLabelValueRow(
|
||||
title: String(localized: "settings.advanced_display.current_brightness", defaultValue: "Current Brightness"),
|
||||
verticalPadding: Design.Spacing.medium
|
||||
) {
|
||||
Text(style.effectiveBrightness, format: .percent.precision(.fractionLength(0)))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(AppTextColors.secondary)
|
||||
.contentTransition(.numericText())
|
||||
.animation(.snappy(duration: 0.3), value: style.effectiveBrightness)
|
||||
}
|
||||
.padding(.vertical, Design.Spacing.medium)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,33 +46,27 @@ struct BasicAppearanceSection: View {
|
||||
}
|
||||
|
||||
if style.selectedColorTheme == "Custom" {
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
ColorPicker(
|
||||
String(localized: "settings.colors.digit_color", defaultValue: "Digit Color"),
|
||||
selection: $digitColor,
|
||||
supportsOpacity: false
|
||||
)
|
||||
SettingsCardRow {
|
||||
ColorPicker(
|
||||
String(localized: "settings.colors.digit_color", defaultValue: "Digit Color"),
|
||||
selection: $digitColor,
|
||||
supportsOpacity: false
|
||||
)
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
.padding(.vertical, Design.Spacing.small)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
ColorPicker(
|
||||
String(localized: "settings.colors.background_color", defaultValue: "Background Color"),
|
||||
selection: $backgroundColor,
|
||||
supportsOpacity: true
|
||||
)
|
||||
SettingsCardRow {
|
||||
ColorPicker(
|
||||
String(localized: "settings.colors.background_color", defaultValue: "Background Color"),
|
||||
selection: $backgroundColor,
|
||||
supportsOpacity: true
|
||||
)
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
.padding(.vertical, Design.Spacing.small)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,10 +28,7 @@ struct BasicDisplaySection: View {
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.display.show_seconds.title", defaultValue: "Show Seconds"),
|
||||
@ -41,10 +38,7 @@ struct BasicDisplaySection: View {
|
||||
)
|
||||
|
||||
if !style.use24Hour {
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.display.show_ampm.title", defaultValue: "Show AM/PM"),
|
||||
@ -54,10 +48,7 @@ struct BasicDisplaySection: View {
|
||||
)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.display.auto_brightness.title", defaultValue: "Auto Brightness"),
|
||||
@ -67,10 +58,7 @@ struct BasicDisplaySection: View {
|
||||
)
|
||||
|
||||
if UIDevice.current.orientation.isPortrait || UIDevice.current.orientation == .unknown {
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.display.horizontal_mode.title", defaultValue: "Horizontal Mode"),
|
||||
|
||||
@ -62,10 +62,7 @@ struct FontSection: View {
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
// Font Weight
|
||||
SettingsNavigationRow(
|
||||
@ -82,10 +79,7 @@ struct FontSection: View {
|
||||
}
|
||||
|
||||
if style.fontFamily == .system {
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
// Font Design
|
||||
SettingsNavigationRow(
|
||||
@ -102,20 +96,15 @@ struct FontSection: View {
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
HStack {
|
||||
Text(String(localized: "settings.font.preview.title", defaultValue: "Preview")).styled(.subheadingEmphasis)
|
||||
Spacer()
|
||||
SettingsLabelValueRow(
|
||||
title: String(localized: "settings.font.preview.title", defaultValue: "Preview")
|
||||
) {
|
||||
Text(String(localized: "settings.font.preview.sample_time", defaultValue: "12:34"))
|
||||
.font(FontUtils.createFont(name: style.fontFamily, weight: style.fontWeight, design: style.fontDesign, size: 24))
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
}
|
||||
.padding(.vertical, Design.Spacing.small)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,10 +28,7 @@ struct NightModeSection: View {
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.night_mode.auto.title", defaultValue: "Auto Night Mode"),
|
||||
@ -41,10 +38,7 @@ struct NightModeSection: View {
|
||||
)
|
||||
|
||||
if style.autoNightMode {
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsSlider(
|
||||
title: String(localized: "settings.night_mode.light_threshold.title", defaultValue: "Light Threshold"),
|
||||
@ -57,10 +51,7 @@ struct NightModeSection: View {
|
||||
)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.night_mode.scheduled.title", defaultValue: "Scheduled Night Mode"),
|
||||
@ -70,53 +61,38 @@ struct NightModeSection: View {
|
||||
)
|
||||
|
||||
if style.scheduledNightMode {
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
HStack {
|
||||
Text(String(localized: "settings.night_mode.start_time", defaultValue: "Start Time"))
|
||||
.font(.subheadline.weight(.medium))
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
Spacer()
|
||||
TimePickerView(timeString: $style.nightModeStartTime)
|
||||
SettingsLabelValueRow(
|
||||
title: String(localized: "settings.night_mode.start_time", defaultValue: "Start Time"),
|
||||
verticalPadding: Design.Spacing.medium
|
||||
) {
|
||||
SettingsTimePicker(timeString: $style.nightModeStartTime, accentColor: AppAccent.primary)
|
||||
}
|
||||
.padding(.vertical, Design.Spacing.medium)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
HStack {
|
||||
Text(String(localized: "settings.night_mode.end_time", defaultValue: "End Time"))
|
||||
.font(.subheadline.weight(.medium))
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
Spacer()
|
||||
TimePickerView(timeString: $style.nightModeEndTime)
|
||||
SettingsLabelValueRow(
|
||||
title: String(localized: "settings.night_mode.end_time", defaultValue: "End Time"),
|
||||
verticalPadding: Design.Spacing.medium
|
||||
) {
|
||||
SettingsTimePicker(timeString: $style.nightModeEndTime, accentColor: AppAccent.primary)
|
||||
}
|
||||
.padding(.vertical, Design.Spacing.medium)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
}
|
||||
|
||||
if style.isNightModeActive {
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
HStack(spacing: Design.Spacing.xSmall) {
|
||||
Image(systemName: "moon.fill")
|
||||
.foregroundStyle(AppStatus.error)
|
||||
Text(String(localized: "settings.night_mode.active", defaultValue: "Night Mode Active"))
|
||||
.font(.subheadline.weight(.medium))
|
||||
.foregroundStyle(AppStatus.error)
|
||||
Spacer()
|
||||
SettingsCardRow {
|
||||
HStack(spacing: Design.Spacing.xSmall) {
|
||||
Image(systemName: "moon.fill")
|
||||
.foregroundStyle(AppStatus.error)
|
||||
Text(String(localized: "settings.night_mode.active", defaultValue: "Night Mode Active"))
|
||||
.font(.subheadline.weight(.medium))
|
||||
.foregroundStyle(AppStatus.error)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.padding(.vertical, Design.Spacing.small)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,10 +30,7 @@ struct OverlaySection: View {
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.overlays.date.title", defaultValue: "Date"),
|
||||
@ -42,10 +39,7 @@ struct OverlaySection: View {
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.overlays.next_alarm.title", defaultValue: "Next Alarm"),
|
||||
@ -54,10 +48,7 @@ struct OverlaySection: View {
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsToggle(
|
||||
title: String(localized: "settings.overlays.noise_controls.title", defaultValue: "Noise Controls"),
|
||||
@ -67,10 +58,7 @@ struct OverlaySection: View {
|
||||
)
|
||||
|
||||
if style.showDate {
|
||||
Rectangle()
|
||||
.fill(AppBorder.subtle)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, Design.Spacing.small)
|
||||
SettingsDivider(color: AppBorder.subtle)
|
||||
|
||||
SettingsNavigationRow(
|
||||
title: String(localized: "settings.overlays.date_format.title", defaultValue: "Date Format"),
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
//
|
||||
// TimePickerView.swift
|
||||
// TheNoiseClock
|
||||
//
|
||||
// Created by Matt Bruce on 9/7/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Bedrock
|
||||
|
||||
struct TimePickerView: View {
|
||||
@Binding var timeString: String
|
||||
@State private var selectedTime = Date()
|
||||
|
||||
var body: some View {
|
||||
DatePicker("", selection: $selectedTime, displayedComponents: .hourAndMinute)
|
||||
.labelsHidden()
|
||||
.tint(AppAccent.primary)
|
||||
.onAppear {
|
||||
updateSelectedTimeFromString()
|
||||
}
|
||||
.onChange(of: selectedTime) { _, newTime in
|
||||
updateStringFromTime(newTime)
|
||||
}
|
||||
.onChange(of: timeString) { _, _ in
|
||||
updateSelectedTimeFromString()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateSelectedTimeFromString() {
|
||||
let components = timeString.split(separator: ":")
|
||||
guard components.count == 2,
|
||||
let hour = Int(components[0]),
|
||||
let minute = Int(components[1]) else {
|
||||
return
|
||||
}
|
||||
|
||||
let calendar = Calendar.current
|
||||
let now = Date()
|
||||
let dateComponents = calendar.dateComponents([.year, .month, .day], from: now)
|
||||
|
||||
var newComponents = dateComponents
|
||||
newComponents.hour = hour
|
||||
newComponents.minute = minute
|
||||
|
||||
if let newDate = calendar.date(from: newComponents) {
|
||||
selectedTime = newDate
|
||||
}
|
||||
}
|
||||
|
||||
private func updateStringFromTime(_ time: Date) {
|
||||
let calendar = Calendar.current
|
||||
let hour = calendar.component(.hour, from: time)
|
||||
let minute = calendar.component(.minute, from: time)
|
||||
timeString = String(format: "%02d:%02d", hour, minute)
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,6 @@
|
||||
{
|
||||
"sourceLanguage" : "en",
|
||||
"strings" : {
|
||||
"" : {
|
||||
|
||||
},
|
||||
"alarm_intent.error.alarm_not_found" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
|
||||
@ -1,83 +0,0 @@
|
||||
//
|
||||
// SettingsSelectionView.swift
|
||||
// TheNoiseClock
|
||||
//
|
||||
// Created by Matt Bruce on 9/8/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Bedrock
|
||||
|
||||
/// A reusable selection view for settings that navigates to a new screen.
|
||||
struct SettingsSelectionView<T: Hashable>: View {
|
||||
@Binding var selection: T
|
||||
let options: [T]
|
||||
let title: String
|
||||
let toString: (T) -> String
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
AppSurface.primary.ignoresSafeArea()
|
||||
|
||||
ScrollView {
|
||||
VStack(spacing: Design.Spacing.medium) {
|
||||
SettingsSectionHeader(
|
||||
title: title,
|
||||
systemImage: "checklist",
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
|
||||
SettingsCard(backgroundColor: AppSurface.card, borderColor: AppBorder.subtle) {
|
||||
VStack(spacing: 0) {
|
||||
ForEach(options, id: \.self) { option in
|
||||
Button(action: {
|
||||
selection = option
|
||||
dismiss()
|
||||
}) {
|
||||
HStack {
|
||||
Text(toString(option))
|
||||
.typography(.body)
|
||||
.foregroundStyle(AppTextColors.primary)
|
||||
Spacer()
|
||||
if selection == option {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundStyle(AppAccent.primary)
|
||||
.font(.body.bold())
|
||||
}
|
||||
}
|
||||
.padding(Design.Spacing.medium)
|
||||
.background(Color.clear)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
|
||||
if option != options.last {
|
||||
Divider()
|
||||
.background(AppBorder.subtle)
|
||||
.padding(.horizontal, Design.Spacing.medium)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, Design.Spacing.large)
|
||||
.padding(.top, Design.Spacing.large)
|
||||
.padding(.bottom, Design.Spacing.xxxLarge)
|
||||
}
|
||||
}
|
||||
.navigationTitle(title)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
NavigationStack {
|
||||
SettingsSelectionView(
|
||||
selection: .constant("Option 1"),
|
||||
options: ["Option 1", "Option 2", "Option 3"],
|
||||
title: "Test Selection",
|
||||
toString: { $0 }
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user