{"id":13688454,"url":"https://github.com/gonzalezreal/AdaptiveCardUI","last_synced_at":"2025-05-01T19:31:04.740Z","repository":{"id":54767282,"uuid":"297719721","full_name":"gonzalezreal/AdaptiveCardUI","owner":"gonzalezreal","description":"Snippets of UI, authored in JSON and rendered with SwiftUI","archived":true,"fork":false,"pushed_at":"2021-03-03T08:55:35.000Z","size":1709,"stargazers_count":93,"open_issues_count":8,"forks_count":8,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-05T00:03:35.236Z","etag":null,"topics":["adaptive-cards","codable","conversational-ui","json","server-driven-ui","swift","swiftui"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gonzalezreal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-22T17:15:51.000Z","updated_at":"2025-02-21T02:19:53.000Z","dependencies_parsed_at":"2022-08-14T02:10:46.608Z","dependency_job_id":null,"html_url":"https://github.com/gonzalezreal/AdaptiveCardUI","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalezreal%2FAdaptiveCardUI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalezreal%2FAdaptiveCardUI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalezreal%2FAdaptiveCardUI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalezreal%2FAdaptiveCardUI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gonzalezreal","download_url":"https://codeload.github.com/gonzalezreal/AdaptiveCardUI/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251932640,"owners_count":21667186,"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":["adaptive-cards","codable","conversational-ui","json","server-driven-ui","swift","swiftui"],"created_at":"2024-08-02T15:01:14.064Z","updated_at":"2025-05-01T19:31:02.419Z","avatar_url":"https://github.com/gonzalezreal.png","language":"Swift","readme":"# AdaptiveCardUI\n[![CI](https://github.com/gonzalezreal/AdaptiveCardUI/workflows/CI/badge.svg)](https://github.com/gonzalezreal/AdaptiveCardUI/actions?query=workflow%3ACI)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fgonzalezreal%2FAdaptiveCardUI%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/gonzalezreal/AdaptiveCardUI)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fgonzalezreal%2FAdaptiveCardUI%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/gonzalezreal/AdaptiveCardUI)\n[![Twitter: @gonzalezreal](https://img.shields.io/badge/twitter-@gonzalezreal-blue.svg?style=flat)](https://twitter.com/gonzalezreal)\n\nAdaptiveCardUI is a library for rendering Adaptive Cards in SwiftUI.\n\nAdaptive Cards are snippets of UI, authored in JSON, that apps and services can openly exchange. AdaptiveCardUI transforms this JSON into a native SwiftUI view tree, allowing the integration of lightweight UI into your SwiftUI app.\n\n* [Motivation](#motivation)\n* [Adaptive Card Basics](#adaptive-card-basics)\n* [Displaying Adaptive Cards](#displaying-adaptive-cards)\n* [Customizing Appearance](#customizing-appearance)\n* [Adding Custom Elements](#adding-custom-elements)\n* [Compatibility](#compatibility)\n* [Installation](#installation)\n* [Other Libraries](#other-libraries)\n\n## Motivation\nMicrosoft builds and maintains the Adaptive Card schema. They have SDKs available for [several platforms](https://github.com/microsoft/AdaptiveCards), including a [UIKit Objective-C++ based implementation](https://github.com/microsoft/AdaptiveCards/tree/main/source/ios) for iOS.\n\nAdaptiveCardUI aims to provide a more natural experience for Swift developers:\n* It uses Swift `Codable` for decoding and encoding Adaptive Cards\n* Allows appearance customization through view modifiers and the SwiftUI `Environment`\n* Supports extensibility through Custom Elements\n* Supports Dark Mode and Dynamic Type\n* Works on all the platforms where SwiftUI is present\n\n## Adaptive Card Basics\nAdaptive Cards are a great way to display and interact with data, clearly and consistently. You can use them to display rich text alongside images, allow users to interact with buttons, or even collect form data.\n\nHere is a simple card that includes a text, followed by an image and a button.\n\n```json\n{\n  \"type\": \"AdaptiveCard\",\n  \"version\": \"1.3\",\n  \"body\": [\n    {\n      \"type\": \"TextBlock\",\n      \"text\": \"Here is very cute dog\"\n    },\n    {\n      \"type\": \"Image\",\n      \"url\": \"https://picsum.photos/id/237/300\"\n    }\n  ],\n  \"actions\": [\n    {\n      \"type\": \"Action.OpenUrl\",\n      \"url\": \"https://picsum.photos\",\n      \"title\": \"Lorem Picsum Photos\"\n    }\n  ]\n}\n```\n\nThe root object is the Adaptive Card itself and specifies the `version` required to display it. The `body` is composed of building blocks known as *elements*. You can arrange them in different ways to create many types of cards. Additionally, Adaptive Cards may include `actions` on which the user can act.\n\nThe most fundamental elements of an Adaptive Card are:\n* `TextBlock` - a block of text and its appearance\n* `RichTextBlock` - allows for inline text formatting\n* `Image` - an image located in a URL and its appearance\n\nAdaptive Cards can also have containers, which arrange a collection of child elements.\n* `Container` - a collection of elements stacked vertically\n* `ColumnSet` - divides a region into Columns, allowing elements to sit side-by-side\n* `ActionSet` - displays a set of actions\n* `FactSet` - displays a series of name/value pairs in a tabular form\n\nWith just these few elements, you can design Adaptive Cards with quite complex layouts.\n\n![iOSScreenshot](Examples/AdaptiveCardVisualizer/Screenshot.png)\n![MacOS Screenshot](Examples/AdaptiveCardVisualizer/ScreenshotMac.png)\n\nAdaptive Cards can collect form data using `Input` elements. AdaptiveCardUI can't render `Input` elements yet, but we plan to support them [soon](https://github.com/gonzalezreal/AdaptiveCardUI/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement).\n\n### Learn More\n* Run the [AdaptiveCardVisualizer example](Examples/AdaptiveCardVisualizer)\n  * Requires Xcode 12 and Swift 5.3. If you want to try the macOS version, you will need to install macOS Big Sur 11 and Xcode 12.2.\n* [Browse sample cards](Examples/AdaptiveCardVisualizer/Cards)\n* Use the [Schema Explorer](https://adaptivecards.io/explorer) to browse the capabilities of the different elements\n\n## Displaying Adaptive Cards\nYou can create an adaptive card view by providing the URL where the adaptive card is located.\n\n```swift\nAdaptiveCardView(url: URL(string: \"https://adaptivecards.io/payloads/ActivityUpdate.json\")!)\n```\n\nOr by providing an adaptive card fetched previously.\n\n```swift\nlet adaptiveCard = try JSONDecoder().decode(AdaptiveCard.self, from: jsonData)\n...\nAdaptiveCardView(adaptiveCard)\n```\n\nBefore displaying the card, the view checks that its version is supported and downloads its content asynchronously.\n    \n## Customizing Appearance\nYou can customize an adaptive card's appearance by providing a configuration. An `AdaptiveCardConfiguration` is a set of values that specify how the library renders the different elements. To set a specific configuration for all the adaptive cards within a view, use the `adaptiveCardConfiguration(_:)` modifier.\n\n```swift\n VStack {\n     AdaptiveCardView(url: URL(string: \"https://adaptivecards.io/payloads/ActivityUpdate.json\")!)\n     AdaptiveCardView(response.adaptiveCard)\n }\n .adaptiveCardConfiguration(AdaptiveCardConfiguration(...))\n ```\n\nAlternatively, you can customize only a specific aspect of an adaptive card's appearance, like the actions or the different spacing values. Use one of the following modifiers to customize a specific aspect of all the adaptive cards within a view:\n * `actionSetConfiguration(_:)` to customize the appearance of the adaptive card actions.\n * `containerStyleConfiguration(_:)` to customize the colors of the different container styles.\n * `factSetConfiguration(_:)` to customize the appearance of the fact set elements.\n * `imageSizeConfiguration(_:)` to provide custom values for the different image size cases.\n * `spacingConfiguration(_:)` to provide custom values for the different spacing cases.\n * `fontTypeConfiguration(_:)` to provide custom fonts for the different font types and sizes.\n    \n## Adding Custom Elements\nAdaptive cards are extensible, so you can add your own elements and the views that display them.\n\nAs an example, imagine that we are designing a card to present the summary of a GitHub repo. One of the elements is the repo language, which GitHub represents with a circle filled with a given color, next to the language name. The JSON representation of the element could look like this:\n\n```json\n{\n  \"type\": \"RepoLanguage\",\n  \"horizontalAlignment\": \"center\",\n  \"language\": \"Swift\",\n  \"color\": \"#ffac45\"\n}\n```\n\nWe have omitted inherited optional properties like `\"id\"`, `\"isVisible\"`, `\"spacing\"`, `\"separator\"`, etc. But you will need to support them, nevertheless.\n\nTo add this new element, you need to create a type that conforms to `CustomCardElement`, `Codable`, and `Equatable`.\n\n```swift\nstruct RepoLanguage: CustomCardElement, Codable, Equatable {\n    // CustomCardElement\n\n    @ItemIdentifier var id: String\n    @Default\u003cTrue\u003e var isVisible: Bool\n    @Default\u003cFalse\u003e var separator: Bool\n    @Default\u003cFirstCase\u003e var spacing: Spacing\n    @Default\u003cFallback.None\u003e var fallback: Fallback\u003cCardElement\u003e\n    @Default\u003cEmptyDictionary\u003e var requires: [String: SemanticVersion]\n\n    // RepoLanguage\n\n    @Default\u003cFirstCase\u003e var horizontalAlignment: HAlignment\n    var language: String\n    var color: String\n}\n```\n\nIn case you are wondering, the `Default` property wrapper lets you provide default values for JSON properties that are not required, removing much of the boilerplate. See [DefaultCodable](https://github.com/gonzalezreal/DefaultCodable) for more information.\n\nAs the new element conforms to `CustomCardElement`, you can add it to the body of an adaptive card, a container, or a column in a column set. It will have a spacing relative to the previous element and an optional separator. Besides that, you can provide a fallback element for those clients that still don't support it.\n\nNotice that you will need to register the new element before any adaptive card decoding happens:\n\n```swift\nCardElement.register(RepoLanguage.self)\n```\n\nYou can create the view that renders the new element as any other SwiftUI view:\n\n```swift\nstruct RepoLanguageView: View {\n    var repoLanguage: RepoLanguage\n\n    var body: some View {\n        HAlign(repoLanguage.horizontalAlignment) {\n            Label {\n                Text(repoLanguage.language)\n            } icon: {\n                Image(systemName: \"circle.fill\")\n                    .imageScale(.small)\n                    .foregroundColor(Color(argbHex: repoLanguage.color))\n            }\n        }\n    }\n}\n```\n\nFinally, to associate the new element and its view to all the adaptive card views within a view hierarchy, use the `customCardElement(_:, content:)` modifier:\n\n```swift\nVStack {\n    AdaptiveCardView(url: URL(string: \"https://adaptivecards.io/payloads/ActivityUpdate.json\")!)\n    AdaptiveCardView(response.adaptiveCard)\n}\n.customCardElement(RepoLanguage.self) {\n    RepoLanguageView($0)\n}\n```\n\n## Compatibility\nAdaptiveCardUI requires Xcode 12 and Swift 5.3. It works on iOS 14.0 and later. If you want to try the macOS support, you will need to install macOS Big Sur 11 and Xcode 12.2.\n\n## Installation\nYou can add AdaptiveCardUI to an Xcode project by adding it as a package dependency.\n1. From the **File** menu, select **Swift Packages › Add Package Dependency…**\n1. Enter `https://github.com/gonzalezreal/AdaptiveCardUI` into the package repository URL text field\n1. Link **AdaptiveCardUI** to your application target\n\n## Other Libraries\n* [Microsoft Adaptive Cards](https://github.com/microsoft/AdaptiveCards)\n","funding_links":[],"categories":["Uncategorized","Swift"],"sub_categories":["Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgonzalezreal%2FAdaptiveCardUI","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgonzalezreal%2FAdaptiveCardUI","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgonzalezreal%2FAdaptiveCardUI/lists"}