Pattern · Auth and Onboarding
NewInterests Picker SwiftUI Block
A first-run step for picking topics: wrapping chips by section, a search that filters, a count that rolls, and Continue at the minimum.
Topics as chips with a symbol and a label, grouped under section titles in a flow layout that fits any width and text size. Picked chips take a light accent tint with a check, the count rolls, a search filters as it's typed, and the button counts down Pick 2 more until the minimum turns it into Continue, which runs your closure through working, done and failed. An optional maximum steps the other chips back.
- SwiftUI
- iOS 17.0+
- interests-picker
$199 once, every piece included. See how installing works · Sign in
01
What's included
SwiftUI source you own, built on Apple frameworks only.
- Chips with a symbol and label in a wrapping flow layout, grouped by section
- Picked chips take an accent tint and a check as the count rolls
- Search filters by topic or section, with a no-match state
- Pick 2 more until the minimum, then Continue with working, done and failed
- An optional maximum, and grey chips while topics load
02
Implementation notes
How it behaves, what it handles, and the decisions behind it.
The step opens with "What are you into?", "Pick at least 3." and a count of what's picked that rolls with each tap. A search field filters the topics as it's typed, by topic or by section, and says "No topics match" when nothing does. One card holds the topics as chips grouped under section titles; the chips wrap in a flow layout that fits any width and text size. Each chip is a symbol and a label on a quiet fill; picked, it takes a light accent tint with a check in place of the symbol. Until the minimum is met the button reads "Pick 2 more" on a quiet fill and can't be tapped; at the minimum it turns into Continue in the accent, which runs your closure and shows working, done and failed in place. With a maximum, the other chips step back once it's reached and a line says to tap a topic to swap it out. Pass nil while the topics load and the card draws grey chips.
Notes
InterestsPicker(categories:selection:minimum:maximum:title:onContinue:onSkip:). It is a section: no navigation stack, background, padding or scroll view of its own, so place it in your onboarding's column, such as aScrollViewwith.padding(.horizontal, 20).categoriesis a list ofInterestsPicker.Category(an id, a title and its topics), each topic anInterestsPicker.Topicwith an id, a title and an SF Symbol name.Category.sampleshas fourteen neutral topics under Make, Move and Learn. Pass nil while you fetch them.onContinuereceives the picked topic ids as aSet<String>. Throw to fail: the block shows a thrownLocalizedError'serrorDescription, or "Couldn't save your interests. Try again." ACancellationErrorgoes back to rest quietly. The check holds for about a second; move to the next step from your closure or after it.selectionis aBinding<Set<String>>for a screen that keeps the picks, to restore them or show them elsewhere. Leave it out and the block keeps its own.minimumis 3 by default; 0 makes Continue available at once.maximumcaps the picks; nil means no limit.onSkipshows "Skip for now" under Continue. Nil hides it.- Search matches a topic's title, or a section's title to show the whole section. Clearing it brings everything back; picks are kept either way.
- Haptics: a selection tick as each chip is picked or unpicked, success when the picks save and an error when they fail.
- VoiceOver reads each chip as a button with Selected when picked, the count as "3 of at least 3 picked", and the locked button as "Pick 2 more to continue". It announces "Interests saved" and failures. Chips are 40 points tall with a 44 point target. At accessibility sizes the count moves under the rule, chips grow and wrap onto more lines, and a label too long for the line wraps inside its chip.
- Reduce Motion turns every change into a short fade.
InterestsPickerExampleat the end ofInterestsPicker.swiftis Fieldnote's third first-run step from the preview. It shows the grey chips for a moment, loadsCategory.samples, needs three picks and saves after a second.
Theming
- Reads
SPThemefrom@Environment(\.spTheme)and requires thedesign-systemitem. - The title is the display face at 28 points, semibold at most, in
textPrimary; the rule istype.bodyintextSecondary; the count istype.subheadmedium with tabular figures,textPrimaryonce the minimum is met. - The search field is 52 points on
fillwithradius.mdand aseparatorhairline that turns totextPrimarywhile searching; its symbol istextSecondary. - The card is
color.surfacewithradius.lg, 16 point padding and 24 points between sections; section titles aretype.headline. - Chips are capsules on
fillwithtype.subheadmedium labels intextPrimaryand symbols intextSecondary. A picked chip isaccentat 14% with a 60%accenthairline and anaccentcheck. Locked chips drop to 40% opacity. - The button is
fillwithtextSecondaryuntil the minimum, thenaccentwithaccentOn, intype.headline,radius.md, 52 points. Skip for now istextPrimarysemibold. Errors aretype.footnoteindanger. - Picks move with
motion.snappy, the loaded topics withmotion.smooth, chips press withmotion.bouncyand the button withmotion.standard.
03
Keep building
Pieces that work well next to this one.