feat: Styles views for macos
This commit is contained in:
@@ -284,9 +284,10 @@ public struct EquipmentMeasurementFormView: View {
|
|||||||
if store.allowEquipmentTypeSelection {
|
if store.allowEquipmentTypeSelection {
|
||||||
Section {
|
Section {
|
||||||
} header: {
|
} header: {
|
||||||
Text("Equipment Type")
|
SectionHeaderLabel("Equipment Type")
|
||||||
} footer: {
|
} footer: {
|
||||||
EquipmentTypePicker(selection: $store.equipmentType)
|
EquipmentTypePicker(selection: $store.equipmentType)
|
||||||
|
.dynamicBottomPadding()
|
||||||
.pickerStyle(.segmented)
|
.pickerStyle(.segmented)
|
||||||
.labelsHidden()
|
.labelsHidden()
|
||||||
}
|
}
|
||||||
@@ -295,9 +296,10 @@ public struct EquipmentMeasurementFormView: View {
|
|||||||
Grid(alignment: .leading, horizontalSpacing: 40) {
|
Grid(alignment: .leading, horizontalSpacing: 40) {
|
||||||
ForEach(store.pressureFields, content: gridRow(for:))
|
ForEach(store.pressureFields, content: gridRow(for:))
|
||||||
}
|
}
|
||||||
|
.dynamicBottomPadding()
|
||||||
} header: {
|
} header: {
|
||||||
HStack {
|
HStack {
|
||||||
Text("Static Measurements")
|
SectionHeaderLabel("Static Measurements")
|
||||||
Spacer()
|
Spacer()
|
||||||
InfoButton { send(.infoButtonTapped) }
|
InfoButton { send(.infoButtonTapped) }
|
||||||
}
|
}
|
||||||
@@ -310,7 +312,7 @@ public struct EquipmentMeasurementFormView: View {
|
|||||||
} header: {
|
} header: {
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(store.sharedSettings.equipmentMetadata.coolingCapacity.description)
|
SectionHeaderLabel(store.sharedSettings.equipmentMetadata.coolingCapacity.description)
|
||||||
}
|
}
|
||||||
} footer: {
|
} footer: {
|
||||||
HStack {
|
HStack {
|
||||||
@@ -348,7 +350,8 @@ public struct EquipmentMeasurementFormView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func gridRow(for field: EquipmentMeasurementForm.State.Field) -> some View {
|
private func gridRow(for field: EquipmentMeasurementForm.State.Field) -> some View {
|
||||||
TextLabeledContent(store.label(field: field)) {
|
GridRow {
|
||||||
|
TextLabel(store.label(field: field))
|
||||||
textField(for: field)
|
textField(for: field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,18 +133,19 @@ public struct EquipmentSettingsFormView: View {
|
|||||||
Form {
|
Form {
|
||||||
Section {
|
Section {
|
||||||
EquipmentTypePicker(selection: $store.equipmentType)
|
EquipmentTypePicker(selection: $store.equipmentType)
|
||||||
|
.dynamicBottomPadding()
|
||||||
.pickerStyle(.segmented)
|
.pickerStyle(.segmented)
|
||||||
EmptyView()
|
|
||||||
} header: {
|
} header: {
|
||||||
Text("Equipment Type")
|
SectionHeaderLabel("Equipment Type")
|
||||||
}
|
}
|
||||||
.listRowBackground(Color.clear)
|
.listRowBackground(Color.clear)
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
FanTypePicker(selection: $store.sharedSettings.fanType)
|
FanTypePicker(selection: $store.sharedSettings.fanType)
|
||||||
|
.dynamicBottomPadding()
|
||||||
.pickerStyle(.segmented)
|
.pickerStyle(.segmented)
|
||||||
} header: {
|
} header: {
|
||||||
Text("Fan Type")
|
SectionHeaderLabel("Fan Type")
|
||||||
}
|
}
|
||||||
.listRowBackground(Color.clear)
|
.listRowBackground(Color.clear)
|
||||||
|
|
||||||
@@ -175,11 +176,13 @@ public struct EquipmentSettingsFormView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.dynamicBottomPadding()
|
||||||
|
// .applyPadding()
|
||||||
} header: {
|
} header: {
|
||||||
if store.equipmentType == .airHandler {
|
if store.equipmentType == .airHandler {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
} else {
|
} else {
|
||||||
Text("Capacities")
|
SectionHeaderLabel("Capacities")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +190,7 @@ public struct EquipmentSettingsFormView: View {
|
|||||||
Grid(alignment: .leading, horizontalSpacing: 40) {
|
Grid(alignment: .leading, horizontalSpacing: 40) {
|
||||||
ForEach(RatingsField.allCases, content: ratingsRow(for:))
|
ForEach(RatingsField.allCases, content: ratingsRow(for:))
|
||||||
}
|
}
|
||||||
|
.dynamicBottomPadding()
|
||||||
.labeledContentStyle(.gridRow)
|
.labeledContentStyle(.gridRow)
|
||||||
} header: {
|
} header: {
|
||||||
header("Rated Static Pressure", infoView: .ratedStaticPressures)
|
header("Rated Static Pressure", infoView: .ratedStaticPressures)
|
||||||
@@ -262,7 +266,7 @@ public struct EquipmentSettingsFormView: View {
|
|||||||
label: @escaping () -> Label
|
label: @escaping () -> Label
|
||||||
) -> some View {
|
) -> some View {
|
||||||
HStack {
|
HStack {
|
||||||
label()
|
SectionHeaderLabel { label() }
|
||||||
Spacer()
|
Spacer()
|
||||||
InfoButton { send(.infoButtonTapped(infoView)) }
|
InfoButton { send(.infoButtonTapped(infoView)) }
|
||||||
}
|
}
|
||||||
@@ -285,6 +289,17 @@ public struct EquipmentSettingsFormView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate extension View {
|
||||||
|
@ViewBuilder
|
||||||
|
func applyPadding() -> some View {
|
||||||
|
#if os(macOS)
|
||||||
|
self.padding(.bottom, 20)
|
||||||
|
#else
|
||||||
|
self
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fileprivate struct BudgetFlagViewStyle: FlaggedViewStyle {
|
fileprivate struct BudgetFlagViewStyle: FlaggedViewStyle {
|
||||||
|
|
||||||
func makeBody(configuration: Configuration) -> some View {
|
func makeBody(configuration: Configuration) -> some View {
|
||||||
|
|||||||
@@ -108,9 +108,11 @@ public struct PressureEstimationsView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
EquipmentSettingsFormView(
|
ScrollView {
|
||||||
store: store.scope(state: \.equipmentSettings, action: \.equipmentSettings)
|
EquipmentSettingsFormView(
|
||||||
)
|
store: store.scope(state: \.equipmentSettings, action: \.equipmentSettings)
|
||||||
|
)
|
||||||
|
}
|
||||||
.navigationTitle("Equipment Settings")
|
.navigationTitle("Equipment Settings")
|
||||||
.toolbar {
|
.toolbar {
|
||||||
NextButton { send(.nextButtonTapped) }
|
NextButton { send(.nextButtonTapped) }
|
||||||
@@ -123,10 +125,11 @@ public struct PressureEstimationsView: View {
|
|||||||
action: \.destination.equipmentMeasurements
|
action: \.destination.equipmentMeasurements
|
||||||
)
|
)
|
||||||
) { measurementStore in
|
) { measurementStore in
|
||||||
EquipmentMeasurementFormView(store: measurementStore)
|
ScrollView {
|
||||||
.navigationTitle("Existing Measurements")
|
EquipmentMeasurementFormView(store: measurementStore)
|
||||||
|
.navigationTitle("Existing Measurements")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
Sources/Styleguide/Modifiers/DynamicPaddingModifier.swift
Normal file
18
Sources/Styleguide/Modifiers/DynamicPaddingModifier.swift
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import SharedModels
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
|
||||||
|
public func dynamicBottomPadding(
|
||||||
|
iOS iOSPadding: CGFloat? = nil,
|
||||||
|
macOS macOSPadding: CGFloat? = 40
|
||||||
|
) -> some View {
|
||||||
|
self
|
||||||
|
#if os(macOS)
|
||||||
|
.padding(.bottom, macOSPadding)
|
||||||
|
#elseif os(iOS)
|
||||||
|
.padding(.bottom, iOSPadding)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
50
Sources/Styleguide/SectionHeaderLabel.swift
Normal file
50
Sources/Styleguide/SectionHeaderLabel.swift
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
public struct SectionHeaderLabel<Content: View>: View {
|
||||||
|
@Environment(\.sectionHeaderLabelStyle) var style
|
||||||
|
|
||||||
|
let content: () -> Content
|
||||||
|
|
||||||
|
public init(@ViewBuilder _ content: @escaping () -> Content) {
|
||||||
|
self.content = content
|
||||||
|
}
|
||||||
|
|
||||||
|
public var body: some View {
|
||||||
|
style.makeBody(
|
||||||
|
configuration: TextLabelConfiguration(
|
||||||
|
label: TextLabelConfiguration.Label(content: content())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SectionHeaderLabel where Content == Text {
|
||||||
|
|
||||||
|
public init(_ text: LocalizedStringKey) {
|
||||||
|
self.init { Text(text) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public init<S>(_ text: S) where S: StringProtocol {
|
||||||
|
self.init { Text(text) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
Form {
|
||||||
|
Section {
|
||||||
|
Text("Content")
|
||||||
|
} header: {
|
||||||
|
SectionHeaderLabel("One")
|
||||||
|
}
|
||||||
|
|
||||||
|
Section {
|
||||||
|
Text("Content")
|
||||||
|
} header: {
|
||||||
|
SectionHeaderLabel("Two")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formStyle(.grouped)
|
||||||
|
#if os(macOS)
|
||||||
|
.frame(width: 400, height: 400)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ extension View {
|
|||||||
public func applyFormStyle() -> some View {
|
public func applyFormStyle() -> some View {
|
||||||
self
|
self
|
||||||
.labelsHidden()
|
.labelsHidden()
|
||||||
|
// .formStyle(.grouped)
|
||||||
.textLabelStyle(.boldSecondary)
|
.textLabelStyle(.boldSecondary)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
|
|||||||
@@ -67,6 +67,15 @@ public struct AutomaticTextLabelStyle: TextLabelStyle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct DefaultSectionHeaderLabelStyle: TextLabelStyle {
|
||||||
|
public func makeBody(configuration: Configuration) -> some View {
|
||||||
|
configuration.label
|
||||||
|
#if os(macOS)
|
||||||
|
.font(.headline)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private struct TextLabelStyleKey: EnvironmentKey {
|
private struct TextLabelStyleKey: EnvironmentKey {
|
||||||
static let defaultValue = MainActor.assumeIsolated {
|
static let defaultValue = MainActor.assumeIsolated {
|
||||||
AnyTextLabelStyle(style: AutomaticTextLabelStyle())
|
AnyTextLabelStyle(style: AutomaticTextLabelStyle())
|
||||||
@@ -75,7 +84,7 @@ private struct TextLabelStyleKey: EnvironmentKey {
|
|||||||
|
|
||||||
private struct SectionHeaderLabelStyleKey: EnvironmentKey {
|
private struct SectionHeaderLabelStyleKey: EnvironmentKey {
|
||||||
static let defaultValue = MainActor.assumeIsolated {
|
static let defaultValue = MainActor.assumeIsolated {
|
||||||
AnyTextLabelStyle(style: AutomaticTextLabelStyle())
|
AnyTextLabelStyle(style: DefaultSectionHeaderLabelStyle())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user