{"id":1088,"url":"https://github.com/playbook-ui/playbook-ios","last_synced_at":"2025-05-14T15:03:43.031Z","repository":{"id":40429919,"uuid":"243712144","full_name":"playbook-ui/playbook-ios","owner":"playbook-ui","description":"📘A library for isolated developing UI components and automatically taking snapshots of them.","archived":false,"fork":false,"pushed_at":"2024-12-04T09:08:20.000Z","size":29456,"stargazers_count":1197,"open_issues_count":5,"forks_count":60,"subscribers_count":23,"default_branch":"master","last_synced_at":"2025-04-05T19:04:14.763Z","etag":null,"topics":["a11y","accessibility","ios","playbook","snapshot","snapshot-testing","swift","swiftui","uicatalog","visual-regression-testing"],"latest_commit_sha":null,"homepage":"https://playbook-ui.github.io/playbook-ios/documentation/playbooksnapshot/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/playbook-ui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-28T08:18:52.000Z","updated_at":"2025-03-28T00:12:53.000Z","dependencies_parsed_at":"2024-01-10T14:19:30.649Z","dependency_job_id":"83fa4849-1340-4745-ab20-c1f06915e528","html_url":"https://github.com/playbook-ui/playbook-ios","commit_stats":{"total_commits":119,"total_committers":9,"mean_commits":"13.222222222222221","dds":"0.11764705882352944","last_synced_commit":"3320069508e677858a5dbfac72622b885f3b351e"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/playbook-ui%2Fplaybook-ios","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/playbook-ui%2Fplaybook-ios/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/playbook-ui%2Fplaybook-ios/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/playbook-ui%2Fplaybook-ios/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/playbook-ui","download_url":"https://codeload.github.com/playbook-ui/playbook-ios/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248631353,"owners_count":21136550,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a11y","accessibility","ios","playbook","snapshot","snapshot-testing","swift","swiftui","uicatalog","visual-regression-testing"],"created_at":"2024-01-05T20:15:38.675Z","updated_at":"2025-04-12T20:36:49.813Z","avatar_url":"https://github.com/playbook-ui.png","language":"Swift","funding_links":[],"categories":["Debugging","Libs","Swift","iOS","Utilities and Extensions","Utility [🔝](#readme)"],"sub_categories":["Getting Started","Utility","Linter"],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/playbook-ui/mediakit/master/logo/default-h%402x.png\" alt=\"Playbook\" width=\"400\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003eA library for isolated developing UI components and automatically taking snapshots of them.\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"assets/overview.png\" alt=\"playbook\" width=\"850\"\u003e\n\u003c/p\u003e\n\n# Playbook\n\n\u003cimg src=\"assets/demo.gif\" alt=\"Playbook\" width=\"250\" align=\"right\"\u003e\n\n\u003ca href=\"https://developer.apple.com/swift\"\u003e\u003cimg alt=\"Swift5\" src=\"https://img.shields.io/badge/language-Swift5-orange.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/playbook-ui/playbook-ios/actions\"\u003e\u003cimg alt=\"CI Status\" src=\"https://github.com/playbook-ui/playbook-ios/workflows/GitHub%20Actions/badge.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"LICENSE\"\u003e\u003cimg alt=\"Lincense\" src=\"http://img.shields.io/badge/License-Apache%202.0-black.svg\"/\u003e\u003c/a\u003e\n\u003cbr\u003e\n\u003ca href=\"https://github.com/playbook-ui/playbook-ios/releases/latest\"\u003e\u003cimg alt=\"Release\" src=\"https://img.shields.io/github/v/release/playbook-ui/playbook-ios.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://swift.org/package-manager\"\u003e\u003cimg alt=\"Swift Package Manager\" src=\"https://img.shields.io/badge/SwiftPM-compatible-yellowgreen.svg\"/\u003e\u003c/a\u003e\n\n`Playbook` is a library that provides a sandbox for building UI components without having to worry about application-specific dependencies, strongly inspired by [Storybook](https://storybook.js.org/) for JavaScript in web-frontend development.  \n\nComponents built by using `Playbook` can generate a standalone app as living styleguide.  \nThis allows you to not only review UI quickly but also deliver more robust designs by separating business logics out of components.\n\nBesides, snapshots of each component can be automatically generated by unit tests, and visual regression testing can be performed using arbitrary third-party tools.\n\nFor complex modern app development, it’s important to catch UI changes more sensitively and keep improving them faster.  \nWith the `Playbook`, you don't have to struggle through preparing the data and spend human resources for manual testings.  \n\n\u003cbr clear=\"all\"\u003e\n\n---\n\n## Usage\n\n- [API Document](https://playbook-ui.github.io/playbook-ios/documentation/playbooksnapshot)\n- [Example App](https://github.com/playbook-ui/playbook-ios/tree/master/Example)\n\n---\n\n### Playbook\n\n`Playbook` is a framework that provides the basic functionality for managing components. It supports both `SwiftUI` and `UIKit`.  \nComponents are uniquely stored as scenarios. A `Scenario` has the way to layout component. Please check the API Doc for the variety of layouts.  \n\n```swift\nPlaybook.default.addScenarios(of: \"Home\") {\n    Scenario(\"CategoryHome\", layout: .fill) {\n        CategoryHome().environmentObject(UserData.stub)\n    }\n\n    Scenario(\"LandmarkList\", layout: .fill) {\n        NavigationView {\n            LandmarkList().environmentObject(UserData.stub)\n        }\n    }\n\n    Scenario(\"UIView red\", layout: .fixed(length: 100)) {\n        let view = UIView()\n        view.backgroundColor = .red\n        return view\n    }\n}\n```\n\n`ScenarioProvider` allows you to isolate additional scenarios and keep your playbook building clean.  \n\n```swift\nstruct HomeScenarios: ScenarioProvider {\n    static func addScenarios(into playbook: Playbook) {\n        playbook.addScenarios(of: \"Home\") {\n            Scenario(\"CategoryHome\", layout: .fill) {\n                CategoryHome().environmentObject(UserData.stub)\n            }\n        }\n    }\n}\n\nstruct AllScenarios: ScenarioProvider {\n    static func addScenarios(into playbook: Playbook) {\n        playbook.add(HomeScenarios.self)\n    }\n}\n```\n\nYou can use the `ScenarioContext` passed to the closure that creates the component to get the screen size in snapshot, or wait before generating a snapshot.  \n\n```swift\nScenario(\"MapView\", layout: .fill) { context in\n    MapView(coordinate: landmarkData[10].locationCoordinate) {\n        // This closure will called after the map has completed to render.\n        context.snapshotWaiter.fulfill()\n     }\n     .onAppear(perform: context.snapshotWaiter.wait)\n}\n```\n\n---\n\n### PlaybookUI\n\n`PlaybookUI` is a framework that provides user interfaces made by `SwiftUI` for browsing a list of scenarios.  \n\n#### PlaybookGallery\n\nThe component visuals are listed and displayed.  \nThose that are displayed on the top screen are not actually doing layout, but rather display the snapshots that are efficiently generated at runtime.  \n\n| Browser | Detail |\n| ------- | ------ |\n|\u003cimg src=\"assets/gallery_light.png\" alt=\"Gellery Light\" width=\"150\"\u003e\u003cimg src=\"assets/gallery_dark.png\" alt=\"Gellery Dark\" width=\"150\"\u003e|\u003cimg src=\"assets/gallery_detail_light.png\" alt=\"Gellery Content Light\" width=\"150\"\u003e\u003cimg src=\"assets/gallery_detail_dark.png\" alt=\"Gellery Content Dark\" width=\"150\"\u003e|\n\n#### PlaybookCatalog\n\nThe UI that search and select a scenario in a drawer. It's more similar to `Storybook`.  \nIf you have too many scenarios, this may be more efficient than `PlaybookCatalog`.  \n\n| Browser | Detail |\n| ------- | ------ |\n|\u003cimg src=\"assets/catalog_light.png\" alt=\"Catalog Light\" width=\"150\"\u003e\u003cimg src=\"assets/catalog_dark.png\" alt=\"Catalog Dark\" width=\"150\"\u003e|\u003cimg src=\"assets/catalog_detail_light.png\" alt=\"Catalog Detail Light\" width=\"150\"\u003e\u003cimg src=\"assets/catalog_detail_dark.png\" alt=\"Catalog Detail Dark\" width=\"150\"\u003e|\n\n#### How to Save Snapshot Images\n\nTo save snapshot images to the photo library from the share button on each UI, `NSPhotoLibraryAddUsageDescription` must be supported.  See the [official document](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW73) for more information.\n\n---\n\n### PlaybookSnapshot\n\nScenarios can be tested by the instance of types conform to `TestTool` protocol.  \n`Snapshot` is one of them, which can generate the snapshots of all scenarios with simulate the screen size and safe area of the given devices.  \nSince Playbook doesn't depend on XCTest, it doesn't necessarily need to be run on Unit-test.  \n\n```swift\nfinal class SnapshotTests: XCTestCase {\n    func testTakeSnapshot() throws {\n        let directory = ProcessInfo.processInfo.environment[\"SNAPSHOT_DIR\"]!\n\n        try Playbook.default.run(\n            Snapshot(\n                directory: URL(fileURLWithPath: directory),\n                clean: true,\n                format: .png,\n                devices: [.iPhone15Pro(.portrait)]\n            )\n        )\n    }\n}\n```\n\n\u003cimg src=\"assets/generated_images.png\" alt=\"Generated Images\" width=\"660\"\u003e\n\n---\n\n### [PlaybookAccessibilitySnapshot](https://github.com/playbook-ui/accessibility-snapshot-ios)\n\nAn extension to `Playbook` that uses [AccessibilitySnapshot](https://github.com/cashapp/AccessibilitySnapshot) to produce snapshots with accessibility information such as activation points and labels.\n\n\u003cimg src=\"assets/accessibility_snapshot.png\" alt=\"Accessibility Snapshot\" width=\"400\"\u003e\n\n---\n\n### Integration with Third-party Tools\n\nThe generated snapshot images can be used for more advanced visual regression testing by using a variety of third party tools.  \n\n#### [percy](https://percy.io)\n\n\u003cimg src=\"assets/percy.png\" alt=\"percy\" width=\"600\"\u003e\n\n#### [reg-viz/reg-suit](https://github.com/reg-viz/reg-suit)\n\n\u003cimg src=\"assets/reg_report.png\" alt=\"reg-suit\" width=\"600\"\u003e\n\n---\n\n## Requirements\n\n- Swift 5.10\n- Xcode 15.4\n- iOS 13.0+ (PlaybookUI: iOS 15.0+)\n\n---\n\n## Installation\n\nPlaybook features are separated into the following frameworks.  \n\n- `Playbook`: Core system of component management.\n- `PlaybookSnapshot`: Generates snapshots of all components.\n- `PlaybookUI`: Products a browsing UI for components managed by Playbook.\n\n### [Swift Package Manager](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app)\n\nSelect Xcode menu `File \u003e Swift Packages \u003e Add Package Dependency...` and enter repository URL with GUI.\n\n```\nRepository: https://github.com/playbook-ui/playbook-ios\n```\n\nNote: Currently, SwiftPM doesn't support specifying the OS version for each library, so only `iOS13` is supported.  \n\n---\n\n## License\n\nPlaybook is released under the [Apache 2.0 License](https://github.com/playbook-ui/playbook-ios/tree/master/LICENSE).\n\n\u003cbr\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg alt=\"Playbook\" src=\"https://raw.githubusercontent.com/playbook-ui/mediakit/master/logo/default%402x.png\" width=\"280\"\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplaybook-ui%2Fplaybook-ios","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplaybook-ui%2Fplaybook-ios","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplaybook-ui%2Fplaybook-ios/lists"}