Implementing, maintaining, documenting and evolving a shared set of UI components is not an easy thing in a large-scale application. Web developers have created a powerful solution for this process - Storybook.js. But what about native iOS development? Can we achieve a somewhat similar experience?
What if we combine a catalog app, snapshot tests, and HTML-based documentation generation into a single system?
Imagine writing a code snippet just once, and then being able to do the following:
- Display a view produced from a snippet in a native catalog app
- Embed a view into SwiftUI previews
- Run a snapshot test for a snippet
- Display this code snippet and the resulting snapshot in a generated HTML-based documentation
This repo is a proof of the concept for such a system!
Check my article about NativeBook for more details: https://hackernoon.com/nativebook-unifying-the-native-ios-development-experience-with-storybookjs
class UIButtonStories: DynamicComponentStories {
@objc static func story_ImageTitleButton() -> UIView {
let button = UIButton()
var config = UIButton.Configuration.plain()
config.title = "Image + Title"
config.image = UIImage(systemName: "bell")
config.imagePlacement = .top
config.titlePadding = 10
button.configuration = config
return button
}
...
}
![](https://private-user-images.githubusercontent.com/2247256/290663792-eb319f5e-7acc-4ae3-ad39-a72225de1c00.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk1NzEzNzYsIm5iZiI6MTczOTU3MTA3NiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2Mzc5Mi1lYjMxOWY1ZS03YWNjLTRhZTMtYWQzOS1hNzIyMjVkZTFjMDAuZ2lmP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMjIxMTE2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YTcwNjViN2ViMDE0OWQyY2IyOGM1NDMwZDQ2MzMzOGNiZDk2NjI1MjdhNWM1YTJkMjQ1MmUyOWU3OWY4OWI3ZSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.95nN0oO_lf0ZCnfts_JfDBfKcKv7BqljOvx6XW3r1Yk)
![](https://private-user-images.githubusercontent.com/2247256/290663752-305c9dd8-1ae7-4a18-a59e-544096ec6352.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk1NzEzNzYsIm5iZiI6MTczOTU3MTA3NiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2Mzc1Mi0zMDVjOWRkOC0xYWU3LTRhMTgtYTU5ZS01NDQwOTZlYzYzNTIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMjIxMTE2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZTMxODhiNWZmNDg5Nzc1OGViNjZjMDY0Mjg0ZWU0YjkwMTEyYjM1MDQwY2I2YTBiZDdmMzZiMmRmZTNlNmZkZCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.LoozUkoPH_AkaaTUfumKXeAmJ1Q0xJRkihCjx5Faz84)
![](https://private-user-images.githubusercontent.com/2247256/290663732-344ca96c-f85e-43c3-9362-9639cf024035.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk1NzEzNzYsIm5iZiI6MTczOTU3MTA3NiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2MzczMi0zNDRjYTk2Yy1mODVlLTQzYzMtOTM2Mi05NjM5Y2YwMjQwMzUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMjIxMTE2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZDRhYWJmMzE3Y2RjZTcxZDI3MzMwOGMzOTAyMzUxYmJiMWY3ZTYxNTNmZDUzM2EyYWUxMzg5MjM1ZTlkYTQ1YyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.OOMhJnwt46qEdR9CGOf66HXDHUMCN3-AQ-sIcR1ljdc)
Site: https://psharanda.github.io/NativeBook
![](https://private-user-images.githubusercontent.com/2247256/290665125-99b78193-2ae4-4ac1-9228-6851efe50327.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk1NzEzNzYsIm5iZiI6MTczOTU3MTA3NiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2NTEyNS05OWI3ODE5My0yYWU0LTRhYzEtOTIyOC02ODUxZWZlNTAzMjcucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMjIxMTE2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OTYyMjFkNTk4OGRjOWViNTM1NzcyNWVlMDg3N2EwZDQ3N2ZiN2Y1MjkzNDI5OWY1NWVjNDcyNjIxZjQxMmYwOCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.Vt7LcZUQWzN2INRRZB9mwGP3G_aUcLpZgBbWYhtm4NU)