| name | ouds-ios-components-navigations |
| description | Usage and code examples for OUDS iOS Navigations components — OUDSLink (text, indicator, icon, size), OUDSTabBar (iOS 15–25 and iOS 26+ APIs) and Toolbars (toolBarTop / toolBarBottom + OUDSToolBarItem with back / close / icon / label / badge / prominent style). Load the ouds-ios-framework-usage skill first for imports, themes and image rules. |
| license | MIT |
OUDS Navigations components
Prerequisite: load ouds-ios-framework-usage first for imports, themes and image rules
(OUDSImage, // swiftlint:disable:next accessibility_label_for_image).
Link
OUDSLink(text: "Text", size: .default) {}
OUDSLink(text: "Text", indicator: .back, size: .default) {}
OUDSLink(text: "Text", icon: OUDSImage(asset: Image("ic")), size: .default) {}
OUDSLink(text: "Text", icon: OUDSImage(asset: Image("ic"), renderingMode: .original), size: .default) {}
Tab Bar
Never combine with OUDSToolBarBottom on the same screen.
@State private var selectedTab = 0
OUDSTabBar(selectedTab: $selectedTab, count: 3) {
SomeView().tabItem { Label("Tab 1", image: "ic_1") }.tag(0)
OtherView().tabItem { Label("Tab 2", image: "ic_2") }.tag(1)
}
OUDSTabBar {
SomeView().tabItem { Label("Tab 1", image: "ic_1") }
OtherView().tabItem { Label("Tab 2", image: "ic_2") }
}
Tab bar images: 26×26 pt. OUDSTabBar(selected:count:content:) (plain Int) is deprecated — use selectedTab: Binding<Int>.
Toolbars
Availability: iOS 15+, visionOS 1+. Not available on watchOS, tvOS, macOS.
Setup (top toolbar):
- Must be inside
NavigationStack.
- Call
.oudsNavigationBarAppearance() once on the root NavigationStack.
- On iOS ≤ 18: add
.accentColor(theme.colors.contentDefault) on root view for the back chevron.
subtitle rendered on iOS 26+ only; ignored when hasLargeTitle: true.
Setup (bottom toolbar):
- Never combine with
OUDSTabBar on the same screen.
groupedItems layout meaningful on iOS 26+ only.
NavigationStack {
ContentView().toolBarTop("Title")
}
NavigationStack {
ContentView()
.toolBarTop("Title",
leadingItems: { OUDSToolBarItem(navigation: .back()) },
trailingItems: {
OUDSToolBarItem(icon: Image("ic_settings"), accessibilityLabel: "Settings") {}
})
}
ContentView().toolBarTop("Title", hasLargeTitle: true, subtitle: "Sub")
ContentView()
.toolBarBottom(
leadingItems: { OUDSToolBarItem(label: "Edit") {} },
trailingItems: { OUDSToolBarItem(icon: Image("ic_share"), accessibilityLabel: "Share") {} })
ContentView()
.toolBarBottom(groupedItems: {
OUDSToolBarItem(label: "Save") {}
OUDSToolBarItem(icon: Image("ic_delete"), accessibilityLabel: "Delete") {}
})
OUDSToolBarItem reference:
OUDSToolBarItem(label: "Edit") {}
OUDSToolBarItem(icon: Image("ic"), accessibilityLabel: "X") {}
OUDSToolBarItem(navigation: .back())
OUDSToolBarItem(navigation: .back(label: "Cancel"))
OUDSToolBarItem(navigation: .back(label: "Back") { saveDraft() })
OUDSToolBarItem(navigation: .close)
OUDSToolBarItem(action: .icon(asset: Image("ic_bell"), accessibilityLabel: "Notif",
badgeType: .standard))
OUDSToolBarItem(action: .icon(asset: Image("ic_mail"), accessibilityLabel: "Mail",
badgeType: .number(count: 9)))
if #available(iOS 26, *) {
OUDSToolBarItem(action: .label("Save", emphasized: false, accessibilityHint: nil) {},
style: .prominent)
}
OUDSToolBarItem { Menu("More") { Button() {} } }
.toolBarTop(, trailingItems: {
isEditing {
(label: ) { isEditing }
} {
(label: ) { isEditing }
}
})
Badge rendering: iOS ≤ 25 → OUDSBadge; iOS 26+ top → native system badge; iOS 26+ bottom → OUDSBadge forced.
List Items
Common Patterns
Shared types:
| Type | Purpose |
|---|
OUDSListItemData | Textual data: label, description, overline, extraLabel, helperText |
OUDSListItemLeading | Leading element: icon, image, flag, avatar |
OUDSListItemTrailing | Trailing element: text, badge, tag, icon, image, flag, avatar |
Shared view modifiers:
.oudsListItemSize(.standard)
.oudsListItemContainerAlignment(.center)
.oudsListItemStyle(divider: true, background: false)
.oudsListCardStyle(.outlined())
.oudsListItemRoundedMedia(true)
Static List Item
OUDSStaticListItem(data: OUDSListItemData(label: "Label"))
OUDSStaticListItem(data: OUDSListItemData(
label: "Label",
description: "Description",
overline: "Overline",
extraLabel: "Extra"
))
OUDSStaticListItem(
data: OUDSListItemData(label: "Info"),
leading: .icon(OUDSListItemIcon(status: .info, description: "", size: .medium))
)
OUDSStaticListItem(
data: OUDSListItemData(label: "Notifications"),
trailing: .badge(.count(.init(3, accessibilityLabel: "3", status: .negative, size: .medium)))
)
OUDSStaticListItem(
data: OUDSListItemData(label: "Profile"),
leading: .avatar(OUDSListItemAvatar(type: .icon, size: .medium)),
trailing: .tag(OUDSTag(label: "New", size: .small))
)
OUDSStaticListItem(
data: OUDSListItemData(label: "Status"),
trailing: .text(.labelMuted("Active"))
)
OUDSStaticListItem(
data: OUDSListItemData(label: "Country"),
leading: .flag(OUDSListItemFlag(asset: Image("flag_fr"), size: .medium))
)
(
data: (label: ),
slot: ()
)
Navigation List Item
OUDSNavigationListItem(data: OUDSListItemData(label: "Next")) {
}
OUDSNavigationListItem(data: OUDSListItemData(label: "Back"), indicatorType: .previous) {
}
OUDSNavigationListItem(data: OUDSListItemData(label: "Website"), indicatorType: .external) {
openURL(url)
}
OUDSNavigationListItem(
data: OUDSListItemData(label: "Profile", description: "View details"),
leading: .avatar(OUDSListItemAvatar(type: .initials("JD"), size: .medium)),
trailing: .text(.labelMuted("Details"))
) {
}
OUDSNavigationListItem(
data: OUDSListItemData(label: "Settings"),
slot: Text("Configure options")
) {
}
OUDSNavigationListItem(
data: OUDSListItemData(label: "Documentation"),
indicatorType: .external,
trailing: .badge(.standard(.init(accessibilityLabel: "New", status: .accent, size: .small)))
) {
openURL(url)
}
Associated Types — Icon
OUDSListItemIcon(status: .info, description: "", size: .medium)
OUDSListItemIcon(status: .warning, description: "", size: .large)
OUDSListItemIcon(status: .negative, description: "", size: .medium)
OUDSListItemIcon(status: .positive, description: "", size: .medium)
OUDSListItemIcon(status: .neutral(asset: Image("ic"), description: "Label"), size: .medium)
OUDSListItemIcon(status: .neutral(asset: Image("ic"), description: "Label", badge: true), size: .medium)
Associated Types — Avatar
OUDSListItemAvatar(type: .icon, size: .medium)
OUDSListItemAvatar(type: .image(Image("photo")), size: .large)
OUDSListItemAvatar(type: .initials("AB"), size: .extraLarge)
OUDSListItemAvatar(
type: .icon,
size: .medium,
badgeType: .standard(.init(accessibilityLabel: "Online", status: .positive, size: .small))
)
OUDSListItemAvatar(
type: .initials("JD"),
size: .large,
badgeType: .icon(.init(status: .negative, accessibilityLabel: "Offline", size: .small))
)
Associated Types — Image & Flag
OUDSListItemImage(asset: Image("photo"), size: .medium)
OUDSListItemImage(asset: Image("photo"), size: .large)
OUDSListItemFlag(asset: Image("flag_fr"), size: .medium)
OUDSListItemFlag(asset: Image("flag_us"), size: .large)