The Problem

Developers building macOS or iOS apps often need UI that mirrors the look‑and‑feel of shadcn/ui and Vercel AI Elements but must avoid heavyweight third‑party libraries. Maintaining visual fidelity while keeping the dependency footprint at zero creates friction when teams copy‑paste HTML/CSS or rely on wrappers that drift from the source designs.

What This Does

ShadKit delivers a pure‑SwiftUI implementation of the shadcn component library, the AI Elements UI set, a React‑Flow‑style node canvas, and a small demo gallery.

  • The design‑token stack lives under Sources/ShadcnUI/Theme/ (e.g. ShadcnPalette.swift, ThemeLoading.swift).
  • UI primitives such as Button.swift, Badge.swift, and Card.swift are in Sources/ShadcnUI/Primitives/.
  • AI‑focused views and runtime live in Sources/AIElementsUI/ (AssistantPanel.swift, Chatbot.swift, CodeBlock.swift, ChatRuntime.swift).
  • The canvas implementation is under Sources/CanvasUI/ (CanvasView.swift, CanvasModel.swift).
  • A runnable showcase is provided by Sources/ShadKitDemo/main.swift and the gallery files in Sources/AIElementsGallery/.

All components are compiled as a single Swift package (Package.swift) that can be added to a host app with the standard Swift Package Manager line shown in the README.

How It Is Wired

Entry pointSources/ShadKitDemo/main.swift creates a NSHostingView that hosts ShadcnAIGallery() (the top‑level view from Sources/AIElementsGallery/Gallery.swift). The gallery imports the UI modules and presents a tabbed interface that instantiates each component demo.

Control flow

  1. main.swiftShadcnAIGallery() (gallery view).
  2. The gallery selects a demo (e.g., AI chat) and instantiates AIChatbot from Sources/AIElementsUI/Chatbot.swift.
  3. AIChatbot owns a @StateObject of type AIChat (runtime in ChatRuntime.swift).
  4. AIChat talks to a transport that conforms to AIChatTransport. The default mock transport (AIMockChatTransport) streams AIChatChunks, which ChatRuntime parses and forwards to UI components (AIMessageView, AICodeBlock, etc.).
  5. UI primitives (e.g., Button, Badge) read the current theme from the Environment injected by ShadcnTheme (defined in Sources/ShadcnUI/Theme/ShadcnTheme.swift). Theme loading occurs once in ThemeLoading.swift and populates ShadcnPalette used throughout the UI layer.

Effect ownership

  • ThemeLoading.swift has the widest blast radius: any change to token parsing affects every primitive.
  • ChatRuntime.swift and AssistantPanel.swift contain deep nesting (max depth 9) and host the majority of branching logic for AI message handling.
  • CanvasView.swift owns all canvas‑rendering side effects (node layout, drag handling). No module cycles were detected; the import graph is flat with 0 internal edges.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/ShadKit
cd ShadKit

# Build the package
swift build

# Run the demo app (macOS)
swift run ShadKitDemo
# Optional: open a specific gallery section in dark mode
swift run ShadKitDemo --section aiTemplates --scheme dark

No external configuration files, environment variables, or secrets are required. Add the package to another project with:

.package(url: "https://github.com/moses-y/ShadKit", from: "0.1.0")

Real‑World Use

A product that ships a native macOS chat assistant can replace a web‑based UI by importing ShadKit. In the host app’s root view:

import ShadcnUI
import AIElementsUI

ContentView()
    .shadcnSurface()
    .shadcnTheme(myCustomTheme)   // OKLCH‑based palette
    .overlay {
        AIChatbot(chat: AIChat(transport: MyBackendTransport()))
    }

The assistant now looks identical to the original Vercel AI Elements while remaining fully SwiftUI‑native and dependency‑free.

Code Health & Issues

  • High – cognitive_load – Deep nesting (max depth 9) in Gallery.swift, AssistantPanel.swift, CodeBlock.swift. Flatten with early returns or guard clauses, and consider extracting inner blocks.
  • High – clarity – Repeated 6‑line code blocks across 14 UI files (AssistantPanel.swift, Chatbot.swift, Conversation.swift, Surfaces.swift, …). Consolidate into shared helpers.
  • Medium – cognitive_load – High branching density in Gallery.swift, ChatRuntime.swift, ThemeLoading.swift. Break decision‑heavy sections into smaller, strategy‑based functions.
  • High – CI missing – No workflow builds or tests the 69 source files. Add a GitHub Actions workflow that runs swift build and swift test on push and pull‑request.

All other hygiene items are satisfactory: tests exist (Tests/…), a LICENSE is present, and no secrets were found.

The Bottom Line

ShadKit provides a faithful, dependency‑free SwiftUI port of popular design systems, making it attractive for teams that need visual parity without external packages. The codebase is functional but suffers from deep nesting, duplicated snippets, and a lack of CI automation, which could hinder maintainability and rapid iteration. It is best suited for developers comfortable with SwiftUI who can invest in modest refactoring and CI setup.