Tark UI: Why Top Devs Are Ditching Component Libraries
What if your favorite UI library worked in React↗ Bright Coding Blog, Vue, Solid, AND Svelte—without rewriting a single line?
You've been there. Stuck in framework purgatory. Your team finally settles on React, builds a gorgeous component library, then—plot twist—the next project demands Vue. Or Solid. Or Svelte. Suddenly, that meticulously crafted <Button> with its 47 variants, dark mode logic, and accessibility hooks? Gone. Poof. Back to square one, rebuilding the same primitives for the fourth time this year.
Or worse: you're locked into a monolithic UI framework that ships half a megabyte of JavaScript↗ Bright Coding Blog just to render a dropdown. Your Lighthouse scores weep. Your users bounce. Your CEO asks why the site loads slower than a dial-up connection in 1999.
Here's the uncomfortable truth most developers avoid: traditional component libraries are framework traps. They seduce you with speed, then shackle you to their ecosystem, their styling opinions, their breaking changes every six months.
But what if there was a different path? A collection of beautiful, accessible components that transcend framework boundaries—powered by modern primitives and utility-first styling?
Enter Tark UI. Built on the rock-solid foundation of Ark UI and styled with Tailwind CSS↗ Bright Coding Blog, this isn't just another component library. It's a framework-agnostic revolution that's making senior engineers quietly abandon their old dependencies. And once you see how it works, you'll understand why.
What Is Tark UI?
Tark UI is an open-source collection of 50+ accessible, customizable UI components engineered for modern web development↗ Bright Coding Blog. Created by Anubra266—a prolific contributor to the headless UI ecosystem—Tark UI leverages Ark UI's state machines and Tailwind CSS's utility classes to deliver components that just work across JavaScript frameworks.
The project emerged from a critical observation: developers were rebuilding identical components repeatedly, not because the logic differed, but because framework boundaries forced duplication. Ark UI solved the logic problem with its framework-agnostic state machines. Tailwind solved the styling problem with its atomic approach. Tark UI marries these two philosophies into a cohesive, copy-paste-ready component system.
Why it's trending now:
- The rise of polyglot frontend teams (React here, Vue there, Solid everywhere)
- Ark UI's 1.0 release brought production-ready state machines to multiple frameworks simultaneously
- Tailwind's v4 alpha promises even smaller bundles, making utility-first styling irresistible
- The "shadcn/ui effect" proved developers prefer copy-paste components over npm dependencies—but want them framework-portable
Tark UI isn't published as a traditional npm package you npm install and pray upgrades don't break. Instead, it follows the "copy-paste component" model: grab the source, own it, customize it, ship it. No phantom dependencies. No version conflicts. No treeshaking anxiety.
Key Features That Separate Tark UI From the Herd
✨ 50+ Production-Ready Components
From humble buttons to complex data tables, date pickers, and command palettes—Tark UI covers the 80% of UI patterns you'll actually build. Each component ships with thoughtful defaults: loading states, error boundaries, focus management, and keyboard navigation baked in.
🎨 True Framework Agnosticism
This isn't marketing fluff. Tark UI components share identical APIs across React, Vue, Solid, and Svelte because Ark UI's state machines handle the framework-specific reactivity. Learn once, deploy everywhere. Your design system becomes truly portable for the first time.
🎯 TypeScript-First Architecture
Every component exports strict type definitions. No any types lurking in corners. No cryptic prop errors at runtime. Your IDE autocompletes props, variants, and event handlers with surgical precision.
📦 Zero Runtime Dependencies
Tark UI's only requirements? Peer dependencies on Ark UI, Tailwind CSS, and Lucide Icons. No styled-components runtime. No Emotion server-side rendering hacks. No CSS-in-JS overhead inflating your bundle. The components compile to plain HTML, CSS, and framework-native code.
🌙 Dark Mode Without the Drama
Toggle dark class on your root element. Done. Tark UI uses Tailwind's dark: modifier throughout, with smooth CSS transitions between themes. No context providers. No JavaScript theme state management. Just CSS doing what CSS does best.
⚡ Performance Obsessed
Components are optimized for minimal bundle impact. No unused features drag down your initial load. Copy only what you need, customize what you copy, ship only what you use.
Real-World Use Cases Where Tark UI Dominates
1. Multi-Framework Design Systems
Your enterprise has three teams: React for the marketing site, Vue for the admin dashboard, Solid for the embedded widget. Previously, you'd maintain three separate component libraries or settle for lowest-common-denominator solutions. With Tark UI, one design system specification serves all three. Same component APIs. Same visual output. Same accessibility behavior.
2. Agency Work With Unpredictable Stacks
Freelancers and agencies live in framework chaos. This client demands React. The next worships Svelte. Rather than mastering five different UI libraries, learn Tark UI once. Arrive at any project with instant productivity, adapting your proven component patterns to whatever stack the client chose.
3. Migrating Between Frameworks
Legacy React app needs rebuilding in Vue? Instead of component archaeology—deciphering old prop interfaces and CSS-in-JS magic—Tark UI components map 1:1 across frameworks. The migration becomes mechanical, not creative. Less risk. Faster delivery.
4. Performance-Critical Applications
E-commerce. Financial dashboards. Real-time analytics. Every kilobyte matters. Traditional UI libraries ship entire design systems when you only need three components. Tark UI's copy-paste model means you ship exactly what you use—often cutting component-related bundle size by 60-80%.
5. Accessibility-First Projects
Ark UI's state machines implement WCAG-compliant keyboard navigation, focus trapping, and ARIA patterns by default. When your audit deadline looms, Tark UI components won't surprise you with missing aria-describedby attributes or broken Escape-key handlers.
Step-by-Step Installation & Setup Guide
Tark UI doesn't install via npm install. Instead, you adopt components directly into your codebase. Here's how to get started:
Prerequisites
Ensure your project has these peer dependencies:
# React example (Vue/Solid/Svelte equivalents apply)
npm install @ark-ui/react tailwindcss lucide-react
# or
yarn add @ark-ui/react tailwindcss lucide-react
# or
pnpm add @ark-ui/react tailwindcss lucide-react
Tailwind Configuration
Add Tark UI's color tokens and utilities to your tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: 'class', // Enable class-based dark mode
content: [
'./src/**/*.{js,ts,jsx,tsx,vue,svelte}',
// Include Tark UI components if in separate directory
],
theme: {
extend: {
// Tark UI uses CSS custom properties for theming
// These are defined in your global CSS (shown next)
},
},
plugins: [],
}
Global CSS Setup
Create your theme variables in globals.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
/* Light mode color scale */
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5.9% 10%;
--radius: 0.5rem;
}
.dark {
/* Dark mode color scale */
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
}
}
Adopting Your First Component
Browse the Tark UI GitHub repository, find your component, and copy its source into your project. Each component lives in a self-contained file with clear dependencies.
REAL Code Examples From Tark UI
Let's examine actual implementation patterns from the Tark UI repository. These aren't toy examples—they're production code you can adapt immediately.
Example 1: Button Component with Variants
The Button component demonstrates Tark UI's variant system using cva (class-variance-authority) for type-safe styling:
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils' // Tailwind class merging utility
// Define variant configurations with strict type safety
const buttonVariants = cva(
// Base styles applied to all button variants
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
// Visual style variants
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
// Size variants for different contexts
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 rounded-md px-3',
lg: 'h-11 rounded-md px-8',
icon: 'h-10 w-10', // Square buttons for icon-only usage
},
},
// Default fallback values when props aren't specified
defaultVariants: {
variant: 'default',
size: 'default',
},
}
)
// Extract variant prop types from cva configuration
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
// Forward ref for proper DOM access and accessibility
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, ...props }, ref) => {
return (
<button
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = 'Button'
export { Button, buttonVariants }
What's happening here? The cva function creates type-safe variant mappings that Tailwind can optimize at build time. No runtime style computation. The cn() utility (typically clsx + tailwind-merge) prevents class conflicts when consumers override styles. Notice how CSS custom properties (bg-primary, text-primary-foreground) enable instant theming without JavaScript intervention.
Example 2: Dialog with Ark UI's State Machine
Dialogs are notoriously complex—focus trapping, scroll locking, escape handling. Tark UI delegates this to Ark UI's battle-tested state machine:
import * as Dialog from '@ark-ui/react/dialog'
import { X } from 'lucide-react' // Icon system
import { cn } from '@/lib/utils'
const DialogDemo = () => {
return (
// Dialog.Root manages open/close state and focus trapping
<Dialog.Root>
{/* Trigger renders as any element; asChild pattern preserves your markup */}
<Dialog.Trigger asChild>
<Button variant="outline">Edit Profile</Button>
</Dialog.Trigger>
{/* Portal ensures dialog renders outside normal DOM hierarchy */}
<Dialog.Portal>
{/* Backdrop with fade animation via Tailwind */}
<Dialog.Backdrop
className={cn(
'fixed inset-0 z-50 bg-black/80',
'data-[state=open]:animate-in data-[state=closed]:animate-out',
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0'
)}
/>
{/* Positioned content container */}
<Dialog.Positioner className="fixed inset-0 z-50 flex items-center justify-center p-4">
<Dialog.Content
className={cn(
'relative w-full max-w-lg rounded-lg border bg-background p-6 shadow-lg',
'data-[state=open]:animate-in data-[state=closed]:animate-out',
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
'data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]',
'data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]'
)}
>
{/* Accessible title (required for screen readers) */}
<Dialog.Title className="text-lg font-semibold leading-none tracking-tight">
Edit Profile
</Dialog.Title>
{/* Description provides context for assistive technologies */}
<Dialog.Description className="text-sm text-muted-foreground mt-2">
Make changes to your profile here. Click save when you're done.
</Dialog.Description>
{/* Custom content area */}
<div className="grid gap-4 py-4">
{/* Form fields would live here */}
</div>
{/* Close button with automatic focus management */}
<Dialog.CloseTrigger asChild>
<Button
variant="outline"
size="icon"
className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100"
>
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</Button>
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Portal>
</Dialog.Root>
)
}
The magic: Ark UI's Dialog.Root handles focus trapping, Escape key dismissal, scroll locking, and ARIA attributes automatically. The data-[state=open] selectors hook into Ark's state machine for CSS-driven animations—no JavaScript animation libraries required. This pattern repeats across all Tark UI components: behavior from Ark, presentation from Tailwind, composition from your code.
Example 3: Dark Mode Toggle Implementation
Tark UI's dark mode is remarkably simple—no context providers, no JavaScript state:
import { Moon, Sun } from 'lucide-react'
import { Button } from '@/components/ui/button'
const ThemeToggle = () => {
const toggleTheme = () => {
// Direct DOM manipulation—no React state needed
const root = window.document.documentElement
root.classList.toggle('dark')
// Optional: persist preference
const isDark = root.classList.contains('dark')
localStorage.setItem('theme', isDark ? 'dark' : 'light')
}
// Initialize from localStorage or system preference
React.useEffect(() => {
const root = window.document.documentElement
const saved = localStorage.getItem('theme')
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
if (saved === 'dark' || (!saved && systemPrefersDark)) {
root.classList.add('dark')
}
}, [])
return (
<Button variant="ghost" size="icon" onClick={toggleTheme}>
{/* Sun icon visible in dark mode */}
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
{/* Moon icon visible in light mode */}
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
)
}
Why this matters: The dark: Tailwind modifier responds instantly to the .dark class. No flash of wrong-theme content. No hydration mismatches. The icon animation uses CSS transforms—GPU-accelerated, 60fps, zero layout thrashing.
Advanced Usage & Best Practices
Component Composition Patterns
Tark UI components use the "asChild" pattern extensively. This lets you swap the rendered element without losing behavior:
{/* Renders as <a> with Button styling and Dialog behavior */}
<Dialog.Trigger asChild>
<a href="/profile">View Profile</a>
</Dialog.Trigger>
Customizing Without Forking
Since you own the source, extend components directly:
// Add your brand's loading spinner to Button
const LoadingButton = ({ isLoading, children, ...props }) => (
<Button disabled={isLoading} {...props}>
{isLoading && <Spinner className="mr-2 h-4 w-4 animate-spin" />}
{children}
</Button>
)
Bundle Optimization
Import only used Lucide icons (not the entire library):
// ✅ Tree-shakeable: only this icon included
import { ChevronDown } from 'lucide-react'
// ❌ Avoid: imports all 1000+ icons
import * as Icons from 'lucide-react'
Server Component Compatibility
Tark UI's CSS-custom-property theming works flawlessly with React Server Components. No "use client" directives needed for theme switching—it's pure CSS.
Comparison With Alternatives
| Feature | Tark UI | shadcn/ui | Material UI | Chakra UI |
|---|---|---|---|---|
| Framework Support | React, Vue, Solid, Svelte | React only | React only | React only |
| Styling Approach | Tailwind CSS | Tailwind CSS | Emotion/CSS-in-JS | Emotion/CSS-in-JS |
| Dependency Model | Copy-paste (zero deps) | Copy-paste (zero deps) | npm install (heavy) | npm install (heavy) |
| State Management | Ark UI state machines | Radix UI primitives | Custom | Custom |
| Bundle Size | Minimal (use only what you copy) | Minimal | ~300KB+ | ~250KB+ |
| Dark Mode | CSS-only toggle | CSS-only toggle | JavaScript context | JavaScript context |
| Customization | Full source ownership | Full source ownership | Theme overrides | Style props |
| Type Safety | Strict (cva variants) | Strict (cva variants) | Good | Good |
| Accessibility | WCAG 2.1 (Ark UI) | WCAG 2.1 (Radix) | Good | Good |
The verdict: Choose Tark UI when you need framework portability or anticipate stack changes. Choose shadcn/ui for React-only projects with its larger ecosystem. Avoid Material UI and Chakra UI for new projects unless you're locked into their design systems—the bundle tax is real.
FAQ: Your Burning Questions Answered
Is Tark UI free for commercial use?
Yes. Tark UI is open-source under the MIT license. Use it in personal projects, client work, or commercial products without attribution requirements.
How do I update Tark UI components?
Since components live in your codebase, updates are manual and intentional. Check the GitHub repository for changes, then selectively merge improvements. This prevents surprise breaking changes from automatic updates.
Can I use Tark UI with CSS Modules or styled-components?
Technically yes, but you'd lose the primary benefits. Tark UI is optimized for Tailwind's utility-first workflow. Converting to other styling systems requires significant rework.
Does Tark UI support React Server Components?
Absolutely. The CSS-custom-property theming requires no client-side JavaScript. Components using Ark UI's interactive primitives (dialogs, dropdowns) need the "use client" directive, but presentational components work server-side.
How does Tark UI handle form validation?
Tark UI provides accessible form components (inputs, selects, checkboxes) styled consistently. For validation logic, integrate with your preferred library: React Hook Form, Formik, or native HTML5 validation. The components expose standard ref and event props for seamless integration.
What's the browser support?
Tark UI targets modern evergreen browsers. Ark UI's state machines require JavaScript, so progressive enhancement without JS isn't supported. For IE11 or legacy environments, you'll need polyfills or alternative solutions.
Is there a Figma/Sketch design kit?
Not officially yet, but the Tailwind color tokens map cleanly to design system tools. Community contributions are welcome on the GitHub repository.
Conclusion: The Future Is Framework-Agnostic
Here's what I've learned after fifteen years of frontend development↗ Bright Coding Blog: frameworks are temporary, components are eternal. React will evolve. Vue will reimagine itself. The Next Big Framework™ will arrive, breathlessly promoted at conferences. But a well-designed button? A properly trapped-focus dialog? These primitives transcend the hype cycle.
Tark UI understands this. By building on Ark UI's state machines and Tailwind's styling engine, it creates components that outlive any single framework's popularity. The copy-paste model gives you ownership without overhead. The zero-dependency architecture keeps your bundle lean and your upgrades predictable.
Is it perfect? No. The manual update process demands discipline. The framework-agnostic promise requires Ark UI to maintain parity across React, Vue, Solid, and Svelte—an ambitious engineering challenge. But the direction is unmistakably correct.
If you're starting a new project, migrating a legacy app, or simply exhausted from rebuilding the same dropdown for the fifth time, give Tark UI a serious look. Clone the repository, copy a component, feel the difference of truly owning your UI layer.
The best component library isn't the one you install. It's the one you never have to replace.
Have you tried Tark UI? What framework-agnostic tools are you excited about? Drop your thoughts below—let's debate the future of component architecture.