Ribbon šŸŽ€
  • March 11, 2024

A simple cross-platform toolbar/custom input accessory view library for iOS & macOS.
Written in Swift.


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Ā NSMenuItems 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.

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


Contributors


Frameworks & Libraries


RibbonĀ depends on the wonderful contributions of the Swift community, namely:

GitHub


View Github

#carthage #cocoapods #ios #swift #toolbar
YOU MIGHT ALSO LIKE...
SwiftSpeech

Recognize your user's voice elegantly without having to figure out authorization and audio engines. SwiftSpeech Examples Features Installation Getting Started ...

SwiftUIValueSlider

Example To run the example project, clone the repo, and runĀ pod installĀ from the Example directory first. Requirements iOS 14.0 Installation ...

Sliders

SlidersĀ is a compilation of all my stylable drag based SwiftUI components. It provides a variety of unique controls as well ...

SlidingRuler

SlidingRulerĀ is a Swift package containing a SwiftUI control that acts like an linear infinite slider or a finite, more precise ...

Skeletonui

SkeletonUI aims to bring an elegant, declarative syntax to skeleton loading animations. Get rid of loading screens or spinners and ...