- SettingsToggle.swift - Toggle row with title/subtitle - VolumePicker.swift - Volume slider with speaker icons - SegmentedPicker.swift - Horizontal capsule-style picker - SelectableRow.swift - Card-like selectable row with badge support - SelectionIndicator.swift - Checkmark/outline selection indicator - BadgePill.swift - Capsule-shaped badge for values/tags - SettingsSectionHeader.swift - Section header with icon - SettingsRow.swift - Navigation-style row with icon Each file has its own preview for easier development.
79 lines
2.4 KiB
Swift
79 lines
2.4 KiB
Swift
//
|
|
// VolumePicker.swift
|
|
// Bedrock
|
|
//
|
|
// A volume slider with speaker icons.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
/// A volume slider with speaker icons.
|
|
///
|
|
/// Use this for audio volume or similar 0-1 range settings.
|
|
public struct VolumePicker: View {
|
|
/// The label for the picker.
|
|
public let label: String
|
|
|
|
/// Binding to the volume level (0.0 to 1.0).
|
|
@Binding public var volume: Float
|
|
|
|
/// The accent color for the slider.
|
|
public let accentColor: Color
|
|
|
|
/// Creates a volume picker.
|
|
/// - Parameters:
|
|
/// - label: The label text (default: "Volume").
|
|
/// - volume: Binding to volume (0.0-1.0).
|
|
/// - accentColor: The accent color (default: primary accent).
|
|
public init(
|
|
label: String = "Volume",
|
|
volume: Binding<Float>,
|
|
accentColor: Color = .Accent.primary
|
|
) {
|
|
self.label = label
|
|
self._volume = volume
|
|
self.accentColor = accentColor
|
|
}
|
|
|
|
public var body: some View {
|
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
|
HStack {
|
|
Text(label)
|
|
.font(.system(size: Design.BaseFontSize.medium, weight: .medium))
|
|
.foregroundStyle(.white)
|
|
|
|
Spacer()
|
|
|
|
Text("\(Int(volume * 100))%")
|
|
.font(.system(size: Design.BaseFontSize.body, weight: .medium, design: .rounded))
|
|
.foregroundStyle(.white.opacity(Design.Opacity.medium))
|
|
}
|
|
|
|
HStack(spacing: Design.Spacing.medium) {
|
|
Image(systemName: "speaker.fill")
|
|
.font(.system(size: Design.BaseFontSize.body))
|
|
.foregroundStyle(.white.opacity(Design.Opacity.medium))
|
|
|
|
Slider(value: $volume, in: 0...1, step: 0.1)
|
|
.tint(accentColor)
|
|
|
|
Image(systemName: "speaker.wave.3.fill")
|
|
.font(.system(size: Design.BaseFontSize.body))
|
|
.foregroundStyle(.white.opacity(Design.Opacity.medium))
|
|
}
|
|
}
|
|
.padding(.vertical, Design.Spacing.xSmall)
|
|
}
|
|
}
|
|
|
|
// MARK: - Preview
|
|
|
|
#Preview {
|
|
VStack(spacing: Design.Spacing.medium) {
|
|
VolumePicker(volume: .constant(0.8))
|
|
VolumePicker(label: "Music", volume: .constant(0.5))
|
|
}
|
|
.padding()
|
|
.background(Color.Surface.overlay)
|
|
}
|