Ninna UI - Full Component API Source Reference
This document contains the unminified TypeScript Implementation and Styling layer of all Ninna UI components. It is explicitly designed for LLMs to read and instantly understand the current API boundaries, DOM structures, and prop-types of the design system.
======================================================
View Category: blocks
======================================================
### File: app/views/blocks/BlockCard.tsx
```tsx
import { Link } from "react-router";
import { ArrowRight } from "lucide-react";
import { Skeleton } from "@ninna-ui/feedback";
import type { BlockMeta } from "./registry";
// ─── Per-slug realistic skeleton previews ───────────────────────────────────
function DashboardSkeleton() {
return (
{/* Copy when in code view */}
{sourceCode && view === "code" && (
)}
{/* Divider */}
{/* Open in new tab */}
Raw View
{/* ── Content ── */}
{view === "code" ? (
💡
Note on Icons: The source code below uses lucide-react for iconography. We recommend installing it via npm i lucide-react, or you can easily swap them out for your own SVGs.
{/* Code toolbar */}
{meta.slug}.tsx
{sourceCode && }
{/* Content */}
{isLoading ? (
Loading source code...
) : sourceCode ? (
{sourceCode.split("\n").map((line, i) => (
{line || " "}
))}
) : (
No source code available for this block.
)}
) : (
{/* Viewport feedback (visible when width is not 100%) */}
{width !== "100%" && (
All {totalCount} blocks free during launch - no account required in 2026
Production-Ready UI Blocks
Beautiful, responsive UI blocks built entirely with Ninna UI. Copy, paste,
and make them your own. Works with Next.js, Vite, and React Router.
{/* ── How it works ── */}
{[
{ icon: MousePointerClick, title: "1. Browse", desc: "Find the block you need from our curated collection." },
{ icon: Copy, title: "2. Copy", desc: "Click the copy button to grab the full source code." },
{ icon: Paintbrush, title: "3. Customize", desc: "Paste into your project and customize with Tailwind CSS." },
].map((step) => (
);
}
```
### File: app/views/blocks/article-page/ArticlePage.tsx
```tsx
import { Heading, Text, Badge, Avatar, Link } from "@ninna-ui/primitives";
import { VStack, HStack, Container, Box, Separator } from "@ninna-ui/layout";
import { Card } from "@ninna-ui/data-display";
import {
Clock,
Calendar,
ArrowLeft,
ArrowRight,
Twitter,
Github,
Bookmark,
Share2,
ThumbsUp,
MessageSquare,
ChevronRight,
} from "lucide-react";
const ARTICLE = {
title: "Building Accessible Design Systems with Radix UI and Tailwind CSS v4",
subtitle:
"A deep dive into combining Radix UI primitives with Tailwind CSS v4 to create accessible, themeable component libraries that scale across teams and products.",
author: {
name: "Alex Rivera",
role: "Lead Engineer, Ninna UI",
bio: "Full-stack developer with 8 years of experience building design systems and component libraries for startups and Fortune 500 companies.",
},
date: "March 18, 2026",
readTime: "8 min read",
tags: ["Engineering", "Accessibility", "Design Systems"],
likes: 142,
comments: 23,
};
const TOC = [
{ id: "intro", label: "Introduction", level: 1 },
{ id: "radix", label: "Why Radix UI Primitives", level: 1 },
{ id: "radix-aria", label: "WAI-ARIA built-in", level: 2 },
{ id: "radix-keyboard", label: "Keyboard navigation", level: 2 },
{ id: "tailwind", label: "Tailwind CSS v4 Integration", level: 1 },
{ id: "tailwind-theme", label: "CSS-first @theme config", level: 2 },
{ id: "tailwind-slots", label: "Data-slot targeting", level: 2 },
{ id: "theming", label: "Zero-Runtime Theming", level: 1 },
{ id: "contrast", label: "oklch and Contrast", level: 1 },
{ id: "conclusion", label: "Conclusion", level: 1 },
];
const RELATED = [
{
title: "Zero Runtime Theming: How CSS Custom Properties Replace JavaScript",
date: "Mar 15, 2026",
readTime: "6 min",
tag: "Design",
tagColor: "secondary" as const,
},
{
title: "From shadcn to npm: Why We Ship as a Library",
date: "Mar 12, 2026",
readTime: "5 min",
tag: "Opinion",
tagColor: "accent" as const,
},
{
title: "Tailwind CSS v4 Migration Guide for Component Libraries",
date: "Mar 10, 2026",
readTime: "12 min",
tag: "Tutorial",
tagColor: "info" as const,
},
];
export function ArticlePage() {
return (
{/* Scroll Progress Indicator */}
{/* Hero */}
Back to Blog
{ARTICLE.tags.map((tag) => (
{tag}
))}
{ARTICLE.title}
{ARTICLE.subtitle}
{ARTICLE.author.name}{ARTICLE.author.role}{ARTICLE.date}{ARTICLE.readTime}
{/* Content grid */}
{/* Article body */}
{/* Action bar */}
{/* Article prose content */}
Introduction
Building a production-ready design system is one of the most impactful investments a team can make.
When done right, it accelerates development, enforces consistency, and makes accessibility a default
rather than an afterthought. In this article, we explore how combining Radix UI primitives with
Tailwind CSS v4 creates a powerful foundation for exactly that.
Why Radix UI Primitives
Radix UI provides unstyled, accessible primitives for the hardest parts of the UI: dialogs, dropdowns,
tooltips, and more. These primitives handle the behavior - including focus trapping, keyboard
navigation, screen reader announcements, and ARIA attributes - so you can focus on the look.
"The hardest part of building accessible UI is not knowing what you don't know. Radix solves this
by making accessibility the default, not the exception."
- Ninna UI TeamWAI-ARIA built-in
Every Radix primitive ships with the correct WAI-ARIA roles, states, and properties. A Dialog
automatically manages aria-modal, aria-labelledby,
and aria-describedby. A DropdownMenu manages aria-expanded and
synchronizes focus when opened or closed.
Keyboard navigation
Arrow key navigation, Home/End keys, typeahead search in menus - all handled without a single line
of custom event listener code. This matters because keyboard navigation is the primary interface for
many users with motor disabilities.
Tailwind CSS v4 Integration
Tailwind CSS v4 introduces a CSS-first configuration model that is a perfect match for component
libraries. The @theme directive lets you define design tokens in CSS,
and @source lets libraries safeload their own utility classes
without requiring the consumer to configure anything.
Zero-Runtime Theming
Unlike CSS-in-JS solutions, Ninna UI themes are pure CSS files. Switching themes requires nothing
more than swapping a <link> tag. No JavaScript bundles. No
hydration cost. No flash of unstyled content. The browser does all the work.
Conclusion
The combination of Radix UI primitives, Tailwind CSS v4, and CSS custom properties gives you the
trifecta: accessibility by default, styling flexibility, and zero runtime overhead. This is the
stack we chose for Ninna UI, and we haven't looked back.
{/* Author bio */}
{ARTICLE.author.name}{ARTICLE.author.role}
{ARTICLE.author.bio}
{/* Next/Prev navigation */}
{/* Sidebar - Table of Contents */}
);
}
```
### File: app/views/blocks/authentication-login/AuthenticationLogin.tsx
```tsx
import { useState } from "react";
import { Button, Heading, Text, Link as NinnaLink, IconButton } from "@ninna-ui/primitives";
import { Input, InputGroup, Field, Checkbox } from "@ninna-ui/forms";
import { VStack, HStack, Center, Separator } from "@ninna-ui/layout";
import { Mail, Lock, Github, Eye, EyeOff } from "lucide-react";
export function AuthenticationLogin() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [remember, setRemember] = useState(false);
return (
{/* Verify button */}
{/* Back link */}
Back to sign in
{/* Help text */}
);
}
```
### File: app/views/blocks/authentication-reset-password/AuthenticationResetPassword.tsx
```tsx
import { useState } from "react";
import { Button, Heading, Text, Link as NinnaLink } from "@ninna-ui/primitives";
import { Input, InputGroup, Field } from "@ninna-ui/forms";
import { VStack, Center } from "@ninna-ui/layout";
import { Alert } from "@ninna-ui/feedback";
import { Stepper } from "@ninna-ui/navigation";
import { Mail, Lock, ArrowLeft, ArrowRight, KeyRound, CheckCircle2 } from "lucide-react";
export function AuthenticationResetPassword() {
const [step, setStep] = useState(0);
const [email, setEmail] = useState("");
const [code, setCode] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
return (
{/* Logo */}
Reset your password
{step === 0 && "Enter the email address associated with your account."}
{step === 1 && "We sent a 6-digit code to your email."}
{step === 2 && "Choose a new password for your account."}
{/* Changes list */}
{release.changes.map((change, ci) => (
{/* Icon component logic should ideally be outside map but keeping it simple for now as per original */}
{change.type === "added" && }
{change.type === "changed" && }
{change.type === "fixed" && }
{change.type === "removed" && }
{CHANGE_CONFIG[change.type].label}
{change.text}
System StatusNinna Cloud Infrastructure
{/* Main Status Banner */}
}
className="rounded-2xl p-6 border-warning/20 border-2"
>
We are experiencing increased latency in our Europe (Frankfurt) region affecting the Primary Database. Our engineers are investigating the root cause.
{/* Stats Grid */}
Global Uptime99.98% Within SLA
Avg. Latency42ms
+12% vs last 24h
Requests / Sec12.4k
Peak: 18.2k
Security Probes0
All systems secure
{/* Services Grid */}
Core Services
{SERVICES.map((service) => (
{service.icon}
{service.status}
{service.name}Uptime{service.uptime}Latency{service.latency}
{/* Simulated Uptime Bar Graph */}
{BAR_HEIGHTS.map((h, i) => (
))}
))}
{/* Regional Status Section */}
Incident History
{[
{ date: "April 10, 2026", title: "API Latency in eu-central-1", desc: "Resolved - The issue was caused by an upstream provider and has been fully mitigated.", status: "resolved" },
{ date: "April 08, 2026", title: "Scheduled Maintenance: Auth DB", desc: "Completed - All database clusters have been updated to v5.4. No downtime was observed.", status: "completed" },
{ date: "April 05, 2026", title: "CDN Cache Invalidation Delay", desc: "Resolved - Purge requests were queuing up during peak traffic. Capacity has been tripled.", status: "resolved" },
].map((incident, i) => (
{incident.date}{incident.title}{incident.desc}
))}
Regional Health
{REGIONS.map((region) => (
{region.name}{region.id}-1
))}
);
}
```
### File: app/views/blocks/contact-form/ContactForm.tsx
```tsx
import { useState } from "react";
import { Button, Heading, Text } from "@ninna-ui/primitives";
import { Input, InputGroup, Field, Textarea, Select, SelectItem } from "@ninna-ui/forms";
import { Alert } from "@ninna-ui/feedback";
import { VStack, HStack, Container, Box } from "@ninna-ui/layout";
import { Mail, User, Phone, Send, CheckCircle, MapPin, Clock } from "lucide-react";
const CONTACT_INFO = [
{ icon: Mail, label: "Email", value: "hello@ninna-ui.dev" },
{ icon: MapPin, label: "Address", value: "123 Component Lane, React City" },
{ icon: Clock, label: "Hours", value: "Mon-Fri, 9am-5pm UTC" },
];
export function ContactForm() {
const [submitted, setSubmitted] = useState(false);
return (
Get in touch
Have a question or want to work together? Fill out the form below and we'll get back to you within 24 hours.
{/* Contact info sidebar */}
{CONTACT_INFO.map((item) => (
{item.label}{item.value}
))}
{/* Form */}
{submitted ? (
Message sent!
Thank you for reaching out. Our team will review your message and get back to you shortly.
) : (
)}
);
}
```
### File: app/views/blocks/cookie-consent/CookieConsent.tsx
```tsx
import { useState } from "react";
import { Button, Heading, Text, Badge, IconButton } from "@ninna-ui/primitives";
import { VStack, HStack, Box } from "@ninna-ui/layout";
import { Checkbox } from "@ninna-ui/forms";
import { Cookie, ShieldCheck, X, Settings } from "lucide-react";
export function CookieConsent() {
const [isOpen, setIsOpen] = useState(true);
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
if (!isOpen) return null;
return (
{!isSettingsOpen ? (
/* Minimal Banner */
We value your privacy
We use cookies to enhance your browsing experience, provide secure login, and analyze our traffic. By clicking "Accept All", you consent to our use of these technologies.
) : (
/* Detailed Settings Panel */
Cookie PreferencesManage your privacy settings
setIsSettingsOpen(false)}
icon={}
aria-label="Close settings"
/>
{[
{ id: "necessary", title: "Strictly Necessary", desc: "Required for the website to function properly. Includes security and language preferences.", checked: true, disabled: true },
{ id: "analytics", title: "Performance & Analytics", desc: "Allows us to count visits and traffic sources so we can measure and improve performance.", checked: true, disabled: false },
{ id: "marketing", title: "Targeting & Marketing", desc: "May be set through our site by our advertising partners to build a profile of your interests.", checked: false, disabled: false },
].map((item) => (
{item.desc}
))}
Ninna Privacy Standard
)}
);
}
```
### File: app/views/blocks/cta-banner/CtaBanner.tsx
```tsx
import { Heading, Text, Button } from "@ninna-ui/primitives";
import { Container, HStack } from "@ninna-ui/layout";
import { ArrowRight, Sparkles, Zap } from "lucide-react";
export function CtaBanner() {
return (
{/* Background Decorative Elements */}
Limited time offer
Ready to build something extraordinary?
Join 12,000+ developers who are building high-performance, beautiful user interfaces in record time. Grab Ninna UI today and unlock the launch pricing.
{user.name}{user.email}
{/* Role */}
{role.label}
{/* Status */}
{status.label}
{/* Joined */}
{formatDate(user.joined)}
{/* Last Active */}
{user.lastActive}
{/* Actions */}
}
aria-label={`Edit ${user.name}`}
className="text-base-content/40 hover:text-primary hover:bg-primary/10 transition-all rounded-md"
/>
}
aria-label={`More options for ${user.name}`}
className="text-base-content/40 hover:text-base-content hover:bg-base-200 transition-all rounded-md"
/>
);
})
)}
{/* ── Pagination ── */}
{totalPages > 0 && (
)}
);
}
```
### File: app/views/blocks/empty-state-showcase/EmptyStateShowcase.tsx
```tsx
import { Heading, Text, Button, Badge } from "@ninna-ui/primitives";
import { Container, SimpleGrid, VStack, Box } from "@ninna-ui/layout";
import { Search, MailOpen, AlertCircle, Plus, RefreshCcw, Home } from "lucide-react";
export function EmptyStateShowcase() {
return (
Empty States
Empty state patterns
Well-designed empty states guide users toward action when there's no data to show. Here are four common scenarios.
{/* No search results */}
No results found
We couldn't find anything matching your search. Try different keywords or clear your filters.
{/* Empty inbox */}
All caught up!
Your inbox is empty. New messages and notifications will appear here when they arrive.
{/* Access denied */}
Access restricted
You don't have permission to view this content. Contact your admin to request access.
{/* Empty project / create first item */}
Create your first project
Click to get started
);
}
```
### File: app/views/blocks/error-403/Error403.tsx
```tsx
import { Button, Heading, Text } from "@ninna-ui/primitives";
import { VStack, HStack, Center } from "@ninna-ui/layout";
import { Home, ArrowLeft, ShieldX, LogIn } from "lucide-react";
export function Error403() {
return (
{/* Premium 4 icon 3 layout */}
4
{/* Decorative rings for security feel */}
3
Oops! Access Denied
You don't have the permission to view this page. Please contact your administrator or try a different account.
);
}
```
### File: app/views/blocks/error-500/Error500.tsx
```tsx
import { Button, Heading, Text } from "@ninna-ui/primitives";
import { VStack, HStack, Center } from "@ninna-ui/layout";
import { Alert } from "@ninna-ui/feedback";
import { Home, RefreshCw, AlertTriangle, Headphones } from "lucide-react";
export function Error500() {
return (
{/* Premium 5 icon 0 layout */}
5
{/* Pulsing error effect */}
0
Server Error
Something went wrong on our end. We've been notified and are working to fix it as quickly as possible.
An unexpected error occurred while processing your request. Our engineering team is looking into it. (Error Code: ERR_SRV_500)
Still having issues?
);
}
```
### File: app/views/blocks/faq-accordion/FaqAccordion.tsx
```tsx
import { Heading, Text, Badge } from "@ninna-ui/primitives";
import { Accordion } from "@ninna-ui/navigation";
import { VStack, Container } from "@ninna-ui/layout";
const FAQ_ITEMS = [
{
question: "What is Ninna UI?",
answer: "Ninna UI is a production-ready React component library with 69 accessible components, 5 theme presets, and zero runtime theming. It uses pure CSS custom properties with oklch perceptual colors for guaranteed WCAG AA contrast.",
},
{
question: "How does zero runtime theming work?",
answer: "Instead of using JavaScript context providers or runtime CSS-in-JS, Ninna UI themes are pure CSS files that define custom properties. You switch your entire design system with one CSS import - no ThemeProvider, no hydration cost, no layout shift.",
},
{
question: "Which frameworks are supported?",
answer: "Ninna UI works with any React framework. We provide first-class setup guides for Vite, Next.js (App Router), and React Router v7. The CLI scaffolds complete starter projects for all three.",
},
{
question: "Can I customize the theme?",
answer: "Absolutely. Ninna UI ships with 5 presets (Default, Ocean, Sunset, Forest, Minimal), and you can create your own by overriding CSS custom properties. Every component exposes data-slot attributes for targeted CSS styling without !important hacks.",
},
{
question: "Is Ninna UI accessible?",
answer: "Yes. All interactive components are built on Radix UI primitives with full WAI-ARIA support, keyboard navigation, and focus management. We run automated vitest-axe audits across 700+ tests to catch regressions.",
},
{
question: "How does Ninna UI compare to shadcn/ui?",
answer: "shadcn/ui copies component source into your project; Ninna UI is a proper npm library with tree-shakeable packages. You get consistent updates, no copy-paste drift, and a CLI that scaffolds complete projects - not just individual components.",
},
{
question: "Do I need Tailwind CSS?",
answer: "Yes, Ninna UI is built natively for Tailwind CSS v4. Components use Tailwind utility classes internally, and theme presets integrate with Tailwind's @theme directive. No tailwind.config.ts is needed - everything is CSS-first.",
},
{
question: "Is it free and open source?",
answer: "Yes. Ninna UI is 100% open source under the MIT license. You can use it in personal and commercial projects without restrictions.",
},
];
export function FaqAccordion() {
return (
FAQ
Frequently asked questions
Everything you need to know about Ninna UI. Can't find what you're looking for? Reach out on GitHub Discussions.
);
}
```
### File: app/views/blocks/hero-header/HeroHeader.tsx
```tsx
import { Button, Heading, Text, Badge } from "@ninna-ui/primitives";
import { VStack, Container } from "@ninna-ui/layout";
import { ArrowRight, Play } from "lucide-react";
const STATS = [
{ value: "69+", label: "Components" },
{ value: "5", label: "Theme Presets" },
{ value: "12", label: "Packages" },
{ value: "AA", label: "WCAG" },
];
export function HeroHeader() {
return (
{/* Dynamic gradient background */}
{/* Announcement */}
Introducing Ninna UI v1.0 - 69 Components
{/* Headline */}
Build beautiful React apps{" "}
10x faster
{/* Subheadline */}
A production-ready component library with zero runtime theming,
native Tailwind CSS v4 support, and full accessibility built in.
One CSS import - instant design system.
{/* CTAs */}
{/* Stats row */}
{STATS.map((stat) => (
{stat.value}
{stat.label}
))}
{/* Trust line */}
Open source · MIT License · React 19 · TypeScript strict · Tailwind CSS v4
);
}
```
### File: app/views/blocks/hero-video-background/HeroVideoBackground.tsx
```tsx
import { Heading, Text, Button, Badge } from "@ninna-ui/primitives";
import { HStack, VStack, Box, Container } from "@ninna-ui/layout";
import { Play, ArrowRight, Star, ShieldCheck, Globe, Zap, MousePointer2 } from "lucide-react";
export function HeroVideoBackground() {
return (
{/* Video Background Layer */}
{/* Placeholder for video - in production use a
{/* Floating Elements Background */}
{[1, 2, 3, 4, 5].map(i => )}
5.0 App Rating
Intelligence Reimagined
Build the impossible with Ninna.
The only component library designed for high-performance AI applications.
Interactive, accessible, and ready for your next big breakthrough.
{/* Scroll Indicator */}
Scroll
);
}
```
### File: app/views/blocks/landing-hero-split/LandingHeroSplit.tsx
```tsx
import { Heading, Text, Button, Badge } from "@ninna-ui/primitives";
import { Container, HStack, VStack, Box } from "@ninna-ui/layout";
import { CodeBlock } from "@ninna-ui/code-block";
import { ArrowRight, Play, CheckCircle2, Star, Zap } from "lucide-react";
export function LandingHeroSplit() {
const exampleCode = `import { Button, Badge } from "@ninna-ui/primitives";
import { Box, HStack } from "@ninna-ui/layout";
export function Welcome() {
return (
New Release
);
}`;
return (
V5.0 is now live
The modern UI toolkit for high-growth teams.
Beautifully designed, accessible, and fully typed components that help you build production-ready interfaces in record time. Built with React 19 and Tailwind CSS v4.
Scheduled Maintenance
We'll be back soon
We're performing scheduled maintenance to improve performance and reliability. We expect to be back online shortly.
{/* Progress */}
Upgrade progress75%
Estimated completion: ~30 minutes
{/* Status updates */}
Status Updates
{STATUS_UPDATES.map((update, i) => (
{update.message}{update.time}
))}
{/* Notification signup */}
Get notified when we're back online:
{subscribed ? (
We'll notify you at {email}
) : (
)}
Follow{" "}
@ninna_ui
{" "}on X for real-time updates
Stay in the loop
Get the latest from our blog
Weekly insights on design systems, React patterns, accessibility best practices, and Tailwind CSS tips - delivered straight to your inbox.
{/* Subscribe form */}
{status === "success" ? (
You're subscribed! Check {email} for a confirmation link.
What clients say about our impact.
We believe in long-term partnerships that drive real business results through thoughtful design and engineering excellence.
Notifications
Choose what notifications you receive.
Email notificationsReceive updates via email.Push notificationsBrowser push notifications for real-time alerts.Weekly digestSummary of activity sent every Monday.Mentions & repliesWhen someone mentions you or replies to your comments.
);
}
function SecuritySection() {
return (
Security
Manage your password and security settings.
Two-factor authenticationRecommendedAdd an extra layer of security to your account.
);
}
const SETTINGS_TABS = [
{ value: "profile", label: "Profile", icon: Globe },
{ value: "notifications", label: "Notifications", icon: Bell },
{ value: "security", label: "Security", icon: Shield },
{ value: "appearance", label: "Appearance", icon: Palette },
];
export function SettingsPage() {
return (
Settings
Manage your account settings and preferences.
Growth Metrics
Numbers that speak for themselves
We've empowered thousands of developers to build faster, more reliable, and visually stunning web applications.
{FEATURES.map((f) => (
{f.value}
{f.label}
))}
{STATS.map((s, idx) => (
{s.trend}
{s.value}
{s.label}
))}
);
}
```
### File: app/views/blocks/team-grid/TeamGrid.tsx
```tsx
import { Heading, Text, Avatar, Badge, IconButton } from "@ninna-ui/primitives";
import { Container, Grid, VStack, HStack } from "@ninna-ui/layout";
import { Tooltip } from "@ninna-ui/overlays";
import { Twitter, Linkedin, Github, Mail, ExternalLink } from "lucide-react";
const TEAM = [
{
name: "Elena Rodriguez",
role: "CEO & Founder",
bio: "Visionary leader with 10+ years experience in the design systems space.",
avatar: "ER",
socials: { twitter: "#", linkedin: "#", github: "#" },
},
{
name: "James Wilson",
role: "Lead UI Designer",
bio: "Crafting beautiful and functional interfaces with a focus on minimalism.",
avatar: "JW",
socials: { twitter: "#", github: "#", linkedin: "#" },
},
{
name: "Aisha Kamau",
role: "Senior Frontend Engineer",
bio: "Accessibility advocate and expert in React performance optimization.",
avatar: "AK",
socials: { mail: "#", github: "#", twitter: "#" },
},
{
name: "Liam O'Connor",
role: "Fullstack Developer",
bio: "Specializing in scalable cloud architectures and developer tooling.",
avatar: "LO",
socials: { github: "#", linkedin: "#", mail: "#" },
},
];
export function TeamGrid() {
return (
The Dream Team
Meet the minds behind Ninna UI
The small, dedicated group of designers and engineers working to build the future of the web.
{TEAM.map((member, idx) => (
);
}
```
### File: app/views/blocks/timeline-activity/TimelineActivity.tsx
```tsx
import { Heading, Text, Badge, Avatar, Button } from "@ninna-ui/primitives";
import { Container, VStack, HStack, Box } from "@ninna-ui/layout";
import { Timeline, Card } from "@ninna-ui/data-display";
import { CheckCircle2, MessageSquare, UserPlus, GitMerge, FileText, ChevronRight } from "lucide-react";
export function TimelineActivity() {
return (
Activity Feed
Tracking real-time workspace updates
24 New Events
Design System V5.0 Published1h ago
The latest iteration of the core component library is now live on npm. Includes full support for Tailwind CSS v4 and React 19. All 69 components have been verified for accessibility.
Release ManagerMerged by Alex Rivera
{PINNED_REPOS.length} public repositories
{PINNED_REPOS.map((repo) => (
{
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
// open repo
}
}}
>
{repo.name}
Public
{repo.description}
{repo.language}{repo.stars.toLocaleString()}{repo.forks}
))}
{ACTIVITY.map((item, i) => (
{item.repo}{" "}
- {item.message}
{item.time}
))}
{PINNED_REPOS.slice(0, 3).map((repo) => (
{USER.username}/{repo.name}
{repo.description}
))}
);
}
```
======================================================
View Category: compare
======================================================
### File: app/views/compare/AlternativeView.tsx
```tsx
import { Link } from "react-router";
import { Heading, Text, Badge } from "@ninna-ui/primitives";
import { VStack, Container, Separator } from "@ninna-ui/layout";
import { ArrowRight, Check, ChevronRight, ExternalLink } from "lucide-react";
import type { CompetitorData } from "./comparison-registry";
import { COMPETITORS } from "./comparison-registry";
import { buildBreadcrumbJsonLd } from "~/utils/structuredData";
export function AlternativeView({ data }: { data: CompetitorData }) {
const alt = data.alternative;
const breadcrumbJsonLd = buildBreadcrumbJsonLd([
{ name: "Home", path: "/" },
{ name: "Alternative", path: "/compare" },
{ name: `${data.name} Alternative`, path: `/alternative/${data.slug}` },
]);
return (
{/* Hero */}
Alternative
Ninna UI - A Better {data.name} Alternative
{alt.headline}
{/* Summary */}
{alt.summary}
{/* Why developers switch */}
Why developers switch from {data.name}
Common reasons developers move from {data.name} to Ninna UI:
{alt.whySwitch.map((reason, i) => (
{reason}
))}
{/* Quick stats */}
At a glance
69Ninna UI components
5Theme presets included
0JS theming runtime
{/* Detailed comparison link */}
Want a detailed comparison?
See a side-by-side feature table, honest trade-offs, and a step-by-step migration guide.
{data.name} vs Ninna UI - Full Comparison
{/* Install CTA */}
Ready to try Ninna UI?
Install in under 60 seconds. One CSS import, zero JavaScript config.
{/* Cross-links to other alternative pages */}
More alternatives
{COMPETITORS.filter((c) => c.slug !== data.slug).map((c) => (
{c.name} Alternative
))}
{/* Disclaimer */}
This page is for informational purposes only. All trademarks, logos, and brand names are the property
of their respective owners. Information is based on official documentation and public data.
Last updated: March 2026.
);
}
```
### File: app/views/compare/CompareHub.tsx
```tsx
import { Link } from "react-router";
import { Heading, Text, Badge } from "@ninna-ui/primitives";
import { VStack, Container, Separator } from "@ninna-ui/layout";
import { ArrowRight, ChevronRight } from "lucide-react";
import { COMPETITORS } from "./comparison-registry";
export function CompareHub() {
return (
{/* Hero */}
Compare
React Component Library Comparisons
Honest, side-by-side comparisons of Ninna UI against popular React UI libraries.
CSS-first theming, Radix accessibility, Tailwind CSS v4 native, and zero runtime overhead.
{/* Compare cards */}
Compare Ninna UI vs popular alternatives
Each comparison covers features, trade-offs, and migration guides.
{COMPETITORS.map((c) => (
{c.name} vs Ninna UI
{c.tagline}
{c.approach}
))}
{/* Alternative pages */}
Looking for an alternative?
Opinionated guides on why developers switch from popular libraries to Ninna UI.
{COMPETITORS.map((c) => (
{c.name} Alternative
))}
{/* Framework landing pages */}
Ninna UI for your framework
Framework-specific setup guides, examples, and install instructions.
{/* CTA */}
Want to see all libraries at once?
Our feature matrix compares Ninna UI against 5 popular alternatives in a single table.
Full Feature Matrix
);
}
```
### File: app/views/compare/CompareView.tsx
```tsx
import { Link } from "react-router";
import { Heading, Text, Badge } from "@ninna-ui/primitives";
import { VStack, HStack, Container, Separator } from "@ninna-ui/layout";
import { ArrowRight, Check, AlertTriangle, ArrowLeftRight, ExternalLink, ChevronRight } from "lucide-react";
import type { CompetitorData } from "./comparison-registry";
import { COMPETITORS } from "./comparison-registry";
import { buildBreadcrumbJsonLd, buildFAQPageJsonLd } from "~/utils/structuredData";
export function CompareView({ data }: { data: CompetitorData }) {
const breadcrumbJsonLd = buildBreadcrumbJsonLd([
{ name: "Home", path: "/" },
{ name: "Compare", path: "/compare" },
{ name: `${data.name} vs Ninna UI`, path: `/compare/${data.slug}-vs-ninna-ui` },
]);
const faqJsonLd = buildFAQPageJsonLd([
{
question: `How does ${data.name} compare to Ninna UI?`,
answer: data.description + " Ninna UI offers CSS-only theming, Radix accessibility, and Tailwind CSS v4 native support.",
},
{
question: `Should I switch from ${data.name} to Ninna UI?`,
answer: data.ninnaAdvantages.join(" "),
},
{
question: `What are ${data.name}'s advantages over Ninna UI?`,
answer: data.competitorAdvantages.join(" "),
},
]);
return (
{/* Hero */}
Comparison
{data.name} vs Ninna UI
{data.tagline}. Compare {data.name} and Ninna UI side by side to find which React component library
fits your project in 2026.
{/* Quick verdict */}
Quick Verdict
{data.name} {data.description.split(". ").slice(0, 2).join(". ")}.{" "}
Ninna UI offers CSS-only theming with zero runtime overhead, Radix-powered
accessibility, Tailwind CSS v4 native support, and oklch perceptual colors - all delivered
as standard npm packages with automatic updates.
{/* Feature comparison table */}
Feature Comparison
Side-by-side comparison of key features between {data.name} and Ninna UI.
Feature
Ninna UI
{data.name}
{data.features.map((row, i) => (
{row.feature}
{row.ninnaUi}
{row.competitor}
))}
{/* Why Ninna UI */}
Why choose Ninna UI
Key advantages of Ninna UI over {data.name} for your next project.
{data.ninnaAdvantages.map((adv, i) => (
{adv}
))}
{/* Honest trade-offs */}
Honest trade-offs
Where {data.name} has advantages - we believe in transparent comparisons.
{data.competitorAdvantages.map((adv, i) => (
{adv}
))}
{/* Migration guide */}
Migrating from {data.name}
Step-by-step guide to move your project from {data.name} to Ninna UI.
{data.migrationSteps.map((step, i) => (
{i + 1}
{step}
))}
{/* Install CTA */}
Ready to try Ninna UI?
Install in under 60 seconds. One CSS import, zero JavaScript config.
{/* Disclaimer */}
This comparison page is for informational purposes only. Information is based on official documentation
and public data. All trademarks, logos, and brand names are the property of their respective owners.
Last updated: March 2026.