{"id":15033732,"url":"https://github.com/uias/tabman","last_synced_at":"2025-05-14T12:08:40.478Z","repository":{"id":38434484,"uuid":"82300088","full_name":"uias/Tabman","owner":"uias","description":"™️ A powerful paging view controller with interactive indicator bars","archived":false,"fork":false,"pushed_at":"2024-05-16T22:01:05.000Z","size":79425,"stargazers_count":2906,"open_issues_count":85,"forks_count":241,"subscribers_count":33,"default_branch":"main","last_synced_at":"2025-04-03T20:07:41.310Z","etag":null,"topics":["ios","swift","tabs","ui","uipageviewcontroller","uitabbar","viewpager"],"latest_commit_sha":null,"homepage":"https://uias.github.io/Tabman","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uias.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["msaps"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2017-02-17T13:30:00.000Z","updated_at":"2025-04-01T00:57:50.000Z","dependencies_parsed_at":"2024-04-14T10:35:07.864Z","dependency_job_id":"5e9d01e2-b4c0-4f1b-a2bd-66ad7f982bcd","html_url":"https://github.com/uias/Tabman","commit_stats":{"total_commits":1807,"total_committers":40,"mean_commits":45.175,"dds":"0.31322634200332045","last_synced_commit":"6a87a2825939f5da06cf52a6582d67a646488cff"},"previous_names":[],"tags_count":99,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uias%2FTabman","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uias%2FTabman/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uias%2FTabman/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uias%2FTabman/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uias","download_url":"https://codeload.github.com/uias/Tabman/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247070922,"owners_count":20878586,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","swift","tabs","ui","uipageviewcontroller","uitabbar","viewpager"],"created_at":"2024-09-24T20:22:32.032Z","updated_at":"2025-04-03T20:08:34.262Z","avatar_url":"https://github.com/uias.png","language":"Swift","readme":"![](Docs/img/tm_logo.png)\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/uias/Tabman\"\u003e\n        \u003cimg src=\"https://github.com/uias/Tabman/workflows/Build/badge.svg\" /\u003e\n    \u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Swift-5-orange?logo=Swift\u0026logoColor=white\" /\u003e\n\t\u003ca href=\"https://github.com/uias/Tabman/releases\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/release/uias/Tabman.svg\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://swift.org/package-manager/\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n![](Docs/img/tm_header.png)\n\n## ⭐️ Features\n- Easy to implement page view controller with interactive indicator bars.\n- Highly adaptable and powerful customization.\n- Fully extensible with mix-and-match component library.\n- Built on [Pageboy](https://github.com/uias/Pageboy), a simple, informative page view controller.\n- Automatically insets child view controller contents.\n\n## 📋 Requirements\nTabman requires iOS 12 or above; and is compatibile with Swift 5.\n\n## 📲 Installation\n\n### Swift Package Manager\nTabman is compatible with [Swift Package Manager](https://swift.org/package-manager) and can be integrated via Xcode.\n\n### CocoaPods\nTabman is also available through [CocoaPods](http://cocoapods.org):\n\n```ruby\npod 'Tabman', '~\u003e 3.2'\n```\n\n### Carthage\nTabman is also available through [Carthage](https://github.com/Carthage/Carthage):\n\n```ogdl\ngithub \"uias/Tabman\" ~\u003e 3.2\n```\n\n## 🚀 Usage\n\n### The Basics\n1) Set up your view controller with the an array of view controllers that you want to appear.\n2) Set the `PageboyViewControllerDataSource` data source of the `TabmanViewController`.\n3) Create, customize and add as many `TMBar`s as you want.\n\n```swift\nimport Tabman\nimport Pageboy\n\nclass TabViewController: TabmanViewController {\n\n    private var viewControllers = [UIViewController(), UIViewController()]\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        self.dataSource = self\n\n        // Create bar\n        let bar = TMBar.ButtonBar()\n        bar.layout.transitionStyle = .snap // Customize\n\n        // Add to view\n        addBar(bar, dataSource: self, at: .top)\n    }\n}\n```\n\n**When adding a bar, you can choose to add it to the predefined areas (`.top`, `.bottom`, `.navigationItem(item:)`) or to a custom view with `.custom(view:layout:)`. For more information, read the [Adding a Bar](https://uias.github.io/Tabman/main/adding-a-bar.html) guide.**\n\n4) Configure your data sources.\n\n```swift\nextension TabViewController: PageboyViewControllerDataSource, TMBarDataSource {\n\n    func numberOfViewControllers(in pageboyViewController: PageboyViewController) -\u003e Int {\n        return viewControllers.count\n    }\n\n    func viewController(for pageboyViewController: PageboyViewController,\n                        at index: PageboyViewController.PageIndex) -\u003e UIViewController? {\n        return viewControllers[index]\n    }\n\n    func defaultPage(for pageboyViewController: PageboyViewController) -\u003e PageboyViewController.Page? {\n        return nil\n    }\n\n    func barItem(for bar: TMBar, at index: Int) -\u003e TMBarItemable {\n        let title = \"Page \\(index)\"\n        return TMBarItem(title: title)\n    }\n}\n```\n\n### Bar Items\nA bar will ask for a `TMBarItemable` for each page that is provided to the `TabmanViewController` `dataSource`. `TMBarItemable` is a  protocol that can be used for custom item types, the default in Tabman being `TMBarItem`:\n\n```swift\nlet item = TMBarItem()\nitem.title = \"Item 1\"\nitem.image = UIImage(named: \"item.png\")\nitem.badgeValue = \"New\"\n```\n\n#### UIKit Itemables\n\nTabman also provides support for some native `UIKit` types as `TMBarItemable`:\n- `UINavigationItem`\n- `UITabBarItem`\n\n*These types are unfortunately unable to support the dynamic updating of the bar when setting properties.*\n\n### Choosing a look\nTabman provides numerous, easy to use template styles out of the box:\n\n![](Docs/img/bar_styles.png)\n\nThese are all available as types of `TMBar` in [TMBar+Templates](https://github.com/uias/Tabman/blob/main/Sources/Tabman/Bar/TMBar%2BTemplates.swift).\n\n```swift\nlet bar = TMBar.ButtonBar()\nlet tabBar = TMBar.TabBar()\n```\n\n### Customization\nBar customization is available via properties on each functional area of the bar. Each bar is made up of 4 distinct areas:\n\n![](Docs/img/bar_breakdown.png)\n\n\n#### TMBarView\n`TMBarView` is the root view of every bar, and provides the glue for meshing all the other functional areas together. You can change a few things here, such as background style and transitioning behavior.\n\n```swift\nbar.background.style = .blur(style: .extraLight)\nbar.transitionStyle = .snap\n```\n*This is also the entry point for all other customization.*\n\n##### 🧲 Properties of  Interest\n- `backgroundView` - `TMBarBackgroundView` which provides background styling.\n- `scrollMode` - What type of interactive scrolling to allow.\n- `fadesContentEdges` - Whether to fade the edges of the bar contents as it goes off-screen.\n\n**More: [**TMBarView Docs**](https://uias.github.io/Tabman/main/Bar.html)**\n\n#### TMBarLayout\n`TMBarLayout` is the foundation of a `TMBarView`, dictating how bar buttons are displayed and laid out. Look here if you want to change things such as button spacing, content insets and other layout'y things.\n\n```swift\nbar.layout.contentInset = UIEdgeInsets(top: 0.0, left: 20.0, bottom: 0.0, right: 20.0)\n```\n\n##### 🧲 Properties of  Interest\n- `contentMode` - How the layout should display its contents; either restricted to the bar width with `.fit` or intrinsically sized with `.intrinsic`.\n- `contentInset` - Inset to be applied to the edges of the layout.\n- `transitionStyle` - How the layout should perform transition animations.\n- `alignment` - How the layout should be aligned in the bar.\n\n**More: [**TMBarLayout Docs**](https://uias.github.io/Tabman/main/Layout.html)**\n\n#### TMBarButton\n`TMBarButton` views are populated in the `TMBarLayout` and correspond to the items provided by the data source. This is the place to change things like fonts, image sizing and highlight colors.\n\nAs you will most likely dealing with more than one button, you can modify the whole set at once:\n\n```swift\nbar.buttons.customize { (button) in\n\tbutton.tintColor = .orange\n\tbutton.selectedTintColor = .red\n}\n```\n\n*This will be applied to both existing bar buttons and any that are added to the bar afterwards.*\n\n##### 🧲 Properties of  Interest\n- `backgroundView` - `TMBarBackgroundView` which provides background styling.\n- `contentInset` - Inset to be applied to the edges of the button.\n- `transitionStyle` (`TMBarButtonCollection`) - How the buttons should should perform transition animations.\n- `badge` - `TMBadgeView` that displays `badgeValue` from bar item.\n\n**More: [**TMBarButton Docs**](https://uias.github.io/Tabman/main/Buttons.html)**\n\n#### TMBarIndicator\nLastly is `TMBarIndicator` - which indicates the current page index status for the bar. You can change behavior characteristics here as well as how the indicator looks.\n\n```swift\nbar.indicator.overscrollBehavior = .compress\nbar.indicator.weight = .heavy\n```\n\n##### 🧲 Properties of  Interest\n- `overscrollBehavior` - How the indicator should handle scrolling beyond the bounds of the bar items.\n- `isProgressive` - Whether the indicator should act progressively when transitioning through page indexes.\n- `transitionStyle` - How the indicator should should perform transition animations.\n\n**More: [**TMBarIndicator Docs**](https://uias.github.io/Tabman/main/Indicator.html)**\n\n## 🎨 Advanced Customization\nTabman provides the complete freedom to mix-and-match the built-in components; and also define your own.\n\n`TMBarView` leverages generics to define and serve the three distinct functional areas of the bar. This means...\n\n```swift\n// ...that the preset...\nlet bar = Bar.ButtonBar()\n\n// ...is actually under the hood:\nlet bar = BarView\u003cHorizontalBarLayout, LabelBarButton, LineBarIndicator\u003e\n```\nSo swapping in another type of layout, button or indicator could not be simpler.\n\nLets say you wanted to actually use a `DotBarIndicator` rather than the `LineBarIndicator`:\n\n```swift\nlet bar = BarView\u003cHorizontalBarLayout, LabelBarButton, DotBarIndicator\u003e\n```\n\n**The following components are available in Tabman:**\n\n#### Bar Layouts\n- `TMHorizontalBarLayout` - Layout that displays bar buttons sequentially along the horizontal axis.\n- `TMConstrainedHorizontalBarLayout` - Layout that displays bar buttons sequentially along the horizontal axis, but is constrained by the number of items it can display.\n\n#### Bar Buttons\n- `TMLabelBarButton` - Button which contains a single text label.\n- `TMTabItemBarButton` - Button which mimics appearance of a `UITabBarItem`, containing a image and label vertically aligned.\n- `TMBarButton.None` - Display no visible bar buttons.\n\n#### Bar Indicators\n- `TMLineBarIndicator` - Simple indicator that displays as a horizontal line.\n- `TMChevronBarIndicator` - Indicator that displays a vertical chevron centered along the X-axis.\n- `TMBlockBarIndicator` - Indicator that fills the bar, displaying a solid color.\n- `TMDotBarIndicator` - Indicator that displays a circular dot centered along the X-axis.\n- `TMBarIndicator.None` - Display no visible indicator.\n\n### Going Completely Custom\nAs replacing the type of layout, button or indicator is as easy as above; you have the ability to define your own subclasses without too much of a headache.\n\n[**Custom Tabman Components**](https://uias.github.io/Tabman/main/going-custom.html)\n\nThere are also example projects that showcase custom layouts and such:\n\n- [**Tinderbar**](https://github.com/uias/Tinderbar) - Tinder iOS app layout built with Tabman.\n\n## 📐 Content Insetting\nTabman automatically adjusts any content in its child view controllers so that it displays correctly beneath any visible bars. It provides the following behaviors:\n\n- Updates `contentInset` and `contentOffset` appropriately for any `UIScrollView` or derived subclass found in the child view controller's subviews.\n- Sets `additionalSafeAreaInsets` to reflect the required safe areas including the bar contents. Any views constrained to the safe area in the child view controller will be laid out correctly (**Only available in iOS 11 and above.**)\n\n`TabmanViewController` also provides `barLayoutGuide`, a `UILayoutGuide` that provides top and bottom anchors taking into account any bars added to the `.top` or `.bottom` `TabmanViewController.BarLocation` areas. The raw `UIEdgeInsets` are also available via `.barInsets`.\n\nAuto insetting can be **disabled** by setting `automaticallyAdjustsChildInsets` to `false` - however this **must be done before `viewDidLoad`**.\n\n*Tabman will not provide any insetting behavior for bars that are added to custom views.*\n\n## ⚠️ Troubleshooting\nIf you are encountering issues with Tabman, please check out the [Troubleshooting Guide](https://uias.github.io/Tabman/main/troubleshooting.html).\n\nIf you're still having problems, feel free to raise an [issue](https://github.com/uias/Tabman/issues/new).\n\n## 👨🏻‍💻 About\n- Created by [Merrick Sapsford](https://github.com/msaps) ([@MerrickSapsford](https://twitter.com/MerrickSapsford))\n- Contributed to by a growing [list of others](https://github.com/uias/Tabman/graphs/contributors).\n\n## ❤️ Contributing\nBug reports and pull requests are welcome on GitHub at [https://github.com/uias/Tabman](https://github.com/uias/Tabman).\n\n## 👮🏻‍♂️ License\nThe library is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","funding_links":["https://github.com/sponsors/msaps"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuias%2Ftabman","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuias%2Ftabman","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuias%2Ftabman/lists"}