DesignFoundation Pro ships 55 production-ready SwiftUI screens across 12 verticals, 30 composite UI blocks, and 18 shell layouts — plus 12 wired composition examples you can run as-is or steal from. Theme with one modifier, wire your data layer, ship.
DFPlayground · Free · macOS
DFPlayground is a free companion macOS app with the complete Pro catalog built in. Browse all 30 blocks, 55 screens, 18 shells, and 12 composition examples — live, interactive, and themeable. Open any screen in its own window. Switch between all five theme presets. Then decide.
⬇ Download DFPlayground — Free · macOS · 14.6 MBDFAIChatThreadScreen into your app and your AI chat is done. No design decisions. No accessibility wiring.DFTheme. Swap the entire visual identity of 55 screens and 30 blocks with one modifier at the app root. Slate, Aurora, Copper, Sage, Garnet — or your own tokens.What's included
Three product layers, one license. Wire up a complete screen vertical in minutes, compose with blocks, or use shell layouts to nail your app's navigation skeleton.
DFAIThinkingView, DFAISummaryCard) outside the 30UI Blocks
Each block accepts a typed Configuration struct and inherits every visual token from your active DFTheme automatically.







All three chart blocks are built on DFChartBlockShell<Period, Chart> — the shared card/title/loading/period-toolbar chrome around any Swift Charts view. Use it directly for a chart shape none of the three cover, or conform to DFChartBlock to compose the same way. Their periods: field accepts the built-in DFChartPeriodPreset (7D/1M/3M/1Y) or your own type conforming to DFChartPeriodRepresentable.



Screen Verticals
Each vertical is a self-contained set of full-page SwiftUI screens covering a complete feature domain — domain models, typed configuration, and @MainActor-isolated action closures included.
Also ships DFAIThinkingView (a staggered-dot "model is thinking" indicator) and DFAISummaryCard (a themed AI-generated summary card with headline, body, and key points) for building your own chat UI around the screens.
Shell Layouts
Navigation-level container views that handle sidebar / tab bar / split view logic. Drop your content in — the shell adapts to the device and size class automatically. Works with any content, any theme.
Vertical spotlight
From your store home through browsing products, managing orders, and reviewing revenue — every screen shares a typed model layer and connects through closures your view model already speaks.
// Wire up an orders screen in three lines. NavigationStack { DFEcommerceOrdersScreen( configuration: .init( orders: viewModel.orders, onSelectOrder: { order in path.append(order) }, onMarkShipped: { order in viewModel.markShipped(order) } ) ) }
Technical contract
Every block, screen, and shell ships with non-negotiable guarantees — not aspirational, contractual.
Configuration struct per block and screen — no stringly-typed API, no loose dictionaries, full autocompleteDFTheme — zero hardcoded colors, radii, fonts, or shadows anywhereStrictConcurrency enabled, no suppressions#Preview variants included for every block, screen, and shellDFOrder, DFProduct, CRMContact, AIChatMessage, etc.@MainActor-isolated action closures — safe to call directly into your actor-isolated view model#if os() guards required in consuming codeTwo packages. A clean stack. DesignFoundation is free and open-source — Pro adds everything on top.
| Package | What it provides | License | Requires |
|---|---|---|---|
| DesignFoundation | Theme engine, 44 components + 12 presentation and layout modifiers, preset themes, Liquid Glass, full style system | MIT — free | — |
| DesignFoundationPro | 30 UI blocks + 55 screens across 12 verticals + 18 shell layouts + 12 composition examples + advanced popups (unified overlay/sheet/window presentation, scroll popup, priority queue, celebration, permission, rating, input, consent and action popups, undo and progress toasts, notification banners, live capsule, coachmark tours, motion presets) | Commercial | DesignFoundation |
Composition examples
Each composition example is a complete, runnable SwiftUI app built entirely from Pro blocks, screens, and shells — themed, wired with dfToast, and written to production quality. Copy the whole thing or take just the parts you need.
See The Foundation Way for side-by-side line counts — how much code stays out of your repo (and out of AI prompts). All 12 examples are in DFPlayground.
Advanced popups New in Pro 2.3.0
DesignFoundation's free .dfPopup engine covers cards, toasts, floaters and sheets. Pro layers a complete popup system on top of it: a unified presentation API, dismiss reasons, keyboard and scrim control, motion presets, a priority queue, scroll popups, and a set of finished rich popups. Card-style rich popups are built on the free DFPopupCard and follow the environment DFPopupStyle. New in Pro 2.3.0, which requires DesignFoundation 1.7.1 or later. Every clip is a real recording.
Hover a tile (or tap it) to play the real recording. Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
| API | What it does |
|---|---|
.dfPopupPresentation(isPresented:display:configuration:keyboard:scrim:motion:pausesOnHold:chrome:haptic:onDismiss:content:) | One API, three display modes (.overlay, .sheet, .window). |
DFPopupScrim, DFPopupMotion, DFPopupDismissReason | Scrim, motion and dismissal vocabulary shared by every Pro presenter. |
.dfScrollPopup(...) | Scrollable popup with detents, side sheets, header styles and a pinned footer. |
DFPopupCenter + .dfPopupCenter(_:) | Priority queue with preemption and id de-duplication. |
.dfCelebrationPopup .dfPermissionPrompt .dfPromoPopup .dfRatingPrompt .dfInputPopup .dfConsentSheet .dfActionPopup | Finished popups, each a public view plus a presenting modifier. |
.dfUndoToast .dfProgressToast .dfNotificationBanners .dfLiveCapsule | Toasts and live status. |
DFCoachmarkTour + .dfCoachmarkTour(_:) .dfCoachmark .dfPopupAnchor(_:) | Spotlight coachmarks over marked targets. |
DFPopupCountdownBar DFPopupCountdownRing DFPopupHaptic | Countdown indicators and tactile cues. |
dfPopupPresentation presents a popup in one of three modes: .overlay (default), .sheet (a real SwiftUI sheet for bottom-anchored popups, a full-screen cover for the rest, binding kept in sync both ways) or .window (a transparent UIWindow on iOS above sheets and navigation bars; a borderless child NSPanel on macOS; an overlay on visionOS). keyboard: .avoid (default) lifts the popup above the software keyboard. DFPopupScrim is .dim(_:), .blur(_:), .custom { } or .clear; .passingTouches() keeps a visible scrim from blocking the app. dfPopupWindow remains as shorthand for display: .window.
YourContentView().dfPopupPresentation(
isPresented: $showPopup,
display: .window, // .overlay (default) | .sheet | .window
configuration: .floater(position: .top),
keyboard: .avoid, // .avoid (default) | .ignore
scrim: .blur(0.7), // .dim(0.3) | .blur(_:) | .custom { } | .clear
motion: .zoom,
pausesOnHold: true,
chrome: .style, // .style wraps content in DFPopupStyle; .none draws it as-is
haptic: .success,
onDismiss: { reason in print(reason) }
) {
Text("Hello")
}
// A visible scrim that lets touches reach the app
YourContentView().dfPopupPresentation(isPresented: $showPopup, scrim: .dim(0.2).passingTouches()) {
Text("Non-blocking")
}
// Shorthand for display: .window
YourContentView().dfPopupWindow(isPresented: $showPopup, configuration: .toast(position: .top)) {
Text("Above the sheet")
}
Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
The Pro presenters (dfPopupPresentation, dfScrollPopup, DFPopupCenter.present and the rich popups and toasts below, except the live capsule, coachmarks and notification banners) deliver a DFPopupDismissReason (.timeout .tap .outsideTap .drag .programmatic .preempted) to onDismiss. dfPopupWindow keeps a plain () -> Void onDismiss, and notification banners report (item, reason). Content can close its own popup through @Environment(\.dfPopupDismiss). Resting a finger or pointer on an auto-dismissing popup pauses its timer. DFPopupCountdownBar and DFPopupCountdownRing follow the popup's live, pausable countdown.
struct CloseButton: View {
@Environment(\.dfPopupDismiss) private var dismiss // no-op outside a Pro popup
@Environment(\.dfPopupCountdown) private var countdown // the auto-dismiss timer, if any
var body: some View {
VStack {
DFPopupCountdownBar()
Button("Done") { dismiss(.tap) }
}
}
}
YourContentView().dfPopupPresentation(
isPresented: $showPopup,
configuration: .floater(position: .bottom, autoDismissAfter: 5),
pausesOnHold: true,
onDismiss: { reason in
if reason == .timeout { commitDelete() }
}
) {
HStack {
DFPopupCountdownRing()
Text("Message deleted")
}
}
Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
dfScrollPopup is a popup with a pinned header, scrolling body and optional pinned footer. Dragging dismisses only when the content is at its top, so the drag and the scroll never fight. detents: (.medium .large .fraction .height) snap the height; edge: adds .leading/.trailing side sheets on regular width (compact falls back to the bottom); headerStyle: is .plain .centered .prominent .closable; fromTop: true presents from the top edge.
YourContentView().dfScrollPopup(
isPresented: $showPopup,
edge: .automatic,
detents: [.medium, .large],
headerStyle: .closable,
scrim: .dim(),
onDismiss: { reason in print(reason) }
) {
Text("Release notes")
} content: {
Text("Long, scrollable content…")
} footer: {
Button("Update now") { }
}
YourContentView().dfScrollPopup(isPresented: $showPopup, fromTop: true) {
Text("Ticket #4821")
} content: {
Text("Comments…")
}
Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
DFPopupCenter puts many popups behind one presenter. One shows at a time; the rest wait by DFPopupPriority (.low .normal .high .critical). A higher priority preempts the current popup (its onDismiss gets .preempted and it re-queues), and presenting an id that is already showing or waiting replaces it. The optional haptic plays when the popup takes over.
YourContentView().dfPopupCenter(popups) // popups: @StateObject DFPopupCenter
popups.present(id: "offline", priority: .high, configuration: .toast(),
haptic: .warning, onDismiss: { reason in print(reason) }) {
VStack {
Text("You're offline")
DFPopupCountdownBar()
}
}
popups.dismiss(id: "offline")
Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
DFCelebrationPopup: a hero icon springs in and a DFConfettiBurst fires from it. With Reduce Motion it fades only. Nothing needs image assets: everything is SF Symbols and theme gradients.
YourContentView().dfCelebrationPopup(
isPresented: $showPopup,
title: "Order placed!",
message: "Tracking is on its way.",
actionTitle: "Continue"
)
Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
Each is a public view plus a presenting modifier. The celebration, permission, promo, rating, input, consent and action popups and the undo and progress toasts accept display: and a reason-style onDismiss:; the live capsule accepts display: but has no onDismiss; coachmarks and notification banners have neither display: nor the reason-style onDismiss (banners report (item, reason)). The card-style ones follow the environment DFPopupStyle. Permission prompt: pre-permission priming; you trigger the system prompt in onAllow. Promo: media area (.symbol, .gradient, .image), badge and CTA. Rating: stars, then a feedback step below the threshold or a review nudge at or above it. Input: validated, keyboard-aware, auto-focused. Consent: a sheet of toggleable categories. Action: rows with normal, destructive and cancel roles, centered, as a bottom sheet, or anchored to a view.
YourContentView().dfPermissionPrompt(isPresented: $showPopup, kind: .notifications,
onAllow: { /* trigger the system prompt */ }, onDecline: { })
YourContentView().dfPermissionPrompt(
isPresented: $showPopup, icon: "heart.fill", title: "Health data", message: "Why we ask",
benefits: [DFPermissionBenefit(icon: "figure.walk", title: "Track steps", detail: "Stays on device")],
onAllow: { }
)
YourContentView().dfPromoPopup(
isPresented: $showPopup, badge: "New", media: .symbol("sparkles"),
title: "Meet Focus mode", message: "Silence the noise.",
actionTitle: "Try it", secondaryTitle: "Later", onAction: { }
)
YourContentView().dfRatingPrompt(
isPresented: $showPopup, appName: "Orbit", threshold: 4,
onSubmit: { stars, feedback in }, onRequestReview: { }
)
YourContentView().dfInputPopup(
isPresented: $showPopup, title: "Rename folder", initialText: "Projects",
validators: [DFRequiredValidator(), DFMaxLengthValidator(maxLength: 40)],
onSubmit: { name in }
)
YourContentView().dfConsentSheet(isPresented: $showPopup, categories: DFConsentCategory.standard,
onSave: { enabledIDs in })
YourContentView().dfActionPopup(isPresented: $showPopup, title: "Photo", actions: [
DFActionPopupItem("Share", systemImage: "square.and.arrow.up") { },
DFActionPopupItem("Delete", systemImage: "trash", role: .destructive) { },
DFActionPopupItem("Cancel", role: .cancel) { },
], anchor: .bottom) // .center | .bottom | .target(id)
Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
DFUndoToast: message plus Undo with a live countdown ring (or .bar); holding pauses it, and onExpire fires only on .timeout, so it is the place to commit the destructive action. DFProgressToast: the ring morphs from progress to a success check or failure cross, with Cancel while running and Retry on failure. DFNotificationBanner: push-style banners stacked with depth, newest in front, swipe up to dismiss. DFLiveCapsule: a Dynamic-Island-style pill that expands with matched geometry.
YourContentView().dfUndoToast(
isPresented: $showPopup, message: "Photo deleted", duration: 5, indicator: .ring,
onUndo: { }, onExpire: { }
)
YourContentView().dfProgressToast(
isPresented: $showPopup, state: uploadState, title: "Uploading photo", detail: "3.2 of 8 MB",
onCancel: { }, onRetry: { }
) // state: .progress(Double?) | .success | .failure
YourContentView().dfNotificationBanners(items: $banners, onTap: { item in })
YourContentView().dfLiveCapsule(isPresented: $showPopup, isExpanded: $isExpanded, label: "Recording") {
Image(systemName: "waveform")
} trailing: {
Text("0:42")
} expanded: {
Text("Recording voice memo")
}
banners.insert(
DFNotificationBannerItem(icon: .symbol("message.fill"), title: "Maya", message: "Lunch tomorrow?", timestamp: "now"),
at: 0
)
Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
Mark targets with .dfPopupAnchor(_:) and run a DFCoachmarkTour over the view that contains them. The dim gets a spotlight cut-out (spotlight: false for a plain scrim) and the callout arrow points at the target. .dfCoachmark shows a single step.
VStack {
Button("Share") { }.dfPopupAnchor("share")
}
.dfCoachmarkTour(tour, spotlight: true)
// tour: DFCoachmarkTour(steps: [DFCoachmarkStep(target: "share", title: "Share", message: "Send it to a friend.")])
// tour.start() .next() .back() .skip() .finish()
YourContentView().dfCoachmark(isPresented: $showPopup, target: "share",
title: "Share", message: "Send it to a friend.")
Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
DFPopupMotion replaces the theme's ease with a spring or a choreography: .snappy .bouncy .gentle springs, .zoom .zoomOut .drop .slideFade .elastic (scale, blur and fade; Reduce Motion falls back to a fade) or .custom(Animation). .motion(_:enterFrom:exitTo:) lets a popup enter from one edge and leave toward another. DFPopupHaptic plays a tactile cue and is a no-op on visionOS (the Simulator produces no haptics, so none are shown here).
YourContentView().dfPopupPresentation(isPresented: $showPopup, motion: .elastic) {
Text("Bouncy")
}
let bouncy = DFPopupConfiguration.floater(position: .bottom)
.motion(.bouncy, enterFrom: .bottom, exitTo: .trailing)
DFPopupHaptic.success.play() // .light .medium .selection .success .warning .error
Recorded from the DFPlayground Popup Lab running on iOS 26 (light/dark, DesignFoundation presets).
Get started
Theme → shell → block → screen → your data. Or start with The Foundation Way to see why teams switch — same UI, ~87% fewer lines in your target.
Read the Integration Guide → Compare line counts →Pricing
No subscriptions. No seat counting. License it once — it's yours for every project you ever ship.
Questions about licensing? nerdsnipe.inc@gmail.com
FAQ
DFTheme is in the environment. Apply your own custom theme or any of the five presets (Slate, Aurora, Copper, Sage, Garnet) and every component adapts automatically. No per-component configuration required.DesignFoundationPro depends on DesignFoundation (the free MIT package). Add both to your Package.swift — Foundation provides the primitives, theming engine, and style system; Pro adds the 30 blocks, 55 screens, and 18 shell layouts on top. Pro is distributed via a licensed private repository.DFSignInBlock, DFStatCardBlock — that you compose into screens yourself. Screens are full-page SwiftUI views with domain model layers already wired — DFAIChatThreadScreen, DFCRMPipelineScreen — ready to connect to your data. Shells are navigation-level containers (DFAdaptiveShell, DFThreeColumnShell) that handle tab bar / sidebar logic and wrap any content. One license covers all three layers.StrictConcurrency experimental feature enabled in Package.swift). It targets iOS 18+, macOS 15+, and visionOS 2+. All action closures are @MainActor-isolated so they compose safely with your actor-isolated view models.55 screens. 30 blocks. 18 shells. 12 composition examples. Everything you need to ship a real app.
Get Pro — from $149 ⬇ Try DFPlayground first