DynamicUI

0.0.9

Create a SwiftUI user interface through a JSON file. The JSON file will contain the structure of the user interface, and the program will create the user interface based on the JSON file.
0xWDG/DynamicUI

What's New

0.0.9

2026-06-14T10:09:35Z

What's Changed

  • Change to a view modifier, add 'foregroundColor', 'backgroundColor', and support .frame. by @0xWDG in #4
  • Make DynamicUIHelper's functions static by @0xWDG in #5
  • Lint fixes by @0xWDG in #6
  • Remove AnyView by @0xWDG in #7
  • Support onError, removed the need for an Internal struct by @0xWDG in #8
  • Update documentation by @0xWDG in #9
  • Init should not have an optional json parameter by @0xWDG in #10
  • More initializers, and updated playground application by @0xWDG in #11
  • Add Section, and previews by @0xWDG in #13
  • Add JSON schema example documentation for DynamicUI forms by @Copilot in #14
  • Improve documentation by @0xWDG in #17
  • Support idenfifiers, fixes #16 by @0xWDG in #19
  • Fix typos and indentation by @0xWDG in #22

Full Changelog: 0.0.8...0.0.9

DynamicUI

Create SwiftUI interfaces from JSON component trees. DynamicUI supports nested layouts, interactive controls, runtime value updates, conditional strings, and a focused set of SwiftUI modifiers.

Swift Package Manager License

Requirements

  • Swift 5.9+ (Xcode 15+)
  • iOS 15+, macOS 12+, tvOS 14+, watchOS 8+, macCatalyst 15+, visionOS 1.0+

Installation

Add DynamicUI using Swift Package Manager:

dependencies: [
    .package(url: "https://github.com/0xWDG/DynamicUI.git", branch: "main"),
],
targets: [
    .target(name: "MyTarget", dependencies: [
        .product(name: "DynamicUI", package: "DynamicUI"),
    ]),
]

And import it:

import DynamicUI

Usage

import SwiftUI
import DynamicUI

struct ContentView: View {
    let json = """
    [
        {
            "type": "Text",
            "title": "Wait, am i generating views from JSON?",
            "modifiers": {"foregroundStyle":"red","opacity":0.6}
        },
        {
            "type": "Button",
            "title": "Click me",
            "eventHandler": "customHandler"
        },
        {
            "type": "Toggle",
            "title": "Toggle me",
            "identifier": "my.toggle.1"
        }
    ]
    """

    @State private var component: DynamicUIComponent?
    @State private var error: Error?

    var body: some View {
        DynamicUI(
            json: json,
            component: $component,
            error: $error
        )
    }
}

Conditional expressions can select a string value using another component's current state:

[
    {
        "type": "Toggle",
        "title": "Toggle me",
        "identifier": "myIdentifier"
    },
    {
        "type": "Label",
        "title": "Shine",
        "url": "{$myIdentifier ? star.fill : star}"
    }
]

The syntax is {$identifier ? valueWhenTrue : valueWhenFalse}. It works in string-valued component fields, including title, text, url, modifiers, and parameters.

Handle interactions

The component binding receives the latest interacted-with component. Stateful controls include their new value in state; identifier and eventHandler let your application route the update.

.onChange(of: component) { component in
    guard let component else { return }

    print(component.identifier as Any)
    print(component.eventHandler as Any)
    print(component.state as Any)
}

You can use a callback instead of a binding:

import SwiftUI
import DynamicUI

struct ContentView: View {
    let json = """
    [
        {
            "type": "Text",
            "title": "Wait, am i generating views from JSON?",
            "modifiers": {"foregroundStyle":"red","opacity":0.6}
        },
        {
            "type": "Button",
            "title": "Click me",
            "eventHandler": "customHandler"
        },
        {
            "type": "Toggle",
            "title": "Toggle me",
            "identifier": "my.toggle.1"
        }
    ]
    """

    @State private var error: Error?

    var body: some View {
        DynamicUI(
            json: json,
            callback: { component in
                // This contains everything passed as a component (type, title, identifier, ...)
                print(component)
            },
            error: $error
        )
    }
}

JSON schema

Every component requires a case-sensitive type. Common optional fields are:

Field Purpose
title Label, title, placeholder, or accessibility label
identifier Stable key for updates and conditional expressions
eventHandler Application-defined event name returned on interaction
defaultValue Initial value for stateful controls
children Nested component array for containers
url SF Symbol name for images, labels, and tab labels
disabled Disables the component
modifiers Visual and behavioral modifiers
minimumValue, maximumValue Numeric bounds for sliders and progress views

Unknown component types render no view. Decode failures are written to the optional error binding and display a fallback error view.

Playground application

The Playground directory contains an Xcode project with basic and exhaustive JSON examples. It is available for macOS, iOS, watchOS, tvOS, and visionOS.

Supported SwiftUI views

DynamicUI supports content views, controls, layouts, containers, navigation, tabs, and split views. See the complete schema, platform behavior, component examples, and modifier reference in the documentation.

Images

Playground

image image

Used By

Contact

๐Ÿฆ‹ @0xWDG ๐Ÿ˜ mastodon.social/@0xWDG ๐Ÿฆ @0xWDG ๐Ÿงต @0xWDG ๐ŸŒ wesleydegroot.nl ๐Ÿค– Discord

Description

  • Swift Tools 5.8.0
View More Packages from this Author

Dependencies

  • None
Last updated: Sun Jun 14 2026 01:42:11 GMT-0900 (Hawaii-Aleutian Daylight Time)