Pattern · Navigation Bars
NewLocation Header SwiftUI Block
The header of a delivery or local app: the address and its chooser, search, a Now or Schedule pill, and the bag with its count.
Deliver to over the current address opens a chooser of saved addresses with a radio selection, Use current location through CoreLocation and Add address. Picking an address runs your check in the row before it applies. A search field, a Now or Schedule pill and the bag with its count complete the header.
- SwiftUI
- iOS 17.0+
- location-header
$199 once, every piece included. See how installing works · Sign in
01
What's included
SwiftUI source you own, built on Apple frameworks only.
- The current address with a chooser of saved addresses and a radio selection
- Use current location asks for permission, finds you and handles location being off
- Your address check runs in the row, with its error shown in place
- A pill for Now or a scheduled time, with a menu to switch
- A search field and the bag's count, with grey shapes while loading
02
Implementation notes
How it behaves, what it handles, and the decisions behind it.
"Deliver to" sits over the current address, its name in semibold and the street after it, with a chevron that opens the address chooser; the bag sits beside it with its item count in the accent. Under them a search field opens your search, and a pill reads Now or the time you scheduled, with a menu to switch back to now or open your scheduler. The chooser is a sheet: saved addresses with a radio selection, Use current location and Add address. Picking an address runs your check in the row with a spinner, moves the radio, updates the header and closes the sheet; a thrown error stays in the row in the danger colour and keeps the old address. Use current location asks for When In Use permission the first time, finds you once and hands the coordinate to your closure for an address; when location is off it says so with Open Settings. Pass nil addresses while they load and the header shows grey shapes in its own layout.
Notes
LocationHeader(addresses:selection:timing:cartCount:searchPrompt:onSelect:onUseCurrentLocation:onAddAddress:onSchedule:onSearch:onCart:)takes the saved addresses, a binding to the chosenAddress(nil reads "Choose an address") and a binding to theTiming. It is a section with no background, padding or scroll view; the chooser owns its sheet and the scroll view inside it.LocationHeader.Addresshas anid, alabel("Home"), onelineof the address and an SF Symbol for its row.Address.samplesholds Home, Work and Sam's.LocationHeader.Timingholds theestimatefor an order now ("25–35 min") and an optionalscheduleddate. The pill reads "Now", a time today, or the weekday and time.onSelectisasync throwsand runs before an address becomes the selection, so you can check that you deliver there. Throw aLocalizedError("We don't deliver there yet") to show its message in the row, orCancellationError()to back out quietly. Without it a pick applies at once.onUseCurrentLocationreceives aCLLocationCoordinate2Dand returns anAddress, fromCLGeocoderor your own places service; the result becomes the selection. The row shows "Waiting for permission", "Finding you…", "Location access is off for this app." with Open Settings, or the error. Nil hides the row.onAddAddressopens your new address form after the sheet closes;onScheduleopens your scheduler from the pill's menu and nil leaves the pill a plain label;onSearchandonCartnil hide the field and the bag.- Haptics mark a pick with a selection tick and a failure with an error.
- VoiceOver reads the address as one button ("Deliver to, Home, 221 Elm Street, Apt 4"), the bag as "Bag, 2 items", the pill as "Delivery time, Now", and each saved address with Selected on the current one. It announces the new address, a denied permission and failures. Rows grow with Dynamic Type and every control has a 44 point target.
- Reduce Motion turns the loading shimmer off and state changes into short fades.
LocationHeaderExampleat the end ofLocationHeader.swiftis the Order tab in the preview: delivering Home with two items in the bag, an address check that takes a moment, and Use current location throughCLGeocoder. PasswrapsInNavigationStack: falseto push it in your own stack.
Theming
- Reads
SPThemefrom@Environment(\.spTheme)and requires thedesign-systemitem. - "Deliver to" is
type.footnoteintextSecondary; the address istype.body, its label semiboldtextPrimaryand its linetextSecondary. - The search field and the pill sit on
fillwith a 1 pointseparatorstroke, the field atradius.mdand the pill as a capsule; the prompt istextTertiary, the pill's timetype.subheadmedium intextPrimarywith monospaced digits. - The bag is
fillwith aseparatorring; its count is theaccentwithaccentOnfigures, ringed inbg: the block's only accent. - The chooser sits on
bg, its cards onsurfacewithradius.lgandSPHairlinedividers inset to the text. Symbols aretextSecondary. The radio is aseparatorring, or atextPrimarydisc with a check insurfacewhen chosen. Failures aredanger. - Changes use
motion.smoothandmotion.snappy, adapted for Reduce Motion.
Requirements
NSLocationWhenInUseUsageDescriptionin Info.plist for Use current location. Leave outonUseCurrentLocationand it needs nothing.
03
Keep building
Pieces that work well next to this one.