orange-opensource/ouds-ios/ouds-ios-components-navigations

Claude Code and agent skill by orange-opensource/ouds-ios

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

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.

Install

npx vskill@latest install orange-opensource/ouds-ios/ouds-ios-components-navigations

SKILL.md

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

swift
OUDSLink(text: "Text", size: .default) {}
OUDSLink(text: "Text", indicator: .previous, size: .default) {}
OUDSLink(text: "Text", image: OUDSImage(asset: Image("ic")), size: .default) {}
OUDSLink(text: "Text", image: OUDSImage(asset: Image("ic"), renderingMode: .original), size: .default) {} // raw image (not tinted)

Tab Bar

Never combine with OUDSToolBarBottom on the same screen.
swift
// iOS 15–25
@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)
}
// iOS 26+
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.
  • principalItem (at most one item, center position): when set, subtitle is never displayed (whatever hasLargeTitle is —

.principal only replaces the inline bar title, not .navigationSubtitle() on iOS 26+); title is displayed only if hasLargeTitle: true (shown below the bar, large mode — never inside the bar next to principalItem).

Setup (bottom toolbar):

  • Never combine with OUDSTabBar on the same screen.
  • groupedItems layout meaningful on iOS 26+ only.
swift
// Top — minimal
NavigationStack {
ContentView().toolBarTop("Title")
}
// Top — with items
NavigationStack {
ContentView()
.toolBarTop("Title",
leadingItems: { OUDSToolBarItem(navigation: .back()) },
principalItem: OUDSToolBarItem(icon: Image("ic_search"), accessibilityLabel: "Search") {},
trailingItems: {
OUDSToolBarItem(icon: Image("ic_settings"), accessibilityLabel: "Settings") {}
})
}
// Top — principalItem + hasLargeTitle: title shown below the bar (large mode), subtitle never shown
ContentView()
.toolBarTop("Title", hasLargeTitle: true, subtitle: "Never shown",
principalItem: OUDSToolBarItem(icon: Image("ic_search"), accessibilityLabel: "Search") {})
// Top — principalItem without hasLargeTitle: neither title nor subtitle shown
ContentView()
.toolBarTop("Title", principalItem: OUDSToolBarItem(icon: Image("ic_search"), accessibilityLabel: "Search") {})
// Top — large title + subtitle (subtitle iOS 26+ only)
ContentView().toolBarTop("Title", hasLargeTitle: true, subtitle: "Sub")
// Bottom — leading/trailing split
ContentView()
.toolBarBottom(
leadingItems: { OUDSToolBarItem(label: "Edit") {} },
trailingItems: { OUDSToolBarItem(icon: Image("ic_share"), accessibilityLabel: "Share") {} })
// Bottom — grouped (iOS 26+ only)
ContentView()
.toolBarBottom(groupedItems: {
OUDSToolBarItem(label: "Save") {}
OUDSToolBarItem(icon: Image("ic_delete"), accessibilityLabel: "Delete") {}
})

`OUDSToolBarItem` reference:

swift
OUDSToolBarItem(label: "Edit") {} // text action
OUDSToolBarItem(icon: Image("ic"), accessibilityLabel: "X") {} // icon action
OUDSToolBarItem(navigation: .back()) // back — auto dismiss
OUDSToolBarItem(navigation: .back(label: "Cancel")) // back with label (ignored iOS 26+)
OUDSToolBarItem(navigation: .back(label: "Back") { saveDraft() }) // back + custom action
OUDSToolBarItem(navigation: .close) // close — NO closure, auto dismiss
// Badge on icon (v2.0.0+) — icon actions only
OUDSToolBarItem(action: .icon(asset: Image("ic_bell"), accessibilityLabel: "Notif",
badgeType: .standard))
OUDSToolBarItem(action: .icon(asset: Image("ic_mail"), accessibilityLabel: "Mail",
badgeType: .number(count: 9)))
// Action style — iOS 26+ only
if #available(iOS 26, *) {
OUDSToolBarItem(action: .label("Save", emphasized: false, accessibilityHint: nil) {},
style: .prominent) // .default | .prominent | .tinted
}
// Custom view
OUDSToolBarItem { Menu("More") { Button("Option 1") {} } }
// Conditional (result-builder syntax)
.toolBarTop("Title", principalItem: showSearch ? OUDSToolBarItem(icon: Image("ic_search"), accessibilityLabel: "Search") { showSearch = false } : nil, trailingItems: {
if isEditing {
OUDSToolBarItem(label: "Done") { isEditing = false }
} else {
OUDSToolBarItem(label: "Edit") { isEditing = true }
}
})
Badge rendering: iOS ≤ 25 → OUDSBadgeStandard / OUDSBadgeCount; iOS 26+ top → native system badge; iOS 26+ bottom → OUDSBadgeStandard / OUDSBadgeCount forced.

List Items

Common Patterns

Shared types:

TypePurpose
OUDSListItemDataTextual data: label, description, overline, extraLabel, helperText, textSlot, bottomSlot
OUDSListItemData.LabelLabel content: .textual(OUDSTextualContent, isBold:), .custom(AnyView, accessibilityLabel:) (.text is deprecated); string-literal convertible
OUDSTextualContentShared text payload for description / overline / extraLabel / helperText: .raw(String), .localized(LocalizedStringKey, tableName:, bundle:) or .rich(AttributedString); string-literal convertible
OUDSListItemLeadingLeading element: icon, image, flag, avatar, custom view
OUDSListItemTrailingTrailing element: text, badge, tag, icon, image, flag, avatar, custom view
.custom { ... } accepts any @ViewBuilder content (e.g. OUDSCircularProgressIndicator, custom control). Unlike .flag/.avatar,
it is not auto-hidden from accessibility — the custom view must carry its own accessibility label/value.
Rich text: every textual field (label, description, overline, extraLabel, helperText) accepts
a raw String, a localized string or a styled AttributedString. Pass string literals directly
(label: "Label", description: "Desc"), or use .textual(.rich(...)) for the label and
.rich(...) / .localized(...) for the other fields. Never use the deprecated Label.text.
Literal pitfall: a bare literal label with no textual field (OUDSListItemData(label: "Label"), or with only textSlot / bottomSlot)
may select a deprecated initializer (warning): write label: .textual("Label"). Same for a custom view label with a literal overline: write overline: .raw("…").

Shared view modifiers:

swift
.oudsListItemSize(.standard) // or .small
.oudsListItemContainerAlignment(.center) // or .top
.oudsListItemStyle(divider: true, background: false)
.oudsListCardStyle(.outlined())
.oudsListItemRoundedMedia(true)

Static List Item
swift
// Minimal
OUDSStaticListItem(data: OUDSListItemData(label: .textual("Label")))
// Full textual content (string literals auto-convert to .raw OUDSTextualContent)
OUDSStaticListItem(data: OUDSListItemData(
label: "Label",
description: "Description",
overline: "Overline",
extraLabel: "Extra"
))
// Rich text content for any textual field
OUDSStaticListItem(data: OUDSListItemData(
label: .textual(.rich(AttributedString.from(text: "Premium", foregroundColor: .orange, font: .headline))),
description: .rich(myStyledDescription),
overline: "Plain overline",
helperText: .rich(AttributedString.from(text: "A rich helper", foregroundColor: .gray, font: .caption))
))
// Alternative: using theme colors
OUDSStaticListItem(data: OUDSListItemData(
label: .textual(.rich(AttributedString.from(
text: "Important",
foregroundColor: Color(hexadecimalCode: theme.colors.repositoryNegativeHigh),
font: .body
))),
description: .rich(AttributedString.from(
text: "Warning",
foregroundColor: Color(hexadecimalCode: theme.colors.repositoryOpacityWarningMedium),
font: .body
))
))
// With leading icon
OUDSStaticListItem(
data: OUDSListItemData(label: .textual("Info")),
leading: .icon(OUDSListItemIcon(status: .info, description: "", size: .medium))
)
// With trailing badge
OUDSStaticListItem(
data: OUDSListItemData(label: .textual("Notifications")),
trailing: .badge(.count(.init(3, accessibilityLabel: "3", status: .negative, size: .medium)))
)
// With avatar + tag
OUDSStaticListItem(
data: OUDSListItemData(label: .textual("Profile")),
leading: .avatar(OUDSListItemAvatar(type: .icon, size: .medium, accessibilityLabel: "")),
trailing: .tag(OUDSTag(label: "New", size: .small))
)
// With trailing text
OUDSStaticListItem(
data: OUDSListItemData(label: .textual("Status")),
trailing: .text(.labelMuted("Active"))
)
// With flag
OUDSStaticListItem(
data: OUDSListItemData(label: .textual("Country")),
leading: .flag(OUDSListItemFlag(asset: Image("flag_fr"), description: "France"))
)
// With slot (view under texts, before helper text)
OUDSStaticListItem(
data: OUDSListItemData(label: .textual("With slot"), textSlot: .init { Text("Additional content") })
)
// With bottomSlot (view under main content, before helper text)
OUDSStaticListItem(
data: OUDSListItemData(label: .textual("With bottom slot"), bottomSlot: .init { Text("Bottom content") })
)
// With both slot and bottomSlot
OUDSStaticListItem(
data: OUDSListItemData(
label: "Label",
textSlot: .init { Text("Slot content") },
bottomSlot: .init { Text("Bottom content") },
helperText: "Helper text"
)
)
// With a custom view in leading/trailing (e.g. a gauge for a remaining SMS credit)
OUDSStaticListItem(
data: OUDSListItemData(label: .textual("SMS credit")),
trailing: .custom {
OUDSCircularProgressIndicator(progress: 0.75)
}
)

Navigation List Item
swift
// Forward navigation (default)
OUDSNavigationListItem(data: OUDSListItemData(label: .textual("Next"))) {
// action
}
// Backward navigation
OUDSNavigationListItem(data: OUDSListItemData(label: .textual("Back")), indicatorType: .previous) {
// action
}
// External navigation
OUDSNavigationListItem(data: OUDSListItemData(label: .textual("Website")), indicatorType: .external) {
openURL(url)
}
// With leading/trailing
OUDSNavigationListItem(
data: OUDSListItemData(label: "Profile", description: "View details"),
leading: .avatar(OUDSListItemAvatar(type: .initials("JD"), size: .medium)),
trailing: .text(.labelMuted("Details"))
) {
// navigate
}
// With slot (view under texts, before helper text)
OUDSNavigationListItem(
data: OUDSListItemData(label: .textual("Settings"), textSlot: .init { Text("Configure options") })
) {
// navigate
}
// With bottomSlot (view under main content, before helper text)
OUDSNavigationListItem(
data: OUDSListItemData(label: .textual("Profile"), bottomSlot: .init { Text("Additional info") })
) {
// navigate
}
// With both slot and bottomSlot
OUDSNavigationListItem(
data: OUDSListItemData(
label: "Settings",
textSlot: .init { Text("Slot content") },
bottomSlot: .init { Text("Bottom content") },
helperText: "Helper text"
)
) {
// navigate
}

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
34
Repository forks
9
7-day trend score
18

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/orange-opensource/ouds-ios/ouds-ios-components-navigations/badge)](https://verified-skill.com/skills/orange-opensource/ouds-ios/ouds-ios-components-navigations)

Something wrong with this skill or its page? Tell us.