6.9 KiB
6.9 KiB
iOS Components Catalog
Complete reference for native iOS UI components following Apple Human Interface Guidelines.
Navigation Components
Navigation Bar
Top bar for hierarchical navigation.
NavigationStack {
List {
Text("Item 1")
Text("Item 2")
}
.navigationTitle("Title")
.navigationBarTitleDisplayMode(.large) // or .inline
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Add") {
// Action
}
}
}
}
Guidelines:
- Use
.largefor top-level views - Use
.inlinefor detail views - Maximum 2-3 toolbar items
- Keep actions relevant to context
Tab Bar
Bottom navigation for peer destinations.
TabView {
HomeView()
.tabItem {
Label("Home", systemImage: "house")
}
SearchView()
.tabItem {
Label("Search", systemImage: "magnifyingglass")
}
}
Guidelines:
- 3-5 tabs maximum
- Use SF Symbols for icons
- One-word labels
- Never hide or disable tabs
Toolbar
Actions for current context.
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Edit") { }
}
ToolbarItem(placement: .bottomBar) {
Button("Delete") { }
}
}
Controls
Button
Primary action control.
// Prominent (primary action)
Button("Continue") { }
.buttonStyle(.borderedProminent)
// Bordered (secondary action)
Button("Cancel") { }
.buttonStyle(.bordered)
// Plain (tertiary action)
Button("Learn More") { }
.buttonStyle(.plain)
Toggle (Switch)
Boolean control.
Toggle("Enable notifications", isOn: $isEnabled)
.toggleStyle(.switch)
Slider
Continuous value selection.
Slider(value: $volume, in: 0...100)
.accessibilityLabel("Volume")
.accessibilityValue("\(Int(volume))%")
Picker
Selection from multiple options.
// Menu style
Picker("Size", selection: $size) {
Text("Small").tag("S")
Text("Medium").tag("M")
Text("Large").tag("L")
}
.pickerStyle(.menu)
// Segmented (2-5 options)
Picker("View", selection: $viewType) {
Text("List").tag(0)
Text("Grid").tag(1)
}
.pickerStyle(.segmented)
TextField
Text input.
TextField("Username", text: $username)
.textFieldStyle(.roundedBorder)
.textContentType(.username)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
SecureField
Password input.
SecureField("Password", text: $password)
.textFieldStyle(.roundedBorder)
.textContentType(.password)
Content Views
List
Scrollable rows of content.
List {
Section("Today") {
ForEach(items) { item in
NavigationLink {
DetailView(item: item)
} label: {
HStack {
Image(systemName: item.icon)
Text(item.title)
}
}
}
.onDelete { indices in
items.remove(atOffsets: indices)
}
}
}
.listStyle(.insetGrouped)
List Styles:
.plain- Edge-to-edge.insetGrouped- Rounded sections (iOS default).sidebar- Navigation sidebar
ScrollView
Custom scrollable content.
ScrollView {
VStack(spacing: 16) {
ForEach(items) { item in
CardView(item: item)
}
}
.padding()
}
Grid
Multi-column layout.
// LazyVGrid for vertical scrolling
LazyVGrid(columns: [
GridItem(.adaptive(minimum: 150))
]) {
ForEach(items) { item in
CardView(item: item)
}
}
// LazyHGrid for horizontal scrolling
LazyHGrid(rows: [
GridItem(.fixed(200))
]) {
ForEach(items) { item in
CardView(item: item)
}
}
Presentations
Sheet (Modal)
Present content modally.
.sheet(isPresented: $showSheet) {
NavigationStack {
DetailView()
.navigationTitle("Details")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
showSheet = false
}
}
}
}
.presentationDetents([.medium, .large])
}
Detents:
.medium- Half screen.large- Full screen- Custom:
.height(400)
Alert
Important messages.
.alert("Delete Item?", isPresented: $showAlert) {
Button("Delete", role: .destructive) {
deleteItem()
}
Button("Cancel", role: .cancel) { }
} message: {
Text("This action cannot be undone.")
}
Confirmation Dialog
Action selection.
.confirmationDialog("Options", isPresented: $showOptions) {
Button("Edit") { }
Button("Share") { }
Button("Delete", role: .destructive) { }
Button("Cancel", role: .cancel) { }
}
Indicators
Progress View
Loading indicator.
// Indeterminate
ProgressView()
// Determinate
ProgressView(value: progress, total: 1.0)
// With label
ProgressView("Loading...") {
// Optional current task
Text("5 of 10 items")
}
Activity Indicator
Spinning indicator.
ProgressView()
.progressViewStyle(.circular)
.scaleEffect(1.5)
Content Containers
Card View
Contained content block.
struct CardView: View {
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("Title")
.font(.headline)
Text("Description")
.font(.subheadline)
.foregroundColor(.secondary)
Button("Action") { }
.buttonStyle(.borderedProminent)
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(12)
.shadow(color: .black.opacity(0.1), radius: 8)
}
}
GroupBox
Labeled group of views.
GroupBox("Settings") {
Toggle("Notifications", isOn: $notifications)
Toggle("Location", isOn: $location)
}
Form
Settings and input grouping.
Form {
Section("Account") {
TextField("Username", text: $username)
SecureField("Password", text: $password)
}
Section("Preferences") {
Toggle("Notifications", isOn: $notifications)
Picker("Theme", selection: $theme) {
Text("Light").tag("light")
Text("Dark").tag("dark")
}
}
}
Best Practices
Navigation:
- Use NavigationStack for hierarchical
- Use TabView for flat (3-5 peers)
- Never combine TabView + Toolbar in same view
Forms:
- Group related inputs
- Provide clear labels
- Show validation errors inline
- Use appropriate input types
Lists:
- Use
.insetGroupedstyle - Support swipe actions
- Provide pull-to-refresh when relevant
- Use sections for organization
Modals:
- Use for focused tasks
- Provide clear dismiss action
- Don't nest modals
- Use appropriate detent
For more details: https://developer.apple.com/design/human-interface-guidelines/components