You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
DFCalendarView: a new themed month-grid calendar primitive (Supplementary/Calendar/) — single-date selection: Binding<Date>, optional external displayedMonth control, minimumDate/maximumDate bounds with disabled out-of-range days, and a generic @ViewBuilder dayContent: (Date) -> Content slot for event dots/badges. Respects @Environment(\.calendar)/\.locale — no hardcoded first-weekday assumption. Ships one built-in style, .standard.
DFEmptyState: a free-tier "no results" primitive (Supplementary/EmptyState/) — icon + title + optional message + optional action button, all independent optionals beyond the required icon/title. Previously this pattern only existed behind DesignFoundationPro's DFEmptyStateBlock.
DFCommandPalette: a new Cmd-K-style overlay modifier (Overlays/CommandPalette/) — .dfCommandPalette(isPresented:items:placeholder:onSelect:), case-insensitive substring filtering on title/subtitle, and keyboard navigation on macOS (↑/↓ to highlight, Return to select, Escape to dismiss).
DFMaterialTokens wired in:DFTheme.materials: DFMaterialTokens is now a real theme property, and all 16 .glass styles read theme.materials.surfaceMaterial/elevatedMaterial instead of hardcoding .regularMaterial/.thickMaterial. Setting theme.materials.preferLiquidGlass = false opts every .glass style back to its non-glass color-token appearance — useful for accessibility, branding, or pre-26 OS parity testing. DFMaterialTokens itself no longer carries an @available gate (only the individual .glass styles remain iOS/macOS 26+, unchanged).
DFComponentTokens expanded: seven new per-component override structs — DFDividerTokens, DFProgressBarTokens, DFSkeletonTokens, DFToggleTokens, DFDatePickerTokens, DFSidebarTokens, DFTabBarTokens — following the existing "every field optional, nil inherits the theme default" pattern. (Slider, Picker, and NavigationBar were evaluated and intentionally excluded — they're thin native-control wrappers with nothing custom-drawn worth exposing as an override.)
DFChip: a new themed chip/tag primitive (Primitives/Chip/) — variants .label, .labelWithIcon, .dismissible(onDismiss:), .selectable(isSelected:); styles .filled (default), .tinted, .outlined. Closes a real gap versus competing SwiftUI component libraries (see the dskit competitor profile) that we had no answer for.
DFRatingView: a new themed rating primitive (Primitives/Rating/) — .stars (default, half-star support) and .numeric styles; .readOnly and .interactive(onChange:) modes, the latter exposing a VoiceOver-adjustable action.
DFPriceView / DFPriceSummaryView: currency-formatted price display (Primitives/Price/, locale-aware via Decimal.formatted(.currency(code:))) with an optional strikethrough compareAtAmount, plus a line-item order-summary layout (Layouts/PriceSummary/) built from DFPriceLineItems with a .total emphasis row.
DFEntityRow / DFEntityCard: a new themed "media + title/subtitle + trailing metadata" summary pair (Layouts/EntityRow/) for contacts, orders, and search-result-shaped content — deliberately distinct from DFListRow (which stays a plain structural row with arbitrary leading/trailing views and no styling). DFEntityRow is the list-context form; DFEntityCard is the grid/card-context sibling, built on DFCard.
DFGrid / DFCarousel: themed LazyVGrid (.fixed(Int) or .adaptive(minWidth:) columns) and horizontal-scroll (Layouts/Grid/, Layouts/Carousel/) container wrappers — no content opinions, spacing read from DFTheme unless overridden.
DFQuantityStepper: a new themed quantity-stepper input (Inputs/Stepper/, named to avoid colliding with SwiftUI's own Stepper) — .bordered (default) and .compact styles, VoiceOver-adjustable.
DFEmptyState secondary action: new optional secondaryActionTitle/onSecondaryAction parameters render a second, ghost-styled button alongside the primary one — covers permission-prompt-shaped two-choice screens (e.g. "Allow" / "Not Now") without introducing a near-duplicate component.
DFBanner: a new full-width, persistent, inline banner (Supplementary/Banner/) — reuses DFToastSeverity (.info/.success/.warning/.error), optional action button, optional user-dismiss. Deliberately not built on DFToastQueue — toast's floating-capsule/auto-dismiss/global-overlay-queue model doesn't fit a banner's full-width/user-dismissed/inline-in-content shape; conflating the two would have meant bolting a persistent mode onto an auto-timeout-only queue. Place DFBanner directly in your view hierarchy, the same way DFAlert/DFEmptyState work.
Five theme presets:.garnet was already shipped in code and CHANGELOG.md, but README.md, CLAUDE.md, AGENTS.md, .cursor/rules/design-foundation.mdc, and the published docs pages still said "four presets" in several places — corrected everywhere to five (.slate, .aurora, .copper, .sage, .garnet).
Fixed
Swift 6 strict-concurrency build blocker:DFProgressBarStyle, DFSecureFieldStyle, DFSliderStyle, DFToggleStyle, DFSidebarStyle, and DFDatePickerStyle failed a clean swift build on newer toolchains (their *Style protocol requirements weren't @MainActor, but built-in style implementations called MainActor-isolated SwiftUI statics like .circular/.plain/.switch/Spacer()). Fixed by marking each protocol's view-building requirement @MainActor, matching the pattern already used by DFAlert's closures. Four test files (DFTableTests, DFListTests, DFSidebarTests, DFProgressBarTests, plus the new DFChipTests/DFRatingViewTests) needed the same @MainActor annotation on specific test functions that construct these types directly.
Stale DFTextScale test assertion:DFTextTests.swift asserted DFTextScale.allCases.count == 6; the enum has shipped 8 cases (display, title, headline, labelLarge, body, bodySmall, label, caption) since labelLarge/bodySmall were added. Corrected the assertion — unrelated to the concurrency fix above, just test-data drift.
Docs
CLAUDE.md, AGENTS.md, and .cursor/rules/design-foundation.mdc updated with reference sections for all of the above, verified against source and mechanically compiled via the doc-snippet CI gate.
The dedicated docs/theme-presets/index.html landing page still needs a Garnet swatch card + screenshot asset (docs/images/theme-garnet.png doesn't exist yet) — tracked separately, not done as part of this pass since it needs a real screenshot, not a text fix.