Sutra UI
We define the rules, so you don't have to.
A pure Phoenix LiveView UI component library inspired by shadcn/ui.
Built for Elixir 1.20+, Phoenix 1.8+, Phoenix LiveView 1.2+, and Tailwind CSS v4.
See the live demo and component examples at sutraui.gurujada.com.
Why Sutra UI?
- No external JavaScript packages - No React, no npm packages, no node_modules bloat. Just Phoenix LiveView and colocated hooks.
- CSS-first theming - Customize colors with CSS variables and no Tailwind config file.
- Copy-paste friendly - Like shadcn/ui, components are meant to be understood and modified.
- Phoenix-native - Workflows live in LiveView; small hooks only handle local UI behavior.
- Production-minded - Tests, accessibility-minded patterns, and dark mode included.
- LLM-friendly - Includes
SKILL.md, usage rules, recipes, and cheatsheets for AI assistants.
Features
- 55 Components - Buttons, forms, dialogs, tables, calendars, upload fields, AI primitives, and more
- Pure LiveView - No external JavaScript frameworks
- Colocated Hooks - JS hooks live with their components (Phoenix 1.8+)
- CSS Variables - Override any color in one line
- Accessible - Semantic markup, ARIA patterns, and keyboard behavior where components are interactive
- Dark Mode - Built-in light/dark theme support
- No bundled icon set - Components own their internal SVGs; app icons come from your app or inline SVG
- Lightweight - CSS-first styling with minimal colocated JS hooks
Installation
1. Add Dependency
# mix.exs
def deps do
[
{:sutra_ui, "~> 0.4.0"}
]
end
Then run:
mix deps.get
2. Run the Installer
mix sutra_ui.install
This handles CSS setup and adds use SutraUI to your web module's html_helpers.
3. Delete core_components.ex
Sutra UI replaces Phoenix's generated button, input, flash, and related UI helpers. Delete core_components.ex and remove its import:
rm lib/my_app_web/components/core_components.ex
In your my_app_web.ex, remove the import MyAppWeb.CoreComponents line.
If your app uses Phoenix's generated <.icon> helper, move that helper to a
separate module or replace those calls before deleting core_components.ex.
Icons
Sutra UI does not ship a general icon component or bundled icon set. Some components render their own internal SVGs, but application icons are owned by your app.
Use your existing app helper, such as a Phoenix-generated <.icon> or a Lucide
helper, when your app provides one. Otherwise use inline SVG with appropriate
accessibility attributes. Do not import or invent SutraUI.Icon; it is not part
of the public API.
4. Colocated Hooks
Sutra UI uses Phoenix 1.8+ colocated hooks.
Most hooks load at runtime. Components such as dialog and animated response
use extracted hooks; merge the generated Sutra UI hooks into your LiveSocket:
import {hooks as sutraUiHooks} from "phoenix-colocated/sutra_ui"
const liveSocket = new LiveSocket("/live", Socket, {
hooks: {...sutraUiHooks}
})
5. Deployment Setup
Update your deployment aliases in mix.exs:
"assets.deploy": [
"compile", # Required: extracts colocated hooks
"esbuild my_app --minify",
"tailwind my_app --minify",
"phx.digest"
]
Usage
<.button>Click me</.button>
<.button variant="destructive">Delete</.button>
<.button variant="outline" phx-click="open_confirm">
Open Dialog
</.button>
<.dialog id="confirm-dialog" show={@show_confirm} on_cancel="close_confirm">
<:title>Confirm Action</:title>
<:description>Are you sure you want to continue?</:description>
<:footer>
<.button variant="outline" phx-click="close_confirm">
Cancel
</.button>
<.button phx-click="confirm">Confirm</.button>
</:footer>
</.dialog>
Theme Customization
Sutra UI uses CSS custom properties for theming. Override them in your app.cssafter importing sutra_ui.css:
@import "../../deps/sutra_ui/priv/static/sutra_ui.css";
/* Custom theme overrides */
:root {
/* Primary brand color (buttons, links, focus rings) */
--primary: oklch(0.65 0.20 145); /* Green */
--primary-foreground: oklch(0.98 0 0); /* White text on primary */
/* Destructive actions (delete buttons, error states) */
--destructive: oklch(0.55 0.25 30); /* Red */
/* Border radius */
--radius: 0.5rem;
}
/* Dark mode overrides */
.dark {
--primary: oklch(0.70 0.18 145);
--destructive: oklch(0.65 0.22 25);
}
Using shadcn/ui Themes
Since Sutra UI uses the same CSS variable names as shadcn/ui, you can copy theme variables directly from shadcn/ui themes and paste them into your app.css:
@import "../../deps/sutra_ui/priv/static/sutra_ui.css";
/* Paste compatible shadcn theme variables here */
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0);
--card-foreground: oklch(0.141 0.005 285.823);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.141 0.005 285.823);
--primary: oklch(0.21 0.006 285.885);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.967 0.001 286.375);
--secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375);
--muted-foreground: oklch(0.552 0.016 285.938);
--accent: oklch(0.967 0.001 286.375);
--accent-foreground: oklch(0.21 0.006 285.885);
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.985 0 0);
--border: oklch(0.92 0.004 286.32);
--input: oklch(0.92 0.004 286.32);
--ring: oklch(0.705 0.015 286.067);
--radius: 0.5rem;
}
.dark {
/* Dark mode variables from shadcn */
}
CSS Variables Reference
| Variable | Description | Usage |
|---|---|---|
--background | Page background | bg-background |
--foreground | Default text color | text-foreground |
--card | Card backgrounds | bg-card |
--card-foreground | Card text | text-card-foreground |
--popover | Popover/dropdown backgrounds | bg-popover |
--popover-foreground | Popover text | text-popover-foreground |
--primary | Primary brand color | bg-primary, text-primary |
--primary-foreground | Text on primary backgrounds | text-primary-foreground |
--secondary | Secondary/muted actions | bg-secondary |
--secondary-foreground | Text on secondary | text-secondary-foreground |
--muted | Muted backgrounds | bg-muted |
--muted-foreground | Muted/placeholder text | text-muted-foreground |
--accent | Hover/active states | bg-accent |
--accent-foreground | Text on accent | text-accent-foreground |
--destructive | Error/danger color | bg-destructive |
--destructive-foreground | Text on destructive | text-destructive-foreground |
--border | Border color | border-border |
--input | Input border color | border-input |
--ring | Focus ring color | ring-ring |
--radius | Base border radius | Used by rounded-lg, etc. |
Color Format
Sutra UI uses OKLCH colors for better perceptual uniformity:
--primary: oklch(0.623 0.214 259.815);
/* oklch(L C H )
L = Lightness (0-1)
C = Chroma (0-0.4, saturation)
H = Hue (0-360, color wheel)
*/
Common hues: Red ~30, Orange ~70, Yellow ~100, Green ~145, Cyan ~195, Blue ~260, Purple ~300, Pink ~350
Components
Foundation
button- Buttons with variants (primary, secondary, destructive, outline, ghost, link)badge- Status badgesspinner- Loading spinnerkbd- Keyboard shortcut display
Form Controls
input- Text inputs (text, email, password, number, date, etc.)textarea- Multi-line text inputcheckbox- Checkbox inputswitch- Toggle switchradio_group- Radio button groupsselect- Custom dropdown with searchslider- Range sliderrange_slider- Dual-handle range sliderlive_select- LiveComponent async searchable select with tagslabel- Form labelssimple_form- Form with auto-stylinginput_group- Input with prefix/suffixinput_otp- One-time password and PIN inputfile_upload- LiveView upload dropzonefilter_bar- Filter controls layout
Layout
card- Content container with header/footerheader- Page header with title/actionstable- Data tableitem- List item componentdrawer- Collapsible drawer navigationstepper- Multi-step progress indicatorstepper_wizard- Multi-step wizard shelltree_view- Hierarchical tree navigation
Feedback
alert- Alert messagesflash- Phoenix flash messagesprogress- Progress barskeleton- Loading placeholderempty- Empty stateloading_state- Loading indicator with messagetoast- Toast notifications
Overlay
dialog- Modal dialogspopover- Click-triggered popupstooltip- Hover tooltipshover_card- Rich hover previewsdropdown_menu- Dropdown menuscontext_menu- Right-click action menuscommand- Command palette with search
Navigation
tabs- Tab panelsaccordion- Collapsible sectionsbreadcrumb- Breadcrumb navigationpagination- Page navigationtab_nav- Responsive routed tab navigation
Display
avatar- User avatars with fallbackcarousel- Image/content carouseltheme_switcher- Light/dark theme event buttonmarquee- Scrolling content bannerseparator- Visual or semantic dividercalendar- Monthly calendar gridtimeline- Chronological event list
AI
response- Text responses with reveal styles, or streamed Markdownactivity- Safe user-facing agent progress with slot-owned rows
For AI Assistants
This library includes SKILL.md, usage_rules.md, and cheatsheets for AI
assistants working with this codebase. Start with SKILL.md for design
philosophy and reference routing, use cheatsheets/components.cheatmd and
cheatsheets/forms.cheatmd for compact examples, and use usage_rules.md when
editing library internals. These files cover:
- CSS-first styling patterns
- Required ID attributes for hook-based components
- Event naming conventions (
sutra-ui:*namespace) - Component structure patterns
- Testing conventions
- Icon guidance: Sutra UI does not provide a general icon helper; use the host app's helper or inline accessible SVG
If you're using an AI assistant to help build application UI with Sutra, point
it to SKILL.md. If it is modifying or extending Sutra UI itself, also point it
to usage_rules.md.
Accessibility
Sutra UI components use accessibility patterns appropriate to their behavior:
- Semantic HTML elements
- ARIA roles and attributes for composite widgets
- Keyboard navigation for interactive components
- Focus management and visible focus indicators where applicable
- Screen reader announcements for status-style components
Browser Support
- Chrome/Edge 120+
- Firefox 120+
- Safari 17+
Requires support for:
- CSS
@layer - CSS custom properties
- CSS
:has()selector - Native
<dialog>element forcommand_dialog
License
MIT License - see LICENSE for details.
Documentation
- Live Demo - Browse components, examples, and docs
- HexDocs - Full API reference
- Installation Guide - Setup for Phoenix 1.8+ and Tailwind v4
- Theming Guide - CSS variables, OKLCH colors, shadcn themes
- Accessibility Guide - ARIA patterns, keyboard navigation
- JavaScript Hooks - Colocated hooks, custom events
- Components Cheatsheet - Quick reference for all 55 components
- Forms Cheatsheet - Form patterns and validation