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.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3NDM4MTIsIm5iZiI6MTczOTc0MzUxMiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2Mzc5Mi1lYjMxOWY1ZS03YWNjLTRhZTMtYWQzOS1hNzIyMjVkZTFjMDAuZ2lmP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTZUMjIwNTEyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NGUzYTAzYTA1ZDNjNWY0YzIzYzU1NzY4OWJmMDliNTBjMDM2YWZkMzViYWJjOTk0ZTQ4OTY5NmFiMzk4MjIxMSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.4sV0VzqBueJbZTunucIkjDwhXtL33_BRbFYIpvYwK6Q)
![](https://private-user-images.githubusercontent.com/2247256/290663752-305c9dd8-1ae7-4a18-a59e-544096ec6352.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3NDM4MTIsIm5iZiI6MTczOTc0MzUxMiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2Mzc1Mi0zMDVjOWRkOC0xYWU3LTRhMTgtYTU5ZS01NDQwOTZlYzYzNTIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTZUMjIwNTEyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YTA4NzNmZjk3NDMxNDY4NWE2MmQzMGViNjVhYmUyNTRjOGI3Y2NiMzRhZDJhYzYyYWM3MTQ3YjUyZjQ1N2NiZCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.WXk29D7UHH-vn0tKSa2tOeHQQ_2AczFGCArqVVlzU-w)
![](https://private-user-images.githubusercontent.com/2247256/290663732-344ca96c-f85e-43c3-9362-9639cf024035.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3NDM4MTIsIm5iZiI6MTczOTc0MzUxMiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2MzczMi0zNDRjYTk2Yy1mODVlLTQzYzMtOTM2Mi05NjM5Y2YwMjQwMzUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTZUMjIwNTEyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YmVlNzAzZGVmMTA1ZDdkOTcxNGQyNzk4Yzg2MzBiNWJhMzFkY2Q5YWE3Nzg4YTNjZDk2Yzg4NjI5YzUxM2YyMCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.5ujCGH-Iih9iocC9zoCZDrbbvtA_OXXFRqakH40R-ro)
Site: https://psharanda.github.io/NativeBook
![](https://private-user-images.githubusercontent.com/2247256/290665125-99b78193-2ae4-4ac1-9228-6851efe50327.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3NDM4MTIsIm5iZiI6MTczOTc0MzUxMiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2NTEyNS05OWI3ODE5My0yYWU0LTRhYzEtOTIyOC02ODUxZWZlNTAzMjcucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTZUMjIwNTEyWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MjRmMjlhODc4YzI4ZGI4OTJkYzAzNDEyMDcxODI5MGVhMjc3MmUxMjYyZmVhYmU0ZTdiODgxNDU2ZDQ5MmM5OCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.jPWfDX5orXwqDAMSXb5OCeI1MRBM6TwHsZN8ruLAWEw)