A modern, CLI-first Blazor component library inspired by shadcn/ui.
Copy components directly into your project and customize them to match your needs.
New here? Check out the Quick Start section below!
ShellUI transforms Blazor component development with a hybrid approach:
- CLI-First: Copy components to YOUR codebase for full control (
shellui add button) - NuGet Option: Traditional package install for quick starts (
dotnet add package ShellUI.Components) - Choose your workflow: Use CLI for customization, NuGet for speed, or mix both
- Powered by Tailwind CSS v4.1.18 (standalone CLI - no Node.js required!)
- Best of both worlds: flexibility when you need it, convenience when you want it
ShellUI is in alpha! Test and provide feedback before we ship stable. We've completed:
- β
CLI Tool (
dotnet tool install -g ShellUI.CLI) - β
NuGet Package (
dotnet add package ShellUI.Components) - β
68 Installable Components with Tailwind v4.1.18 (top-level components you
shellui addβ sub-components, variants, models, and services auto-install as dependencies) - β Hybrid Workflow (CLI + NuGet)
- β No Node.js Required (Standalone Tailwind CLI)
- β Comprehensive Documentation
- β Working Demos & Examples
Ready to use today! π
# Install CLI globally
dotnet tool install -g ShellUI.CLI
# Initialize in your Blazor project (choose npm or standalone)
shellui init
# For CI/CD or automated environments:
shellui init --yes # Uses standalone Tailwind with default options
# Add components
shellui add button input card dialog
# List all available components
shellui listshellui commands (not dotnet shellui).
ShellUI uses a centralized versioning system where all components, CLI tool, and packages share the same version number. This ensures consistency and simplifies dependency management.
To update ShellUI version across all components:
-
Edit
Directory.Build.propsin the repository root:<ShellUIVersion>0.3.0</ShellUIVersion> <ShellUIVersionSuffix></ShellUIVersionSuffix> <!-- Leave empty for stable releases -->
-
Clean and rebuild all projects:
dotnet clean dotnet build --configuration Release
This single file change updates:
- β
All NuGet packages (
ShellUI.CLI,ShellUI.Components) - β All component templates (68 installable components)
- β Build configurations and metadata
Example for pre-release:
<ShellUIVersion>0.3.0</ShellUIVersion>
<ShellUIVersionSuffix>alpha.2</ShellUIVersionSuffix>Results in version: 0.3.0-alpha.2
By Design: All components share the same version because they:
- Work together as a cohesive system
- Depend on shared utilities and theming
- Follow consistent design patterns
- Are tested together
For Advanced Users: Future versions may support component-specific versioning for power users who need granular control.
Counts below are top-level components you can shellui add directly. Sub-components (e.g. SidebarTrigger, DialogContent, TableRow), variants (ButtonVariants, AlertVariants, β¦), models, and services auto-install as dependencies and are not counted.
Form (17): Button, Checkbox, Combobox, DatePicker, DateRangePicker, FileUpload, Form, Input, InputOTP, Label, RadioGroup, Select, Slider, Switch, Textarea, TimePicker, Toggle
Layout (12): Accordion, Breadcrumb, Card, Collapsible, DashboardLayout01, DashboardLayout02, LinkCard, Navbar, Resizable, ScrollArea, Separator, Sidebar
Navigation (7): ContextMenu, Menubar, NavigationMenu, Pagination, PrevNextNav, Stepper, Tabs
Overlay (8): AlertDialog, Command, Dialog, Drawer, Dropdown, HoverCard, Popover, Sheet
Data Display (13): AreaChart, Avatar, Badge, BarChart, Calendar, Carousel, Chart, ChartSeries, DataTable, LineChart, MultiSeriesChart, PieChart, Table
Feedback (9): Alert, Callout, EmptyState, Loading, Progress, Skeleton, Sonner, Toast, Tooltip
Utility (2): CopyButton, ThemeToggle
Two Setup Methods:
Method 1: Standalone CLI (No Node.js!)
shellui init # Choose "standalone"
# Or: dotnet shellui init- Downloads Tailwind CLI binary automatically
- No Node.js or npm required
- Auto-builds on project compile
Method 2: npm (If you prefer)
shellui init # Choose "npm"
# Or: dotnet shellui init- Installs
tailwindcss@^4.1.18+@tailwindcss/cli@^4.1.18 - Uses
npx @tailwindcss/clifor builds - Requires Node.js
Customize themes instantly with tweakcn:
- Visit tweakcn and design your perfect theme
- Copy the generated CSS variables
- Paste into
wwwroot/input.css - All ShellUI components update automatically!
Custom fonts? Add Google Fonts links and update your CSS variables - works seamlessly! π€
Target: Q1 2026
- More advanced components
- Enhanced DataTable features (sorting/filtering)
- Charts and data visualization
- VirtualScroll for large lists
- PDFViewer component
- And more...
Target: Q2 2026
- Complete documentation website
- Video tutorials
- Migration guides
- Performance optimization
- Testing infrastructure
- Copy, Don't Install: Components are copied to your project, not imported from a package
- Tailwind-First: All styling uses Tailwind CSS v4.1.18 utility classes
- Accessible by Default: WCAG 2.1 AA compliant out of the box
- Composable: Build complex components from simple ones
- Customizable: Modify any component to fit your needs
- Type-Safe: Leverage C# type system for better DX
- Performance: Optimized for both Server and WASM scenarios
- No Node.js Required: Standalone Tailwind CLI for maximum compatibility
CLI Benefits:
- Full control over component code
- Customize without forking
- Only include what you use (smaller bundles)
- No version lock-in
- Better debugging experience
NuGet Benefits:
- Traditional workflow developers know
- Faster initial setup
- Automatic updates via package manager
- Good for prototyping
- Team familiarity
Use both: Start with NuGet, migrate to CLI for components you customize heavily!
- Latest stable version with v4 features
- Better performance than v3
- Improved dark mode support
- Native CSS variable support
- Smaller output CSS
- Standalone CLI (no Node.js required!)
Components/UI/- ShellUI components (Button.razor, Input.razor, Card.razor, ...)Components/UI/Variants/- Variant classes (*Variants.cs)wwwroot/- input.css, app.css (compiled).shellui/bin/- Tailwind CLI binary (standalone)tailwind.config.js,shellui.jsonBuild/ShellUI.targets- MSBuild integration
# Install CLI globally
dotnet tool install -g ShellUI.CLI
# Initialize in your Blazor project (choose npm or standalone)
shellui init
# Or: dotnet shellui init
# Add components
shellui add button input card dialog
# Or: dotnet shellui add button input card dialog
shellui list # See all 68 available components
# Or: dotnet shellui list@page "/example"
<Card>
<CardHeader>
<CardTitle>Welcome to ShellUI</CardTitle>
<CardDescription>Build beautiful Blazor apps</CardDescription>
</CardHeader>
<CardContent>
<Input Placeholder="Enter your email" Type="email" />
<Button Class="mt-4">Subscribe</Button>
</CardContent>
</Card>Simply edit the component file in Components/UI/ - it's yours to modify!
- .NET 8.0 or higher
- Choice of Tailwind setup:
- Standalone CLI (recommended): No Node.js required
- npm: Requires Node.js, uses
tailwindcss@^4.1.18
| Feature | ShellUI | MudBlazor | Radzen | Blazorise |
|---|---|---|---|---|
| CLI Installation | β | β | β | β |
| NuGet Package | β | β | β | β |
| Component Ownership (CLI) | β | β | β | β |
| Tailwind CSS | β (v4.1.18) | β | β | β |
| No Node.js Required | β | N/A | N/A | N/A |
| Hybrid Workflow | β | β | β | β |
| Free & Open Source | β | β | Partial | β |
| Customization | Full | Limited | Limited | Limited |
| Components | 68 | 70+ | 50+ | 80+ |
| Current Status | Production Ready | Mature | Commercial | Mature |
ShellUI ships two NuGet packages β the CLI is the primary install path; the runtime DLL is optional.
| Package | Type | Required? | Purpose |
|---|---|---|---|
ShellUI.CLI |
.NET global tool | β Yes β primary install path | Sets up Tailwind, theme CSS, patches App.razor, and copies component source so Tailwind can scan it |
ShellUI.Components |
Razor class library | Optional | Runtime DLL with the same components + shellui.js interop + Shell.Cn helper. Useful when you want to reference component types from your own code or build a library on top of ShellUI |
ShellUI.Core and ShellUI.Templates are internal to the CLI and not published to NuGet β consumers never reference them directly.
ShellUI is a CLI-first library. The CLI is what wires up Tailwind, drops the theme into wwwroot/input.css, patches App.razor with the render mode and theme bootstrap, and copies component source into your project so Tailwind can scan it.
dotnet tool install -g ShellUI.CLI
shellui init # one-time setup
shellui add button card dialog # any time you want more componentsThat's it. Components render styled out of the box. Re-run shellui add whenever you want more.
The NuGet package ships the same component DLLs, the JS interop (shellui.js), and helpers like Shell.Cn. It's useful when you want the runtime types referenced directly β e.g. consuming Shell.Cn from your own code, or shipping a library that re-exports ShellUI components.
The NuGet package alone does not produce styled components. Tailwind v4 builds the CSS at compile time by scanning .razor source files. The component source lives inside the DLL, so Tailwind never sees the utility classes used inside ShellUI components and emits no rules for them. The result: components render with the right HTML structure but with most styling missing.
The supported way to get styled components is:
dotnet tool install -g ShellUI.CLIshellui initβ sets up Tailwind, theme CSS, and patchesApp.razorshellui add <component-name>for every component you want styled β this copies the.razorsource into your project so Tailwind can scan it- (Optional)
dotnet add package ShellUI.Components --prereleaseif you also want the runtime DLL on hand (most projects don't need both β pick one)
We're tracking a proper "NuGet-only with auto-CSS" path for a future release (v0.4.x). Until then, run the CLI.
Create/update wwwroot/tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./**/*.{razor,html,cshtml}",
"./wwwroot/js/**/*.js"
],
theme: {
extend: {},
},
plugins: [],
}Create wwwroot/input.css:
@import "tailwindcss";
/* ShellUI Theme Variables - Light Mode */
:root {
--background: oklch(0.9900 0 0);
--foreground: oklch(0 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0 0 0);
--popover: oklch(0.9900 0 0);
--popover-foreground: oklch(0 0 0);
--primary: oklch(0 0 0);
--primary-foreground: oklch(1 0 0);
--secondary: oklch(0.9400 0 0);
--secondary-foreground: oklch(0 0 0);
--muted: oklch(0.9700 0 0);
--muted-foreground: oklch(0.4400 0 0);
--accent: oklch(0.9400 0 0);
--accent-foreground: oklch(0 0 0);
--destructive: oklch(0.6300 0.1900 23.0300);
--destructive-foreground: oklch(1 0 0);
--border: oklch(0.9200 0 0);
--input: oklch(0.9400 0 0);
--ring: oklch(0 0 0);
--chart-1: oklch(0.8100 0.1700 75.3500);
--chart-2: oklch(0.5500 0.2200 264.5300);
--chart-3: oklch(0.7200 0 0);
--chart-4: oklch(0.9200 0 0);
--chart-5: oklch(0.5600 0 0);
--sidebar: oklch(0.9900 0 0);
--sidebar-foreground: oklch(0 0 0);
--sidebar-primary: oklch(0 0 0);
--sidebar-primary-foreground: oklch(1 0 0);
--sidebar-accent: oklch(0.9400 0 0);
--sidebar-accent-foreground: oklch(0 0 0);
--sidebar-border: oklch(0.9400 0 0);
--sidebar-ring: oklch(0 0 0);
--font-sans: Geist, sans-serif;
--font-serif: Georgia, serif;
--font-mono: Geist Mono, monospace;
--radius: 0.5rem;
--shadow-x: 0px;
--shadow-y: 1px;
--shadow-blur: 2px;
--shadow-spread: 0px;
--shadow-opacity: 0.18;
--shadow-color: hsl(0 0% 0%);
--shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
--shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
--shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
--shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
--shadow-md: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 2px 4px -1px hsl(0 0% 0% / 0.18);
--shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18);
--shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18);
--shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45);
--tracking-normal: 0em;
--spacing: 0.25rem;
}
/* Dark Mode Variables */
.dark {
--background: oklch(0 0 0);
--foreground: oklch(1 0 0);
--card: oklch(0.1400 0 0);
--card-foreground: oklch(1 0 0);
--popover: oklch(0.1800 0 0);
--popover-foreground: oklch(1 0 0);
--primary: oklch(1 0 0);
--primary-foreground: oklch(0 0 0);
--secondary: oklch(0.2500 0 0);
--secondary-foreground: oklch(1 0 0);
--muted: oklch(0.2300 0 0);
--muted-foreground: oklch(0.7200 0 0);
--accent: oklch(0.3200 0 0);
--accent-foreground: oklch(1 0 0);
--destructive: oklch(0.6900 0.2000 23.9100);
--destructive-foreground: oklch(0 0 0);
--border: oklch(0.2600 0 0);
--input: oklch(0.3200 0 0);
--ring: oklch(0.7200 0 0);
--chart-1: oklch(0.8100 0.1700 75.3500);
--chart-2: oklch(0.5800 0.2100 260.8400);
--chart-3: oklch(0.5600 0 0);
--chart-4: oklch(0.4400 0 0);
--chart-5: oklch(0.9200 0 0);
--sidebar: oklch(0.1800 0 0);
--sidebar-foreground: oklch(1 0 0);
--sidebar-primary: oklch(1 0 0);
--sidebar-primary-foreground: oklch(0 0 0);
--sidebar-accent: oklch(0.3200 0 0);
--sidebar-accent-foreground: oklch(1 0 0);
--sidebar-border: oklch(0.3200 0 0);
--sidebar-ring: oklch(0.7200 0 0);
--font-sans: Geist, sans-serif;
--font-serif: Georgia, serif;
--font-mono: Geist Mono, monospace;
--radius: 0.5rem;
--shadow-x: 0px;
--shadow-y: 1px;
--shadow-blur: 2px;
--shadow-spread: 0px;
--shadow-opacity: 0.18;
--shadow-color: hsl(0 0% 0%);
--shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
--shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
--shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
--shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
--shadow-md: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 2px 4px -1px hsl(0 0% 0% / 0.18);
--shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18);
--shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18);
--shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45);
}
/* Tailwind Theme Integration */
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--font-sans: var(--font-sans);
--font-mono: var(--font-mono);
--font-serif: var(--font-serif);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--shadow-2xs: var(--shadow-2xs);
--shadow-xs: var(--shadow-xs);
--shadow-sm: var(--shadow-sm);
--shadow: var(--shadow);
--shadow-md: var(--shadow-md);
--shadow-lg: var(--shadow-lg);
--shadow-xl: var(--shadow-xl);
--shadow-2xl: var(--shadow-2xl);
}Update wwwroot/app.css (or create it):
@import "./input.css";Add the link to your layout (_Layout.cshtml or MainLayout.razor):
<link href="app.css" rel="stylesheet" />This is what shellui init does for you automatically; documented here for the manual path.
.razor source into your project (shellui add <name>) so Tailwind sees the classes it uses. There's no way around this for Tailwind v4 short of pre-compiling a complete CSS bundle and shipping it with the package β which is what the v0.4.x NuGet-only path will deliver.
ShellUI is production-ready! We welcome contributions:
- π Bug reports via GitHub Issues
- π‘ Feature requests for new components
- π Documentation improvements
- π§ͺ Testing and feedback
MIT License - See LICENSE.txt for details
- Inspired by shadcn/ui for the CLI-first approach
- Forked from Sysinfocus simple/ui by @sysinfocus
- Built with love for the Blazor community
Quick Links:
- tailwind-setup.md - Tailwind CSS setup guide
- COMPONENT_ROADMAP.md - Component development roadmap
Installation & Usage:
- QUICKSTART.md - Quick start guide
- FAQ.md - Frequently asked questions
- CLI_SYNTAX.md - CLI command reference
Architecture:
- ARCHITECTURE.md - System architecture, diagrams, and design decisions
Alpha: 68 components, CLI + NuGet, Tailwind v4.1.18. Test before stable. π Ready to use today!
ShellUI is fully functional and ready for production use! π