A flexible and customizable three-column layout framework for macOS SwiftUI applications.
ThreeColumnLayout provides a reusable solution for implementing the common three-column layout pattern found in many macOS applications (like Xcode, Finder, etc.). It offers:
- Navigator Column: Typically used for navigation, file browsers, or content lists
- Canvas Column: Main content area for editing, viewing, or primary interactions
- Inspector Column: Properties panel, settings, or additional information
- ✅ Flexible Configuration: Customize column widths, visibility, and behavior
- ✅ Theme Support: Built-in themes with support for light/dark mode
- ✅ Responsive Layout: Automatic adaptation to window size changes
- ✅ Smooth Animations: Fluid column show/hide transitions
- ✅ Toolbar Integration: Built-in toolbar support with customizable items
- ✅ SwiftUI Native: Pure SwiftUI implementation using NavigationSplitView
- ✅ macOS 13+: Optimized for modern macOS versions
Add the following to your Package.swift file:
dependencies: [
.package(url: "https://github.com/yourusername/ThreeColumnLayout.git", from: "1.0.0")
]Or add it through Xcode:
- File → Add Package Dependencies
- Enter the repository URL
- Select the version and add to your target
import SwiftUI
import ThreeColumnLayout
struct ContentView: View {
var body: some View {
ThreeColumnLayoutView(
navigator: {
NavigatorView()
},
canvas: {
CanvasView()
},
inspector: {
InspectorView()
}
)
}
}import SwiftUI
import ThreeColumnLayout
struct ContentView: View {
let configuration = ThreeColumnLayoutConfiguration(
navigatorColumn: ColumnConfiguration(
minWidth: 200,
defaultWidth: 250,
maxWidth: 400
),
inspectorColumn: ColumnConfiguration(
minWidth: 250,
defaultWidth: 300,
maxWidth: 500
),
theme: .minimal,
showsToolbar: true
)
var body: some View {
ThreeColumnLayoutView(configuration: configuration) {
// Navigator content
List(items) { item in
NavigationLink(item.name, value: item)
}
} canvas: {
// Canvas content
if let selectedItem = selectedItem {
ItemDetailView(item: selectedItem)
} else {
Text("Select an item")
.foregroundColor(.secondary)
}
} inspector: {
// Inspector content
if let selectedItem = selectedItem {
ItemInspectorView(item: selectedItem)
}
}
}
}let columnConfig = ColumnConfiguration(
minWidth: 200, // Minimum column width
maxWidth: 400, // Maximum column width (nil for unlimited)
defaultWidth: 250, // Default/ideal column width
isResizable: true, // Whether column can be resized
isCollapsible: true // Whether column can be collapsed
)let themeConfig = ThemeConfiguration(
backgroundColor: Color(NSColor.controlBackgroundColor),
dividerColor: Color(NSColor.separatorColor),
toolbarBackgroundColor: Color(NSColor.windowBackgroundColor),
cornerRadius: 8,
dividerWidth: 1
)// Column configurations
ColumnConfiguration.navigator // Optimized for navigation
ColumnConfiguration.canvas // Optimized for main content
ColumnConfiguration.inspector // Optimized for properties panel
// Theme configurations
ThemeConfiguration.default // Standard macOS appearance
ThemeConfiguration.minimal // Clean, minimal appearancestruct ContentView: View {
@StateObject private var visibilityManager = ColumnVisibilityManager()
var body: some View {
ThreeColumnLayoutView(
visibilityManager: visibilityManager,
navigator: { NavigatorView() },
canvas: { CanvasView() },
inspector: { InspectorView() }
)
.toolbar {
ToolbarItem(placement: .navigation) {
Button("Toggle Navigator") {
visibilityManager.toggleNavigator()
}
}
}
}
}class MyLayoutDelegate: ThreeColumnLayoutDelegate {
func columnVisibilityDidChange(column: ColumnType, isVisible: Bool) {
print("\(column.displayName) visibility changed: \(isVisible)")
}
func toolbarItems(for layout: ThreeColumnLayoutView) -> [ToolbarItem] {
return [
ToolbarItem(placement: .primaryAction) {
Button("Custom Action") {
// Custom action
}
}
]
}
}let configuration = ThreeColumnLayoutBuilder()
.navigator(.navigator)
.canvas(.canvas)
.inspector(.inspector)
.theme(.minimal)
.toolbar(true)
.animationDuration(0.25)
.build()- macOS 13.0+
- Swift 5.7+
- Xcode 14.0+
MIT License - see LICENSE file for details.
Contributions are welcome! Please read the contributing guidelines before submitting pull requests.