Awesome
Ribbon ๐
<p align="center"> <img alt="Supported Platforms" src ="https://img.shields.io/badge/platform-iOS%20%7C%20macOS-informational"/> <a href="https://github.com/Carthage/Carthage" style="text-decoration:none" target="_blank"> <img alt="Carthage compatible" src ="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat"/> </a> <a href="https://cocoapods.org/pods/Ribbon" style="text-decoration:none" target="_blank"> <img alt="Pod Version" src ="https://img.shields.io/cocoapods/v/Ribbon.svg?style=flat"/> </a> <a href="https://travis-ci.org/chriszielinski/Ribbon" style="text-decoration:none" target="_blank"> <img src="https://travis-ci.org/chriszielinski/Ribbon.svg?branch=master"> </a> <a href="https://sonarcloud.io/dashboard?id=chriszielinski_Ribbon" style="text-decoration:none" target="_blank"> <img src="https://sonarcloud.io/api/project_badges/measure?project=chriszielinski_Ribbon&metric=alert_status"> </a> <a href="https://sonarcloud.io/component_measures?id=chriszielinski_Ribbon&metric=Coverage" style="text-decoration:none" target="_blank"> <img src="https://sonarcloud.io/api/project_badges/measure?project=chriszielinski_Ribbon&metric=coverage"> </a> <a href="https://codebeat.co/projects/github-com-chriszielinski-ribbon-master" style="text-decoration:none" target="_blank"> <img alt="codebeat badge" src="https://codebeat.co/badges/8fa0b6cf-73e1-425a-a196-8b62197cfa40"/> </a> <a href="https://developer.apple.com/swift" style="text-decoration:none" target="_blank"> <img alt="Swift Version" src ="https://img.shields.io/badge/language-Swift%205-blue.svg"/> </a> <a href="https://github.com/chriszielinski/Ribbon/blob/master/LICENSE" style="text-decoration:none" target="_blank"> <img alt="GitHub license" src ="https://img.shields.io/badge/license-MIT-blue.svg"/> </a> <img alt="PRs Welcome" src="https://img.shields.io/badge/PRs-welcome-blue.svg" /> <br> <br> <img src="https://raw.githubusercontent.com/chriszielinski/Ribbon/master/.readme-assets/header.jpg" alt="Header"> <br> <br> <b>A simple cross-platform toolbar/custom input accessory view library for iOS & macOS. <br> Written in Swift.</b> <br> </p>Looking for...
- A type-safe, XPC-available SourceKitten (SourceKit) interface with some sugar? Check out Sylvester ๐ผ.
- A Floating Action Button for macOS? Check out Fab. ๐๏ธ.
- An Expanding Bubble Text Field for macOS? Check out BubbleTextField ๐ฌ.
- An integrated spotlight-based onboarding and help library for macOS? Check out Enlighten ๐ก.
Features
๐ก Try: Includes an iOS & macOS demo.
- Provide items either programmatically or from a JSON configuration file.
- Dark mode.
- + more!
iOS
-
Supports push buttonsโa segmented item's subitems become push buttons.
-
iOS 13: action items use the new context menu interaction:
Note: Due to an internal assertion, the keyboard can no longer remain visible during the interaction.
macOS
- Supports push, action, & segmented control toolbar items.
- Provides
NSMenuItem
s for each item.
Requirements
- iOS 10.0+ (12.0+ for dark mode)
- macOS 10.12+ (10.13+ for full functionality)
Installation
Ribbon
is available for installation using Carthage or CocoaPods.
Carthage
github "chriszielinski/Ribbon"
CocoaPods
pod "Ribbon"
Usage
There are two ways of integrating Ribbon
into your project:
Configuration File
๐ฅ The recommended approach.
The configuration file makes for a quick & easy integration. The default configuration filename is ribbon-configuration.json
and should be copied into the target's bundle resources (in the Copy Bundle Resources build phase).
The JSON below defines a single action item and toolbar configurationโwhich is only relevant for the macOS platform.
๐ง See: Demos/Shared/ribbon-configuration.json for a more comprehensive example.
{
"items": [
{
"action": "actionItemHandler",
"controlKind": "action",
"identifier": "action-item-identifier",
"imageName": "NSActionTemplate",
"keyEquivalent": "a",
"keyEquivalentModifier": ["command", "shift"],
"title": "Action Item",
"toolTip": "The action button's tool-tip.",
"subitems": [
{
"action": "firstActionSubitemHandler",
"identifier": "first-action-subitem",
"imageName": "hand.thumbsup",
"keyEquivalent": "1",
"keyEquivalentModifier": ["command"],
"title": "First Action Subitem",
"toolTip": "The first action's tool-tip."
},
{
"action": "secondActionSubitemHandler",
"identifier": "second-action-subitem",
"imageName": "hand.thumbsdown",
"keyEquivalent": "2",
"keyEquivalentModifier": ["command"],
"title": "Second Action Subitem",
"toolTip": "The second action's tool-tip."
}
]
}
],
"toolbar": {
"displayMode": "iconOnly",
"sizeMode": "regular",
"identifier": "toolbar-identifier",
"defaultItems" : ["NSToolbarFlexibleSpaceItem", "action-item-identifier"]
}
}
Integration into your view controller is as simple as:
๐ Note: The code below is an abstraction and will not compile.
import Ribbon
class YourViewController ... {
...
var ribbon: Ribbon!
override func viewDidLoad() {
ribbon = try! Ribbon.loadFromMainBundle(target: self)
#if canImport(UIKit)
textView.inputAccessoryView = ribbon
#endif
}
#if canImport(AppKit)
override func viewWillAppear() {
view.window?.toolbar = ribbon.toolbar
super.viewWillAppear()
}
#endif
@objc
func actionItemHandler() { }
@objc
func firstActionSubitemHandler() { }
@objc
func secondActionSubitemHandler() { }
}
Programmatically
๐ Note: The code below is an abstraction and will not compile.
import Ribbon
class YourViewController ... {
...
var ribbon: Ribbon!
override func viewDidLoad() {
let firstActionSubitem = RibbonItem(subItemTitle: "First Action Subitem")
firstActionSubitem.action = #selector(firstActionSubitemHandler)
let secondActionSubitem = RibbonItem(subItemTitle: "Second Action Subitem")
secondActionSubitem.action = #selector(secondActionSubitemHandler)
let actionItem = RibbonItem(controlKind: .action,
title: "Action Item",
subitems: [firstActionSubitem, secondActionSubitem])
actionItem.action = #selector(actionItemHandler)
ribbon = Ribbon(items: [actionItem], target: self)
#if canImport(UIKit)
textView.inputAccessoryView = ribbon
#endif
}
#if canImport(AppKit)
override func viewWillAppear() {
view.window?.toolbar = ribbon.toolbar
super.viewWillAppear()
}
#endif
@objc
func actionItemHandler() { }
@objc
func firstActionSubitemHandler() { }
@objc
func secondActionSubitemHandler() { }
}
// ToDo:
- Add documentation.
- Implement
UIKeyCommand
.
Community
- Found a bug? Open an issue.
- Feature idea?
Open an issue.Do it yourself & PR when done ๐ (or you can open an issue ๐). - Want to contribute? Submit a pull request.
Acknowledgements
- Based on Rudd Fawcett's
RFKeyboardToolbar
.
Contributors
- Chris Zielinski โ Original author.
Frameworks & Libraries
Ribbon
depends on the wonderful contributions of the Swift community, namely:
- realm/SwiftLint โ A tool to enforce Swift style and conventions.
License
Ribbon
is available under the MIT license, see the LICENSE file for more information.