Bonsplit is a custom tab bar and layout split library for macOS apps. Out of the box 120fps animations, drag-and-drop reordering, SwiftUI support & keyboard navigation.
.package(url: "https://github.com/almonk/bonsplit.git", from: "1.0.0")
### Features
Create tabs with optional icons and dirty indicators. Target specific panes or use the focused pane.
let tabId = controller.createTab(title: "Document.swift",icon: "swift",isDirty: false,inPane: paneId)
Split any pane horizontally or vertically. New panes are empty by default, giving you full control.
// Split focused pane horizontallylet newPaneId = controller.splitPane(orientation: .horizontal)// Split with a tab already in the new panecontroller.splitPane(orientation: .vertical,withTab: Tab(title: "New", icon: "doc"))
Update tab properties at any time. Changes animate smoothly.
// Mark document as modifiedcontroller.updateTab(tabId, isDirty: true)// Rename tabcontroller.updateTab(tabId, title: "NewName.swift")// Change iconcontroller.updateTab(tabId, icon: "doc.text")
Programmatically navigate between panes using directional navigation.
// Move focus between panescontroller.navigateFocus(direction: .left)controller.navigateFocus(direction: .right)controller.navigateFocus(direction: .up)controller.navigateFocus(direction: .down)// Or focus a specific panecontroller.focusPane(paneId)
### Reference
Complete reference for all Bonsplit classes, methods, and configuration options.
The main controller for managing tabs and panes. Create an instance and pass it to BonsplitView.
Implement this protocol to receive callbacks about tab bar events. All methods have default implementations and are optional.
Configure behavior and appearance. Pass to BonsplitController on initialization.
allowSplitsBoolEnable split buttons and drag-to-split
Default: true
allowCloseTabsBoolShow close buttons on tabs
Default: true
allowCloseLastPaneBoolAllow closing the last remaining pane
Default: false
allowTabReorderingBoolEnable drag-to-reorder tabs within a pane
Default: true
allowCrossPaneTabMoveBoolEnable moving tabs between panes via drag
Default: true
autoCloseEmptyPanesBoolAutomatically close panes when their last tab is closed
Default: true
contentViewLifecycleContentViewLifecycleHow tab content views are managed when switching tabs
Default: .recreateOnSwitch
let config = BonsplitConfiguration(allowSplits: true,allowCloseTabs: true,allowCloseLastPane: false,autoCloseEmptyPanes: true,contentViewLifecycle: .keepAllAlive)let controller = BonsplitController(configuration: config)
Controls how tab content views are managed when switching between tabs.
| Mode | Memory | State | Use Case |
|---|---|---|---|
.recreateOnSwitch | Low | None | Simple content |
.keepAllAlive | Higher | Full | Complex views, forms |
tabBarHeightCGFloatHeight of the tab bar
Default: 33
tabMinWidthCGFloatMinimum width of a tab
Default: 140
tabMaxWidthCGFloatMaximum width of a tab
Default: 220
tabSpacingCGFloatSpacing between tabs
Default: 0
minimumPaneWidthCGFloatMinimum width of a pane
Default: 100
minimumPaneHeightCGFloatMinimum height of a pane
Default: 100
showSplitButtonsBoolShow split buttons in the tab bar
Default: true
animationDurationDoubleDuration of animations in seconds
Default: 0.15
enableAnimationsBoolEnable or disable all animations
Default: true
.defaultBonsplitConfigurationDefault configuration with all features enabled
.singlePaneBonsplitConfigurationSingle pane mode with splits disabled
.readOnlyBonsplitConfigurationRead-only mode with all modifications disabled