Screen · Navigation
App Shell SwiftUI Screen
The root of a tabbed app: a floating tab bar, a stack per tab and real reselect behaviour.
An app shell on the lens tab bar in a bottom safe-area inset, generic per-tab content, hide-on-scroll through ShellScrollView, and reselect that pops to root and scrolls to top.
- SwiftUI
- iOS 17.0+
- tab-shell
$199 once, every piece included. See how installing works · Sign in
01
What's included
SwiftUI source you own, built on Apple frameworks only.
- One
NavigationStackper tab on the Lens Tab Bar - The bar hides on scroll through
ShellScrollView - Reselecting a tab pops to root and scrolls to top
- Cadence's four tabs as a working example
Includes
Lessons. Installed together, automatically.
In the Build Kit
SwiftPieces Skill (setup), Native (style), Onboarding to Paywall (recipe). Your agent builds around this screen in the same design.
Used in
Subscription App (template), Finance App (template), AI Assistant (template), Productivity App (template), Meditation App (template), Travel App (template)
02
Implementation notes
How it behaves, what it handles, and the decisions behind it.
One NavigationStack per tab, the system tab bar hidden, and LensTabBar placed in .safeAreaInset(edge: .bottom) so scrolling content is never covered. Wrap each tab's scrolling content in ShellScrollView: it reports its offset to the shell, which hides the bar on a downward scroll and shows it again on an upward one or near the top. Reselecting a tab pops its stack to root and scrolls the root to the top.
Notes
- Tab content avoids the keyboard, so a composer rides above it, and the bar steps aside while the keyboard is up.
- Tab content is generic, built by a
(LensTab) -> Contentclosure, with noAnyView. ShellScrollViewusesScrollPositionandonScrollGeometryChangeon iOS 18, andScrollViewReaderwith a geometry probe on iOS 17. Scroll offsets travel up through a preference and the scroll-to-top token travels down through the environment, so the scroll container can live anywhere in the tab, including pushed screens.- Only the selected tab drives the bar. A
Listdoes not report offsets; useShellScrollViewwith aLazyVStackfor rows. - Built on
LensTabBarfrom the Lessons screen; the CLI installs it with this screen. TabShellScreenExampleat the end ofTabShellScreen.swiftis the screen shown in the preview; copy it as a starting point.
Theming
- Reads
SPThemetokens from@Environment(\.spTheme)and requires thedesign-systemitem. - The shell passes
color.accenttoLensTabBaras itstint, spaces the bar withspace.sm, and scrolls to top withmotion.smooth. - Your tab content is not restyled. Read the same
@Environment(\.spTheme)in your screens so they match the bar. LensTabBarstays self-contained: its unselected icons, material fallback and springs use system values.
03
Keep building
Pieces that work well next to this one.