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.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ2OTU3ODYsIm5iZiI6MTcyNDY5NTQ4NiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2Mzc5Mi1lYjMxOWY1ZS03YWNjLTRhZTMtYWQzOS1hNzIyMjVkZTFjMDAuZ2lmP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDgyNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA4MjZUMTgwNDQ2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YmUyMTAzYmM4ZDFiZTdmODM4OWZjYzFlMmViZGU3NTIwOTlkZGM4MDdhNzUzZjUyMTBmYmIyYWZlYzliNmU2YSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.ZDbRtI7uW-C6rg6IBN2eTOJH9QBqcUMqjuWPqNVr7T0)
![](https://private-user-images.githubusercontent.com/2247256/290663752-305c9dd8-1ae7-4a18-a59e-544096ec6352.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ2OTU3ODYsIm5iZiI6MTcyNDY5NTQ4NiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2Mzc1Mi0zMDVjOWRkOC0xYWU3LTRhMTgtYTU5ZS01NDQwOTZlYzYzNTIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDgyNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA4MjZUMTgwNDQ2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MGViYjBhZjRhMWQ2ZjI3NzM5MTQ3MzQ2NzZhNTNkNjNiM2Y4ZDM3ZmYxOWMxNzU4MDNkMGNlYzlkZWRmMmVlNSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.t1unM0QVnuyJsSpT2u_2BmXKLIYS9V-3vjMh_sC9LJI)
![](https://private-user-images.githubusercontent.com/2247256/290663732-344ca96c-f85e-43c3-9362-9639cf024035.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ2OTU3ODYsIm5iZiI6MTcyNDY5NTQ4NiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2MzczMi0zNDRjYTk2Yy1mODVlLTQzYzMtOTM2Mi05NjM5Y2YwMjQwMzUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDgyNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA4MjZUMTgwNDQ2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZTkwYzkyZWZlZGIxZmE0ZDA5M2JlM2NhNDI5YTJhNjg3NzMxNGY1NThiMmYxZmVlMWY3OTUxZjVjYmFlYTEwYiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.BkHIT0YCRHnTka961Uc9CcJja1pUrXbgGcJo2bxVTZw)
Site: https://psharanda.github.io/NativeBook
![](https://private-user-images.githubusercontent.com/2247256/290665125-99b78193-2ae4-4ac1-9228-6851efe50327.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ2OTU3ODYsIm5iZiI6MTcyNDY5NTQ4NiwicGF0aCI6Ii8yMjQ3MjU2LzI5MDY2NTEyNS05OWI3ODE5My0yYWU0LTRhYzEtOTIyOC02ODUxZWZlNTAzMjcucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDgyNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA4MjZUMTgwNDQ2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9N2I0ZjQ5MThiMjI1NjhkM2ZjZjA4ZjRlYTljZGE4NDk2OWY2MmQ1MGQxNWQwNzZlMGUwMDUzN2U1NjRjMTc2YSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.hjoTWHbniWRcm0sfi6e9mq0AJHO53gGftwlPSlzOa_s)