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, andCard.swiftare inSources/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.swiftand the gallery files inSources/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 point – Sources/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 –
main.swift→ShadcnAIGallery()(gallery view).- The gallery selects a demo (e.g., AI chat) and instantiates
AIChatbotfromSources/AIElementsUI/Chatbot.swift. AIChatbotowns a@StateObjectof typeAIChat(runtime inChatRuntime.swift).AIChattalks to a transport that conforms toAIChatTransport. The default mock transport (AIMockChatTransport) streamsAIChatChunks, whichChatRuntimeparses and forwards to UI components (AIMessageView,AICodeBlock, etc.).- UI primitives (e.g.,
Button,Badge) read the current theme from theEnvironmentinjected byShadcnTheme(defined inSources/ShadcnUI/Theme/ShadcnTheme.swift). Theme loading occurs once inThemeLoading.swiftand populatesShadcnPaletteused throughout the UI layer.
Effect ownership –
ThemeLoading.swifthas the widest blast radius: any change to token parsing affects every primitive.ChatRuntime.swiftandAssistantPanel.swiftcontain deep nesting (max depth 9) and host the majority of branching logic for AI message handling.CanvasView.swiftowns 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 buildandswift teston 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.