CardParts
A reactive, card-based UI framework built on UIKit for iOS developers.
Install / Use
/learn @intuit/CardPartsREADME
CardParts - made with ❤️ by Intuit:
- Example
- Requirements
- Installation
- Communication & Contribution
- Overview
- Quick Start
- Architecture
- CardsViewController
- Card Traits
- CardPartsViewController
- CardPartsFullScreenViewController
- CardParts
- CardPartTextView
- CardPartAttributedTextView
- CardPartImageView
- CardPartButtonView
- CardPartTitleView
- CardPartTitleDescriptionView
- CardPartPillLabel
- CardPartIconLabel
- CardPartSeparatorView
- CardPartVerticalSeparatorView
- CardPartTableView
- CardPartTableViewCell
- CardPartTableViewCardPartsCell
- CardPartCollectionView
- CardPartCollectionViewCardPartsCell
- CardPartBarView
- CardPartPagedView
- CardPartSliderView
- CardPartMultiSliderView
- CardPartSpacerView
- CardPartTextField
- CardPartCenteredView
- CardPartOrientedView
- CardPartConfettiView
- CardPartProgressBarView
- CardPartMapView
- CardPartRadioButton
- CardPartSwitchView
- CardPartHistogramView
- CardPartsBottomSheetViewController
- CardPartVideoView
- Card States
- Data Binding
- Themes
- Clickable Cards
- Listeners
- Apps That Love CardParts
- Publications
- License
Example
To run the example project, clone the repo, and run pod install from the Example directory first.
In ViewController.swift you will be able to change the cards displayed and/or their order by commenting out one of the loadCards(cards: ) functions.
If you want to change the content of any of these cards, you can look into each of the CardPartsViewController you pass into the function such as: TestCardController, Thing1CardController, Thing2CardController, etc.
Requirements
- iOS 10.0+
- Xcode 10.2+
- Swift 5.0+
- CocoaPods 1.6.1+
Installation
CardParts is available through CocoaPods. You can install it with the following command:
$ gem install cocoapods
To add CardParts to your project, simply add the following line to your Podfile:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'CardParts'
end
Then, run the following command:
$ pod install
Communication and Contribution
- If you need help, open an issue and tag as
help wanted. - If you found a bug, open an issue and tag as
bug. - If you have a feature request, open an issue and tag as
feature. - If you want to contribute, submit a pull request.
- In order to submit a pull request, please fork this repo and submit a PR from your forked repo.
- Have a detailed message as to what your PR fixes/enhances/adds.
- Each PR must get two approvals from our team before we will merge.
Overview
CardParts is the second generation Card UI framework for the iOS Mint application. This version includes many updates to the original card part framework, including improved MVVM, data binding (via RxSwift), use of stack views and self sizing collection views instead sizing cells, 100% swift and much more. The result is a much simpler, easier to use, more powerful, and easier to maintain framework. This framework is currently used by the iOS Mint application and the iOS Turbo application.
<p align="center"> <img src="https://raw.githubusercontent.com/Intuit/CardParts/master/images/cardPartExample.png" alt="CardPart Example in Mint"/> </p>Quick Start
See how quickly you can get a card displayed on the screen while adhering to the MVVM design pattern:
import RxCocoa
class MyCardsViewController: CardsViewController {
let cards: [CardController] = [TestCardController()]
override func viewDidLoad() {
super.viewDidLoad()
loadCards(cards: cards)
}
}
class TestCardController: CardPartsViewController {
var viewModel = TestViewModel()
var titlePart = CardPartTitleView(type: .titleOnly)
var textPart = CardPartTextView(type: .normal)
override func viewDidLoad() {
super.viewDidLoad()
viewModel.title.asObservable().bind(to: titlePart.rx.title).disposed(by: bag)
viewModel.text.asObservable().bind(to: textPart.rx.text).disposed(by: bag)
setupCardParts([titlePart, textPart])
}
}
class TestViewModel {
var title = BehaviorRelay(value: "")
var text = BehaviorRelay(value: "")
init() {
// When these values change, the UI in the TestCardController
// will automatically update
title.accept("Hello, world!")
text.accept("CardParts is awesome!")
}
}
Note: RxCocoa is required for BehaviorRelay, thus you must import it wherever you may find yourself using it.
Architecture
There are two major parts to the card parts framework. The first is the CardsViewController which will display the cards. It is responsible for displaying cards in the proper order and managing the lifetime of the cards. The second major component is the cards themselves which are typically instances of CardPartsViewController. Each instance of CardPartsViewController displays the content of a single card, using one or more card parts (more details later).
CardsViewController
The CardsViewController uses a collection view where each cell is a single card. The cells will render the frames for the cards, but are designed to have a child ViewController that will display the contents of the card. Thus CardsViewController is essentially a list of child view controllers that are rendered in special cells that draw the card frames.
To use a CardsViewController, you first need to subclass it. Then in the viewDidLoad method call the super class loadCards method passing an array of CardControllers. Each instance of a CardController will be rendered as a single card. The loadCards method does this by getting the view controller for each CardController and adding them as child view controllers to the card cells. Here is an example:
class TestCardsViewController: CardsViewController {
let cards: [CardController] = [TestCardController(), AnotherTestCardController()]
override func viewDidLoad() {
super.viewDidLoad()
loadCards(cards: cards)
}
}
Each card must implement the CardController protocol (note that CardPartsViewController discussed later implements this protocol already). The
CardController protocol has a single method:
protocol CardController : NSObjectProtocol {
func viewController() -> UIViewController
}
The viewController() method must return the viewController that will be added as a child controller to the card cell. If the CardController is a UIViewController it can simply return self for this method.
Load specific cards
While normally you may call loadCards(cards:) to load an array of CardControllers, you may want the ability to load reload a specific set of cards. We offer the ability via the loadSpecificCards(cards: [CardController] , indexPaths: [IndexPath]) API. Simply pass in the full array of new cards as well as the indexPaths that you would like
Related Skills
node-connect
344.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
99.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
344.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
344.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
