Production-ready SwiftUI layout components for wrapping, flowing, and centering content
UnionStacks provides powerful, flexible layout containers that solve common SwiftUI layout challenges. Whether you need tags that wrap like text or perfectly centered navigation bars, UnionStacks makes it effortless.
- π¦ WrappingHStack - Auto-wrapping horizontal layout for tags, chips, and dynamic collections
- βοΈ CStack - Centered layout with balanced distribution for navigation bars
- π Production Ready - Battle-tested in real applications
- β‘οΈ Performant - Efficient layout algorithms optimized for typical UI scenarios
- π± Responsive - Adapts automatically to different screen sizes
- π¨ Customizable - Flexible spacing and configuration options
import UnionStacks
struct TagsView: View {
let tags = ["SwiftUI", "iOS", "Layout", "Custom Views", "Flow"]
var body: some View {
WrappingHStack(horizontalSpacing: 8, verticalSpacing: 8) {
ForEach(tags, id: \.self) { tag in
Text(tag)
.padding(.horizontal, 12)
.padding(.vertical, 6)
.background(Color.blue.opacity(0.2))
.clipShape(Capsule())
}
}
.padding()
}
}Perfect for:
- Tag collections (hashtags, categories, keywords)
- Filter chips and buttons
- Dynamic content from APIs
- Any variable-width items that should wrap naturally
import UnionStacks
struct NavBar: View {
var body: some View {
CStack(spacing: 16) {
Button("Back") { }
Text("Settings").font(.headline)
Button("Save") { }
}
.frame(height: 44)
.padding(.horizontal)
}
}Perfect for:
- Navigation bars with guaranteed center alignment
- Toolbars with symmetric left/right actions
- Any layout where the center item must be perfectly centered
Add UnionStacks to your project using Xcode:
- File β Add Package Dependencies
- Enter:
https://github.com/unionst/union-stacks - Select version and add to your target
Or add to your Package.swift:
dependencies: [
.package(url: "https://github.com/unionst/union-stacks", from: "1.0.0")
]import SwiftUI
import UnionStacksstruct ContentView: View {
let items = ["Swift", "Kotlin", "Python", "JavaScript", "TypeScript", "Rust"]
var body: some View {
WrappingHStack(horizontalSpacing: 12, verticalSpacing: 12) {
ForEach(items, id: \.self) { item in
Text(item)
.padding()
.background(Color.blue.opacity(0.2))
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}
}
}struct CustomNavBar: View {
var body: some View {
CStack {
Button("Cancel") { dismiss() }
Text("Title")
Button("Done") { save() }
}
}
}Comprehensive guides and API documentation:
- Building a Wrapping HStack in SwiftUI - Complete tutorial
- WrappingHStack API Reference
- CStack API Reference
struct FilterView: View {
let filters = ["All", "Active", "Completed", "Archived"]
@State private var selected = "All"
var body: some View {
WrappingHStack(horizontalSpacing: 12) {
ForEach(filters, id: \.self) { filter in
Button {
selected = filter
} label: {
Text(filter)
.padding(.horizontal, 16)
.padding(.vertical, 8)
.background(selected == filter ? Color.blue : Color.gray.opacity(0.2))
.foregroundStyle(selected == filter ? .white : .primary)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
.buttonStyle(.plain)
}
}
}
}struct HashtagView: View {
@State private var hashtags = ["#swift", "#ios", "#dev"]
var body: some View {
ScrollView {
WrappingHStack(horizontalSpacing: 8, verticalSpacing: 8) {
ForEach(hashtags, id: \.self) { tag in
Button {
searchHashtag(tag)
} label: {
Text(tag)
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(Color.purple.opacity(0.2))
.clipShape(Capsule())
}
.buttonStyle(.plain)
}
}
.padding()
}
}
func searchHashtag(_ tag: String) {
print("Searching: \(tag)")
}
}struct EditableTagsView: View {
@State private var tags = ["SwiftUI", "iOS", "Development"]
var body: some View {
WrappingHStack(horizontalSpacing: 8, verticalSpacing: 8) {
ForEach(tags, id: \.self) { tag in
HStack(spacing: 4) {
Text(tag)
Button {
tags.removeAll { $0 == tag }
} label: {
Image(systemName: "xmark.circle.fill")
.foregroundStyle(.secondary)
}
.buttonStyle(.plain)
}
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(Color.blue.opacity(0.2))
.clipShape(Capsule())
}
}
.animation(.spring(), value: tags)
}
}β Excellent performance for:
- Small to medium collections (1-100 items)
- Variable-width content (tags, labels)
- Dynamic content that changes infrequently
- Very large collections (100+ items) β Use
LazyVGridinstead - Uniform grid layouts β Use
LazyVGridwith fixed columns - Infinite scrolling β Use
ListorLazyVStack
WrappingHStack {
ForEach(items, id: \.id) { item in
ItemView(item: item)
.drawingGroup()
}
}Use stable identifiers and consider .drawingGroup() for complex child views.
| Feature | WrappingHStack | HStack | LazyVGrid |
|---|---|---|---|
| Multiple rows | β Automatic | β Single row | β Grid-based |
| Wrapping | β Natural flow | β Truncates | β Column-based |
| Item sizing | Ideal size | May compress | Grid cells |
| Performance | Good (<100 items) | Excellent | Excellent (lazy) |
| Best for | Tags, chips | Fixed layouts | Photos, grids |
| Alignment | Left-aligned flow | Flexible | Vertical columns |
Use WrappingHStack when:
- Items have different widths
- You want natural text-like flow
- Collection is small to medium
- Content feels like "tags" or "chips"
Use HStack when:
- Content always fits in one row
- You need flexible spacing
- Building navigation bars or toolbars
Use LazyVGrid when:
- Items should align in columns
- You have 100+ items
- Items are uniform in size
- You need lazy loading
- iOS 16.0+ / macOS 13.0+ / tvOS 16.0+ / watchOS 9.0+
- Swift 6.0+
- Xcode 16.0+
UnionStacks is available under the MIT license. See LICENSE for details.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- union-ui - Comprehensive SwiftUI component library
- union-buttons - Beautiful button components
- union-haptics - Haptic feedback utilities
Is your app using UnionStacks? Open an issue to be featured here!
Built with β€οΈ by Ben Sage
SwiftUI, Layout, Custom Layout, Flow Layout, Wrapping Stack, Wrapped HStack, Tag Layout, Chip Layout, iOS Development, Swift Package, SwiftUI Components, Responsive Layout, Dynamic Layout, Auto-wrapping, Horizontal Stack, Centered Layout, Navigation Bar Layout, SwiftUI Layout Protocol, iOS 16, Modern SwiftUI
βοΈ If you find UnionStacks useful, please star the repository!