Loading...
Loading...
Use when implementing iOS 26 SwiftUI features - covers Liquid Glass design system, performance improvements, @Animatable macro, 3D spatial layout, scene bridging, WebView/WebPage, AttributedString rich text editing, drag and drop enhancements, and visionOS integration for iOS 26+
npx skill4agent add megastep/codex-skills axiom-swiftui-26-refenabledBoundsaxiom-liquid-glassaxiom-liquid-glass-refpresentationBackground.toolbar {
ToolbarItem(placement: .bottomBar) { Button("Archive", systemImage: "archivebox") { } }
ToolbarSpacer(.flexible, placement: .bottomBar) // Push items apart
ToolbarItem(placement: .bottomBar) { Button("Compose", systemImage: "square.and.pencil") { } }
}
// .fixed separates groups visually; .flexible pushes apart (like Spacer in HStack)ToolbarItemGroupToolbarItemPlacementconfirmationActionglassProminentcancellationAction.sharedBackgroundVisibility(.hidden).toolbar {}toolbar(id:)ToolbarItem(id:)// MailboxList
.toolbar(id: "main") {
ToolbarItem(id: "filter", placement: .bottomBar) { Button("Filter") { } }
ToolbarSpacer(.flexible, placement: .bottomBar)
ToolbarItem(id: "compose", placement: .bottomBar) { Button("New Message") { } }
}
// MessageList — "filter" absent (animates out), "compose" stays stable
.toolbar(id: "main") {
ToolbarSpacer(.flexible, placement: .bottomBar)
ToolbarItem(id: "compose", placement: .bottomBar) { Button("New Message") { } }
}DefaultToolbarItem(kind: .search, placement: .bottomBar)
// Replaces system's default placement of matching kindNavigationSplitViewif #available(iOS 26.0, *)toolbar(id:).secondaryActionshowsByDefault: falseToolbarCommands().navigationSubtitle("3 unread").badge(3)axiom-swiftui-search-refNavigationSplitView {
List { }.searchable(text: $searchText)
}
// Bottom-aligned on iPhone, top trailing on iPad (automatic)
// Use placement: .sidebar to restore sidebar-embedded search on iPadsearchToolbarBehavior(.minimize)Tab(role: .search)Button("To Top", systemImage: "chevron.up") { scrollToTop() }
.padding()
.glassEffect() // Add .interactive for custom controls on iOSGlassEffectContainerglassEffectID(_:in:).matchedTransitionSource.navigationTransition(.zoom(...)).buttonBorderShape(.roundedRectangle).controlSize(.extraLarge).controlSize(.small)GlassButtonStyle(.clear/.glass/.tint).buttonSizing(.fit/.stretch/.flexible)Button(role: .close)Button(role: .confirm).clipShape(.rect(cornerRadius: 12, style: .containerConcentric))SliderTick<V>SliderTickContentForEachSliderTickBuilder// Static ticks with labels
Slider(value: $value, in: 0...10) {
Text("Rating")
} ticks: {
SliderTick(0) { Text("Min") }
SliderTick(5) { Text("Mid") }
SliderTick(10) { Text("Max") }
}
// Dynamic ticks from collection
SliderTickContentForEach(stops, id: \.self) { value in
SliderTick(value) { Text("\(Int(value))°").font(.caption2) }
}
// Step-based ticks (called for each step value)
Slider(value: $volume, in: 0...10, step: 2, label: { Text("Volume") }, tick: { value in
SliderTick(value) { Text("\(Int(value))") }
})SliderTickContentForEachData.ElementSliderTick<V>chapters.map(\.time)chapters.first(where: { $0.time == time })Slider(
value: $rating, in: 0...100,
neutralValue: 50, // Starting point / center value
enabledBounds: 20...80, // Restrict selectable range
label: { Text("Rating") },
currentValueLabel: { Text("\(Int(rating))") },
minimumValueLabel: { Text("0") },
maximumValueLabel: { Text("100") },
ticks: { SliderTick(50) { Text("Mid") } },
onEditingChanged: { editing in print(editing ? "Started" : "Ended") }
).sliderThumbVisibility(.hidden).automatic.visible.hiddenList { ForEach(1...20, id: \.self) { Text("\($0). Item") } }
.safeAreaBar(edge: .bottom) {
Text("Bottom Action Bar").padding(.vertical, 15)
}
.scrollEdgeEffectStyle(.soft, for: .bottom) // or .hardsafeAreaInset@Environment(\.openURL) var openURL
// openURL(url, prefersInApp: true) — Opens in SFSafariViewController-style in-app browser
// Default Link opens in Safari; prefersInApp keeps users in your appaxiom-swiftui-search-ref.searchable.searchable(text: $searchText)
.searchToolbarBehavior(.minimize) // Compact button, expands on tap.searchPresentationToolbarBehavior(.avoidHidingContent)extension View {
@ViewBuilder func minimizedSearch() -> some View {
if #available(iOS 26.0, *) {
self.searchToolbarBehavior(.minimize)
} else { self }
}
}
// Usage
.searchable(text: $searchText)
.minimizedSearch().toolbar {
if #available(iOS 26.0, *) {
DefaultToolbarItem(kind: .search, placement: .bottomBar)
ToolbarSpacer(.flexible, placement: .bottomBar)
}
ToolbarItem(placement: .bottomBar) {
NewNoteButton()
}
}
.searchable(text: $searchText).commands {
TextEditingCommands() // Same API as macOS menu bar
CommandGroup(after: .newItem) {
Button("Add Note") {
addNote()
}
.keyboardShortcut("n", modifiers: [.command, .shift])
}
}
// Creates menu bar on iPad when people swipe down// MIGRATION REQUIRED:
// Remove deprecated property list key in iPadOS 26:
// UIRequiresFullscreen (entire key deprecated, all values)
// For split view navigation, system automatically shows/hides columns
// based on available space during resize
NavigationSplitView {
Sidebar()
} detail: {
Detail()
}
// Adapts to resizing automatically.windowResizeAnchor(.topLeading) // Tailor where animation originates
// SwiftUI now synchronizes animation between content view size changes
// and window resizing - great for preserving continuity when switching tabsList(trips) { trip in // 100k+ items
TripRow(trip: trip)
}
// Loads 6x faster, updates 16x faster on macOS (iOS 26+)ScrollView(.horizontal) {
LazyHStack {
ForEach(photoSets) { photoSet in
ScrollView(.vertical) {
LazyVStack {
ForEach(photoSet.photos) { photo in
PhotoView(photo: photo)
}
}
}
}
}
}
// Nested scrollviews now properly delay loading with lazy stacks
// Great for building photo carousels@Observable
class TripStore {
var trips: [Trip] = []
func loadTrips() async {
trips = await TripService.fetchTrips()
// Swift 6 verifies data race safety at compile time
}
}animatableDatastruct HikingRouteShape: Shape {
var startPoint: CGPoint
var endPoint: CGPoint
var elevation: Double
var drawingDirection: Bool // Don't want to animate this
// Tedious manual animatableData declaration
var animatableData: AnimatablePair<CGPoint.AnimatableData,
AnimatablePair<Double, CGPoint.AnimatableData>> {
get {
AnimatablePair(startPoint.animatableData,
AnimatablePair(elevation, endPoint.animatableData))
}
set {
startPoint.animatableData = newValue.first
elevation = newValue.second.first
endPoint.animatableData = newValue.second.second
}
}
}@Animatable
struct HikingRouteShape: Shape {
var startPoint: CGPoint
var endPoint: CGPoint
var elevation: Double
@AnimatableIgnored
var drawingDirection: Bool // Excluded from animation
// animatableData automatically synthesized!
}animatableData@AnimatableIgnoredstruct SunPositionView: View {
@State private var timeOfDay: Double = 12.0
var body: some View {
HikingRouteView()
.overlay(alignment: sunAlignment) {
SunView()
.spatialOverlay(alignment: sunAlignment)
}
}
var sunAlignment: Alignment3D {
// Align sun in 3D space based on time of day
Alignment3D(
horizontal: .center,
vertical: .top,
depth: .back
)
}
}Model3D(named: "WaterBottle")
.manipulable() // People can pick up and move the object@Environment(\.surfaceSnappingInfo) var snappingInfo: SurfaceSnappingInfo
var body: some View {
VStackLayout().depthAlignment(.center) {
Model3D(named: "waterBottle")
.manipulable()
Pedestal()
.opacity(snappingInfo.classification == .table ? 1.0 : 0.0)
}
}MenuBarExtraImmersiveSpaceRemoteImmersiveSpaceAssistiveAccess.windowStyle().immersiveEnvironmentBehavior()// In your macOS app
@main
struct MyMacApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
RemoteImmersiveSpace(id: "stereoView") {
// Render stereo content on Apple Vision Pro
// Uses CompositorServices
}
}
}@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
AssistiveAccessScene {
SimplifiedUI() // UI shown when iPhone is in AssistiveAccess mode
}
}
}// Show SwiftUI view in AppKit sheet
let hostingController = NSHostingController(rootView: SwiftUISettingsView())
presentAsSheet(hostingController)
// Great for incremental SwiftUI adoption// Bridge AppKit gestures to SwiftUI
struct AppKitPanGesture: NSGestureRecognizerRepresentable {
func makeNSGestureRecognizer(context: Context) -> NSPanGestureRecognizer {
NSPanGestureRecognizer()
}
func updateNSGestureRecognizer(_ recognizer: NSPanGestureRecognizer, context: Context) {
// Update configuration
}
}@Observable
class RealityEntity {
var position: SIMD3<Float>
var rotation: simd_quatf
}
struct MyView: View {
@State private var entity = RealityEntity()
var body: some View {
// SwiftUI views automatically observe changes
Text("Position: \(entity.position.x)")
}
}// Present SwiftUI popovers from RealityKit entities
let popover = Entity()
mapEntity.addChild(popover)
popover.components[PresentationComponent.self] = PresentationComponent(
isPresented: $popoverPresented,
configuration: .popover(arrowEdge: .bottom),
content: DetailsView()
)ViewAttachmentComponentGestureComponentimport WebKit
struct ArticleView: View {
let articleURL: URL
var body: some View {
WebView(url: articleURL)
}
}import WebKit
struct InAppBrowser: View {
@State private var page = WebPage()
var body: some View {
VStack {
Text(page.title ?? "Loading...")
WebView(page)
.ignoresSafeArea()
.onAppear {
page.load(URLRequest(url: articleURL))
}
HStack {
Button("Back") { page.goBack() }
.disabled(!page.canGoBack)
Button("Forward") { page.goForward() }
.disabled(!page.canGoForward)
}
}
}
}goBack()goForward()titleurlcanGoBackcanGoForwardaxiom-tvosTextEditorAttributedStringstruct CommentView: View {
@State private var comment = AttributedString("Enter your comment")
var body: some View {
TextEditor(text: $comment)
// Built-in text formatting controls included
// Users can apply bold, italic, underline, etc.
}
}AttributedStringstruct PhotoGrid: View {
@State private var selectedPhotos: [Photo.ID] = []
var body: some View {
ScrollView {
LazyVGrid(columns: gridColumns) {
ForEach(model.photos) { photo in
view(photo: photo)
.draggable(containerItemID: photo.id)
}
}
}
.dragContainer(for: Photo.self, selection: selectedPhotos) { draggedIDs in
photos(ids: draggedIDs)
}
}
}.draggable(containerItemID:containerNamespace:)nil.dragContainer(for:selection:).dragConfiguration(DragConfiguration(allowMove: false, allowDelete: true)).onDragSessionUpdated { session in
let ids = session.draggedItemIDs(for: Photo.ID.self)
if session.phase == .ended(.delete) {
trash(ids)
deletePhotos(ids)
}
}.dragPreviewsFormation(.stack) // Items stack nicely on top of one another
// Other formations:
// - .default
// - .grid
// - .stack.dragContainer.dragConfiguration.dragPreviewsFormation.onDragSessionUpdatedChart3Dimport Charts
struct HikePlotView: View {
var body: some View {
Chart3D {
SurfacePlot(x: "x", y: "y", z: "z") { x, y in
sin(x) * cos(y)
}
.foregroundStyle(Gradient(colors: [.orange, .pink]))
}
.chartXScale(domain: -3...3)
.chartYScale(domain: -3...3)
.chartZScale(domain: -3...3)
}
}Chart3DSurfacePlot.chartZScale().chartZAxis()LineMark3Dstruct FavoriteLocationControl: ControlWidget {
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(kind: "FavoriteLocation") {
ControlWidgetButton(action: MarkFavoriteIntent()) {
Label("Mark Favorite", systemImage: "star")
}
}
}
}
// Access from watch face or Shortcutsstruct CountdownWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "Countdown") { entry in
CountdownView(entry: entry)
}
}
}
struct PhotoCountdownView: View {
@Environment(\.levelOfDetail) var levelOfDetail: LevelOfDetail
var body: some View {
switch levelOfDetail {
case .default:
RecentPhotosView() // Full detail when close
case .simplified:
CountdownView() // Simplified when further away
default:
CountdownView()
}
}
}<key>UIRequiresFullscreen</key>
<!-- Entire property list key is deprecated (all values) -->presentationBackground.fixed.glassEffect()glassEffectIDGlassEffectContainersharedBackgroundVisibility(.hidden)navigationZoomTransitionTab(role: .search).searchToolbarBehavior(.minimize).controlSize(.extraLarge).containerConcentric.commands.windowResizeAnchor().dragContainerSliderTickSliderTickContentForEach.sliderThumbVisibility().safeAreaBar().scrollEdgeEffectStyle()openURL(url, prefersInApp: true)Button(role: .close)GlassButtonStyle.buttonSizing().toolbar {}toolbar(id:)toolbar(id:)CustomizableToolbarContent.tabBarMinimizeBehavior(.onScrollDown).tabViewBottomAccessory(isEnabled:content:).toolbar {}presentationBackgroundGlassEffectContainer.safeAreaPadding().padding()axiom-swiftui-layout-refAttributedStringTextEditorAlignment3D.manipulable()| Symptom | Fix |
|---|---|
| Old design after updating to iOS 26 SDK | Clean build (Shift-Cmd-K), rebuild targeting iOS 26 SDK, check deployment target |
| Search remains at top on iPhone | Place |
| @Animatable "does not conform" | All properties must be |
| Rich text formatting lost in TextEditor | Bind |
| Drag delete not working | Enable |
| SliderTickContentForEach won't compile | Iterate over numeric values ( |
| Toolbar not morphing during navigation | Move |