-
Notifications
You must be signed in to change notification settings - Fork 0
feat: let the host set the sheet background and badge the address field #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -17,17 +17,19 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #if canImport(UIKit) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import SwiftUI | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Outside the view, not nested in it: `AddressFieldView` is generic over its | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// accessory, and a generic type cannot hold static stored properties. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private enum Layout { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let hSpacing: CGFloat = 20 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let lPadding: CGFloat = 20 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let tPadding: CGFloat = 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let iconSize: CGFloat = 17 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let cornerRadius: CGFloat = 16 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let actionTapArea: CGFloat = 40 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @available(iOS 15, macOS 12, *) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public struct AddressFieldView: View { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private enum Layout { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let hSpacing: CGFloat = 20 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let lPadding: CGFloat = 20 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let tPadding: CGFloat = 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let iconSize: CGFloat = 17 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let cornerRadius: CGFloat = 16 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static let actionTapArea: CGFloat = 40 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public struct AddressFieldView<Accessory: View>: View { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Binding private var text: String | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private let label: String | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -37,6 +39,11 @@ public struct AddressFieldView: View { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var isDisabled: Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var onScanQR: (() -> Void)? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var onPaste: (() -> Void)? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Trailing content on the label row — a badge naming what the entered | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// address turned out to be, say. Sits opposite `label`, so it is for | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// something that describes the field rather than acts on it; the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// controls that act live inside the field itself. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private let accessory: Accessory | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @FocusState private var isTextFieldFocused: Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -48,7 +55,8 @@ public struct AddressFieldView: View { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| errorText: String? = nil, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isDisabled: Bool = false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onScanQR: (() -> Void)? = nil, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onPaste: (() -> Void)? = nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onPaste: (() -> Void)? = nil, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @ViewBuilder accessory: () -> Accessory | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._text = text | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.label = label | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -58,14 +66,21 @@ public struct AddressFieldView: View { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.isDisabled = isDisabled | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.onScanQR = onScanQR | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.onPaste = onPaste | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.accessory = accessory() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public var body: some View { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VStack(alignment: .leading, spacing: 10) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Text(label) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .dashFont(.footnote) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .foregroundStyle(Color.dash.gray500) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .frame(maxWidth: .infinity, alignment: .leading) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HStack(spacing: 8) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Text(label) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .dashFont(.footnote) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .foregroundStyle(Color.dash.gray500) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Spacer(minLength: 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| accessory | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .frame(maxWidth: .infinity, alignment: .leading) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HStack(alignment: .center, spacing: Layout.hSpacing) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| textField | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -101,6 +116,37 @@ public struct AddressFieldView: View { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @available(iOS 15, macOS 12, *) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public extension AddressFieldView where Accessory == EmptyView { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// No label accessory — the original shape, unchanged for callers that | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// have nothing to put there. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| init( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| text: Binding<String>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: String, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| placeholder: String, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hasError: Bool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| errorText: String? = nil, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isDisabled: Bool = false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onScanQR: (() -> Void)? = nil, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onPaste: (() -> Void)? = nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.init( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| text: text, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: label, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| placeholder: placeholder, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hasError: hasError, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| errorText: errorText, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isDisabled: isDisabled, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onScanQR: onScanQR, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onPaste: onPaste, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| accessory: { EmptyView() }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @available(iOS 15, macOS 12, *) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| extension AddressFieldView { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // MARK: - Subviews | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var showsPasteButton: Bool { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -292,5 +338,31 @@ public struct AddressFieldView: View { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .padding() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @available(iOS 17, macOS 14, *) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #Preview("Label accessory") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AddressFieldView( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| text: .constant("yV1D1ivvSUyKPJnbFmzSTVh1MyZ3JbeVkY"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: "Address", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| placeholder: "Dash address", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hasError: false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // What the host puts here is its own: a badge naming the kind of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // address that was entered, decided by the host's own decoder. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HStack(spacing: 4) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Image(systemName: "d.circle.fill") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .font(.system(size: 10, weight: .semibold)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+352
to
+353
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win Use a
As per coding guidelines, represent icons with 🤖 Prompt for AI AgentsSource: Coding guidelines |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Text("Transparent address") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .dashFont(.caption2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+343
to
+356
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win Localize the preview strings.
Proposed change- label: "Address",
- placeholder: "Dash address",
+ label: NSLocalizedString("Address", bundle: .module, comment: "DashUIKit"),
+ placeholder: NSLocalizedString("Dash address", bundle: .module, comment: "DashUIKit"),
...
- Text("Transparent address")
+ Text(NSLocalizedString("Transparent address", bundle: .module, comment: "DashUIKit"))As per coding guidelines, localize all user-facing strings with 📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsSource: Coding guidelines |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .foregroundStyle(Color.dash.blueText) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .padding(.horizontal, 8) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .padding(.vertical, 3) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .background(Color.dash.blueAlpha10) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .clipShape(Capsule()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .padding() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .background(Color.dash.primaryBackground) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+341
to
+365
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win Guard the iOS 17 preview with The new As per coding guidelines, preview-only code may require iOS 17 only when guarded by 🤖 Prompt for AI AgentsSource: Coding guidelines |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif // canImport(UIKit) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,19 +17,26 @@ public struct BottomSheet<Content: View>: View { | |
| /// when natural sizing is needed — it guarantees `fillsHeight: false` and the modifier are | ||
| /// always applied together. | ||
| public var fillsHeight: Bool = true | ||
| /// Fill behind the whole sheet — grabber, header and content alike. Also | ||
| /// used as the presentation background so the home-indicator inset the | ||
| /// detent adds matches; a host that only restyles its own content would | ||
| /// otherwise get a strip of this colour along the bottom edge. | ||
| public var background: Color = .dash.primaryBackground | ||
| @ViewBuilder public var content: () -> Content | ||
|
|
||
| public init( | ||
| title: String = "", | ||
| showBackButton: Binding<Bool>, | ||
| onBackButtonPressed: (() -> Void)? = nil, | ||
| fillsHeight: Bool = true, | ||
| background: Color = .dash.primaryBackground, | ||
| @ViewBuilder content: @escaping () -> Content | ||
| ) { | ||
| self.title = title | ||
| self._showBackButton = showBackButton | ||
| self.onBackButtonPressed = onBackButtonPressed | ||
| self.fillsHeight = fillsHeight | ||
| self.background = background | ||
| self.content = content | ||
| } | ||
|
|
||
|
|
@@ -42,7 +49,7 @@ public struct BottomSheet<Content: View>: View { | |
|
|
||
| contentSection | ||
| } | ||
| .background(Color.dash.primaryBackground) | ||
| .background(background) | ||
|
|
||
| if fillsHeight { | ||
| sheet.edgesIgnoringSafeArea(.bottom) | ||
|
|
@@ -103,13 +110,13 @@ public struct BottomSheet<Content: View>: View { | |
| .navigationBarHidden(true) | ||
| #endif | ||
| .frame(maxWidth: .infinity, maxHeight: .infinity) | ||
| .background(Color.dash.primaryBackground) | ||
| .background(background) | ||
| } | ||
| } else { | ||
| // Natural height — no greedy NavigationView / maxHeight so the sheet can self-size. | ||
| content() | ||
| .frame(maxWidth: .infinity) | ||
| .background(Color.dash.primaryBackground) | ||
| .background(background) | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -134,6 +141,7 @@ public extension BottomSheet { | |
| onBackButtonPressed: (() -> Void)? = nil, | ||
| fallback: CGFloat = 0, | ||
| maxHeightFraction: CGFloat = 0.95, | ||
| background: Color = .dash.primaryBackground, | ||
| cornerRadius: CGFloat? = nil, | ||
| @ViewBuilder content: @escaping () -> Content | ||
| ) -> some View { | ||
|
|
@@ -142,9 +150,14 @@ public extension BottomSheet { | |
| showBackButton: showBackButton, | ||
| onBackButtonPressed: onBackButtonPressed, | ||
| fillsHeight: false, | ||
| background: background, | ||
| content: content | ||
| ) | ||
| .selfSizingSheet(fallback: fallback, maxHeightFraction: maxHeightFraction, cornerRadius: cornerRadius) | ||
| .selfSizingSheet( | ||
| fallback: fallback, | ||
| maxHeightFraction: maxHeightFraction, | ||
| background: background, | ||
| cornerRadius: cornerRadius) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -163,28 +176,34 @@ public extension View { | |
| /// - fallback: Height used before the first measurement (avoids a `.medium` flash). | ||
| /// - maxHeightFraction: Caps the sheet at this fraction of the window height; taller content | ||
| /// is clipped, so wrap it in a `ScrollView`. | ||
| /// - background: Fill for the sheet and its presentation, so the bottom | ||
| /// safe-area strip matches the content. Defaults to the sheet's own. | ||
| /// - cornerRadius: Optional corner radius applied via `presentationCornerRadius` on | ||
| /// iOS 16.4..<26 (iOS 26+ keeps the system corner styling). When provided, the sheet | ||
| /// background is also filled so the bottom safe-area strip matches the content. | ||
| /// iOS 16.4..<26 (iOS 26+ keeps the system corner styling). | ||
| @ViewBuilder | ||
| func selfSizingSheet( | ||
| fallback: CGFloat = 0, | ||
| maxHeightFraction: CGFloat = 0.95, | ||
| background: Color = .dash.primaryBackground, | ||
| cornerRadius: CGFloat? = nil | ||
|
Comment on lines
+179
to
188
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift Make the direct modifier default match the wrapped sheet.
Propagate the sheet color through an environment value, or remove “Defaults to the sheet’s own” and require direct modifier calls to pass the same color. 🤖 Prompt for AI Agents |
||
| ) -> some View { | ||
| if #available(iOS 16.0, macOS 13.0, *) { | ||
| let modified = modifier(SelfSizingSheetModifier(fallback: fallback, maxHeightFraction: maxHeightFraction)) | ||
| #if os(iOS) | ||
| if #available(iOS 16.4, *), let cornerRadius { | ||
| if #unavailable(iOS 26.0) { | ||
| // iOS 16.4..<26: apply the custom corner radius + fill the sheet background. | ||
| if #available(iOS 16.4, *) { | ||
| // The background is filled whatever the corner radius: the | ||
| // measured height excludes the home-indicator inset that | ||
| // `.presentationDetents([.height])` adds back, so that strip | ||
| // sits outside the sheet's own `VStack` and shows the system | ||
| // background unless this fills it. | ||
| if #unavailable(iOS 26.0), let cornerRadius { | ||
| modified | ||
| .presentationCornerRadius(cornerRadius) | ||
| .presentationBackground(Color.dash.primaryBackground) | ||
| .presentationBackground(background) | ||
| } else { | ||
| // iOS 26+: keep the system corner styling, just fill the background. | ||
| // iOS 26+ keeps the system corner styling. | ||
| modified | ||
| .presentationBackground(Color.dash.primaryBackground) | ||
| .presentationBackground(background) | ||
|
Comment on lines
190
to
+206
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
file="Sources/DashUIKit/Components/BottomSheet.swift"
rg -n -C 6 'presentationBackground|`#if` os\(iOS\)|macOS 13\.0|`@available`\(iOS 14' "$file"Repository: dashpay/DashUIKit Length of output: 4155 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- BottomSheet.swift ---'
sed -n '130,240p' Sources/DashUIKit/Components/BottomSheet.swift
printf '%s\n' '--- Package manifests and platform declarations ---'
fd -i -t f 'Package.swift|.*\.podspec|.*\.yml|.*\.yaml' . -x sh -c 'printf "\n--- %s ---\n" "$1"; rg -n -C 3 "platform|macOS|iOS|swift-tools-version" "$1"' sh {}
printf '%s\n' '--- selfSizingSheet usages ---'
rg -n -C 3 'selfSizingSheet|BottomSheet\.selfSizing|BottomSheet\(' Sources Tests 2>/dev/null || trueRepository: dashpay/DashUIKit Length of output: 12451 🌐 Web query:
💡 Result: The presentationBackground(:) modifier in SwiftUI is available on macOS starting with macOS 13.3 [1][2]. It allows you to customize the background of modal presentations such as sheets, popovers, and full-screen covers [3][4]. Key details regarding this modifier include: Availability: It was introduced in iOS 16.4 and macOS 13.3 [1][2]. Functionality: The modifier applies a ShapeStyle (such as a color, gradient, or material) to the background of an enclosing presentation [5][3]. A secondary version, presentationBackground(alignment:content:), allows for more complex, custom view backgrounds [6][3]. Platform Behavior: Unlike the standard background(:) modifier, presentationBackground(_:) automatically fills the entire presentation area and supports translucency, allowing underlying views to show through when using appropriate styles [5][7][4]. When using this modifier, ensure that nested container views like List or Form have their default backgrounds disabled (e.g., using.scrollContentBackground(.hidden)) if you wish for your custom presentation background to be visible [3]. Citations:
Apply the presentation background on macOS 13.3 and later.
🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| } | ||
| } else { | ||
| modified | ||
|
|
@@ -283,3 +302,25 @@ private struct SelfSizingSheetModifier: ViewModifier { | |
| .padding() | ||
| } | ||
| } | ||
|
|
||
| @available(iOS 17, macOS 14, *) | ||
| #Preview("BottomSheet Custom Background") { | ||
| BottomSheet( | ||
| title: "Bottom Sheet", | ||
| showBackButton: .constant(false), | ||
| fillsHeight: false, | ||
| background: .dash.secondaryBackground | ||
| ) { | ||
| VStack(alignment: .leading, spacing: 12) { | ||
| Text("Cards on a tinted sheet") | ||
| .dashFont(.calloutMedium) | ||
| .foregroundColor(.dash.primaryText) | ||
|
|
||
| Text("The host picks the fill; cards drawn on top keep their own.") | ||
| .dashFont(.body) | ||
| .foregroundColor(.dash.secondaryText) | ||
| .modifier(MenuViewModifier()) | ||
| } | ||
| .padding() | ||
| } | ||
| } | ||
|
Comment on lines
+305
to
+326
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
file="Sources/DashUIKit/Components/BottomSheet.swift"
rg -n -B 8 -A 4 '`#Preview`|`#if` DEBUG|`#endif`' "$file"Repository: dashpay/DashUIKit Length of output: 2543 Guard all 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: dashpay/DashUIKit
Length of output: 3522
🏁 Script executed:
Repository: dashpay/DashUIKit
Length of output: 14889
🏁 Script executed:
Repository: dashpay/DashUIKit
Length of output: 768
Restore iOS 14 and macOS 11 support for the public API.
Package.swiftdeclares iOS 14 support, butAddressFieldViewand its compatibility initializer require iOS 15 and macOS 12. The type also uses@FocusStatein its focus-dependent state and both text-field branches. Isolate this behavior and provide an iOS 14 fallback before changing the public declarations to@available(iOS 14, macOS 11, *).🤖 Prompt for AI Agents
Source: Coding guidelines