EmptyStateKit
Beautiful, animated & fully customizable empty state view. A great way to engage and keep users whenever the view has no content to display.
Install / Use
/learn @alberdev/EmptyStateKitREADME
EmptyStateKit
- [x] Awesome fade & scale animations
- [x] Totally customizable
- [x] Use it also in your own tables and collection views
- [x] Easy usage
- [x] Supports iOS, developed in Swift 5
Table of Contents
- Installation
- Usage
- Format
- Animation Types
- Position Types
- Apps using EmptyStateKit
- Author
- Contributing
- License
Installation
CocoaPods
EmptyStateKit is available through CocoaPods. To install
it, simply add the following line to your Podfile and run pod install:
pod 'EmptyStateKit'
Then you can import it when you need
import EmptyStateKit
Carthage
Add the following to your Cartfile:
github "alberdev/EmptyStateKit"
Run carthage update.
Usage
It's important, when an error or empty state occurs, to inform or teach the user how to recover from the error or how to populate the screen with content. Keep in mind to give your users a next step, like a link to another section, a button to recover from an error or content to interact with. This will help you to increase engagement! In the example you will see multiple types of empty states and how you can customize them. Be creative!.
Once you've installed the pod, follow next steps. It's really simple:
1. Complete empty states data
To complete empty states data, you can choose implementing EmptyStateDataSource or extend your custom enum states with image, title, description and titleButton params.
I recommend the second option to keep states data outside your view controller.
Using EmptyStateDataSource
Implement EmptyStateDataSource and complete with each custom state you have.
extension ViewController: EmptyStateDataSource {
func imageForState(_ state: CustomState, inEmptyState emptyState: EmptyState) -> UIImage? {
switch state as! MainState {
case .noInternet: return UIImage(named: "Internet")
}
}
func titleForState(_ state: CustomState, inEmptyState emptyState: EmptyState) -> String? {
switch state as! MainState {
case .noInternet: return "We’re Sorry"
}
}
func descriptionForState(_ state: CustomState, inEmptyState emptyState: EmptyState) -> String? {
switch state as! MainState {
case .noInternet: return "Our staff is still working on the issue for better experience"
}
}
func titleButtonForState(_ state: CustomState, inEmptyState emptyState: EmptyState) -> String? {
switch state as! MainState {
case .noInternet: return "Try again?"
}
}
}
Remember to assign dataSource to your empty state view
view.emptyState.dataSource = self
Using CustomState enum
You can implement image, title, description and titleButton params for each state. Create your custom states enum that implements CustomState. Then complete with required params:
enum State: CustomState {
case noNotifications
case noSearch
case noInternet
var image: UIImage? {
switch self {
case .noNotifications: return UIImage(named: "Messages")
case .noSearch: return UIImage(named: "Search")
case .noInternet: return UIImage(named: "Internet")
}
}
var title: String? {
switch self {
case .noNotifications: return "No message notifications"
case .noSearch: return "No results"
case .noInternet: return "We’re Sorry"
}
}
var description: String? {
switch self {
case .noNotifications: return "Sorry, you don't have any message. Please come back later!"
case .noSearch: return "Please try another search item"
case .noInternet: return "Our staff is still working on the issue for better experience"
}
}
var titleButton: String? {
switch self {
case .noNotifications: return "Search again?"
case .noSearch: return "Go back"
case .noInternet: return "Try again?"
}
}
}
2. Show or hide your empty state
This step is really simple ;)
view.emptyState.show(State.noInternet)
You can use empty states in your Table or Collection views maintaining refreshing content features. For this, table or collection view must be empty (0 rows). EmptyStateKit will complete the table or collection background view and remove the separatorStyle to show your empty state.
3. Handling button action with EmptyStateDelegate
Implement EmptyStateDelegate protocol to delegate the button action.
extension ViewController: EmptyStateDelegate {
func emptyState(emptyState: EmptyState, didPressButton button: UIButton) {
view.emptyState.hide()
}
}
Remember to assign delegate to your empty state view
view.emptyState.delegate = self
Format
You can format your empty states or use default values. See EmptyStateFormat default values:
/// Title attributes
public var titleAttributes: [NSAttributedString.Key: Any] = [.font: UIFont(name: "AvenirNext-DemiBold", size: 26)!, .foregroundColor: UIColor.darkGray]
/// Description attributes
public var descriptionAttributes: [NSAttributedString.Key: Any] = [.font: UIFont(name: "Avenir Next", size: 14)!, .foregroundColor: UIColor.darkGray]
/// Button attributes
public var buttonAttributes: [NSAttributedString.Key: Any] = [.font: UIFont(name: "AvenirNext-DemiBold", size: 14)!, .foregroundColor: UIColor.white]
/// Button color
public var buttonColor: UIColor = .red
/// Button shadow radius
public var buttonShadowRadius: CGFloat = 0
/// Button corner radius
public var buttonRadius: CGFloat = 20.0
/// Button width, nil = auto
public var buttonWidth: CGFloat? = nil
/// Button top margin
public var buttonTopMargin: CGFloat = 20
/// Set image as background
public var coverImage: Bool = false
/// Image animation type
public var animation: EmptyStateAnimation? = .scale(0.3, 0.3)
/// Alpha container
public var alpha: CGFloat = 1.0
/// Tint color for template image
public var imageTintColor: UIColor? = nil
/// Background color
public var backgroundColor: UIColor = .white
/// Background Gradient color
public var gradientColor: (UIColor, UIColor)? = nil
/// Position
public var position = EmptyStatePosition()
/// Margin for vertical position
public var verticalMargin: CGFloat = 40
/// Left & right margin
public var horizontalMargin: CGFloat = 40
/// Image size
public var imageSize: CGSize = CGSize(width: 200, height: 200)
Remember to assign format object to your empty state view.
view.emptyState.format = format
Animation Types
Fade
This type will make first fade animation with text and second fade animation with the image when empty state appears
format.animation = EmptyStateAnimation.fade(0.3, 0.3)
(Text fade animation duration, Image fade animation duration)
Scale
This type will make first fade animation with text and second scale animation with the image when empty state appears
format.animation = EmptyStateAnimation.scale(0.3, 0.3)
(Text fade animation duration, Image scale animation duration)
Position Types
EmptyStateViewPosition
public enum EmptyStateViewPosition {
case top
case center
case bottom
}
EmptyStateTextPosition
public enum EmptyStateTextPosition {
case left
case center
case right
}
Related Skills
docs-writer
99.6k`docs-writer` skill instructions As an expert technical writer and editor for the Gemini CLI project, you produce accurate, clear, and consistent documentation. When asked to write, edit, or revie
model-usage
342.0kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
arscontexta
2.9kClaude Code plugin that generates individualized knowledge systems from conversation. You describe how you think and work, have a conversation and get a complete second brain as markdown files you own.
cursor-agent-tracking
134A repository that provides a structured system for maintaining context and tracking changes in Cursor's AGENT mode conversations through template files, enabling better continuity and organization of AI interactions.
