Improve footers in macOS form sections (#814)
Revisit the use of informational footers in forms because: - iOS uses Section footers - macOS uses a secondary label below the main row label Therefore: - Add .themeRow() modifier to accomplish macOS behavior - iOS: leave .themeSection() as is, and add a dummy .themeRow() that does nothing - macOS: make footer ineffective in .themeSection(), but add .themeRow() modifiers to move footers to rows
This commit is contained in:
parent
346aaec441
commit
735d3b2fbe
|
@ -103,6 +103,7 @@ private extension OnDemandView {
|
|||
}
|
||||
}
|
||||
.themeSection(footer: policyFooterDescription)
|
||||
.themeRow(footer: policyFooterDescription)
|
||||
}
|
||||
|
||||
var policyFooterDescription: String {
|
||||
|
|
|
@ -51,6 +51,7 @@ struct AppleTVSection: View {
|
|||
private extension AppleTVSection {
|
||||
var availableToggle: some View {
|
||||
Toggle(Strings.Modules.General.Rows.appleTv(Strings.Unlocalized.appleTV), isOn: $profileEditor.isAvailableForTV)
|
||||
.themeRow(footer: footer)
|
||||
}
|
||||
|
||||
var purchaseButton: some View {
|
||||
|
|
|
@ -44,7 +44,7 @@ struct StorageSection: View {
|
|||
}
|
||||
.themeSection(
|
||||
header: Strings.Global.storage,
|
||||
footer: Strings.Modules.General.Sections.Storage.footer
|
||||
footer: footer
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,11 @@ struct StorageSection: View {
|
|||
private extension StorageSection {
|
||||
var sharingToggle: some View {
|
||||
Toggle(Strings.Modules.General.Rows.icloudSharing, isOn: $profileEditor.isShared)
|
||||
.themeRow(footer: footer)
|
||||
}
|
||||
|
||||
var footer: String {
|
||||
Strings.Modules.General.Sections.Storage.footer
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,10 +56,11 @@ struct SettingsSectionGroup: View {
|
|||
.themeSection(header: Strings.Global.general)
|
||||
Group {
|
||||
eraseCloudKitButton
|
||||
.themeRow(footer: iCloudFooter)
|
||||
}
|
||||
.themeSection(
|
||||
header: Strings.Unlocalized.iCloud,
|
||||
footer: Strings.Views.Settings.Sections.Icloud.footer
|
||||
footer: iCloudFooter
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -99,4 +100,8 @@ private extension SettingsSectionGroup {
|
|||
}
|
||||
.disabled(isErasingiCloud)
|
||||
}
|
||||
|
||||
var iCloudFooter: String {
|
||||
Strings.Views.Settings.Sections.Icloud.footer
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,6 +130,13 @@ extension ThemeSectionWithHeaderFooterModifier {
|
|||
}
|
||||
}
|
||||
|
||||
extension ThemeRowWithFooterModifier {
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
// omit footer on iOS/tvOS, use ThemeSectionWithHeaderFooterModifier
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Views
|
||||
|
||||
extension ThemeTappableText {
|
||||
|
|
|
@ -78,14 +78,25 @@ extension ThemeSectionWithHeaderFooterModifier {
|
|||
func body(content: Content) -> some View {
|
||||
Section {
|
||||
content
|
||||
} header: {
|
||||
header.map(Text.init)
|
||||
}
|
||||
// omit footer on macOS, use ThemeRowWithFooterModifier
|
||||
}
|
||||
}
|
||||
|
||||
extension ThemeRowWithFooterModifier {
|
||||
func body(content: Content) -> some View {
|
||||
VStack {
|
||||
content
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
footer.map {
|
||||
Text($0)
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.callout)
|
||||
.font(.caption)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
} header: {
|
||||
header.map(Text.init)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,13 @@ extension ThemeSectionWithHeaderFooterModifier {
|
|||
}
|
||||
}
|
||||
|
||||
extension ThemeRowWithFooterModifier {
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
// omit footer on iOS/tvOS, use ThemeSectionWithHeaderFooterModifier
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Views
|
||||
|
||||
extension ThemeTextField {
|
||||
|
|
|
@ -91,6 +91,10 @@ extension View {
|
|||
modifier(ThemeSectionWithHeaderFooterModifier(header: header, footer: footer))
|
||||
}
|
||||
|
||||
public func themeRow(footer: String? = nil) -> some View {
|
||||
modifier(ThemeRowWithFooterModifier(footer: footer))
|
||||
}
|
||||
|
||||
public func themeNavigationDetail() -> some View {
|
||||
#if os(iOS)
|
||||
navigationBarTitleDisplayMode(.inline)
|
||||
|
@ -290,6 +294,10 @@ struct ThemeSectionWithHeaderFooterModifier: ViewModifier {
|
|||
let footer: String?
|
||||
}
|
||||
|
||||
struct ThemeRowWithFooterModifier: ViewModifier {
|
||||
let footer: String?
|
||||
}
|
||||
|
||||
#if !os(tvOS)
|
||||
|
||||
struct ThemeWindowModifier: ViewModifier {
|
||||
|
|
|
@ -130,6 +130,7 @@ private extension OpenVPNCredentialsView {
|
|||
var interactiveSection: some View {
|
||||
Group {
|
||||
Toggle(Strings.Modules.Openvpn.Credentials.interactive, isOn: $isInteractive)
|
||||
.themeRow(footer: interactiveFooter)
|
||||
|
||||
if isInteractive {
|
||||
Picker(Strings.Unlocalized.otp, selection: $builder.otpMethod) {
|
||||
|
|
Loading…
Reference in New Issue