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.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjIzMzg4MzIsIm5iZiI6MTcyMjMzODUzMiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2Mzc5Mi1lYjMxOWY1ZS03YWNjLTRhZTMtYWQzOS1hNzIyMjVkZTFjMDAuZ2lmP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDczMCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA3MzBUMTEyMjEyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZTEwZDk0ZjhjN2QyZjExM2FiZTBhZjkzZjc4ZWNmZmM4ODRiMTk3MzViODk5OWJiMWNiNmJlNzRiNWFjNThiYyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.yconCBiWxCZsOktG8gRzREuPgAbux5u-XPufTUcv-HY)
![](https://private-user-images.githubusercontent.com/2247256/290663752-305c9dd8-1ae7-4a18-a59e-544096ec6352.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjIzMzg4MzIsIm5iZiI6MTcyMjMzODUzMiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2Mzc1Mi0zMDVjOWRkOC0xYWU3LTRhMTgtYTU5ZS01NDQwOTZlYzYzNTIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDczMCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA3MzBUMTEyMjEyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NmYzMWI3MjdmOWYxYmNiNDJiMmY5ZDdlODhmNzllYWZkMjYwNTExMmIxZTdiNTAxODZkMzM5Y2ViM2Q5ZDk1MiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.ZOCeqLvJTS5GwBFkxQgPA7d0Ex9QWg_eiIFzuAQJwG4)
![](https://private-user-images.githubusercontent.com/2247256/290663732-344ca96c-f85e-43c3-9362-9639cf024035.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjIzMzg4MzIsIm5iZiI6MTcyMjMzODUzMiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2MzczMi0zNDRjYTk2Yy1mODVlLTQzYzMtOTM2Mi05NjM5Y2YwMjQwMzUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDczMCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA3MzBUMTEyMjEyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MGZhMGJlYTNiZWFmN2Y3NGMzYzA2MjIzNTRjYjZjNmE0ODAwMDI3YjEzMzkxYzExNjYwM2MzNDQ3NDg3NzMxZSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.VVz9_sqTjh15E3OjgYOorveN8jjgi_I2yw6SQhVbwfU)
Site: https://psharanda.github.io/NativeBook
![](https://private-user-images.githubusercontent.com/2247256/290665125-99b78193-2ae4-4ac1-9228-6851efe50327.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjIzMzg4MzIsIm5iZiI6MTcyMjMzODUzMiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2NTEyNS05OWI3ODE5My0yYWU0LTRhYzEtOTIyOC02ODUxZWZlNTAzMjcucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDczMCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA3MzBUMTEyMjEyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ODBhMzVmYTc2NDQzOGI1NmUwYWVkYTdjMDg5Nzg5NDFiNjg0YzUwZGViZjcxNmQ2MTJjZTI0NjhlMWVlY2E4NiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.IlwcJs3E7ag4c6Lvs_UlRWnztocNQ64qBVQm5vxB6q0)