Manual Installation
Setup Selia manually by following the steps below.
Tailwind CSS
Before we start, make sure you have Tailwind CSS installed in your project. If you don't, you can follow the Tailwind CSS installation guide.
Dependencies
First, install the dependencies:
Tailwind Configuration
Your CSS should include the following:
@custom-variant dark (&:where(.dark, .dark *));
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.2036 0.0029 247.97);
--accent: oklch(0.9616 0.0011 247.83);
--muted: oklch(0.5076 0.0103 248.03);
--dimmed: oklch(0.6971 0.009 247.96);
--shadow: 0 3px 4px -1px rgba(0, 0, 0, 0.05);
--border: oklch(0.915 0.0024 247.85);
--separator: oklch(0.915 0.0024 247.85);
--input: oklch(1 0 0);
--input-border: oklch(0.915 0.0024 247.85);
--input-accent-border: oklch(0.8599 0.0041 247.87);
--input-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
--track: oklch(0.915 0.0024 247.85);
--scrollbar: oklch(0.8039 0.0057 247.9);
--code: oklch(0.9847 0.0004 247.83);
--avatar: oklch(0.8836 0.0034 247.86);
--avatar-foreground: var(--foreground);
--card: oklch(1 0 0);
--card-border: oklch(0.9384 0.0018 247.84);
--card-separator: oklch(0.9306 0.002 247.84);
--card-footer: oklch(0.977 0.0007 247.83);
--card-shadow:
0px 5px 10px rgba(0, 0, 0, 0.03), 0px 8px 3px -4px rgba(0, 0, 0, 0.02);
--item: oklch(1 0 0);
--item-border: oklch(0.9384 0.0018 247.84);
--chip: oklch(0.9616 0.0011 247.83);
--chip-border: oklch(0.915 0.0024 247.85);
--popover: oklch(1 0 0);
--popover-foreground: var(--foreground);
--popover-border: oklch(0.9384 0.0018 247.84);
--popover-separator: oklch(0.9384 0.0018 247.84);
--popover-shadow:
0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--popover-accent: oklch(0.9616 0.0011 247.83);
--dialog: oklch(1 0 0);
--dialog-foreground: var(--foreground);
--dialog-border: oklch(0.9384 0.0018 247.84);
--dialog-footer: oklch(0.977 0.0007 247.83);
--toast: oklch(1 0 0);
--toast-foreground: var(--foreground);
--toast-border: oklch(0.9384 0.0018 247.84);
--table: transparent;
--table-foreground: var(--foreground);
--table-separator: oklch(0.9306 0.002 247.84);
--table-head: oklch(0.9693 0.0009 247.83);
--table-accent: oklch(0.9616 0.0011 247.83);
--tabs: oklch(0.9384 0.0018 247.84);
--tabs-foreground: var(--foreground);
--tabs-border: oklch(0.915 0.0024 247.85);
--tabs-accent: oklch(1 0 0);
--primary: oklch(0.5784 0.2057 262.95);
--primary-foreground: oklch(0.9764 0.0013 286.38);
--primary-border: oklch(0.5938 0.1979 263.03);
--secondary: oklch(0.9616 0.0011 247.83);
--secondary-foreground: var(--foreground);
--secondary-border: oklch(0.915 0.0024 247.85);
--danger: oklch(0.6098 0.244 28.41);
--danger-foreground: oklch(0.9764 0.0013 286.38);
--danger-border: oklch(0.5416 0.2178 28.52);
--tertiary: oklch(0.2797 0.0047 247.99);
--tertiary-foreground: oklch(0.9764 0.0013 286.38);
--tertiary-border: oklch(0.5351 0.0119 248.05);
--warning: oklch(0.744 0.1539 78.47);
--warning-foreground: oklch(0.9764 0.0013 286.38);
--warning-border: oklch(0.6303 0.1299 78.77);
--success: oklch(0.6554 0.187 148.39);
--success-foreground: oklch(0.9764 0.0013 286.38);
--success-border: oklch(0.5152 0.1446 148.94);
--info: oklch(0.6649 0.1854 249.66);
--info-foreground: oklch(0.9764 0.0013 286.38);
--info-border: oklch(0.5703 0.160671 249.8244);
--kbd: oklch(0.9197 0.004 286.32);
--kbd-foreground: var(--foreground);
--kbd-border: oklch(0.8377 0.0083 286.22);
--radius: 0.75rem;
--radius-xs: 5px;
--radius-sm: calc(var(--radius) - 0.25rem);
--radius-md: var(--radius);
--radius-lg: calc(var(--radius) + 0.25rem);
--radius-xl: calc(var(--radius) + 0.5rem);
--spinner-light: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0_339_178)'%3E%3Cpath d='M22 12.0005C21.9999 14.1123 21.3313 16.1698 20.0899 17.8782C18.8486 19.5866 17.0983 20.8582 15.0899 21.5107C13.0814 22.1632 10.918 22.1631 8.9096 21.5105C6.90121 20.8579 5.15098 19.5862 3.90974 17.8777C2.6685 16.1693 1.99998 14.1117 2 11.9999C2.00002 9.88816 2.66856 7.83061 3.90982 6.12216C5.15109 4.4137 6.90134 3.14205 8.90974 2.48946C10.9181 1.83687 13.0816 1.83684 15.09 2.48938' stroke='%23F7F7F8' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_339_178'%3E%3Crect width='24' height='24' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A");
--spinner-dark: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0_339_178)'%3E%3Cpath d='M22 12.0005C21.9999 14.1123 21.3313 16.1698 20.0899 17.8782C18.8486 19.5866 17.0983 20.8582 15.0899 21.5107C13.0814 22.1632 10.918 22.1631 8.9096 21.5105C6.90121 20.8579 5.15098 19.5862 3.90974 17.8777C2.6685 16.1693 1.99998 14.1117 2 11.9999C2.00002 9.88816 2.66856 7.83061 3.90982 6.12216C5.15109 4.4137 6.90134 3.14205 8.90974 2.48946C10.9181 1.83687 13.0816 1.83684 15.09 2.48938' stroke='%23161718' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_339_178'%3E%3Crect width='24' height='24' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A");
--chevron-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E");
--chevron-right-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E");
--chevron-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
--chevron-down-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
.dark {
--background: oklch(0.2036 0.0029 247.97);
--foreground: oklch(0.977 0.0007 247.83);
--accent: oklch(0.3095 0.0055 248.01);
--muted: oklch(0.7958 0.006 247.9);
--dimmed: oklch(0.6971 0.009 247.96);
--border: oklch(0.359 0.0067 248.02);
--shadow: 0 3px 4px rgba(0, 0, 0, 0.15);
--separator: oklch(0.308 0.0046 247.98);
--input: oklch(0.2788 0.0048 248);
--input-border: oklch(0.3974 0.0076 248.02);
--input-shadow: 0 3px 4px -1px rgba(0, 0, 0, 0.05);
--input-accent-border: oklch(0.4349 0.0085 248.02);
--track: oklch(0.2788 0.0048 248);
--scrollbar: oklch(0.4625 0.0092 248.03);
--code: oklch(0.2579 0.0043 247.99);
--avatar: oklch(0.3196 0.0058 248.01);
--avatar-foreground: var(--foreground);
--card: oklch(0.2579 0.0043 247.99);
--card-border: oklch(0.2878 0.0046 247.99);
--card-separator: oklch(0.2878 0.0046 247.99);
--card-footer: oklch(0.2366 0.0037 247.99);
--card-shadow: 0 8px 6px -4px rgb(0 0 0 / 0.08);
--item: oklch(0.2579 0.0043 247.99);
--item-border: oklch(0.2878 0.0046 247.99);
--chip: oklch(0.3879 0.0074 248.02);
--chip-border: oklch(0.4349 0.0085 248.02);
--popover: oklch(0.3196 0.0058 248.01);
--popover-foreground: var(--foreground);
--popover-border: oklch(0.3974 0.0076 248.02);
--popover-separator: oklch(0.3974 0.0076 248.02);
--popover-shadow:
0px 90px 40px rgba(0, 0, 0, 0.03), 0px 40px 50px rgba(0, 0, 0, 0.05),
0px 14px 22px rgba(0, 0, 0, 0.06);
--popover-accent: oklch(0.4068 0.0079 248.02);
--dialog: oklch(0.2579 0.0043 247.99);
--dialog-foreground: var(--foreground);
--dialog-border: oklch(0.308 0.0046 247.98);
--dialog-footer: oklch(0.2366 0.0037 247.99);
--toast: oklch(0.3196 0.0058 248.01);
--toast-foreground: var(--foreground);
--toast-border: oklch(0.3974 0.0076 248.02);
--table: transparent;
--table-foreground: var(--foreground);
--table-separator: oklch(0.308 0.0046 247.98);
--table-head: oklch(0.2894 0.004 247.97);
--table-accent: oklch(0.2888 0.0039 264.5);
--tabs: oklch(0.2994 0.0053 248);
--tabs-foreground: var(--foreground);
--tabs-accent: oklch(0.3879 0.0074 248.02);
--tabs-border: oklch(0.2684 0.0045 248);
--primary: oklch(0.5784 0.2057 262.95);
--primary-foreground: var(--foreground);
--primary-border: oklch(0.4217 0.1869 262.77);
--secondary: oklch(0.3174 0.0065 264.48);
--secondary-foreground: var(--foreground);
--secondary-border: oklch(0.2657 0.0055 286.02);
--danger: oklch(0.5705 0.2297 28.57);
--danger-foreground: var(--foreground);
--danger-border: oklch(0.4058 0.161 28.31);
--tertiary: oklch(0.9456 0.0017 247.84);
--tertiary-foreground: oklch(0.2011 0.0039 286.04);
--tertiary-border: oklch(0.4432 0.0104 248.06);
--warning: oklch(0.744 0.1539 78.47);
--warning-foreground: var(--foreground);
--warning-border: oklch(0.6303 0.1299 78.77);
--success: oklch(0.6554 0.187 148.39);
--success-foreground: var(--foreground);
--success-border: oklch(0.5152 0.1446 148.94);
--info: oklch(0.6649 0.1854 249.66);
--info-foreground: var(--foreground);
--info-border: oklch(0.5703 0.160671 249.8244);
--kbd: oklch(0.3911 0.0121 273.1);
--kbd-foreground: var(--foreground);
--kbd-border: oklch(0.4122 0.0107 264.45);
}
@theme inline {
--font-sans:
'Inter', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--font-mono:
'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
'Liberation Mono', 'Courier New', monospace;
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
--color-primary-border: var(--primary-border);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary-border: var(--secondary-border);
--color-danger: var(--danger);
--color-danger-foreground: var(--danger-foreground);
--color-danger-border: var(--danger-border);
--color-tertiary: var(--tertiary);
--color-tertiary-foreground: var(--tertiary-foreground);
--color-tertiary-border: var(--tertiary-border);
--color-info: var(--info);
--color-info-foreground: var(--info-foreground);
--color-info-border: var(--info-border);
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-success-border: var(--success-border);
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
--color-warning-border: var(--warning-border);
--color-avatar: var(--avatar);
--color-avatar-foreground: var(--avatar-foreground);
--color-card: var(--card);
--color-card-border: var(--card-border);
--color-card-separator: var(--card-separator);
--color-card-footer: var(--card-footer);
--color-item: var(--item);
--color-item-border: var(--item-border);
--color-input: var(--input);
--color-input-foreground: var(--foreground);
--color-input-border: var(--input-border);
--color-input-accent-border: var(--input-accent-border);
--color-track: var(--track);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-popover-border: var(--popover-border);
--color-popover-separator: var(--popover-separator);
--color-popover-accent: var(--popover-accent);
--color-kbd: var(--kbd);
--color-kbd-foreground: var(--kbd-foreground);
--color-kbd-border: var(--kbd-border);
--color-dialog: var(--dialog);
--color-dialog-foreground: var(--dialog-foreground);
--color-dialog-border: var(--dialog-border);
--color-dialog-footer: var(--dialog-footer);
--color-tabs: var(--tabs);
--color-tabs-foreground: var(--tabs-foreground);
--color-tabs-border: var(--tabs-border);
--color-tabs-accent: var(--tabs-accent);
--color-toast: var(--toast);
--color-toast-foreground: var(--toast-foreground);
--color-toast-border: var(--toast-border);
--color-table: var(--table);
--color-table-foreground: var(--table-foreground);
--color-table-separator: var(--table-separator);
--color-table-head: var(--table-head);
--color-table-accent: var(--table-accent);
--color-chip: var(--chip);
--color-chip-border: var(--chip-border);
--color-muted: var(--muted);
--color-dimmed: var(--dimmed);
--color-separator: var(--separator);
--color-accent: var(--accent);
--color-border: var(--border);
--color-scrollbar: var(--scrollbar);
--color-code: var(--code);
--radius: var(--radius);
--radius-xs: var(--radius-xs);
--radius-sm: var(--radius-sm);
--radius-md: var(--radius-md);
--radius-lg: var(--radius-lg);
--radius-xl: var(--radius-xl);
--shadow: var(--shadow);
--shadow-card: var(--card-shadow);
--shadow-input: var(--input-shadow);
--shadow-popover: var(--popover-shadow);
--text-xs: 0.625rem;
--text-sm: 0.75rem;
--text-base: 0.875rem;
--text-base--line-height: calc(1.25 / 0.875);
--text-lg: 1rem;
--text-xl: 1.125rem;
--text-2xl: 1.25rem;
--text-3xl: 1.5rem;
--text-4xl: 1.875rem;
--text-5xl: 2.25rem;
--text-6xl: 3rem;
--text-7xl: 3.75rem;
--text-8xl: 4.5rem;
--text-9xl: 6rem;
}
@utility bg-spinner {
background-image: var(--spinner-light);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
@utility bg-spinner-dark {
background-image: var(--spinner-dark);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
@utility bg-chevron-right {
background-image: var(--chevron-right);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
@utility bg-chevron-right-dark {
background-image: var(--chevron-right-dark);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
@utility bg-chevron-down {
background-image: var(--chevron-down);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
@utility bg-chevron-down-dark {
background-image: var(--chevron-down-dark);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
@layer base {
.root {
isolation: isolate;
}
body {
@apply text-base bg-background text-foreground;
}
}Helper Function
Create a new helper function to merge class names:
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}Portals
Base UI uses portals for components that render popups, such as Dialog and Popover. To make portaled components always appear on top of the entire page, add the following style to your application layout root:
<body>
<div className="root">
{children}
</div>
</body>Path Aliases
Add the baseUrl compiler option to your tsconfig.json file:
{
"compilerOptions": {
"baseUrl": "."
}
}Selia Configuration
Create a new file selia.json in the root of your project:
{
"framework": "react",
"paths": {
"components": "components/selia",
"utils": "lib/utils.ts"
},
"imports": {
"components": "components/selia",
"utils": "lib/utils"
}
}Components
Use the Selia CLI to add components to your project:
Font Family (Recommended)
You can use any font you like, but Selia was designed with Inter and JetBrains Mono.
Add the following to your CSS file:
@theme inline {
--font-sans:
'Inter', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--font-mono:
'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
'Liberation Mono', 'Courier New', monospace;
}Icons (optional)
You don’t need to install a separate icon library. We embed icons as SVGs directly inside the components that need them. This way, you’re free to use any icon library you like, without worrying about breaking other components.