[!NOTE] This is a fork of the original Origin UI project. This project is not affiliated with the original. I'm grateful for their work and have created these Svelte components copied from their design.
[!NOTE] This is a work in progress. For some components the necessary libraries are coming soon (e.g. Bits UI) or are just not available yet (e.g. React Payment Inputs). Maybe i will add them in the future myself.
Origin UI - Svelte is a collection of copy-and-paste components for quickly building app UIs using Svelte.
The Original Origin UI is built with Next.js. This is a built with Svelte.
If you want to use the components in your project, you need to setup the following:
[!NOTE] This project uses pnpm as package manager.
Setup
git clone https://github.com/max-got/originui-svelte.git
cd originui-svelte
pnpm install
Development
pnpm dev
http://localhost:5173
Code Quality
pnpm lint # Run ESLint
pnpm format # Run Prettier
You can copy and use the components in your Svelte project. Note that some components may require additional libraries - refer to the listed dependencies in the component preview.
In the src/lib/utils.ts
folder you will find the common cn
function for tailwindcss class merging.
In the src/lib/hooks
folder you will find the common hooks.
In the src/lib/actions
folder you will find the common actions.
You need to copy the base components from the src/lib/components/ui
folder to your project and adjust the imports accordingly.
Import the CSS in your src/lib/app.css
file (the following is based on tailwindcss):
@layer base {
:root {
--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% 100%;
--border: 240 5.9% 90%;
--input: 240 4.9% 83.9%;
--ring: 240 5% 64.9%;
--radius: 0.5rem;
}
.dark {
--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 5.9% 10%;
--muted-foreground: 240 4.4% 58%;
--accent: 240 5.9% 10%;
--accent-foreground: 0 0% 98%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 100%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 3.8% 46.1%;
}
}
We welcome contributions to Origin UI - Svelte!
This guide will help you understand our project structure and contribution workflow.
src/
├── lib/
│ ├── components/ # UI Components organized by type
│ │ ├── ui/ # Base UI components
│ │ │ ├── badge.svelte # one component
│ │ │ ├── button.svelte # one component
│ │ │ ├── accordion.svelte # needs multiple components
│ │ │ │ │── accordion-item.svelte # Base component Accordion Item
│ │ │ │ │── accordion-trigger.svelte # Base component Accordion Trigger
│ │ │ │ │── ...
│ │ │ └── ...
│ │ ├── inputs/ # Input components
│ │ │ ├── input-01.svelte
│ │ │ ├── input-02.svelte
│ │ │ └── ...
│ │ ├── buttons/ # Button components
│ │ │ ├── button-01.svelte
│ │ │ ├── button-02.svelte
│ │ │ └── ...
│ │ └─ ... # Other component categories
│ ├── utils/ # Utility functions
│ ├── types/ # TypeScript type definitions
│ ├── hooks/ # Svelte hooks
│ ├── actions/ # Svelte actions
│ └── config/ # Configuration files
The project uses an automated component registry system that connects your components to the routing system. Here's how it works:
Registry Generation
pnpm generate:registry
This script automatically:
src/lib/components/
directorysrc/lib/componentRegistry.types.ts
with component mappingsRegistry Architecture
src/
├── lib/
│ ├── componentRegistry.types.ts # Auto-generated types
│ ├── componentRegistry.ts # Registry implementation
│ └── data/api/
│ ├── components.ts # API endpoints
│ ├── components.handler.ts # Request handlers
│ └── components.route.ts # Route definitions
├── routes/
│ └── (components)/
│ └── [path=componentsPath]/
│ ├── +page.server.ts # Dynamic route handling
│ └── [directory]/[id]/
│ └── +page.server.ts # Component page handling
└── params/
├── componentDirectory.ts # Directory parameter validation
├── componentId.ts # Component ID validation
└── componentsPath.ts # Path parameter validation
How It Works
When to Run Registry Generation
Run pnpm generate:registry
when you:
[!IMPORTANT] Always run
pnpm generate:registry
after making changes to component files or structure. This ensures the routing system stays in sync with your components.
The project includes an automated dependency detection system that analyzes component source code and manages dependencies.
Dependency Configuration
Dependencies must be registered in src/lib/constants.ts
:
export const POSSIBLE_DEPENDENCIES = [
{
dev: false, // Whether it's a dev dependency
name: 'bits-ui', // Import name to detect
packageName: 'bits-ui@next', // NPM package name
url: 'https://github.com/huntabyte/bits-ui' // Reference URL
}
// ... other dependencies
] as const;
[!IMPORTANT] When using a new dependency in your component, you MUST add it to
POSSIBLE_DEPENDENCIES
first. This ensures the dependency detection system can find and document it correctly.
Adding New Dependencies
To add a new dependency:
src/lib/constants.ts
POSSIBLE_DEPENDENCIES
:{
dev: boolean, // true for devDependencies, false for dependencies
name: string, // The import path to detect (e.g., 'your-package')
packageName: string, // The exact package name with version (e.g., '[email protected]')
url: string // Package repository or documentation URL
}
How It Works
The system (src/lib/utils/handleComponentSource.ts
):
POSSIBLE_DEPENDENCIES
Example Output
When a component uses dependencies:
<script>
import * as Accordion from 'bits-ui/accordion';
import { Icon } from '@iconify-json/ri';
</script>
The system automatically:
<!-- Dependencies:
pnpm i -D @iconify-json/ri
pnpm i bits-ui@next
-->
Special Cases
Enhanced Images:
// Automatically detects and adds @sveltejs/enhanced-img
const enhancedImageMatch = source.match(ENHANCED_IMAGE_REGEX);
Multiple Dependencies:
# Combines dev and runtime dependencies
pnpm i -D @iconify-json/ri unplugin-icons && pnpm i bits-ui@next
Integration
The system integrates with:
[!TIP] When adding new components that use external packages:
- First add the dependency to
POSSIBLE_DEPENDENCIES
- Then create your component with the imports
- The system will automatically detect and document the dependencies
The project includes an automatic code collapsing system for better readability in the documentation. This feature is implemented in src/lib/utils/shiki-transformer/collapsible.ts
.
How to Use
Add collapse markers in your component code:
<script module lang="ts">
// [!code collapse-start]
const longDataArray = [
// ... many items
];
// [!code collapse-end]
</script>
Supported Comment Types
The system recognizes collapse markers, like this:
// JavaScript/TypeScript style
// [!code collapse-start]
// long code
// [!code collapse-end]
How It Works
The system:
Example Use Case
Perfect for:
<script module lang="ts">
// [!code collapse-start]
const items = [
{ id: 1, value: '...' },
{ id: 2, value: '...' }
// ... many more items
];
// [!code collapse-end]
</script>
<script lang="ts">
// This code remains visible by default
let selectedItem = items[0];
</script>
Best Practices
[!TIP] Use code collapsing to improve the readability of your components in the documentation while keeping all code accessible when needed.
1. Component Organization
1.1. Base (/ui
) components
Base components are in the src/lib/components/ui
folder.
Each component should be in its own directory if it needs multiple components.
component-category/
├── index.ts # Exports
├── component.svelte # Main component
If a component is a simple one, it can be placed in the src/lib/components/ui
folder.
component-category/
└── component.svelte # Main component
1.2. Origin UI components
Origin UI components are in the src/lib/components
folder.
Each component should be in its own desired category (e.g. inputs
,buttons
, etc.)
component-category/
├── category-01.svelte
├── category-02.svelte
└── ...
If a component isn't achievable (e.g. not the necessary libraries available, not enough time to implement, etc.) you need to add a placeholder component in the src/lib/components
folder. In this case the component should be named category-03.todo.svelte
.
component-category/
└── category-03.todo.svelte
If a component is just waiting for a library to be implemented, you need to add a placeholder component in the src/lib/components
folder. In this case the component should be named category-04.soon.svelte
.
component-category/
└── category-04.soon.svelte
[!NOTE] The component should have content. For example:
<p class="text-center text-sm text-muted-foreground"> waiting for <a class="underline hover:text-foreground" href="https://github.com/huntabyte/bits-ui/pull/582" >Bits UI TimeField</a > </p>
1.3. Route Configuration
When adding a new component category, you must configure its routing in src/lib/config/routes.ts
:
{
componentDirectory: ['your-category'], // Directory name(s) containing components
header: {
description: 'A growing collection of ${count} components built with Svelte and TailwindCSS.',
title: 'Your Category'
},
label: 'Your Category', // Navigation label
path: 'your-category', // URL path
seo: {
description: 'An extensive collection of copy-and-paste components built with Svelte and TailwindCSS.',
keywords: 'your, keywords, component, svelte, tailwindcss',
title: 'Your Category',
twitterDescription: 'An extensive collection of copy-and-paste components built with Svelte and TailwindCSS.',
twitterTitle: 'Your Category'
}
}
For combined categories (like inputs/textareas), use multiple directories:
componentDirectory: ['category1', 'category2'],
path: 'combined-category'
Component Requirements
Styling Guidelines
Before Starting
git checkout -b feature/your-feature-name
Component Development
component-category/
├── category-XX.svelte # Regular component
├── category-XX.todo.svelte # Not yet possible
└── category-XX.soon.svelte # Waiting for dependency
pnpm generate:registry
after adding/modifying componentsQuality Checklist
pnpm format
)pnpm lint
)Route Configuration
src/lib/config/routes.ts
Documentation
.todo
and .soon
componentsSubmitting the PR
git add .
git commit -m "feat: add new component category"
git push origin feature/your-feature-name
feat:
for new components/featuresfix:
for bug fixesdocs:
for documentationrefactor:
for code improvementschore:
for maintenance[!NOTE] Large PRs are harder to review. Consider breaking big changes into smaller, focused PRs.
We appreciate your contributions to the Svelte Community and to this project!
Feel free to use these components in personal and commercial projects. However, while the tutorials and demos are available for your use as-is, they cannot be redistributed or resold.
For any questions or feedback, please open an issue on this repository.
This project is a work in progress, and i am continuously working to improve and expand this collection.