Repository: huntabyte/shadcn-svelte
Branch: main
Commit: 595159755891
Files: 2754
Total size: 3.8 MB
Directory structure:
gitextract_t3sawww4/
├── .changeset/
│ ├── README.md
│ └── config.json
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── 1-documentation_change.yml
│ │ ├── 2-feature_request.yml
│ │ ├── 3-bug_report.yml
│ │ └── config.yml
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── reproduire/
│ │ └── needs-reproduction.md
│ └── workflows/
│ ├── autoformat.yml
│ ├── build-preview.yml
│ ├── ci.yml
│ ├── deploy-preview.yml
│ ├── deploy-prod.yml
│ ├── deploy-svelte-4.yml
│ ├── deploy-tailwind-3.yml
│ ├── pr-guard.yml
│ ├── release.yml
│ ├── reproduire-close.yml
│ └── reproduire.yml
├── .gitignore
├── .npmrc
├── .nvmrc
├── .prettierignore
├── .prettierrc
├── .vscode/
│ └── settings.json
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── docs/
│ ├── .gitignore
│ ├── .npmrc
│ ├── README.md
│ ├── _headers
│ ├── content/
│ │ ├── about.md
│ │ ├── changelog.md
│ │ ├── cli.md
│ │ ├── components/
│ │ │ ├── accordion.md
│ │ │ ├── alert-dialog.md
│ │ │ ├── alert.md
│ │ │ ├── aspect-ratio.md
│ │ │ ├── avatar.md
│ │ │ ├── badge.md
│ │ │ ├── breadcrumb.md
│ │ │ ├── button-group.md
│ │ │ ├── button.md
│ │ │ ├── calendar.md
│ │ │ ├── card.md
│ │ │ ├── carousel.md
│ │ │ ├── chart.md
│ │ │ ├── checkbox.md
│ │ │ ├── collapsible.md
│ │ │ ├── combobox.md
│ │ │ ├── command.md
│ │ │ ├── context-menu.md
│ │ │ ├── data-table.md
│ │ │ ├── date-picker.md
│ │ │ ├── dialog.md
│ │ │ ├── drawer.md
│ │ │ ├── dropdown-menu.md
│ │ │ ├── empty.md
│ │ │ ├── field.md
│ │ │ ├── form.md
│ │ │ ├── hover-card.md
│ │ │ ├── index.md
│ │ │ ├── input-group.md
│ │ │ ├── input-otp.md
│ │ │ ├── input.md
│ │ │ ├── item.md
│ │ │ ├── kbd.md
│ │ │ ├── label.md
│ │ │ ├── menubar.md
│ │ │ ├── native-select.md
│ │ │ ├── navigation-menu.md
│ │ │ ├── pagination.md
│ │ │ ├── popover.md
│ │ │ ├── progress.md
│ │ │ ├── radio-group.md
│ │ │ ├── range-calendar.md
│ │ │ ├── resizable.md
│ │ │ ├── scroll-area.md
│ │ │ ├── select.md
│ │ │ ├── separator.md
│ │ │ ├── sheet.md
│ │ │ ├── sidebar.md
│ │ │ ├── skeleton.md
│ │ │ ├── slider.md
│ │ │ ├── sonner.md
│ │ │ ├── spinner.md
│ │ │ ├── switch.md
│ │ │ ├── table.md
│ │ │ ├── tabs.md
│ │ │ ├── textarea.md
│ │ │ ├── toggle-group.md
│ │ │ ├── toggle.md
│ │ │ ├── tooltip.md
│ │ │ └── typography.md
│ │ ├── components-json.md
│ │ ├── dark-mode/
│ │ │ ├── astro.md
│ │ │ ├── index.md
│ │ │ └── svelte.md
│ │ ├── figma.md
│ │ ├── index.md
│ │ ├── installation/
│ │ │ ├── astro.md
│ │ │ ├── index.md
│ │ │ ├── manual.md
│ │ │ ├── sveltekit.md
│ │ │ └── vite.md
│ │ ├── javascript.md
│ │ ├── legacy.md
│ │ ├── migration/
│ │ │ ├── index.md
│ │ │ ├── svelte-5.md
│ │ │ └── tailwind-v4.md
│ │ ├── registry/
│ │ │ ├── examples.md
│ │ │ ├── faq.md
│ │ │ ├── getting-started.md
│ │ │ ├── index.md
│ │ │ ├── registry-item-json.md
│ │ │ └── registry-json.md
│ │ └── theming.md
│ ├── mdsx.config.js
│ ├── package.json
│ ├── scripts/
│ │ ├── build-icons.ts
│ │ ├── build-llm-placeholders.ts
│ │ ├── build-llms.ts
│ │ ├── build-registry.ts
│ │ ├── pull-styles.ts
│ │ ├── registry.ts
│ │ ├── tsconfig.json
│ │ └── velite/
│ │ ├── velite-update-json.ts
│ │ ├── velite-utils.ts
│ │ └── velite-watch-output.ts
│ ├── src/
│ │ ├── app.css
│ │ ├── app.d.ts
│ │ ├── app.html
│ │ ├── lib/
│ │ │ ├── blocks.ts
│ │ │ ├── colors.ts
│ │ │ ├── components/
│ │ │ │ ├── announcement.svelte
│ │ │ │ ├── block-viewer-code.svelte
│ │ │ │ ├── block-viewer-copy-code-button.svelte
│ │ │ │ ├── block-viewer-file-tree.svelte
│ │ │ │ ├── block-viewer-iframe.svelte
│ │ │ │ ├── block-viewer-toolbar.svelte
│ │ │ │ ├── block-viewer-tree.svelte
│ │ │ │ ├── block-viewer-view-mobile.svelte
│ │ │ │ ├── block-viewer-view.svelte
│ │ │ │ ├── block-viewer.svelte
│ │ │ │ ├── blocks-nav.svelte
│ │ │ │ ├── callout.svelte
│ │ │ │ ├── cards/
│ │ │ │ │ ├── activity-goal.svelte
│ │ │ │ │ ├── appearance-settings.svelte
│ │ │ │ │ ├── calendar.svelte
│ │ │ │ │ ├── cards-demo.svelte
│ │ │ │ │ ├── chat.svelte
│ │ │ │ │ ├── cookie-settings.svelte
│ │ │ │ │ ├── create-account.svelte
│ │ │ │ │ ├── demo.svelte
│ │ │ │ │ ├── exercise-minutes.svelte
│ │ │ │ │ ├── field-checkbox.svelte
│ │ │ │ │ ├── field-hear.svelte
│ │ │ │ │ ├── forms.svelte
│ │ │ │ │ ├── input-demo.svelte
│ │ │ │ │ ├── input-group-button-demo.svelte
│ │ │ │ │ ├── item-demo.svelte
│ │ │ │ │ ├── nested.svelte
│ │ │ │ │ ├── notion-prompt-form.svelte
│ │ │ │ │ ├── payments-actions-cell.svelte
│ │ │ │ │ ├── payments-email-header.svelte
│ │ │ │ │ ├── payments.svelte
│ │ │ │ │ ├── report-issue.svelte
│ │ │ │ │ ├── root-components.svelte
│ │ │ │ │ ├── share.svelte
│ │ │ │ │ ├── stats.svelte
│ │ │ │ │ └── team-members.svelte
│ │ │ │ ├── chart-code-viewer.svelte
│ │ │ │ ├── chart-copy-button.svelte
│ │ │ │ ├── chart-display.svelte
│ │ │ │ ├── chart-toolbar.svelte
│ │ │ │ ├── chart-tooltip-demo-item.svelte
│ │ │ │ ├── charts-nav.svelte
│ │ │ │ ├── code-collapsible-wrapper.svelte
│ │ │ │ ├── code-tabs.svelte
│ │ │ │ ├── color-format-selector.svelte
│ │ │ │ ├── color-indicator.svelte
│ │ │ │ ├── color-palette.svelte
│ │ │ │ ├── color.svelte
│ │ │ │ ├── colors/
│ │ │ │ │ ├── color-card.svelte
│ │ │ │ │ └── colors.ts
│ │ │ │ ├── colors-nav.svelte
│ │ │ │ ├── command-menu/
│ │ │ │ │ ├── command-menu-item.svelte
│ │ │ │ │ └── command-menu.svelte
│ │ │ │ ├── component-code-viewer/
│ │ │ │ │ ├── component-code-viewer-code-title.svelte
│ │ │ │ │ ├── component-code-viewer-code.svelte
│ │ │ │ │ ├── component-code-viewer-copy-code-button.svelte
│ │ │ │ │ ├── component-code-viewer-file-tree.svelte
│ │ │ │ │ ├── component-code-viewer-tree.svelte
│ │ │ │ │ └── component-code-viewer.svelte
│ │ │ │ ├── component-preview-tabs.svelte
│ │ │ │ ├── component-preview.svelte
│ │ │ │ ├── component-source.svelte
│ │ │ │ ├── components-list.svelte
│ │ │ │ ├── copy-button.svelte
│ │ │ │ ├── cta-mobile.svelte
│ │ │ │ ├── cta.svelte
│ │ │ │ ├── customizer.svelte
│ │ │ │ ├── doc-tabs/
│ │ │ │ │ ├── doc-tabs-content.svelte
│ │ │ │ │ ├── doc-tabs-list.svelte
│ │ │ │ │ ├── doc-tabs-trigger.svelte
│ │ │ │ │ ├── doc-tabs.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── docs-copy-page.svelte
│ │ │ │ ├── docs-figure.svelte
│ │ │ │ ├── docs-sidebar.svelte
│ │ │ │ ├── docs-toc.svelte
│ │ │ │ ├── ethical.svelte
│ │ │ │ ├── examples-nav.svelte
│ │ │ │ ├── github-link.svelte
│ │ │ │ ├── github.svelte
│ │ │ │ ├── icon-placeholder/
│ │ │ │ │ ├── hugeicons-icon.svelte
│ │ │ │ │ ├── icon-loader.ts
│ │ │ │ │ ├── icon-placeholder.svelte
│ │ │ │ │ ├── lucide-icon.svelte
│ │ │ │ │ ├── phosphor-icon.svelte
│ │ │ │ │ ├── remixicon-icon.svelte
│ │ │ │ │ └── tabler-icon.svelte
│ │ │ │ ├── icons/
│ │ │ │ │ ├── bash.svelte
│ │ │ │ │ ├── css.svelte
│ │ │ │ │ ├── icons.ts
│ │ │ │ │ ├── json.svelte
│ │ │ │ │ ├── svelte.svelte
│ │ │ │ │ └── ts.svelte
│ │ │ │ ├── install-cards.svelte
│ │ │ │ ├── install-tabs.svelte
│ │ │ │ ├── layout-toggle.svelte
│ │ │ │ ├── linked-card.svelte
│ │ │ │ ├── logo.svelte
│ │ │ │ ├── main-nav.svelte
│ │ │ │ ├── mdsx/
│ │ │ │ │ ├── a.svelte
│ │ │ │ │ ├── blockquote.svelte
│ │ │ │ │ ├── blueprint.svelte
│ │ │ │ │ ├── figcaption.svelte
│ │ │ │ │ ├── h1.svelte
│ │ │ │ │ ├── h2.svelte
│ │ │ │ │ ├── h3.svelte
│ │ │ │ │ ├── h4.svelte
│ │ │ │ │ ├── h5.svelte
│ │ │ │ │ ├── h6.svelte
│ │ │ │ │ ├── hr.svelte
│ │ │ │ │ ├── img.svelte
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── li.svelte
│ │ │ │ │ ├── ol.svelte
│ │ │ │ │ ├── p.svelte
│ │ │ │ │ ├── pre.svelte
│ │ │ │ │ ├── strong.svelte
│ │ │ │ │ ├── table.svelte
│ │ │ │ │ ├── td.svelte
│ │ │ │ │ ├── th.svelte
│ │ │ │ │ ├── tr.svelte
│ │ │ │ │ └── ul.svelte
│ │ │ │ ├── metadata.svelte
│ │ │ │ ├── mobile-nav.svelte
│ │ │ │ ├── mode-switcher.svelte
│ │ │ │ ├── og.svelte
│ │ │ │ ├── page-header/
│ │ │ │ │ ├── page-actions.svelte
│ │ │ │ │ ├── page-header-description.svelte
│ │ │ │ │ ├── page-header-heading.svelte
│ │ │ │ │ └── page-header.svelte
│ │ │ │ ├── page-nav.svelte
│ │ │ │ ├── pm-add-comp.svelte
│ │ │ │ ├── pm-block.svelte
│ │ │ │ ├── pm-create.svelte
│ │ │ │ ├── pm-execute.svelte
│ │ │ │ ├── pm-install.svelte
│ │ │ │ ├── pm-remove.svelte
│ │ │ │ ├── pm-run.svelte
│ │ │ │ ├── pm-upgrade.svelte
│ │ │ │ ├── site-footer.svelte
│ │ │ │ ├── site-header.svelte
│ │ │ │ ├── spinner.svelte
│ │ │ │ ├── step.svelte
│ │ │ │ ├── steps.svelte
│ │ │ │ ├── svelte-white.svelte
│ │ │ │ ├── tab.svelte
│ │ │ │ ├── tailwind-indicator.svelte
│ │ │ │ ├── theme-customizer-code.svelte
│ │ │ │ ├── theme-customizer.svelte
│ │ │ │ └── theme-selector.svelte
│ │ │ ├── config.ts
│ │ │ ├── constants.ts
│ │ │ ├── docs.ts
│ │ │ ├── features/
│ │ │ │ └── design-system/
│ │ │ │ ├── components/
│ │ │ │ │ ├── design-system-provider-state.svelte.ts
│ │ │ │ │ └── design-system-provider.svelte
│ │ │ │ └── index.ts
│ │ │ ├── highlight-code.ts
│ │ │ ├── hooks/
│ │ │ │ ├── use-clipboard.svelte.ts
│ │ │ │ ├── use-is-mac.svelte.ts
│ │ │ │ └── use-mutation-observer.svelte.ts
│ │ │ ├── navigation.ts
│ │ │ ├── package-manager.ts
│ │ │ ├── registry/
│ │ │ │ ├── blocks/
│ │ │ │ │ ├── calendar-01.svelte
│ │ │ │ │ ├── calendar-02.svelte
│ │ │ │ │ ├── calendar-03.svelte
│ │ │ │ │ ├── calendar-04.svelte
│ │ │ │ │ ├── calendar-05.svelte
│ │ │ │ │ ├── calendar-06.svelte
│ │ │ │ │ ├── calendar-07.svelte
│ │ │ │ │ ├── calendar-08.svelte
│ │ │ │ │ ├── calendar-09.svelte
│ │ │ │ │ ├── calendar-10.svelte
│ │ │ │ │ ├── calendar-11.svelte
│ │ │ │ │ ├── calendar-12.svelte
│ │ │ │ │ ├── calendar-13.svelte
│ │ │ │ │ ├── calendar-14.svelte
│ │ │ │ │ ├── calendar-15.svelte
│ │ │ │ │ ├── calendar-16.svelte
│ │ │ │ │ ├── calendar-17.svelte
│ │ │ │ │ ├── calendar-18.svelte
│ │ │ │ │ ├── calendar-19.svelte
│ │ │ │ │ ├── calendar-20.svelte
│ │ │ │ │ ├── calendar-21.svelte
│ │ │ │ │ ├── calendar-22.svelte
│ │ │ │ │ ├── calendar-23.svelte
│ │ │ │ │ ├── calendar-24.svelte
│ │ │ │ │ ├── calendar-25.svelte
│ │ │ │ │ ├── calendar-26.svelte
│ │ │ │ │ ├── calendar-27.svelte
│ │ │ │ │ ├── calendar-28.svelte
│ │ │ │ │ ├── calendar-29.svelte
│ │ │ │ │ ├── calendar-30.svelte
│ │ │ │ │ ├── calendar-31.svelte
│ │ │ │ │ ├── calendar-32.svelte
│ │ │ │ │ ├── chart-area-axes.svelte
│ │ │ │ │ ├── chart-area-default.svelte
│ │ │ │ │ ├── chart-area-gradient.svelte
│ │ │ │ │ ├── chart-area-icons.svelte
│ │ │ │ │ ├── chart-area-interactive.svelte
│ │ │ │ │ ├── chart-area-legend.svelte
│ │ │ │ │ ├── chart-area-linear.svelte
│ │ │ │ │ ├── chart-area-stacked-expand.svelte
│ │ │ │ │ ├── chart-area-stacked.svelte
│ │ │ │ │ ├── chart-area-step.svelte
│ │ │ │ │ ├── chart-bar-active.svelte
│ │ │ │ │ ├── chart-bar-default.svelte
│ │ │ │ │ ├── chart-bar-horizontal.svelte
│ │ │ │ │ ├── chart-bar-interactive.svelte
│ │ │ │ │ ├── chart-bar-label-custom.svelte
│ │ │ │ │ ├── chart-bar-label.svelte
│ │ │ │ │ ├── chart-bar-mixed.svelte
│ │ │ │ │ ├── chart-bar-multiple.svelte
│ │ │ │ │ ├── chart-bar-negative.svelte
│ │ │ │ │ ├── chart-bar-stacked.svelte
│ │ │ │ │ ├── chart-line-default.svelte
│ │ │ │ │ ├── chart-line-dots-colors.svelte
│ │ │ │ │ ├── chart-line-dots-custom.svelte
│ │ │ │ │ ├── chart-line-dots.svelte
│ │ │ │ │ ├── chart-line-interactive.svelte
│ │ │ │ │ ├── chart-line-label-custom.svelte
│ │ │ │ │ ├── chart-line-label.svelte
│ │ │ │ │ ├── chart-line-linear.svelte
│ │ │ │ │ ├── chart-line-multiple.svelte
│ │ │ │ │ ├── chart-line-step.svelte
│ │ │ │ │ ├── chart-pie-donut-active.svelte
│ │ │ │ │ ├── chart-pie-donut-text.svelte
│ │ │ │ │ ├── chart-pie-donut.svelte
│ │ │ │ │ ├── chart-pie-interactive.svelte
│ │ │ │ │ ├── chart-pie-label-custom.svelte
│ │ │ │ │ ├── chart-pie-label-list.svelte
│ │ │ │ │ ├── chart-pie-label.svelte
│ │ │ │ │ ├── chart-pie-legend.svelte
│ │ │ │ │ ├── chart-pie-separator-none.svelte
│ │ │ │ │ ├── chart-pie-simple.svelte
│ │ │ │ │ ├── chart-pie-stacked.svelte
│ │ │ │ │ ├── chart-radar-default.svelte
│ │ │ │ │ ├── chart-radar-dots.svelte
│ │ │ │ │ ├── chart-radar-grid-circle-fill.svelte
│ │ │ │ │ ├── chart-radar-grid-circle-no-lines.svelte
│ │ │ │ │ ├── chart-radar-grid-circle.svelte
│ │ │ │ │ ├── chart-radar-grid-custom.svelte
│ │ │ │ │ ├── chart-radar-grid-fill.svelte
│ │ │ │ │ ├── chart-radar-grid-none.svelte
│ │ │ │ │ ├── chart-radar-icons.svelte
│ │ │ │ │ ├── chart-radar-label-custom.svelte
│ │ │ │ │ ├── chart-radar-legend.svelte
│ │ │ │ │ ├── chart-radar-lines-only.svelte
│ │ │ │ │ ├── chart-radar-multiple.svelte
│ │ │ │ │ ├── chart-radar-radius.svelte
│ │ │ │ │ ├── chart-radial-grid.svelte
│ │ │ │ │ ├── chart-radial-label.svelte
│ │ │ │ │ ├── chart-radial-shape.svelte
│ │ │ │ │ ├── chart-radial-simple.svelte
│ │ │ │ │ ├── chart-radial-stacked.svelte
│ │ │ │ │ ├── chart-radial-text.svelte
│ │ │ │ │ ├── chart-tooltip-advanced.svelte
│ │ │ │ │ ├── chart-tooltip-default.svelte
│ │ │ │ │ ├── chart-tooltip-formatter.svelte
│ │ │ │ │ ├── chart-tooltip-icons.svelte
│ │ │ │ │ ├── chart-tooltip-indicator-line.svelte
│ │ │ │ │ ├── chart-tooltip-indicator-none.svelte
│ │ │ │ │ ├── chart-tooltip-label-custom.svelte
│ │ │ │ │ ├── chart-tooltip-label-formatter.svelte
│ │ │ │ │ ├── chart-tooltip-label-none.svelte
│ │ │ │ │ ├── dashboard-01/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ ├── components/
│ │ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ │ ├── chart-area-interactive.svelte
│ │ │ │ │ │ │ ├── data-table-actions.svelte
│ │ │ │ │ │ │ ├── data-table-cell-viewer.svelte
│ │ │ │ │ │ │ ├── data-table-checkbox.svelte
│ │ │ │ │ │ │ ├── data-table-drag-handle.svelte
│ │ │ │ │ │ │ ├── data-table-header-limit.svelte
│ │ │ │ │ │ │ ├── data-table-header-target.svelte
│ │ │ │ │ │ │ ├── data-table-limit.svelte
│ │ │ │ │ │ │ ├── data-table-reviewer.svelte
│ │ │ │ │ │ │ ├── data-table-status.svelte
│ │ │ │ │ │ │ ├── data-table-target.svelte
│ │ │ │ │ │ │ ├── data-table-type.svelte
│ │ │ │ │ │ │ ├── data-table.svelte
│ │ │ │ │ │ │ ├── nav-documents.svelte
│ │ │ │ │ │ │ ├── nav-main.svelte
│ │ │ │ │ │ │ ├── nav-secondary.svelte
│ │ │ │ │ │ │ ├── nav-user.svelte
│ │ │ │ │ │ │ ├── schemas.ts
│ │ │ │ │ │ │ ├── section-cards.svelte
│ │ │ │ │ │ │ └── site-header.svelte
│ │ │ │ │ │ └── data.ts
│ │ │ │ │ ├── demo-sidebar-controlled.svelte
│ │ │ │ │ ├── demo-sidebar-footer.svelte
│ │ │ │ │ ├── demo-sidebar-group-action.svelte
│ │ │ │ │ ├── demo-sidebar-group-collapsible.svelte
│ │ │ │ │ ├── demo-sidebar-group.svelte
│ │ │ │ │ ├── demo-sidebar-header.svelte
│ │ │ │ │ ├── demo-sidebar-menu-action.svelte
│ │ │ │ │ ├── demo-sidebar-menu-badge.svelte
│ │ │ │ │ ├── demo-sidebar-menu-collapsible.svelte
│ │ │ │ │ ├── demo-sidebar-menu-sub.svelte
│ │ │ │ │ ├── demo-sidebar-menu.svelte
│ │ │ │ │ ├── demo-sidebar.svelte
│ │ │ │ │ ├── login-01/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── login-form.svelte
│ │ │ │ │ ├── login-02/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── login-form.svelte
│ │ │ │ │ ├── login-03/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── login-form.svelte
│ │ │ │ │ ├── login-04/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── login-form.svelte
│ │ │ │ │ ├── login-05/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── login-form.svelte
│ │ │ │ │ ├── new-components-01/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── appearance-settings.svelte
│ │ │ │ │ │ ├── button-group-demo.svelte
│ │ │ │ │ │ ├── button-group-input-group.svelte
│ │ │ │ │ │ ├── button-group-nested.svelte
│ │ │ │ │ │ ├── button-group-popover.svelte
│ │ │ │ │ │ ├── empty-avatar-group.svelte
│ │ │ │ │ │ ├── empty-input-group.svelte
│ │ │ │ │ │ ├── field-choice-card.svelte
│ │ │ │ │ │ ├── field-demo.svelte
│ │ │ │ │ │ ├── field-slider.svelte
│ │ │ │ │ │ ├── input-group-button.svelte
│ │ │ │ │ │ ├── input-group-demo.svelte
│ │ │ │ │ │ ├── input-group-textarea.svelte
│ │ │ │ │ │ ├── item-avatar.svelte
│ │ │ │ │ │ ├── item-demo.svelte
│ │ │ │ │ │ ├── notion-prompt-form.svelte
│ │ │ │ │ │ ├── spinner-badge.svelte
│ │ │ │ │ │ └── spinner-empty.svelte
│ │ │ │ │ ├── otp-01/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── otp-form.svelte
│ │ │ │ │ ├── otp-02/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── otp-form.svelte
│ │ │ │ │ ├── otp-03/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── otp-form.svelte
│ │ │ │ │ ├── otp-04/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── otp-form.svelte
│ │ │ │ │ ├── otp-05/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── otp-form.svelte
│ │ │ │ │ ├── sidebar-01/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ ├── search-form.svelte
│ │ │ │ │ │ └── version-switcher.svelte
│ │ │ │ │ ├── sidebar-02/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ ├── search-form.svelte
│ │ │ │ │ │ └── version-switcher.svelte
│ │ │ │ │ ├── sidebar-03/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── app-sidebar.svelte
│ │ │ │ │ ├── sidebar-04/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── app-sidebar.svelte
│ │ │ │ │ ├── sidebar-05/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ └── search-form.svelte
│ │ │ │ │ ├── sidebar-06/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ ├── nav-main.svelte
│ │ │ │ │ │ └── sidebar-opt-in-form.svelte
│ │ │ │ │ ├── sidebar-07/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ ├── nav-main.svelte
│ │ │ │ │ │ ├── nav-projects.svelte
│ │ │ │ │ │ ├── nav-user.svelte
│ │ │ │ │ │ └── team-switcher.svelte
│ │ │ │ │ ├── sidebar-08/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ ├── nav-main.svelte
│ │ │ │ │ │ ├── nav-projects.svelte
│ │ │ │ │ │ ├── nav-secondary.svelte
│ │ │ │ │ │ └── nav-user.svelte
│ │ │ │ │ ├── sidebar-09/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ └── nav-user.svelte
│ │ │ │ │ ├── sidebar-10/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ ├── nav-actions.svelte
│ │ │ │ │ │ ├── nav-favorites.svelte
│ │ │ │ │ │ ├── nav-main.svelte
│ │ │ │ │ │ ├── nav-secondary.svelte
│ │ │ │ │ │ ├── nav-workspaces.svelte
│ │ │ │ │ │ └── team-switcher.svelte
│ │ │ │ │ ├── sidebar-11/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── app-sidebar.svelte
│ │ │ │ │ ├── sidebar-12/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ ├── calendars.svelte
│ │ │ │ │ │ ├── date-picker.svelte
│ │ │ │ │ │ └── nav-user.svelte
│ │ │ │ │ ├── sidebar-13/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── settings-dialog.svelte
│ │ │ │ │ ├── sidebar-14/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── app-sidebar.svelte
│ │ │ │ │ ├── sidebar-15/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── calendars.svelte
│ │ │ │ │ │ ├── date-picker.svelte
│ │ │ │ │ │ ├── nav-favorites.svelte
│ │ │ │ │ │ ├── nav-main.svelte
│ │ │ │ │ │ ├── nav-secondary.svelte
│ │ │ │ │ │ ├── nav-user.svelte
│ │ │ │ │ │ ├── nav-workspaces.svelte
│ │ │ │ │ │ ├── sidebar-left.svelte
│ │ │ │ │ │ ├── sidebar-right.svelte
│ │ │ │ │ │ └── team-switcher.svelte
│ │ │ │ │ ├── sidebar-16/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ ├── nav-main.svelte
│ │ │ │ │ │ ├── nav-projects.svelte
│ │ │ │ │ │ ├── nav-secondary.svelte
│ │ │ │ │ │ ├── nav-user.svelte
│ │ │ │ │ │ ├── search-form.svelte
│ │ │ │ │ │ └── site-header.svelte
│ │ │ │ │ ├── signup-01/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── signup-form.svelte
│ │ │ │ │ ├── signup-02/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── signup-form.svelte
│ │ │ │ │ ├── signup-03/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── signup-form.svelte
│ │ │ │ │ ├── signup-04/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── signup-form.svelte
│ │ │ │ │ └── signup-05/
│ │ │ │ │ ├── +page.svelte
│ │ │ │ │ └── components/
│ │ │ │ │ └── signup-form.svelte
│ │ │ │ ├── colors.ts
│ │ │ │ ├── config.ts
│ │ │ │ ├── examples/
│ │ │ │ │ ├── accordion-demo.svelte
│ │ │ │ │ ├── alert-demo.svelte
│ │ │ │ │ ├── alert-destructive.svelte
│ │ │ │ │ ├── alert-dialog-demo.svelte
│ │ │ │ │ ├── aspect-ratio-demo.svelte
│ │ │ │ │ ├── avatar-demo.svelte
│ │ │ │ │ ├── badge-demo.svelte
│ │ │ │ │ ├── badge-destructive.svelte
│ │ │ │ │ ├── badge-outline.svelte
│ │ │ │ │ ├── badge-secondary.svelte
│ │ │ │ │ ├── breadcrumb-demo.svelte
│ │ │ │ │ ├── breadcrumb-dropdown.svelte
│ │ │ │ │ ├── breadcrumb-ellipsis.svelte
│ │ │ │ │ ├── breadcrumb-link.svelte
│ │ │ │ │ ├── breadcrumb-responsive.svelte
│ │ │ │ │ ├── breadcrumb-separator.svelte
│ │ │ │ │ ├── button-default.svelte
│ │ │ │ │ ├── button-demo.svelte
│ │ │ │ │ ├── button-destructive.svelte
│ │ │ │ │ ├── button-ghost.svelte
│ │ │ │ │ ├── button-group-demo.svelte
│ │ │ │ │ ├── button-group-dropdown-menu-demo.svelte
│ │ │ │ │ ├── button-group-input-demo.svelte
│ │ │ │ │ ├── button-group-input-group-demo.svelte
│ │ │ │ │ ├── button-group-nested-demo.svelte
│ │ │ │ │ ├── button-group-orientation-demo.svelte
│ │ │ │ │ ├── button-group-popover-demo.svelte
│ │ │ │ │ ├── button-group-select-demo.svelte
│ │ │ │ │ ├── button-group-separator-demo.svelte
│ │ │ │ │ ├── button-group-size-demo.svelte
│ │ │ │ │ ├── button-group-split-demo.svelte
│ │ │ │ │ ├── button-icon.svelte
│ │ │ │ │ ├── button-link.svelte
│ │ │ │ │ ├── button-loading.svelte
│ │ │ │ │ ├── button-outline.svelte
│ │ │ │ │ ├── button-rounded.svelte
│ │ │ │ │ ├── button-secondary.svelte
│ │ │ │ │ ├── button-size.svelte
│ │ │ │ │ ├── button-with-icon.svelte
│ │ │ │ │ ├── calendar-demo.svelte
│ │ │ │ │ ├── calendar-with-selects.svelte
│ │ │ │ │ ├── card-demo.svelte
│ │ │ │ │ ├── card-with-form.svelte
│ │ │ │ │ ├── carousel-api.svelte
│ │ │ │ │ ├── carousel-demo.svelte
│ │ │ │ │ ├── carousel-orientation.svelte
│ │ │ │ │ ├── carousel-plugin.svelte
│ │ │ │ │ ├── carousel-size.svelte
│ │ │ │ │ ├── carousel-spacing.svelte
│ │ │ │ │ ├── chart-bar-axis-tick-demo.svelte
│ │ │ │ │ ├── chart-bar-demo.svelte
│ │ │ │ │ ├── chart-bar-legend-demo.svelte
│ │ │ │ │ ├── chart-bar-tooltip-demo.svelte
│ │ │ │ │ ├── chart-tooltip-demo.svelte
│ │ │ │ │ ├── checkbox-demo.svelte
│ │ │ │ │ ├── checkbox-disabled.svelte
│ │ │ │ │ ├── checkbox-form-multiple.svelte
│ │ │ │ │ ├── checkbox-form-single.svelte
│ │ │ │ │ ├── checkbox-with-text.svelte
│ │ │ │ │ ├── collapsible-demo.svelte
│ │ │ │ │ ├── combobox-demo.svelte
│ │ │ │ │ ├── combobox-dropdown-menu.svelte
│ │ │ │ │ ├── combobox-form.svelte
│ │ │ │ │ ├── combobox-popover.svelte
│ │ │ │ │ ├── combobox-responsive.svelte
│ │ │ │ │ ├── command-demo.svelte
│ │ │ │ │ ├── command-dialog.svelte
│ │ │ │ │ ├── context-menu-demo.svelte
│ │ │ │ │ ├── create/
│ │ │ │ │ │ ├── accordion/
│ │ │ │ │ │ │ ├── accordion-basic.svelte
│ │ │ │ │ │ │ ├── accordion-in-card.svelte
│ │ │ │ │ │ │ ├── accordion-multiple.svelte
│ │ │ │ │ │ │ ├── accordion-with-borders.svelte
│ │ │ │ │ │ │ ├── accordion-with-disabled.svelte
│ │ │ │ │ │ │ └── accordion.svelte
│ │ │ │ │ │ ├── alert/
│ │ │ │ │ │ │ ├── alert-basic.svelte
│ │ │ │ │ │ │ ├── alert-destructive.svelte
│ │ │ │ │ │ │ ├── alert-with-actions.svelte
│ │ │ │ │ │ │ ├── alert-with-icons.svelte
│ │ │ │ │ │ │ └── alert.svelte
│ │ │ │ │ │ ├── alert-dialog/
│ │ │ │ │ │ │ ├── alert-dialog-basic.svelte
│ │ │ │ │ │ │ ├── alert-dialog-destructive.svelte
│ │ │ │ │ │ │ ├── alert-dialog-in-dialog.svelte
│ │ │ │ │ │ │ ├── alert-dialog-small-with-media.svelte
│ │ │ │ │ │ │ ├── alert-dialog-small.svelte
│ │ │ │ │ │ │ ├── alert-dialog-with-media.svelte
│ │ │ │ │ │ │ └── alert-dialog.svelte
│ │ │ │ │ │ ├── aspect-ratio/
│ │ │ │ │ │ │ ├── aspect-ratio-16x9.svelte
│ │ │ │ │ │ │ ├── aspect-ratio-1x1.svelte
│ │ │ │ │ │ │ ├── aspect-ratio-21x9.svelte
│ │ │ │ │ │ │ ├── aspect-ratio-9x16.svelte
│ │ │ │ │ │ │ └── aspect-ratio.svelte
│ │ │ │ │ │ ├── avatar/
│ │ │ │ │ │ │ ├── avatar-group-example.svelte
│ │ │ │ │ │ │ ├── avatar-group-with-count.svelte
│ │ │ │ │ │ │ ├── avatar-group-with-icon-count.svelte
│ │ │ │ │ │ │ ├── avatar-in-empty.svelte
│ │ │ │ │ │ │ ├── avatar-sizes.svelte
│ │ │ │ │ │ │ ├── avatar-with-badge-icon.svelte
│ │ │ │ │ │ │ ├── avatar-with-badge.svelte
│ │ │ │ │ │ │ └── avatar.svelte
│ │ │ │ │ │ ├── badge/
│ │ │ │ │ │ │ ├── badge-as-link.svelte
│ │ │ │ │ │ │ ├── badge-custom-colors.svelte
│ │ │ │ │ │ │ ├── badge-long-text.svelte
│ │ │ │ │ │ │ ├── badge-variants.svelte
│ │ │ │ │ │ │ ├── badge-with-icon-left.svelte
│ │ │ │ │ │ │ ├── badge-with-icon-right.svelte
│ │ │ │ │ │ │ ├── badge-with-spinner.svelte
│ │ │ │ │ │ │ └── badge.svelte
│ │ │ │ │ │ ├── breadcrumb/
│ │ │ │ │ │ │ ├── breadcrumb-basic.svelte
│ │ │ │ │ │ │ ├── breadcrumb-with-dropdown.svelte
│ │ │ │ │ │ │ ├── breadcrumb-with-link.svelte
│ │ │ │ │ │ │ └── breadcrumb.svelte
│ │ │ │ │ │ ├── button/
│ │ │ │ │ │ │ ├── button-examples.svelte
│ │ │ │ │ │ │ ├── button-icon-left.svelte
│ │ │ │ │ │ │ ├── button-icon-only.svelte
│ │ │ │ │ │ │ ├── button-icon-right.svelte
│ │ │ │ │ │ │ ├── button-invalid-states.svelte
│ │ │ │ │ │ │ ├── button-variants-and-sizes.svelte
│ │ │ │ │ │ │ └── button.svelte
│ │ │ │ │ │ ├── button-group/
│ │ │ │ │ │ │ ├── button-group-basic.svelte
│ │ │ │ │ │ │ ├── button-group-navigation.svelte
│ │ │ │ │ │ │ ├── button-group-nested.svelte
│ │ │ │ │ │ │ ├── button-group-pagination-split.svelte
│ │ │ │ │ │ │ ├── button-group-pagination.svelte
│ │ │ │ │ │ │ ├── button-group-text-alignment.svelte
│ │ │ │ │ │ │ ├── button-group-vertical-nested.svelte
│ │ │ │ │ │ │ ├── button-group-vertical.svelte
│ │ │ │ │ │ │ ├── button-group-with-dropdown.svelte
│ │ │ │ │ │ │ ├── button-group-with-fields.svelte
│ │ │ │ │ │ │ ├── button-group-with-icons.svelte
│ │ │ │ │ │ │ ├── button-group-with-input-group.svelte
│ │ │ │ │ │ │ ├── button-group-with-input.svelte
│ │ │ │ │ │ │ ├── button-group-with-like.svelte
│ │ │ │ │ │ │ ├── button-group-with-select-and-input.svelte
│ │ │ │ │ │ │ ├── button-group-with-select.svelte
│ │ │ │ │ │ │ ├── button-group-with-text.svelte
│ │ │ │ │ │ │ └── button-group.svelte
│ │ │ │ │ │ ├── calendar/
│ │ │ │ │ │ │ ├── calendar-booked-dates.svelte
│ │ │ │ │ │ │ ├── calendar-custom-days.svelte
│ │ │ │ │ │ │ ├── calendar-in-card.svelte
│ │ │ │ │ │ │ ├── calendar-in-popover.svelte
│ │ │ │ │ │ │ ├── calendar-multiple.svelte
│ │ │ │ │ │ │ ├── calendar-range-multiple-months.svelte
│ │ │ │ │ │ │ ├── calendar-range.svelte
│ │ │ │ │ │ │ ├── calendar-single.svelte
│ │ │ │ │ │ │ ├── calendar-week-numbers.svelte
│ │ │ │ │ │ │ ├── calendar-with-presets.svelte
│ │ │ │ │ │ │ ├── calendar-with-time.svelte
│ │ │ │ │ │ │ ├── calendar.svelte
│ │ │ │ │ │ │ ├── date-picker-simple.svelte
│ │ │ │ │ │ │ ├── date-picker-with-dropdowns.svelte
│ │ │ │ │ │ │ └── date-picker-with-range.svelte
│ │ │ │ │ │ ├── card/
│ │ │ │ │ │ │ ├── card-default.svelte
│ │ │ │ │ │ │ ├── card-footer-with-border-small.svelte
│ │ │ │ │ │ │ ├── card-footer-with-border.svelte
│ │ │ │ │ │ │ ├── card-header-with-border-small.svelte
│ │ │ │ │ │ │ ├── card-header-with-border.svelte
│ │ │ │ │ │ │ ├── card-login.svelte
│ │ │ │ │ │ │ ├── card-meeting-notes.svelte
│ │ │ │ │ │ │ ├── card-small.svelte
│ │ │ │ │ │ │ ├── card-with-image-small.svelte
│ │ │ │ │ │ │ ├── card-with-image.svelte
│ │ │ │ │ │ │ └── card.svelte
│ │ │ │ │ │ ├── carousel/
│ │ │ │ │ │ │ ├── carousel-basic.svelte
│ │ │ │ │ │ │ ├── carousel-multiple.svelte
│ │ │ │ │ │ │ ├── carousel-with-gap.svelte
│ │ │ │ │ │ │ └── carousel.svelte
│ │ │ │ │ │ ├── chart/
│ │ │ │ │ │ │ ├── chart-area-example.svelte
│ │ │ │ │ │ │ ├── chart-bar-example.svelte
│ │ │ │ │ │ │ ├── chart-line-example.svelte
│ │ │ │ │ │ │ ├── chart-radar-example.svelte
│ │ │ │ │ │ │ ├── chart-radial-example.svelte
│ │ │ │ │ │ │ └── chart.svelte
│ │ │ │ │ │ ├── chatgpt/
│ │ │ │ │ │ │ ├── chatgpt.svelte
│ │ │ │ │ │ │ ├── create-project-form.svelte
│ │ │ │ │ │ │ ├── group-chat-dialog.svelte
│ │ │ │ │ │ │ ├── model-selector.svelte
│ │ │ │ │ │ │ └── prompt-form.svelte
│ │ │ │ │ │ ├── checkbox/
│ │ │ │ │ │ │ ├── checkbox-basic.svelte
│ │ │ │ │ │ │ ├── checkbox-disabled.svelte
│ │ │ │ │ │ │ ├── checkbox-group.svelte
│ │ │ │ │ │ │ ├── checkbox-in-table.svelte
│ │ │ │ │ │ │ ├── checkbox-invalid.svelte
│ │ │ │ │ │ │ ├── checkbox-with-description.svelte
│ │ │ │ │ │ │ ├── checkbox-with-title.svelte
│ │ │ │ │ │ │ └── checkbox.svelte
│ │ │ │ │ │ ├── collapsible/
│ │ │ │ │ │ │ ├── collapsible-file-tree.svelte
│ │ │ │ │ │ │ ├── collapsible-settings.svelte
│ │ │ │ │ │ │ └── collapsible.svelte
│ │ │ │ │ │ ├── combobox/
│ │ │ │ │ │ │ ├── combobox-basic.svelte
│ │ │ │ │ │ │ ├── combobox-disabled-items.svelte
│ │ │ │ │ │ │ ├── combobox-disabled.svelte
│ │ │ │ │ │ │ ├── combobox-in-dialog.svelte
│ │ │ │ │ │ │ ├── combobox-in-popup.svelte
│ │ │ │ │ │ │ ├── combobox-invalid.svelte
│ │ │ │ │ │ │ ├── combobox-large-list.svelte
│ │ │ │ │ │ │ ├── combobox-multiple-invalid.svelte
│ │ │ │ │ │ │ ├── combobox-multiple.svelte
│ │ │ │ │ │ │ ├── combobox-with-custom-items.svelte
│ │ │ │ │ │ │ ├── combobox-with-form.svelte
│ │ │ │ │ │ │ ├── combobox-with-groups-and-separator.svelte
│ │ │ │ │ │ │ ├── combobox-with-groups.svelte
│ │ │ │ │ │ │ └── combobox.svelte
│ │ │ │ │ │ ├── command/
│ │ │ │ │ │ │ ├── command-basic.svelte
│ │ │ │ │ │ │ ├── command-inline.svelte
│ │ │ │ │ │ │ ├── command-many-items.svelte
│ │ │ │ │ │ │ ├── command-with-groups.svelte
│ │ │ │ │ │ │ ├── command-with-shortcuts.svelte
│ │ │ │ │ │ │ └── command.svelte
│ │ │ │ │ │ ├── context-menu/
│ │ │ │ │ │ │ ├── context-menu-basic.svelte
│ │ │ │ │ │ │ ├── context-menu-in-dialog.svelte
│ │ │ │ │ │ │ ├── context-menu-with-checkboxes.svelte
│ │ │ │ │ │ │ ├── context-menu-with-destructive.svelte
│ │ │ │ │ │ │ ├── context-menu-with-groups.svelte
│ │ │ │ │ │ │ ├── context-menu-with-icons.svelte
│ │ │ │ │ │ │ ├── context-menu-with-inset.svelte
│ │ │ │ │ │ │ ├── context-menu-with-radio.svelte
│ │ │ │ │ │ │ ├── context-menu-with-shortcuts.svelte
│ │ │ │ │ │ │ ├── context-menu-with-sides.svelte
│ │ │ │ │ │ │ ├── context-menu-with-submenu.svelte
│ │ │ │ │ │ │ └── context-menu.svelte
│ │ │ │ │ │ ├── demo/
│ │ │ │ │ │ │ └── demo.svelte
│ │ │ │ │ │ ├── dialog/
│ │ │ │ │ │ │ ├── dialog-chat-settings.svelte
│ │ │ │ │ │ │ ├── dialog-no-close-button.svelte
│ │ │ │ │ │ │ ├── dialog-scrollable-content.svelte
│ │ │ │ │ │ │ ├── dialog-with-form.svelte
│ │ │ │ │ │ │ ├── dialog-with-sticky-footer.svelte
│ │ │ │ │ │ │ └── dialog.svelte
│ │ │ │ │ │ ├── drawer/
│ │ │ │ │ │ │ ├── drawer-scrollable-content.svelte
│ │ │ │ │ │ │ ├── drawer-with-sides.svelte
│ │ │ │ │ │ │ └── drawer.svelte
│ │ │ │ │ │ ├── dropdown-menu/
│ │ │ │ │ │ │ ├── dropdown-menu-basic.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-complex.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-in-dialog.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-with-avatar.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-with-checkboxes-icons.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-with-checkboxes.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-with-destructive.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-with-icons.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-with-radio-icons.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-with-radio.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-with-shortcuts.svelte
│ │ │ │ │ │ │ ├── dropdown-menu-with-submenu.svelte
│ │ │ │ │ │ │ └── dropdown-menu.svelte
│ │ │ │ │ │ ├── elevenlabs/
│ │ │ │ │ │ │ ├── bar-visualizer-demo.svelte
│ │ │ │ │ │ │ ├── bar-visualizer.svelte
│ │ │ │ │ │ │ ├── elevenlabs.svelte
│ │ │ │ │ │ │ ├── live-waveform.svelte
│ │ │ │ │ │ │ └── waveform-demo.svelte
│ │ │ │ │ │ ├── empty/
│ │ │ │ │ │ │ ├── empty-basic.svelte
│ │ │ │ │ │ │ ├── empty-in-card.svelte
│ │ │ │ │ │ │ ├── empty-with-border.svelte
│ │ │ │ │ │ │ ├── empty-with-icon.svelte
│ │ │ │ │ │ │ ├── empty-with-muted-background-alt.svelte
│ │ │ │ │ │ │ ├── empty-with-muted-background.svelte
│ │ │ │ │ │ │ └── empty.svelte
│ │ │ │ │ │ ├── field/
│ │ │ │ │ │ │ ├── field-checkbox-fields.svelte
│ │ │ │ │ │ │ ├── field-horizontal-fields.svelte
│ │ │ │ │ │ │ ├── field-input-fields.svelte
│ │ │ │ │ │ │ ├── field-input-otp-fields.svelte
│ │ │ │ │ │ │ ├── field-native-select-fields.svelte
│ │ │ │ │ │ │ ├── field-radio-fields.svelte
│ │ │ │ │ │ │ ├── field-select-fields.svelte
│ │ │ │ │ │ │ ├── field-slider-fields.svelte
│ │ │ │ │ │ │ ├── field-switch-fields.svelte
│ │ │ │ │ │ │ ├── field-textarea-fields.svelte
│ │ │ │ │ │ │ └── field.svelte
│ │ │ │ │ │ ├── github/
│ │ │ │ │ │ │ ├── assign-issue.svelte
│ │ │ │ │ │ │ ├── codespaces-card.svelte
│ │ │ │ │ │ │ ├── contributions-activity.svelte
│ │ │ │ │ │ │ ├── contributors.svelte
│ │ │ │ │ │ │ ├── github.svelte
│ │ │ │ │ │ │ ├── navbar.svelte
│ │ │ │ │ │ │ ├── profile.svelte
│ │ │ │ │ │ │ └── repository-toolbar.svelte
│ │ │ │ │ │ ├── home/
│ │ │ │ │ │ │ ├── badge-examples.svelte
│ │ │ │ │ │ │ ├── button-group-examples.svelte
│ │ │ │ │ │ │ ├── empty-avatar-group.svelte
│ │ │ │ │ │ │ ├── field-examples.svelte
│ │ │ │ │ │ │ ├── form-example.svelte
│ │ │ │ │ │ │ ├── home.svelte
│ │ │ │ │ │ │ ├── input-group-examples.svelte
│ │ │ │ │ │ │ ├── item-example.svelte
│ │ │ │ │ │ │ ├── observability-card.svelte
│ │ │ │ │ │ │ ├── sheet-example.svelte
│ │ │ │ │ │ │ └── small-form-example.svelte
│ │ │ │ │ │ ├── hover-card/
│ │ │ │ │ │ │ ├── hover-card-in-dialog.svelte
│ │ │ │ │ │ │ ├── hover-card-sides.svelte
│ │ │ │ │ │ │ └── hover-card.svelte
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── input/
│ │ │ │ │ │ │ ├── input-basic.svelte
│ │ │ │ │ │ │ ├── input-disabled.svelte
│ │ │ │ │ │ │ ├── input-form.svelte
│ │ │ │ │ │ │ ├── input-invalid.svelte
│ │ │ │ │ │ │ ├── input-types.svelte
│ │ │ │ │ │ │ ├── input-with-button.svelte
│ │ │ │ │ │ │ ├── input-with-description.svelte
│ │ │ │ │ │ │ ├── input-with-label.svelte
│ │ │ │ │ │ │ ├── input-with-native-select.svelte
│ │ │ │ │ │ │ ├── input-with-select.svelte
│ │ │ │ │ │ │ └── input.svelte
│ │ │ │ │ │ ├── input-group/
│ │ │ │ │ │ │ ├── input-group-basic.svelte
│ │ │ │ │ │ │ ├── input-group-in-card.svelte
│ │ │ │ │ │ │ ├── input-group-textarea-examples.svelte
│ │ │ │ │ │ │ ├── input-group-with-addons.svelte
│ │ │ │ │ │ │ ├── input-group-with-buttons.svelte
│ │ │ │ │ │ │ ├── input-group-with-kbd.svelte
│ │ │ │ │ │ │ ├── input-group-with-tooltip.svelte
│ │ │ │ │ │ │ └── input-group.svelte
│ │ │ │ │ │ ├── input-otp/
│ │ │ │ │ │ │ ├── input-otp-alphanumeric.svelte
│ │ │ │ │ │ │ ├── input-otp-disabled.svelte
│ │ │ │ │ │ │ ├── input-otp-form.svelte
│ │ │ │ │ │ │ ├── input-otp-four-digits.svelte
│ │ │ │ │ │ │ ├── input-otp-invalid.svelte
│ │ │ │ │ │ │ ├── input-otp-pattern.svelte
│ │ │ │ │ │ │ ├── input-otp-simple.svelte
│ │ │ │ │ │ │ ├── input-otp-with-separator.svelte
│ │ │ │ │ │ │ └── input-otp.svelte
│ │ │ │ │ │ ├── item/
│ │ │ │ │ │ │ ├── item-as-child.svelte
│ │ │ │ │ │ │ ├── item-footer.svelte
│ │ │ │ │ │ │ ├── item-group.svelte
│ │ │ │ │ │ │ ├── item-header-and-footer.svelte
│ │ │ │ │ │ │ ├── item-header.svelte
│ │ │ │ │ │ │ ├── item-muted-group.svelte
│ │ │ │ │ │ │ ├── item-muted-image.svelte
│ │ │ │ │ │ │ ├── item-muted-link.svelte
│ │ │ │ │ │ │ ├── item-outline-group.svelte
│ │ │ │ │ │ │ ├── item-outline-image-extra-small.svelte
│ │ │ │ │ │ │ ├── item-outline-image-small.svelte
│ │ │ │ │ │ │ ├── item-outline-image.svelte
│ │ │ │ │ │ │ ├── item-outline-link.svelte
│ │ │ │ │ │ │ ├── item-separator.svelte
│ │ │ │ │ │ │ ├── item-variants.svelte
│ │ │ │ │ │ │ ├── item-with-image.svelte
│ │ │ │ │ │ │ └── item.svelte
│ │ │ │ │ │ ├── kbd/
│ │ │ │ │ │ │ ├── kbd-arrow-keys.svelte
│ │ │ │ │ │ │ ├── kbd-basic.svelte
│ │ │ │ │ │ │ ├── kbd-group-example.svelte
│ │ │ │ │ │ │ ├── kbd-in-input-group.svelte
│ │ │ │ │ │ │ ├── kbd-in-tooltip.svelte
│ │ │ │ │ │ │ ├── kbd-modifier-keys.svelte
│ │ │ │ │ │ │ ├── kbd-with-icons-and-text.svelte
│ │ │ │ │ │ │ ├── kbd-with-icons.svelte
│ │ │ │ │ │ │ ├── kbd-with-samp.svelte
│ │ │ │ │ │ │ └── kbd.svelte
│ │ │ │ │ │ ├── label/
│ │ │ │ │ │ │ ├── label-disabled.svelte
│ │ │ │ │ │ │ ├── label-with-checkbox.svelte
│ │ │ │ │ │ │ ├── label-with-input.svelte
│ │ │ │ │ │ │ ├── label-with-textarea.svelte
│ │ │ │ │ │ │ └── label.svelte
│ │ │ │ │ │ ├── menubar/
│ │ │ │ │ │ │ ├── menubar-basic.svelte
│ │ │ │ │ │ │ ├── menubar-destructive.svelte
│ │ │ │ │ │ │ ├── menubar-format.svelte
│ │ │ │ │ │ │ ├── menubar-in-dialog.svelte
│ │ │ │ │ │ │ ├── menubar-insert.svelte
│ │ │ │ │ │ │ ├── menubar-with-checkboxes.svelte
│ │ │ │ │ │ │ ├── menubar-with-icons.svelte
│ │ │ │ │ │ │ ├── menubar-with-inset.svelte
│ │ │ │ │ │ │ ├── menubar-with-radio.svelte
│ │ │ │ │ │ │ ├── menubar-with-shortcuts.svelte
│ │ │ │ │ │ │ ├── menubar-with-submenu.svelte
│ │ │ │ │ │ │ └── menubar.svelte
│ │ │ │ │ │ ├── native-select/
│ │ │ │ │ │ │ ├── native-select-basic.svelte
│ │ │ │ │ │ │ ├── native-select-disabled.svelte
│ │ │ │ │ │ │ ├── native-select-invalid.svelte
│ │ │ │ │ │ │ ├── native-select-sizes.svelte
│ │ │ │ │ │ │ ├── native-select-with-field.svelte
│ │ │ │ │ │ │ ├── native-select-with-groups.svelte
│ │ │ │ │ │ │ └── native-select.svelte
│ │ │ │ │ │ ├── navigation-menu/
│ │ │ │ │ │ │ ├── navigation-menu-with-viewport.svelte
│ │ │ │ │ │ │ ├── navigation-menu-without-viewport.svelte
│ │ │ │ │ │ │ └── navigation-menu.svelte
│ │ │ │ │ │ ├── pagination/
│ │ │ │ │ │ │ ├── pagination-basic.svelte
│ │ │ │ │ │ │ ├── pagination-simple.svelte
│ │ │ │ │ │ │ ├── pagination-with-select.svelte
│ │ │ │ │ │ │ └── pagination.svelte
│ │ │ │ │ │ ├── popover/
│ │ │ │ │ │ │ ├── popover-alignments.svelte
│ │ │ │ │ │ │ ├── popover-basic.svelte
│ │ │ │ │ │ │ ├── popover-in-dialog.svelte
│ │ │ │ │ │ │ ├── popover-with-form.svelte
│ │ │ │ │ │ │ └── popover.svelte
│ │ │ │ │ │ ├── preview/
│ │ │ │ │ │ │ ├── cards/
│ │ │ │ │ │ │ │ ├── activate-agent-dialog.svelte
│ │ │ │ │ │ │ │ ├── analytics-card.svelte
│ │ │ │ │ │ │ │ ├── anomaly-alert.svelte
│ │ │ │ │ │ │ │ ├── assign-issue.svelte
│ │ │ │ │ │ │ │ ├── bar-chart-card.svelte
│ │ │ │ │ │ │ │ ├── bar-visualizer-card.svelte
│ │ │ │ │ │ │ │ ├── book-appointment.svelte
│ │ │ │ │ │ │ │ ├── codespaces-card.svelte
│ │ │ │ │ │ │ │ ├── contributions-activity.svelte
│ │ │ │ │ │ │ │ ├── contributors.svelte
│ │ │ │ │ │ │ │ ├── environment-variables.svelte
│ │ │ │ │ │ │ │ ├── feedback-form.svelte
│ │ │ │ │ │ │ │ ├── file-upload.svelte
│ │ │ │ │ │ │ │ ├── github-profile.svelte
│ │ │ │ │ │ │ │ ├── icon-preview-grid.svelte
│ │ │ │ │ │ │ │ ├── invite-team.svelte
│ │ │ │ │ │ │ │ ├── invoice.svelte
│ │ │ │ │ │ │ │ ├── live-waveform.svelte
│ │ │ │ │ │ │ │ ├── no-team-members.svelte
│ │ │ │ │ │ │ │ ├── not-found.svelte
│ │ │ │ │ │ │ │ ├── observability-card.svelte
│ │ │ │ │ │ │ │ ├── pie-chart-card.svelte
│ │ │ │ │ │ │ │ ├── report-bug.svelte
│ │ │ │ │ │ │ │ ├── shipping-address.svelte
│ │ │ │ │ │ │ │ ├── shortcuts.svelte
│ │ │ │ │ │ │ │ ├── skeleton-loading.svelte
│ │ │ │ │ │ │ │ ├── sleep-report.svelte
│ │ │ │ │ │ │ │ ├── style-overview.svelte
│ │ │ │ │ │ │ │ ├── ui-elements.svelte
│ │ │ │ │ │ │ │ ├── usage-card.svelte
│ │ │ │ │ │ │ │ ├── visitors.svelte
│ │ │ │ │ │ │ │ └── weekly-fitness-summary.svelte
│ │ │ │ │ │ │ └── preview.svelte
│ │ │ │ │ │ ├── progress/
│ │ │ │ │ │ │ ├── progress-bar.svelte
│ │ │ │ │ │ │ ├── progress-controlled.svelte
│ │ │ │ │ │ │ ├── progress-file-upload-list.svelte
│ │ │ │ │ │ │ ├── progress-with-label.svelte
│ │ │ │ │ │ │ └── progress.svelte
│ │ │ │ │ │ ├── radio-group/
│ │ │ │ │ │ │ ├── radio-group-basic.svelte
│ │ │ │ │ │ │ ├── radio-group-disabled.svelte
│ │ │ │ │ │ │ ├── radio-group-grid.svelte
│ │ │ │ │ │ │ ├── radio-group-invalid.svelte
│ │ │ │ │ │ │ ├── radio-group-with-descriptions.svelte
│ │ │ │ │ │ │ ├── radio-group-with-field-set.svelte
│ │ │ │ │ │ │ └── radio-group.svelte
│ │ │ │ │ │ ├── resizable/
│ │ │ │ │ │ │ ├── resizable-controlled.svelte
│ │ │ │ │ │ │ ├── resizable-horizontal.svelte
│ │ │ │ │ │ │ ├── resizable-nested.svelte
│ │ │ │ │ │ │ ├── resizable-vertical.svelte
│ │ │ │ │ │ │ ├── resizable-with-handle.svelte
│ │ │ │ │ │ │ └── resizable.svelte
│ │ │ │ │ │ ├── scroll-area/
│ │ │ │ │ │ │ ├── scroll-area-horizontal.svelte
│ │ │ │ │ │ │ ├── scroll-area-vertical.svelte
│ │ │ │ │ │ │ └── scroll-area.svelte
│ │ │ │ │ │ ├── select/
│ │ │ │ │ │ │ ├── select-basic.svelte
│ │ │ │ │ │ │ ├── select-disabled.svelte
│ │ │ │ │ │ │ ├── select-in-dialog.svelte
│ │ │ │ │ │ │ ├── select-inline.svelte
│ │ │ │ │ │ │ ├── select-invalid.svelte
│ │ │ │ │ │ │ ├── select-item-aligned.svelte
│ │ │ │ │ │ │ ├── select-large-list.svelte
│ │ │ │ │ │ │ ├── select-multiple.svelte
│ │ │ │ │ │ │ ├── select-plan.svelte
│ │ │ │ │ │ │ ├── select-sizes.svelte
│ │ │ │ │ │ │ ├── select-with-button.svelte
│ │ │ │ │ │ │ ├── select-with-field.svelte
│ │ │ │ │ │ │ ├── select-with-groups.svelte
│ │ │ │ │ │ │ ├── select-with-icons.svelte
│ │ │ │ │ │ │ └── select.svelte
│ │ │ │ │ │ ├── separator/
│ │ │ │ │ │ │ ├── separator-horizontal.svelte
│ │ │ │ │ │ │ ├── separator-in-list.svelte
│ │ │ │ │ │ │ ├── separator-vertical-menu.svelte
│ │ │ │ │ │ │ ├── separator-vertical.svelte
│ │ │ │ │ │ │ └── separator.svelte
│ │ │ │ │ │ ├── sheet/
│ │ │ │ │ │ │ ├── sheet-no-close-button.svelte
│ │ │ │ │ │ │ ├── sheet-with-form.svelte
│ │ │ │ │ │ │ ├── sheet-with-sides.svelte
│ │ │ │ │ │ │ └── sheet.svelte
│ │ │ │ │ │ ├── sidebar/
│ │ │ │ │ │ │ └── sidebar.svelte
│ │ │ │ │ │ ├── sidebar-floating/
│ │ │ │ │ │ │ └── sidebar-floating.svelte
│ │ │ │ │ │ ├── sidebar-icon/
│ │ │ │ │ │ │ └── sidebar-icon.svelte
│ │ │ │ │ │ ├── sidebar-inset/
│ │ │ │ │ │ │ └── sidebar-inset.svelte
│ │ │ │ │ │ ├── skeleton/
│ │ │ │ │ │ │ ├── skeleton-avatar.svelte
│ │ │ │ │ │ │ ├── skeleton-card.svelte
│ │ │ │ │ │ │ ├── skeleton-form.svelte
│ │ │ │ │ │ │ ├── skeleton-table.svelte
│ │ │ │ │ │ │ ├── skeleton-text.svelte
│ │ │ │ │ │ │ └── skeleton.svelte
│ │ │ │ │ │ ├── slider/
│ │ │ │ │ │ │ ├── slider-basic.svelte
│ │ │ │ │ │ │ ├── slider-controlled.svelte
│ │ │ │ │ │ │ ├── slider-disabled.svelte
│ │ │ │ │ │ │ ├── slider-multiple.svelte
│ │ │ │ │ │ │ ├── slider-range.svelte
│ │ │ │ │ │ │ ├── slider-vertical.svelte
│ │ │ │ │ │ │ └── slider.svelte
│ │ │ │ │ │ ├── sonner/
│ │ │ │ │ │ │ ├── sonner-basic.svelte
│ │ │ │ │ │ │ ├── sonner-with-description.svelte
│ │ │ │ │ │ │ └── sonner.svelte
│ │ │ │ │ │ ├── spinner/
│ │ │ │ │ │ │ ├── spinner-basic.svelte
│ │ │ │ │ │ │ ├── spinner-in-badges.svelte
│ │ │ │ │ │ │ ├── spinner-in-buttons.svelte
│ │ │ │ │ │ │ ├── spinner-in-empty.svelte
│ │ │ │ │ │ │ ├── spinner-in-input-group.svelte
│ │ │ │ │ │ │ └── spinner.svelte
│ │ │ │ │ │ ├── switch/
│ │ │ │ │ │ │ ├── switch-basic.svelte
│ │ │ │ │ │ │ ├── switch-disabled.svelte
│ │ │ │ │ │ │ ├── switch-sizes.svelte
│ │ │ │ │ │ │ ├── switch-with-description.svelte
│ │ │ │ │ │ │ └── switch.svelte
│ │ │ │ │ │ ├── table/
│ │ │ │ │ │ │ ├── table-basic.svelte
│ │ │ │ │ │ │ ├── table-simple.svelte
│ │ │ │ │ │ │ ├── table-with-actions.svelte
│ │ │ │ │ │ │ ├── table-with-badges.svelte
│ │ │ │ │ │ │ ├── table-with-footer.svelte
│ │ │ │ │ │ │ ├── table-with-input.svelte
│ │ │ │ │ │ │ ├── table-with-select.svelte
│ │ │ │ │ │ │ └── table.svelte
│ │ │ │ │ │ ├── tabs/
│ │ │ │ │ │ │ ├── tabs-basic.svelte
│ │ │ │ │ │ │ ├── tabs-disabled.svelte
│ │ │ │ │ │ │ ├── tabs-icon-only.svelte
│ │ │ │ │ │ │ ├── tabs-line-disabled.svelte
│ │ │ │ │ │ │ ├── tabs-line-with-content.svelte
│ │ │ │ │ │ │ ├── tabs-line.svelte
│ │ │ │ │ │ │ ├── tabs-multiple.svelte
│ │ │ │ │ │ │ ├── tabs-variants-comparison.svelte
│ │ │ │ │ │ │ ├── tabs-vertical.svelte
│ │ │ │ │ │ │ ├── tabs-with-content.svelte
│ │ │ │ │ │ │ ├── tabs-with-dropdown.svelte
│ │ │ │ │ │ │ ├── tabs-with-icons.svelte
│ │ │ │ │ │ │ ├── tabs-with-input-and-button.svelte
│ │ │ │ │ │ │ └── tabs.svelte
│ │ │ │ │ │ ├── textarea/
│ │ │ │ │ │ │ ├── textarea-basic.svelte
│ │ │ │ │ │ │ ├── textarea-disabled.svelte
│ │ │ │ │ │ │ ├── textarea-invalid.svelte
│ │ │ │ │ │ │ ├── textarea-with-description.svelte
│ │ │ │ │ │ │ ├── textarea-with-label.svelte
│ │ │ │ │ │ │ └── textarea.svelte
│ │ │ │ │ │ ├── toggle/
│ │ │ │ │ │ │ ├── toggle-basic.svelte
│ │ │ │ │ │ │ ├── toggle-disabled.svelte
│ │ │ │ │ │ │ ├── toggle-outline.svelte
│ │ │ │ │ │ │ ├── toggle-sizes.svelte
│ │ │ │ │ │ │ ├── toggle-with-button-icon-text.svelte
│ │ │ │ │ │ │ ├── toggle-with-button-icon.svelte
│ │ │ │ │ │ │ ├── toggle-with-button-text.svelte
│ │ │ │ │ │ │ ├── toggle-with-icon.svelte
│ │ │ │ │ │ │ └── toggle.svelte
│ │ │ │ │ │ ├── toggle-group/
│ │ │ │ │ │ │ ├── toggle-group-basic.svelte
│ │ │ │ │ │ │ ├── toggle-group-date-range.svelte
│ │ │ │ │ │ │ ├── toggle-group-filter.svelte
│ │ │ │ │ │ │ ├── toggle-group-font-weight-selector.svelte
│ │ │ │ │ │ │ ├── toggle-group-outline-with-icons.svelte
│ │ │ │ │ │ │ ├── toggle-group-outline.svelte
│ │ │ │ │ │ │ ├── toggle-group-sizes.svelte
│ │ │ │ │ │ │ ├── toggle-group-sort.svelte
│ │ │ │ │ │ │ ├── toggle-group-spacing.svelte
│ │ │ │ │ │ │ ├── toggle-group-vertical-outline-with-icons.svelte
│ │ │ │ │ │ │ ├── toggle-group-vertical-outline.svelte
│ │ │ │ │ │ │ ├── toggle-group-vertical-with-spacing.svelte
│ │ │ │ │ │ │ ├── toggle-group-vertical.svelte
│ │ │ │ │ │ │ ├── toggle-group-with-icons.svelte
│ │ │ │ │ │ │ ├── toggle-group-with-input-and-select.svelte
│ │ │ │ │ │ │ └── toggle-group.svelte
│ │ │ │ │ │ ├── tooltip/
│ │ │ │ │ │ │ ├── tooltip-basic.svelte
│ │ │ │ │ │ │ ├── tooltip-disabled.svelte
│ │ │ │ │ │ │ ├── tooltip-formatted.svelte
│ │ │ │ │ │ │ ├── tooltip-long-content.svelte
│ │ │ │ │ │ │ ├── tooltip-on-link.svelte
│ │ │ │ │ │ │ ├── tooltip-sides.svelte
│ │ │ │ │ │ │ ├── tooltip-with-icon.svelte
│ │ │ │ │ │ │ ├── tooltip-with-keyboard.svelte
│ │ │ │ │ │ │ └── tooltip.svelte
│ │ │ │ │ │ └── vercel/
│ │ │ │ │ │ ├── activate-agent-dialog.svelte
│ │ │ │ │ │ ├── analytics-card.svelte
│ │ │ │ │ │ ├── anomaly-alert.svelte
│ │ │ │ │ │ ├── billing-list.svelte
│ │ │ │ │ │ ├── circular-gauge.svelte
│ │ │ │ │ │ ├── deployment-filter.svelte
│ │ │ │ │ │ ├── feedback-form.svelte
│ │ │ │ │ │ ├── observability-card.svelte
│ │ │ │ │ │ ├── usage-card.svelte
│ │ │ │ │ │ └── vercel.svelte
│ │ │ │ │ ├── dark-mode-dropdown-menu.svelte
│ │ │ │ │ ├── dark-mode-light-switch.svelte
│ │ │ │ │ ├── data-table/
│ │ │ │ │ │ ├── data-table-actions.svelte
│ │ │ │ │ │ ├── data-table-checkbox.svelte
│ │ │ │ │ │ └── data-table-email-button.svelte
│ │ │ │ │ ├── data-table-demo.svelte
│ │ │ │ │ ├── date-picker-demo.svelte
│ │ │ │ │ ├── date-picker-form.svelte
│ │ │ │ │ ├── date-picker-with-presets.svelte
│ │ │ │ │ ├── date-picker-with-range.svelte
│ │ │ │ │ ├── dialog-close-button.svelte
│ │ │ │ │ ├── dialog-demo.svelte
│ │ │ │ │ ├── drawer-demo.svelte
│ │ │ │ │ ├── drawer-dialog.svelte
│ │ │ │ │ ├── dropdown-menu-checkboxes.svelte
│ │ │ │ │ ├── dropdown-menu-demo.svelte
│ │ │ │ │ ├── dropdown-menu-dialog.svelte
│ │ │ │ │ ├── dropdown-menu-radio-group.svelte
│ │ │ │ │ ├── empty-avatar-demo.svelte
│ │ │ │ │ ├── empty-avatar-group-demo.svelte
│ │ │ │ │ ├── empty-background-demo.svelte
│ │ │ │ │ ├── empty-demo.svelte
│ │ │ │ │ ├── empty-input-group-demo.svelte
│ │ │ │ │ ├── empty-outline-demo.svelte
│ │ │ │ │ ├── field-checkbox-demo.svelte
│ │ │ │ │ ├── field-checkbox.svelte
│ │ │ │ │ ├── field-choice-card.svelte
│ │ │ │ │ ├── field-demo.svelte
│ │ │ │ │ ├── field-field-group-demo.svelte
│ │ │ │ │ ├── field-field-set-demo.svelte
│ │ │ │ │ ├── field-input-demo.svelte
│ │ │ │ │ ├── field-input.svelte
│ │ │ │ │ ├── field-radio-demo.svelte
│ │ │ │ │ ├── field-radio.svelte
│ │ │ │ │ ├── field-responsive-layout-demo.svelte
│ │ │ │ │ ├── field-select-demo.svelte
│ │ │ │ │ ├── field-select.svelte
│ │ │ │ │ ├── field-slider-demo.svelte
│ │ │ │ │ ├── field-slider.svelte
│ │ │ │ │ ├── field-switch-demo.svelte
│ │ │ │ │ ├── field-switch.svelte
│ │ │ │ │ ├── field-textarea-demo.svelte
│ │ │ │ │ ├── field-textarea.svelte
│ │ │ │ │ ├── form-demo.svelte
│ │ │ │ │ ├── hover-card-demo.svelte
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── input-demo.svelte
│ │ │ │ │ ├── input-disabled.svelte
│ │ │ │ │ ├── input-file.svelte
│ │ │ │ │ ├── input-group-button-demo.svelte
│ │ │ │ │ ├── input-group-button-group-demo.svelte
│ │ │ │ │ ├── input-group-custom-input-demo.svelte
│ │ │ │ │ ├── input-group-demo.svelte
│ │ │ │ │ ├── input-group-dropdown-demo.svelte
│ │ │ │ │ ├── input-group-icon-demo.svelte
│ │ │ │ │ ├── input-group-label-demo.svelte
│ │ │ │ │ ├── input-group-spinner-demo.svelte
│ │ │ │ │ ├── input-group-text-demo.svelte
│ │ │ │ │ ├── input-group-textarea-demo.svelte
│ │ │ │ │ ├── input-group-tooltip-demo.svelte
│ │ │ │ │ ├── input-invalid.svelte
│ │ │ │ │ ├── input-otp-controlled.svelte
│ │ │ │ │ ├── input-otp-demo.svelte
│ │ │ │ │ ├── input-otp-form.svelte
│ │ │ │ │ ├── input-otp-invalid.svelte
│ │ │ │ │ ├── input-otp-pattern.svelte
│ │ │ │ │ ├── input-otp-separator.svelte
│ │ │ │ │ ├── input-with-button.svelte
│ │ │ │ │ ├── input-with-label.svelte
│ │ │ │ │ ├── input-with-text.svelte
│ │ │ │ │ ├── item-avatar-demo.svelte
│ │ │ │ │ ├── item-demo.svelte
│ │ │ │ │ ├── item-dropdown-demo.svelte
│ │ │ │ │ ├── item-group-demo.svelte
│ │ │ │ │ ├── item-header-demo.svelte
│ │ │ │ │ ├── item-icon-demo.svelte
│ │ │ │ │ ├── item-image-demo.svelte
│ │ │ │ │ ├── item-link-demo.svelte
│ │ │ │ │ ├── item-size-demo.svelte
│ │ │ │ │ ├── item-variants-demo.svelte
│ │ │ │ │ ├── kbd-button-demo.svelte
│ │ │ │ │ ├── kbd-demo.svelte
│ │ │ │ │ ├── kbd-group-demo.svelte
│ │ │ │ │ ├── kbd-input-group-demo.svelte
│ │ │ │ │ ├── kbd-tooltip-demo.svelte
│ │ │ │ │ ├── label-demo.svelte
│ │ │ │ │ ├── menubar-demo.svelte
│ │ │ │ │ ├── native-select-demo.svelte
│ │ │ │ │ ├── native-select-disabled.svelte
│ │ │ │ │ ├── native-select-groups.svelte
│ │ │ │ │ ├── native-select-invalid.svelte
│ │ │ │ │ ├── navigation-menu-demo.svelte
│ │ │ │ │ ├── pagination-demo.svelte
│ │ │ │ │ ├── popover-demo.svelte
│ │ │ │ │ ├── progress-demo.svelte
│ │ │ │ │ ├── radio-group-demo.svelte
│ │ │ │ │ ├── radio-group-form.svelte
│ │ │ │ │ ├── range-calendar-demo.svelte
│ │ │ │ │ ├── resizable-demo.svelte
│ │ │ │ │ ├── resizable-handle.svelte
│ │ │ │ │ ├── resizable-vertical.svelte
│ │ │ │ │ ├── scroll-area-both.svelte
│ │ │ │ │ ├── scroll-area-demo.svelte
│ │ │ │ │ ├── scroll-area-horizontal.svelte
│ │ │ │ │ ├── select-demo.svelte
│ │ │ │ │ ├── select-form.svelte
│ │ │ │ │ ├── select-scrollable.svelte
│ │ │ │ │ ├── separator-demo.svelte
│ │ │ │ │ ├── sheet-demo.svelte
│ │ │ │ │ ├── sheet-side.svelte
│ │ │ │ │ ├── skeleton-card.svelte
│ │ │ │ │ ├── skeleton-demo.svelte
│ │ │ │ │ ├── slider-demo.svelte
│ │ │ │ │ ├── slider-multiple.svelte
│ │ │ │ │ ├── slider-vertical.svelte
│ │ │ │ │ ├── sonner-demo.svelte
│ │ │ │ │ ├── sonner-types.svelte
│ │ │ │ │ ├── spinner-badge-demo.svelte
│ │ │ │ │ ├── spinner-button-demo.svelte
│ │ │ │ │ ├── spinner-color-demo.svelte
│ │ │ │ │ ├── spinner-custom-demo.svelte
│ │ │ │ │ ├── spinner-demo.svelte
│ │ │ │ │ ├── spinner-empty-demo.svelte
│ │ │ │ │ ├── spinner-input-group-demo.svelte
│ │ │ │ │ ├── spinner-item-demo.svelte
│ │ │ │ │ ├── spinner-size-demo.svelte
│ │ │ │ │ ├── switch-demo.svelte
│ │ │ │ │ ├── switch-form.svelte
│ │ │ │ │ ├── table-demo.svelte
│ │ │ │ │ ├── tabs-demo.svelte
│ │ │ │ │ ├── textarea-demo.svelte
│ │ │ │ │ ├── textarea-disabled.svelte
│ │ │ │ │ ├── textarea-form.svelte
│ │ │ │ │ ├── textarea-with-button.svelte
│ │ │ │ │ ├── textarea-with-label.svelte
│ │ │ │ │ ├── textarea-with-text.svelte
│ │ │ │ │ ├── toggle-demo.svelte
│ │ │ │ │ ├── toggle-disabled.svelte
│ │ │ │ │ ├── toggle-group-demo.svelte
│ │ │ │ │ ├── toggle-group-disabled.svelte
│ │ │ │ │ ├── toggle-group-lg.svelte
│ │ │ │ │ ├── toggle-group-outline.svelte
│ │ │ │ │ ├── toggle-group-single.svelte
│ │ │ │ │ ├── toggle-group-sm.svelte
│ │ │ │ │ ├── toggle-group-spacing.svelte
│ │ │ │ │ ├── toggle-lg.svelte
│ │ │ │ │ ├── toggle-outline.svelte
│ │ │ │ │ ├── toggle-sm.svelte
│ │ │ │ │ ├── toggle-with-text.svelte
│ │ │ │ │ ├── tooltip-demo.svelte
│ │ │ │ │ ├── typography-blockquote.svelte
│ │ │ │ │ ├── typography-demo.svelte
│ │ │ │ │ ├── typography-h1.svelte
│ │ │ │ │ ├── typography-h2.svelte
│ │ │ │ │ ├── typography-h3.svelte
│ │ │ │ │ ├── typography-h4.svelte
│ │ │ │ │ ├── typography-inline-code.svelte
│ │ │ │ │ ├── typography-large.svelte
│ │ │ │ │ ├── typography-lead.svelte
│ │ │ │ │ ├── typography-list.svelte
│ │ │ │ │ ├── typography-muted.svelte
│ │ │ │ │ ├── typography-p.svelte
│ │ │ │ │ ├── typography-small.svelte
│ │ │ │ │ └── typography-table.svelte
│ │ │ │ ├── fonts.ts
│ │ │ │ ├── hooks/
│ │ │ │ │ └── is-mobile.svelte.ts
│ │ │ │ ├── icons/
│ │ │ │ │ ├── __hugeicons__/
│ │ │ │ │ │ ├── ActivityIcon.ts
│ │ │ │ │ │ ├── Add01Icon.ts
│ │ │ │ │ │ ├── AddToListIcon.ts
│ │ │ │ │ │ ├── AiCloud01Icon.ts
│ │ │ │ │ │ ├── Alert02Icon.ts
│ │ │ │ │ │ ├── AlertCircleIcon.ts
│ │ │ │ │ │ ├── Archive02Icon.ts
│ │ │ │ │ │ ├── ArchiveIcon.ts
│ │ │ │ │ │ ├── ArrowDown01Icon.ts
│ │ │ │ │ │ ├── ArrowDownIcon.ts
│ │ │ │ │ │ ├── ArrowExpandIcon.ts
│ │ │ │ │ │ ├── ArrowLeft01Icon.ts
│ │ │ │ │ │ ├── ArrowLeft02Icon.ts
│ │ │ │ │ │ ├── ArrowRight01Icon.ts
│ │ │ │ │ │ ├── ArrowRight02Icon.ts
│ │ │ │ │ │ ├── ArrowShrinkIcon.ts
│ │ │ │ │ │ ├── ArrowUp01Icon.ts
│ │ │ │ │ │ ├── ArrowUp02Icon.ts
│ │ │ │ │ │ ├── ArrowUpIcon.ts
│ │ │ │ │ │ ├── ArrowUpRight01Icon.ts
│ │ │ │ │ │ ├── ArrowUpRightIcon.ts
│ │ │ │ │ │ ├── AttachmentIcon.ts
│ │ │ │ │ │ ├── AudioWave01Icon.ts
│ │ │ │ │ │ ├── BankIcon.ts
│ │ │ │ │ │ ├── BluetoothIcon.ts
│ │ │ │ │ │ ├── BookIcon.ts
│ │ │ │ │ │ ├── BookOpen02Icon.ts
│ │ │ │ │ │ ├── BookmarkIcon.ts
│ │ │ │ │ │ ├── BotIcon.ts
│ │ │ │ │ │ ├── BulbIcon.ts
│ │ │ │ │ │ ├── CalculatorIcon.ts
│ │ │ │ │ │ ├── Calendar01Icon.ts
│ │ │ │ │ │ ├── CalendarAdd01Icon.ts
│ │ │ │ │ │ ├── CalendarIcon.ts
│ │ │ │ │ │ ├── Cancel01Icon.ts
│ │ │ │ │ │ ├── Chart03Icon.ts
│ │ │ │ │ │ ├── ChartUpIcon.ts
│ │ │ │ │ │ ├── CheckmarkBadge02Icon.ts
│ │ │ │ │ │ ├── CheckmarkBadgeIcon.ts
│ │ │ │ │ │ ├── CheckmarkCircle02Icon.ts
│ │ │ │ │ │ ├── CircleArrowLeft02Icon.ts
│ │ │ │ │ │ ├── CircleIcon.ts
│ │ │ │ │ │ ├── ClipboardIcon.ts
│ │ │ │ │ │ ├── Clock03Icon.ts
│ │ │ │ │ │ ├── ClockIcon.ts
│ │ │ │ │ │ ├── CloudUploadIcon.ts
│ │ │ │ │ │ ├── CodeIcon.ts
│ │ │ │ │ │ ├── ComputerIcon.ts
│ │ │ │ │ │ ├── ComputerTerminal01Icon.ts
│ │ │ │ │ │ ├── ComputerTerminalIcon.ts
│ │ │ │ │ │ ├── Copy01Icon.ts
│ │ │ │ │ │ ├── CopyIcon.ts
│ │ │ │ │ │ ├── CreditCardIcon.ts
│ │ │ │ │ │ ├── CropIcon.ts
│ │ │ │ │ │ ├── CubeIcon.ts
│ │ │ │ │ │ ├── Cursor01Icon.ts
│ │ │ │ │ │ ├── CursorInWindowIcon.ts
│ │ │ │ │ │ ├── DashedLineCircleIcon.ts
│ │ │ │ │ │ ├── Delete02Icon.ts
│ │ │ │ │ │ ├── DeleteIcon.ts
│ │ │ │ │ │ ├── DollarCircleIcon.ts
│ │ │ │ │ │ ├── DownloadIcon.ts
│ │ │ │ │ │ ├── EditIcon.ts
│ │ │ │ │ │ ├── EyeIcon.ts
│ │ │ │ │ │ ├── FavouriteIcon.ts
│ │ │ │ │ │ ├── File01Icon.ts
│ │ │ │ │ │ ├── File02Icon.ts
│ │ │ │ │ │ ├── FileIcon.ts
│ │ │ │ │ │ ├── FlipHorizontalIcon.ts
│ │ │ │ │ │ ├── FlipVerticalIcon.ts
│ │ │ │ │ │ ├── FloppyDiskIcon.ts
│ │ │ │ │ │ ├── Folder01Icon.ts
│ │ │ │ │ │ ├── FolderAddIcon.ts
│ │ │ │ │ │ ├── FolderIcon.ts
│ │ │ │ │ │ ├── FolderOpenIcon.ts
│ │ │ │ │ │ ├── GitBranchIcon.ts
│ │ │ │ │ │ ├── GlobalIcon.ts
│ │ │ │ │ │ ├── GridIcon.ts
│ │ │ │ │ │ ├── HelpCircleIcon.ts
│ │ │ │ │ │ ├── HomeIcon.ts
│ │ │ │ │ │ ├── ImageIcon.ts
│ │ │ │ │ │ ├── InboxIcon.ts
│ │ │ │ │ │ ├── InformationCircleIcon.ts
│ │ │ │ │ │ ├── KeyboardIcon.ts
│ │ │ │ │ │ ├── LanguageCircleIcon.ts
│ │ │ │ │ │ ├── LayoutIcon.ts
│ │ │ │ │ │ ├── LayoutLeftIcon.ts
│ │ │ │ │ │ ├── LinkIcon.ts
│ │ │ │ │ │ ├── LinkSquare02Icon.ts
│ │ │ │ │ │ ├── Loading03Icon.ts
│ │ │ │ │ │ ├── LogoutIcon.ts
│ │ │ │ │ │ ├── MagicWand05Icon.ts
│ │ │ │ │ │ ├── MailIcon.ts
│ │ │ │ │ │ ├── MailValidation01Icon.ts
│ │ │ │ │ │ ├── MapsIcon.ts
│ │ │ │ │ │ ├── Menu05Icon.ts
│ │ │ │ │ │ ├── Menu09Icon.ts
│ │ │ │ │ │ ├── MessageIcon.ts
│ │ │ │ │ │ ├── MinusSignIcon.ts
│ │ │ │ │ │ ├── MoonIcon.ts
│ │ │ │ │ │ ├── MoreHorizontalCircle01Icon.ts
│ │ │ │ │ │ ├── MoreVerticalCircle01Icon.ts
│ │ │ │ │ │ ├── MultiplicationSignCircleIcon.ts
│ │ │ │ │ │ ├── Notification02Icon.ts
│ │ │ │ │ │ ├── NotificationIcon.ts
│ │ │ │ │ │ ├── PaintBoardIcon.ts
│ │ │ │ │ │ ├── PenIcon.ts
│ │ │ │ │ │ ├── PieChartIcon.ts
│ │ │ │ │ │ ├── PlusSignIcon.ts
│ │ │ │ │ │ ├── RecordIcon.ts
│ │ │ │ │ │ ├── RefreshIcon.ts
│ │ │ │ │ │ ├── RoboticIcon.ts
│ │ │ │ │ │ ├── Rotate01Icon.ts
│ │ │ │ │ │ ├── ScissorIcon.ts
│ │ │ │ │ │ ├── Search01Icon.ts
│ │ │ │ │ │ ├── SearchIcon.ts
│ │ │ │ │ │ ├── SentIcon.ts
│ │ │ │ │ │ ├── ServerStackIcon.ts
│ │ │ │ │ │ ├── Settings01Icon.ts
│ │ │ │ │ │ ├── Settings05Icon.ts
│ │ │ │ │ │ ├── SettingsIcon.ts
│ │ │ │ │ │ ├── Share03Icon.ts
│ │ │ │ │ │ ├── ShareIcon.ts
│ │ │ │ │ │ ├── ShieldIcon.ts
│ │ │ │ │ │ ├── ShoppingBag01Icon.ts
│ │ │ │ │ │ ├── ShoppingBasket01Icon.ts
│ │ │ │ │ │ ├── SidebarLeftIcon.ts
│ │ │ │ │ │ ├── SlidersHorizontalIcon.ts
│ │ │ │ │ │ ├── SmileIcon.ts
│ │ │ │ │ │ ├── SparklesIcon.ts
│ │ │ │ │ │ ├── StarIcon.ts
│ │ │ │ │ │ ├── SunIcon.ts
│ │ │ │ │ │ ├── TableIcon.ts
│ │ │ │ │ │ ├── TagIcon.ts
│ │ │ │ │ │ ├── TextBoldIcon.ts
│ │ │ │ │ │ ├── TextCheckIcon.ts
│ │ │ │ │ │ ├── TextItalicIcon.ts
│ │ │ │ │ │ ├── TextUnderlineIcon.ts
│ │ │ │ │ │ ├── Tick02Icon.ts
│ │ │ │ │ │ ├── TradeUpIcon.ts
│ │ │ │ │ │ ├── UnfoldMoreIcon.ts
│ │ │ │ │ │ ├── Upload01Icon.ts
│ │ │ │ │ │ ├── UserIcon.ts
│ │ │ │ │ │ ├── UserRemove01Icon.ts
│ │ │ │ │ │ ├── ViewOffIcon.ts
│ │ │ │ │ │ ├── VoiceIcon.ts
│ │ │ │ │ │ ├── VolumeOffIcon.ts
│ │ │ │ │ │ ├── WalletIcon.ts
│ │ │ │ │ │ ├── ZapIcon.ts
│ │ │ │ │ │ ├── ZoomInAreaIcon.ts
│ │ │ │ │ │ ├── ZoomOutAreaIcon.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── __lucide__/
│ │ │ │ │ │ ├── ActivityIcon.ts
│ │ │ │ │ │ ├── AlertTriangleIcon.ts
│ │ │ │ │ │ ├── AppWindowIcon.ts
│ │ │ │ │ │ ├── ArchiveIcon.ts
│ │ │ │ │ │ ├── ArrowDownIcon.ts
│ │ │ │ │ │ ├── ArrowLeftCircleIcon.ts
│ │ │ │ │ │ ├── ArrowLeftIcon.ts
│ │ │ │ │ │ ├── ArrowRightIcon.ts
│ │ │ │ │ │ ├── ArrowUpIcon.ts
│ │ │ │ │ │ ├── ArrowUpRightIcon.ts
│ │ │ │ │ │ ├── AudioLinesIcon.ts
│ │ │ │ │ │ ├── BadgeCheck.ts
│ │ │ │ │ │ ├── BadgeCheckIcon.ts
│ │ │ │ │ │ ├── BellIcon.ts
│ │ │ │ │ │ ├── BluetoothIcon.ts
│ │ │ │ │ │ ├── BoldIcon.ts
│ │ │ │ │ │ ├── BookOpen.ts
│ │ │ │ │ │ ├── BookOpenIcon.ts
│ │ │ │ │ │ ├── BookmarkIcon.ts
│ │ │ │ │ │ ├── BotIcon.ts
│ │ │ │ │ │ ├── Building2Icon.ts
│ │ │ │ │ │ ├── CalculatorIcon.ts
│ │ │ │ │ │ ├── CalendarIcon.ts
│ │ │ │ │ │ ├── CalendarPlusIcon.ts
│ │ │ │ │ │ ├── CaptionsIcon.ts
│ │ │ │ │ │ ├── ChartBarIcon.ts
│ │ │ │ │ │ ├── ChartLineIcon.ts
│ │ │ │ │ │ ├── ChartPieIcon.ts
│ │ │ │ │ │ ├── CheckCircle2Icon.ts
│ │ │ │ │ │ ├── CheckIcon.ts
│ │ │ │ │ │ ├── ChevronDownIcon.ts
│ │ │ │ │ │ ├── ChevronLeftIcon.ts
│ │ │ │ │ │ ├── ChevronRightIcon.ts
│ │ │ │ │ │ ├── ChevronUpIcon.ts
│ │ │ │ │ │ ├── ChevronsUpDownIcon.ts
│ │ │ │ │ │ ├── CircleAlertIcon.ts
│ │ │ │ │ │ ├── CircleCheckIcon.ts
│ │ │ │ │ │ ├── CircleDashedIcon.ts
│ │ │ │ │ │ ├── CircleDollarSignIcon.ts
│ │ │ │ │ │ ├── CircleIcon.ts
│ │ │ │ │ │ ├── ClipboardPasteIcon.ts
│ │ │ │ │ │ ├── Clock2Icon.ts
│ │ │ │ │ │ ├── ClockIcon.ts
│ │ │ │ │ │ ├── CloudCogIcon.ts
│ │ │ │ │ │ ├── CodeIcon.ts
│ │ │ │ │ │ ├── ContainerIcon.ts
│ │ │ │ │ │ ├── CopyIcon.ts
│ │ │ │ │ │ ├── CreditCardIcon.ts
│ │ │ │ │ │ ├── DownloadIcon.ts
│ │ │ │ │ │ ├── ExternalLinkIcon.ts
│ │ │ │ │ │ ├── EyeIcon.ts
│ │ │ │ │ │ ├── EyeOffIcon.ts
│ │ │ │ │ │ ├── FileCodeIcon.ts
│ │ │ │ │ │ ├── FileIcon.ts
│ │ │ │ │ │ ├── FileTextIcon.ts
│ │ │ │ │ │ ├── FlipHorizontalIcon.ts
│ │ │ │ │ │ ├── FlipVerticalIcon.ts
│ │ │ │ │ │ ├── FolderIcon.ts
│ │ │ │ │ │ ├── FolderOpenIcon.ts
│ │ │ │ │ │ ├── FolderPlusIcon.ts
│ │ │ │ │ │ ├── FolderSearchIcon.ts
│ │ │ │ │ │ ├── FrameIcon.ts
│ │ │ │ │ │ ├── GitBranchIcon.ts
│ │ │ │ │ │ ├── GlobeIcon.ts
│ │ │ │ │ │ ├── HeartIcon.ts
│ │ │ │ │ │ ├── HelpCircleIcon.ts
│ │ │ │ │ │ ├── HomeIcon.ts
│ │ │ │ │ │ ├── ImageIcon.ts
│ │ │ │ │ │ ├── InboxIcon.ts
│ │ │ │ │ │ ├── InfoIcon.ts
│ │ │ │ │ │ ├── ItalicIcon.ts
│ │ │ │ │ │ ├── KeyboardIcon.ts
│ │ │ │ │ │ ├── LanguagesIcon.ts
│ │ │ │ │ │ ├── LayoutGridIcon.ts
│ │ │ │ │ │ ├── LayoutIcon.ts
│ │ │ │ │ │ ├── LightbulbIcon.ts
│ │ │ │ │ │ ├── LinkIcon.ts
│ │ │ │ │ │ ├── ListFilterIcon.ts
│ │ │ │ │ │ ├── ListIcon.ts
│ │ │ │ │ │ ├── Loader2Icon.ts
│ │ │ │ │ │ ├── LogOutIcon.ts
│ │ │ │ │ │ ├── MailCheckIcon.ts
│ │ │ │ │ │ ├── MailIcon.ts
│ │ │ │ │ │ ├── MapIcon.ts
│ │ │ │ │ │ ├── MaximizeIcon.ts
│ │ │ │ │ │ ├── MenuIcon.ts
│ │ │ │ │ │ ├── MessageSquareIcon.ts
│ │ │ │ │ │ ├── MicIcon.ts
│ │ │ │ │ │ ├── MinimizeIcon.ts
│ │ │ │ │ │ ├── MinusIcon.ts
│ │ │ │ │ │ ├── MonitorIcon.ts
│ │ │ │ │ │ ├── MoonIcon.ts
│ │ │ │ │ │ ├── MoreHorizontalIcon.ts
│ │ │ │ │ │ ├── MoreVerticalIcon.ts
│ │ │ │ │ │ ├── MousePointerIcon.ts
│ │ │ │ │ │ ├── OctagonXIcon.ts
│ │ │ │ │ │ ├── PaletteIcon.ts
│ │ │ │ │ │ ├── PanelLeftIcon.ts
│ │ │ │ │ │ ├── PaperclipIcon.ts
│ │ │ │ │ │ ├── PenToolIcon.ts
│ │ │ │ │ │ ├── PencilIcon.ts
│ │ │ │ │ │ ├── PieChartIcon.ts
│ │ │ │ │ │ ├── PlusIcon.ts
│ │ │ │ │ │ ├── RadioIcon.ts
│ │ │ │ │ │ ├── RefreshCwIcon.ts
│ │ │ │ │ │ ├── RotateCwIcon.ts
│ │ │ │ │ │ ├── SaveIcon.ts
│ │ │ │ │ │ ├── ScissorsIcon.ts
│ │ │ │ │ │ ├── Search.ts
│ │ │ │ │ │ ├── SearchIcon.ts
│ │ │ │ │ │ ├── SendIcon.ts
│ │ │ │ │ │ ├── ServerIcon.ts
│ │ │ │ │ │ ├── Settings2Icon.ts
│ │ │ │ │ │ ├── SettingsIcon.ts
│ │ │ │ │ │ ├── ShareIcon.ts
│ │ │ │ │ │ ├── ShieldIcon.ts
│ │ │ │ │ │ ├── ShoppingBagIcon.ts
│ │ │ │ │ │ ├── SlidersHorizontalIcon.ts
│ │ │ │ │ │ ├── SmileIcon.ts
│ │ │ │ │ │ ├── SparklesIcon.ts
│ │ │ │ │ │ ├── StarIcon.ts
│ │ │ │ │ │ ├── SunIcon.ts
│ │ │ │ │ │ ├── TableIcon.ts
│ │ │ │ │ │ ├── TagIcon.ts
│ │ │ │ │ │ ├── TerminalIcon.ts
│ │ │ │ │ │ ├── TerminalSquareIcon.ts
│ │ │ │ │ │ ├── Trash2Icon.ts
│ │ │ │ │ │ ├── TrashIcon.ts
│ │ │ │ │ │ ├── TrendingUpIcon.ts
│ │ │ │ │ │ ├── TriangleAlertIcon.ts
│ │ │ │ │ │ ├── UnderlineIcon.ts
│ │ │ │ │ │ ├── UploadCloudIcon.ts
│ │ │ │ │ │ ├── UploadIcon.ts
│ │ │ │ │ │ ├── UserIcon.ts
│ │ │ │ │ │ ├── UserRoundXIcon.ts
│ │ │ │ │ │ ├── VolumeX.ts
│ │ │ │ │ │ ├── WalletIcon.ts
│ │ │ │ │ │ ├── WandIcon.ts
│ │ │ │ │ │ ├── XIcon.ts
│ │ │ │ │ │ ├── ZapIcon.ts
│ │ │ │ │ │ ├── ZoomInIcon.ts
│ │ │ │ │ │ ├── ZoomOutIcon.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── __phosphor__/
│ │ │ │ │ │ ├── AppWindowIcon.ts
│ │ │ │ │ │ ├── ArchiveIcon.ts
│ │ │ │ │ │ ├── ArrowCircleLeftIcon.ts
│ │ │ │ │ │ ├── ArrowClockwiseIcon.ts
│ │ │ │ │ │ ├── ArrowDownIcon.ts
│ │ │ │ │ │ ├── ArrowLeftIcon.ts
│ │ │ │ │ │ ├── ArrowRightIcon.ts
│ │ │ │ │ │ ├── ArrowSquareOutIcon.ts
│ │ │ │ │ │ ├── ArrowUpIcon.ts
│ │ │ │ │ │ ├── ArrowUpRightIcon.ts
│ │ │ │ │ │ ├── ArrowsHorizontalIcon.ts
│ │ │ │ │ │ ├── ArrowsVerticalIcon.ts
│ │ │ │ │ │ ├── BagIcon.ts
│ │ │ │ │ │ ├── BankIcon.ts
│ │ │ │ │ │ ├── BellIcon.ts
│ │ │ │ │ │ ├── BluetoothIcon.ts
│ │ │ │ │ │ ├── BookOpenIcon.ts
│ │ │ │ │ │ ├── BookmarkIcon.ts
│ │ │ │ │ │ ├── CalculatorIcon.ts
│ │ │ │ │ │ ├── CalendarBlankIcon.ts
│ │ │ │ │ │ ├── CalendarIcon.ts
│ │ │ │ │ │ ├── CalendarPlusIcon.ts
│ │ │ │ │ │ ├── CaretDownIcon.ts
│ │ │ │ │ │ ├── CaretLeftIcon.ts
│ │ │ │ │ │ ├── CaretRightIcon.ts
│ │ │ │ │ │ ├── CaretUpDownIcon.ts
│ │ │ │ │ │ ├── CaretUpIcon.ts
│ │ │ │ │ │ ├── ChartBarIcon.ts
│ │ │ │ │ │ ├── ChartLineIcon.ts
│ │ │ │ │ │ ├── ChartPieIcon.ts
│ │ │ │ │ │ ├── ChatCircleIcon.ts
│ │ │ │ │ │ ├── CheckCircleIcon.ts
│ │ │ │ │ │ ├── CheckIcon.ts
│ │ │ │ │ │ ├── CircleDashedIcon.ts
│ │ │ │ │ │ ├── CircleIcon.ts
│ │ │ │ │ │ ├── ClipboardIcon.ts
│ │ │ │ │ │ ├── ClockIcon.ts
│ │ │ │ │ │ ├── CloudArrowUpIcon.ts
│ │ │ │ │ │ ├── CodeIcon.ts
│ │ │ │ │ │ ├── CopyIcon.ts
│ │ │ │ │ │ ├── CornersInIcon.ts
│ │ │ │ │ │ ├── CornersOutIcon.ts
│ │ │ │ │ │ ├── CreditCardIcon.ts
│ │ │ │ │ │ ├── CropIcon.ts
│ │ │ │ │ │ ├── CubeIcon.ts
│ │ │ │ │ │ ├── CurrencyCircleDollarIcon.ts
│ │ │ │ │ │ ├── DotsThreeIcon.ts
│ │ │ │ │ │ ├── DotsThreeOutlineIcon.ts
│ │ │ │ │ │ ├── DotsThreeVerticalIcon.ts
│ │ │ │ │ │ ├── DownloadIcon.ts
│ │ │ │ │ │ ├── EnvelopeIcon.ts
│ │ │ │ │ │ ├── EyeIcon.ts
│ │ │ │ │ │ ├── EyeSlashIcon.ts
│ │ │ │ │ │ ├── FileCodeIcon.ts
│ │ │ │ │ │ ├── FileIcon.ts
│ │ │ │ │ │ ├── FileTextIcon.ts
│ │ │ │ │ │ ├── FloppyDiskIcon.ts
│ │ │ │ │ │ ├── FolderIcon.ts
│ │ │ │ │ │ ├── FolderOpenIcon.ts
│ │ │ │ │ │ ├── FolderPlusIcon.ts
│ │ │ │ │ │ ├── GearIcon.ts
│ │ │ │ │ │ ├── GitBranchIcon.ts
│ │ │ │ │ │ ├── GlobeIcon.ts
│ │ │ │ │ │ ├── GridFourIcon.ts
│ │ │ │ │ │ ├── HandPointingIcon.ts
│ │ │ │ │ │ ├── HardDrivesIcon.ts
│ │ │ │ │ │ ├── HeartIcon.ts
│ │ │ │ │ │ ├── HouseIcon.ts
│ │ │ │ │ │ ├── ImageIcon.ts
│ │ │ │ │ │ ├── InfoIcon.ts
│ │ │ │ │ │ ├── KeyboardIcon.ts
│ │ │ │ │ │ ├── LayoutIcon.ts
│ │ │ │ │ │ ├── LightbulbIcon.ts
│ │ │ │ │ │ ├── LightningIcon.ts
│ │ │ │ │ │ ├── LinkIcon.ts
│ │ │ │ │ │ ├── ListIcon.ts
│ │ │ │ │ │ ├── ListPlusIcon.ts
│ │ │ │ │ │ ├── MagicWandIcon.ts
│ │ │ │ │ │ ├── MagnifyingGlassIcon.ts
│ │ │ │ │ │ ├── MagnifyingGlassMinusIcon.ts
│ │ │ │ │ │ ├── MagnifyingGlassPlusIcon.ts
│ │ │ │ │ │ ├── MapTrifoldIcon.ts
│ │ │ │ │ │ ├── MicrophoneIcon.ts
│ │ │ │ │ │ ├── MinusIcon.ts
│ │ │ │ │ │ ├── MonitorIcon.ts
│ │ │ │ │ │ ├── MoonIcon.ts
│ │ │ │ │ │ ├── PaletteIcon.ts
│ │ │ │ │ │ ├── PaperPlaneTiltIcon.ts
│ │ │ │ │ │ ├── PaperclipIcon.ts
│ │ │ │ │ │ ├── PencilIcon.ts
│ │ │ │ │ │ ├── PlusIcon.ts
│ │ │ │ │ │ ├── PulseIcon.ts
│ │ │ │ │ │ ├── QuestionIcon.ts
│ │ │ │ │ │ ├── RecordIcon.ts
│ │ │ │ │ │ ├── RobotIcon.ts
│ │ │ │ │ │ ├── ScissorsIcon.ts
│ │ │ │ │ │ ├── ShareIcon.ts
│ │ │ │ │ │ ├── ShieldIcon.ts
│ │ │ │ │ │ ├── SidebarIcon.ts
│ │ │ │ │ │ ├── SignOutIcon.ts
│ │ │ │ │ │ ├── SlidersHorizontalIcon.ts
│ │ │ │ │ │ ├── SmileyIcon.ts
│ │ │ │ │ │ ├── SparkleIcon.ts
│ │ │ │ │ │ ├── SpeakerSlashIcon.ts
│ │ │ │ │ │ ├── SpinnerIcon.ts
│ │ │ │ │ │ ├── StarIcon.ts
│ │ │ │ │ │ ├── SunIcon.ts
│ │ │ │ │ │ ├── TableIcon.ts
│ │ │ │ │ │ ├── TagIcon.ts
│ │ │ │ │ │ ├── TerminalIcon.ts
│ │ │ │ │ │ ├── TextBIcon.ts
│ │ │ │ │ │ ├── TextItalicIcon.ts
│ │ │ │ │ │ ├── TextTIcon.ts
│ │ │ │ │ │ ├── TextUnderlineIcon.ts
│ │ │ │ │ │ ├── TranslateIcon.ts
│ │ │ │ │ │ ├── TrashIcon.ts
│ │ │ │ │ │ ├── TrayIcon.ts
│ │ │ │ │ │ ├── TrendUpIcon.ts
│ │ │ │ │ │ ├── UploadIcon.ts
│ │ │ │ │ │ ├── UserIcon.ts
│ │ │ │ │ │ ├── UserMinusIcon.ts
│ │ │ │ │ │ ├── WalletIcon.ts
│ │ │ │ │ │ ├── WarningCircleIcon.ts
│ │ │ │ │ │ ├── WarningIcon.ts
│ │ │ │ │ │ ├── XCircleIcon.ts
│ │ │ │ │ │ ├── XIcon.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── __remixicon__/
│ │ │ │ │ │ ├── RiAddBoxLine.ts
│ │ │ │ │ │ ├── RiAddLine.ts
│ │ │ │ │ │ ├── RiAlertLine.ts
│ │ │ │ │ │ ├── RiArchiveLine.ts
│ │ │ │ │ │ ├── RiArrowDownLine.ts
│ │ │ │ │ │ ├── RiArrowDownSLine.ts
│ │ │ │ │ │ ├── RiArrowLeftCircleLine.ts
│ │ │ │ │ │ ├── RiArrowLeftLine.ts
│ │ │ │ │ │ ├── RiArrowLeftSLine.ts
│ │ │ │ │ │ ├── RiArrowRightLine.ts
│ │ │ │ │ │ ├── RiArrowRightSLine.ts
│ │ │ │ │ │ ├── RiArrowRightUpLine.ts
│ │ │ │ │ │ ├── RiArrowUpDownLine.ts
│ │ │ │ │ │ ├── RiArrowUpLine.ts
│ │ │ │ │ │ ├── RiArrowUpSLine.ts
│ │ │ │ │ │ ├── RiAttachmentLine.ts
│ │ │ │ │ │ ├── RiBankCardLine.ts
│ │ │ │ │ │ ├── RiBankLine.ts
│ │ │ │ │ │ ├── RiBarChartLine.ts
│ │ │ │ │ │ ├── RiBluetoothLine.ts
│ │ │ │ │ │ ├── RiBold.ts
│ │ │ │ │ │ ├── RiBookOpenLine.ts
│ │ │ │ │ │ ├── RiBookmarkLine.ts
│ │ │ │ │ │ ├── RiBox1Line.ts
│ │ │ │ │ │ ├── RiCalculatorLine.ts
│ │ │ │ │ │ ├── RiCalendarCheckLine.ts
│ │ │ │ │ │ ├── RiCalendarLine.ts
│ │ │ │ │ │ ├── RiChat1Line.ts
│ │ │ │ │ │ ├── RiCheckLine.ts
│ │ │ │ │ │ ├── RiCheckboxCircleLine.ts
│ │ │ │ │ │ ├── RiCircleLine.ts
│ │ │ │ │ │ ├── RiClipboardLine.ts
│ │ │ │ │ │ ├── RiCloseCircleLine.ts
│ │ │ │ │ │ ├── RiCloseLine.ts
│ │ │ │ │ │ ├── RiClosedCaptioningLine.ts
│ │ │ │ │ │ ├── RiCloudLine.ts
│ │ │ │ │ │ ├── RiCodeLine.ts
│ │ │ │ │ │ ├── RiComputerLine.ts
│ │ │ │ │ │ ├── RiContractUpDownLine.ts
│ │ │ │ │ │ ├── RiCropLine.ts
│ │ │ │ │ │ ├── RiCursorLine.ts
│ │ │ │ │ │ ├── RiDeleteBinLine.ts
│ │ │ │ │ │ ├── RiDownloadLine.ts
│ │ │ │ │ │ ├── RiEmotionLine.ts
│ │ │ │ │ │ ├── RiErrorWarningLine.ts
│ │ │ │ │ │ ├── RiExpandDiagonalLine.ts
│ │ │ │ │ │ ├── RiExpandUpDownLine.ts
│ │ │ │ │ │ ├── RiExternalLinkLine.ts
│ │ │ │ │ │ ├── RiEyeLine.ts
│ │ │ │ │ │ ├── RiEyeOffLine.ts
│ │ │ │ │ │ ├── RiFileCodeLine.ts
│ │ │ │ │ │ ├── RiFileCopyLine.ts
│ │ │ │ │ │ ├── RiFileLine.ts
│ │ │ │ │ │ ├── RiFileTextLine.ts
│ │ │ │ │ │ ├── RiFlashlightLine.ts
│ │ │ │ │ │ ├── RiFlipHorizontalLine.ts
│ │ │ │ │ │ ├── RiFlipVerticalLine.ts
│ │ │ │ │ │ ├── RiFolderAddLine.ts
│ │ │ │ │ │ ├── RiFolderLine.ts
│ │ │ │ │ │ ├── RiFolderOpenLine.ts
│ │ │ │ │ │ ├── RiGitBranchLine.ts
│ │ │ │ │ │ ├── RiGlobalLine.ts
│ │ │ │ │ │ ├── RiGridLine.ts
│ │ │ │ │ │ ├── RiHardDriveLine.ts
│ │ │ │ │ │ ├── RiHeartLine.ts
│ │ │ │ │ │ ├── RiHomeLine.ts
│ │ │ │ │ │ ├── RiImageLine.ts
│ │ │ │ │ │ ├── RiInboxLine.ts
│ │ │ │ │ │ ├── RiInformationLine.ts
│ │ │ │ │ │ ├── RiItalic.ts
│ │ │ │ │ │ ├── RiKeyboardLine.ts
│ │ │ │ │ │ ├── RiLayoutLine.ts
│ │ │ │ │ │ ├── RiLightbulbLine.ts
│ │ │ │ │ │ ├── RiLineChartLine.ts
│ │ │ │ │ │ ├── RiLink.ts
│ │ │ │ │ │ ├── RiLinksLine.ts
│ │ │ │ │ │ ├── RiListUnordered.ts
│ │ │ │ │ │ ├── RiLoaderLine.ts
│ │ │ │ │ │ ├── RiLogoutBoxLine.ts
│ │ │ │ │ │ ├── RiMagicLine.ts
│ │ │ │ │ │ ├── RiMailCheckLine.ts
│ │ │ │ │ │ ├── RiMailLine.ts
│ │ │ │ │ │ ├── RiMapLine.ts
│ │ │ │ │ │ ├── RiMenuLine.ts
│ │ │ │ │ │ ├── RiMicLine.ts
│ │ │ │ │ │ ├── RiMoneyDollarCircleLine.ts
│ │ │ │ │ │ ├── RiMoonLine.ts
│ │ │ │ │ │ ├── RiMore2Line.ts
│ │ │ │ │ │ ├── RiMoreLine.ts
│ │ │ │ │ │ ├── RiNotificationLine.ts
│ │ │ │ │ │ ├── RiPaletteLine.ts
│ │ │ │ │ │ ├── RiPencilLine.ts
│ │ │ │ │ │ ├── RiPieChartLine.ts
│ │ │ │ │ │ ├── RiPriceTagLine.ts
│ │ │ │ │ │ ├── RiPulseLine.ts
│ │ │ │ │ │ ├── RiQuestionLine.ts
│ │ │ │ │ │ ├── RiRecordCircleLine.ts
│ │ │ │ │ │ ├── RiRefreshLine.ts
│ │ │ │ │ │ ├── RiRobotLine.ts
│ │ │ │ │ │ ├── RiSaveLine.ts
│ │ │ │ │ │ ├── RiScissorsLine.ts
│ │ │ │ │ │ ├── RiSearchEyeLine.ts
│ │ │ │ │ │ ├── RiSearchLine.ts
│ │ │ │ │ │ ├── RiSendPlaneLine.ts
│ │ │ │ │ │ ├── RiServerLine.ts
│ │ │ │ │ │ ├── RiSettingsLine.ts
│ │ │ │ │ │ ├── RiShareLine.ts
│ │ │ │ │ │ ├── RiShieldLine.ts
│ │ │ │ │ │ ├── RiShoppingBagLine.ts
│ │ │ │ │ │ ├── RiSideBarLine.ts
│ │ │ │ │ │ ├── RiSparklingLine.ts
│ │ │ │ │ │ ├── RiStarLine.ts
│ │ │ │ │ │ ├── RiSubtractLine.ts
│ │ │ │ │ │ ├── RiSunLine.ts
│ │ │ │ │ │ ├── RiTableLine.ts
│ │ │ │ │ │ ├── RiTerminalBoxLine.ts
│ │ │ │ │ │ ├── RiTimeLine.ts
│ │ │ │ │ │ ├── RiTranslate.ts
│ │ │ │ │ │ ├── RiUnderline.ts
│ │ │ │ │ │ ├── RiUploadCloudLine.ts
│ │ │ │ │ │ ├── RiUploadLine.ts
│ │ │ │ │ │ ├── RiUserLine.ts
│ │ │ │ │ │ ├── RiUserMinusLine.ts
│ │ │ │ │ │ ├── RiUserUnfollowLine.ts
│ │ │ │ │ │ ├── RiVolumeMuteLine.ts
│ │ │ │ │ │ ├── RiWalletLine.ts
│ │ │ │ │ │ ├── RiWindowLine.ts
│ │ │ │ │ │ ├── RiZoomInLine.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── __tabler__/
│ │ │ │ │ │ ├── IconActivity.ts
│ │ │ │ │ │ ├── IconAdjustmentsHorizontal.ts
│ │ │ │ │ │ ├── IconAlertOctagon.ts
│ │ │ │ │ │ ├── IconAlertTriangle.ts
│ │ │ │ │ │ ├── IconAppWindow.ts
│ │ │ │ │ │ ├── IconArchive.ts
│ │ │ │ │ │ ├── IconArrowDown.ts
│ │ │ │ │ │ ├── IconArrowLeft.ts
│ │ │ │ │ │ ├── IconArrowRight.ts
│ │ │ │ │ │ ├── IconArrowUp.ts
│ │ │ │ │ │ ├── IconArrowUpRight.ts
│ │ │ │ │ │ ├── IconBell.ts
│ │ │ │ │ │ ├── IconBluetooth.ts
│ │ │ │ │ │ ├── IconBold.ts
│ │ │ │ │ │ ├── IconBolt.ts
│ │ │ │ │ │ ├── IconBook.ts
│ │ │ │ │ │ ├── IconBookmark.ts
│ │ │ │ │ │ ├── IconBorderCorners.ts
│ │ │ │ │ │ ├── IconBox.ts
│ │ │ │ │ │ ├── IconBrandJavascript.ts
│ │ │ │ │ │ ├── IconBuildingBank.ts
│ │ │ │ │ │ ├── IconBulb.ts
│ │ │ │ │ │ ├── IconCalculator.ts
│ │ │ │ │ │ ├── IconCalendar.ts
│ │ │ │ │ │ ├── IconCalendarPlus.ts
│ │ │ │ │ │ ├── IconChartBar.ts
│ │ │ │ │ │ ├── IconChartLine.ts
│ │ │ │ │ │ ├── IconChartPie.ts
│ │ │ │ │ │ ├── IconCheck.ts
│ │ │ │ │ │ ├── IconChevronDown.ts
│ │ │ │ │ │ ├── IconChevronLeft.ts
│ │ │ │ │ │ ├── IconChevronRight.ts
│ │ │ │ │ │ ├── IconChevronUp.ts
│ │ │ │ │ │ ├── IconCircle.ts
│ │ │ │ │ │ ├── IconCircleArrowLeft.ts
│ │ │ │ │ │ ├── IconCircleCheck.ts
│ │ │ │ │ │ ├── IconCircleCheckFilled.ts
│ │ │ │ │ │ ├── IconCircleDashed.ts
│ │ │ │ │ │ ├── IconClipboard.ts
│ │ │ │ │ │ ├── IconClock.ts
│ │ │ │ │ │ ├── IconClockHour2.ts
│ │ │ │ │ │ ├── IconCloudCog.ts
│ │ │ │ │ │ ├── IconCloudUpload.ts
│ │ │ │ │ │ ├── IconCode.ts
│ │ │ │ │ │ ├── IconCoin.ts
│ │ │ │ │ │ ├── IconCopy.ts
│ │ │ │ │ │ ├── IconCreditCard.ts
│ │ │ │ │ │ ├── IconCut.ts
│ │ │ │ │ │ ├── IconDeviceDesktop.ts
│ │ │ │ │ │ ├── IconDeviceFloppy.ts
│ │ │ │ │ │ ├── IconDots.ts
│ │ │ │ │ │ ├── IconDotsVertical.ts
│ │ │ │ │ │ ├── IconDownload.ts
│ │ │ │ │ │ ├── IconExclamationCircle.ts
│ │ │ │ │ │ ├── IconExternalLink.ts
│ │ │ │ │ │ ├── IconEye.ts
│ │ │ │ │ │ ├── IconEyeClosed.ts
│ │ │ │ │ │ ├── IconFile.ts
│ │ │ │ │ │ ├── IconFileCode.ts
│ │ │ │ │ │ ├── IconFileText.ts
│ │ │ │ │ │ ├── IconFilterPlus.ts
│ │ │ │ │ │ ├── IconFlipHorizontal.ts
│ │ │ │ │ │ ├── IconFlipVertical.ts
│ │ │ │ │ │ ├── IconFolder.ts
│ │ │ │ │ │ ├── IconFolderOpen.ts
│ │ │ │ │ │ ├── IconFolderPlus.ts
│ │ │ │ │ │ ├── IconFolderSearch.ts
│ │ │ │ │ │ ├── IconFrame.ts
│ │ │ │ │ │ ├── IconGitBranch.ts
│ │ │ │ │ │ ├── IconHeadphones.ts
│ │ │ │ │ │ ├── IconHeart.ts
│ │ │ │ │ │ ├── IconHelpCircle.ts
│ │ │ │ │ │ ├── IconHome.ts
│ │ │ │ │ │ ├── IconInbox.ts
│ │ │ │ │ │ ├── IconInfoCircle.ts
│ │ │ │ │ │ ├── IconItalic.ts
│ │ │ │ │ │ ├── IconKeyboard.ts
│ │ │ │ │ │ ├── IconLanguage.ts
│ │ │ │ │ │ ├── IconLayout.ts
│ │ │ │ │ │ ├── IconLayoutGrid.ts
│ │ │ │ │ │ ├── IconLayoutSidebar.ts
│ │ │ │ │ │ ├── IconLink.ts
│ │ │ │ │ │ ├── IconList.ts
│ │ │ │ │ │ ├── IconLoader.ts
│ │ │ │ │ │ ├── IconLogout.ts
│ │ │ │ │ │ ├── IconMail.ts
│ │ │ │ │ │ ├── IconMailCheck.ts
│ │ │ │ │ │ ├── IconMap.ts
│ │ │ │ │ │ ├── IconMenu.ts
│ │ │ │ │ │ ├── IconMenu2.ts
│ │ │ │ │ │ ├── IconMessage.ts
│ │ │ │ │ │ ├── IconMicrophone.ts
│ │ │ │ │ │ ├── IconMinimize.ts
│ │ │ │ │ │ ├── IconMinus.ts
│ │ │ │ │ │ ├── IconMoodSmile.ts
│ │ │ │ │ │ ├── IconMoon.ts
│ │ │ │ │ │ ├── IconPalette.ts
│ │ │ │ │ │ ├── IconPaperclip.ts
│ │ │ │ │ │ ├── IconPencil.ts
│ │ │ │ │ │ ├── IconPhoto.ts
│ │ │ │ │ │ ├── IconPlayerRecordFilled.ts
│ │ │ │ │ │ ├── IconPlus.ts
│ │ │ │ │ │ ├── IconPointer.ts
│ │ │ │ │ │ ├── IconRefresh.ts
│ │ │ │ │ │ ├── IconRobot.ts
│ │ │ │ │ │ ├── IconRosetteDiscountCheck.ts
│ │ │ │ │ │ ├── IconRotateClockwise2.ts
│ │ │ │ │ │ ├── IconSearch.ts
│ │ │ │ │ │ ├── IconSelector.ts
│ │ │ │ │ │ ├── IconSend.ts
│ │ │ │ │ │ ├── IconServer.ts
│ │ │ │ │ │ ├── IconServerSpark.ts
│ │ │ │ │ │ ├── IconSettings.ts
│ │ │ │ │ │ ├── IconShare.ts
│ │ │ │ │ │ ├── IconShare2.ts
│ │ │ │ │ │ ├── IconShield.ts
│ │ │ │ │ │ ├── IconShoppingBag.ts
│ │ │ │ │ │ ├── IconSparkles.ts
│ │ │ │ │ │ ├── IconStar.ts
│ │ │ │ │ │ ├── IconSun.ts
│ │ │ │ │ │ ├── IconTable.ts
│ │ │ │ │ │ ├── IconTag.ts
│ │ │ │ │ │ ├── IconTerminal.ts
│ │ │ │ │ │ ├── IconTerminal2.ts
│ │ │ │ │ │ ├── IconTextCaption.ts
│ │ │ │ │ │ ├── IconTrash.ts
│ │ │ │ │ │ ├── IconTrendingUp.ts
│ │ │ │ │ │ ├── IconUnderline.ts
│ │ │ │ │ │ ├── IconUpload.ts
│ │ │ │ │ │ ├── IconUser.ts
│ │ │ │ │ │ ├── IconUserX.ts
│ │ │ │ │ │ ├── IconVolume.ts
│ │ │ │ │ │ ├── IconWallet.ts
│ │ │ │ │ │ ├── IconWand.ts
│ │ │ │ │ │ ├── IconWaveSine.ts
│ │ │ │ │ │ ├── IconWorld.ts
│ │ │ │ │ │ ├── IconX.ts
│ │ │ │ │ │ ├── IconZoomIn.ts
│ │ │ │ │ │ ├── IconZoomOut.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── logos/
│ │ │ │ │ ├── hugeicons.svelte
│ │ │ │ │ ├── lucide.svelte
│ │ │ │ │ ├── phosphor.svelte
│ │ │ │ │ ├── remixicon.svelte
│ │ │ │ │ └── tabler.svelte
│ │ │ │ ├── index.ts
│ │ │ │ ├── lib/
│ │ │ │ │ ├── casing.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── registry-base-colors.ts
│ │ │ │ ├── registry-block-meta.ts
│ │ │ │ ├── registry-categories.ts
│ │ │ │ ├── registry-colors.ts
│ │ │ │ ├── registry-utils.ts
│ │ │ │ ├── schema.ts
│ │ │ │ ├── styles/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── icons/
│ │ │ │ │ │ ├── lyra.svelte
│ │ │ │ │ │ ├── maia.svelte
│ │ │ │ │ │ ├── mira.svelte
│ │ │ │ │ │ ├── nova.svelte
│ │ │ │ │ │ └── vega.svelte
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── style-lyra.css
│ │ │ │ │ ├── style-maia.css
│ │ │ │ │ ├── style-mira.css
│ │ │ │ │ ├── style-nova.css
│ │ │ │ │ └── style-vega.css
│ │ │ │ ├── templates.ts
│ │ │ │ ├── themes.ts
│ │ │ │ └── ui/
│ │ │ │ ├── accordion/
│ │ │ │ │ ├── accordion-content.svelte
│ │ │ │ │ ├── accordion-item.svelte
│ │ │ │ │ ├── accordion-trigger.svelte
│ │ │ │ │ ├── accordion.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── alert/
│ │ │ │ │ ├── alert-action.svelte
│ │ │ │ │ ├── alert-description.svelte
│ │ │ │ │ ├── alert-title.svelte
│ │ │ │ │ ├── alert.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── alert-dialog/
│ │ │ │ │ ├── alert-dialog-action.svelte
│ │ │ │ │ ├── alert-dialog-cancel.svelte
│ │ │ │ │ ├── alert-dialog-content.svelte
│ │ │ │ │ ├── alert-dialog-description.svelte
│ │ │ │ │ ├── alert-dialog-footer.svelte
│ │ │ │ │ ├── alert-dialog-header.svelte
│ │ │ │ │ ├── alert-dialog-media.svelte
│ │ │ │ │ ├── alert-dialog-overlay.svelte
│ │ │ │ │ ├── alert-dialog-portal.svelte
│ │ │ │ │ ├── alert-dialog-title.svelte
│ │ │ │ │ ├── alert-dialog-trigger.svelte
│ │ │ │ │ ├── alert-dialog.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── aspect-ratio/
│ │ │ │ │ ├── aspect-ratio.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── avatar/
│ │ │ │ │ ├── avatar-badge.svelte
│ │ │ │ │ ├── avatar-fallback.svelte
│ │ │ │ │ ├── avatar-group-count.svelte
│ │ │ │ │ ├── avatar-group.svelte
│ │ │ │ │ ├── avatar-image.svelte
│ │ │ │ │ ├── avatar.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── badge/
│ │ │ │ │ ├── badge.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── breadcrumb/
│ │ │ │ │ ├── breadcrumb-ellipsis.svelte
│ │ │ │ │ ├── breadcrumb-item.svelte
│ │ │ │ │ ├── breadcrumb-link.svelte
│ │ │ │ │ ├── breadcrumb-list.svelte
│ │ │ │ │ ├── breadcrumb-page.svelte
│ │ │ │ │ ├── breadcrumb-separator.svelte
│ │ │ │ │ ├── breadcrumb.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── button/
│ │ │ │ │ ├── button.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── button-group/
│ │ │ │ │ ├── button-group-separator.svelte
│ │ │ │ │ ├── button-group-text.svelte
│ │ │ │ │ ├── button-group.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── calendar/
│ │ │ │ │ ├── calendar-caption.svelte
│ │ │ │ │ ├── calendar-cell.svelte
│ │ │ │ │ ├── calendar-day.svelte
│ │ │ │ │ ├── calendar-grid-body.svelte
│ │ │ │ │ ├── calendar-grid-head.svelte
│ │ │ │ │ ├── calendar-grid-row.svelte
│ │ │ │ │ ├── calendar-grid.svelte
│ │ │ │ │ ├── calendar-head-cell.svelte
│ │ │ │ │ ├── calendar-header.svelte
│ │ │ │ │ ├── calendar-heading.svelte
│ │ │ │ │ ├── calendar-month-select.svelte
│ │ │ │ │ ├── calendar-month.svelte
│ │ │ │ │ ├── calendar-months.svelte
│ │ │ │ │ ├── calendar-nav.svelte
│ │ │ │ │ ├── calendar-next-button.svelte
│ │ │ │ │ ├── calendar-prev-button.svelte
│ │ │ │ │ ├── calendar-year-select.svelte
│ │ │ │ │ ├── calendar.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── card/
│ │ │ │ │ ├── card-action.svelte
│ │ │ │ │ ├── card-content.svelte
│ │ │ │ │ ├── card-description.svelte
│ │ │ │ │ ├── card-footer.svelte
│ │ │ │ │ ├── card-header.svelte
│ │ │ │ │ ├── card-title.svelte
│ │ │ │ │ ├── card.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── carousel/
│ │ │ │ │ ├── carousel-content.svelte
│ │ │ │ │ ├── carousel-item.svelte
│ │ │ │ │ ├── carousel-next.svelte
│ │ │ │ │ ├── carousel-previous.svelte
│ │ │ │ │ ├── carousel.svelte
│ │ │ │ │ ├── context.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── chart/
│ │ │ │ │ ├── chart-container.svelte
│ │ │ │ │ ├── chart-style.svelte
│ │ │ │ │ ├── chart-tooltip.svelte
│ │ │ │ │ ├── chart-utils.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── checkbox/
│ │ │ │ │ ├── checkbox.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── collapsible/
│ │ │ │ │ ├── collapsible-content.svelte
│ │ │ │ │ ├── collapsible-trigger.svelte
│ │ │ │ │ ├── collapsible.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── command/
│ │ │ │ │ ├── command-dialog.svelte
│ │ │ │ │ ├── command-empty.svelte
│ │ │ │ │ ├── command-group.svelte
│ │ │ │ │ ├── command-input.svelte
│ │ │ │ │ ├── command-item.svelte
│ │ │ │ │ ├── command-link-item.svelte
│ │ │ │ │ ├── command-list.svelte
│ │ │ │ │ ├── command-loading.svelte
│ │ │ │ │ ├── command-separator.svelte
│ │ │ │ │ ├── command-shortcut.svelte
│ │ │ │ │ ├── command.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── context-menu/
│ │ │ │ │ ├── context-menu-checkbox-item.svelte
│ │ │ │ │ ├── context-menu-content.svelte
│ │ │ │ │ ├── context-menu-group-heading.svelte
│ │ │ │ │ ├── context-menu-group.svelte
│ │ │ │ │ ├── context-menu-item.svelte
│ │ │ │ │ ├── context-menu-label.svelte
│ │ │ │ │ ├── context-menu-portal.svelte
│ │ │ │ │ ├── context-menu-radio-group.svelte
│ │ │ │ │ ├── context-menu-radio-item.svelte
│ │ │ │ │ ├── context-menu-separator.svelte
│ │ │ │ │ ├── context-menu-shortcut.svelte
│ │ │ │ │ ├── context-menu-sub-content.svelte
│ │ │ │ │ ├── context-menu-sub-trigger.svelte
│ │ │ │ │ ├── context-menu-sub.svelte
│ │ │ │ │ ├── context-menu-trigger.svelte
│ │ │ │ │ ├── context-menu.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── data-table/
│ │ │ │ │ ├── data-table.svelte.ts
│ │ │ │ │ ├── flex-render.svelte
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── render-helpers.ts
│ │ │ │ ├── dialog/
│ │ │ │ │ ├── dialog-close.svelte
│ │ │ │ │ ├── dialog-content.svelte
│ │ │ │ │ ├── dialog-description.svelte
│ │ │ │ │ ├── dialog-footer.svelte
│ │ │ │ │ ├── dialog-header.svelte
│ │ │ │ │ ├── dialog-overlay.svelte
│ │ │ │ │ ├── dialog-portal.svelte
│ │ │ │ │ ├── dialog-title.svelte
│ │ │ │ │ ├── dialog-trigger.svelte
│ │ │ │ │ ├── dialog.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── drawer/
│ │ │ │ │ ├── drawer-close.svelte
│ │ │ │ │ ├── drawer-content.svelte
│ │ │ │ │ ├── drawer-description.svelte
│ │ │ │ │ ├── drawer-footer.svelte
│ │ │ │ │ ├── drawer-header.svelte
│ │ │ │ │ ├── drawer-nested.svelte
│ │ │ │ │ ├── drawer-overlay.svelte
│ │ │ │ │ ├── drawer-portal.svelte
│ │ │ │ │ ├── drawer-title.svelte
│ │ │ │ │ ├── drawer-trigger.svelte
│ │ │ │ │ ├── drawer.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dropdown-menu/
│ │ │ │ │ ├── dropdown-menu-checkbox-group.svelte
│ │ │ │ │ ├── dropdown-menu-checkbox-item.svelte
│ │ │ │ │ ├── dropdown-menu-content.svelte
│ │ │ │ │ ├── dropdown-menu-group-heading.svelte
│ │ │ │ │ ├── dropdown-menu-group.svelte
│ │ │ │ │ ├── dropdown-menu-item.svelte
│ │ │ │ │ ├── dropdown-menu-label.svelte
│ │ │ │ │ ├── dropdown-menu-portal.svelte
│ │ │ │ │ ├── dropdown-menu-radio-group.svelte
│ │ │ │ │ ├── dropdown-menu-radio-item.svelte
│ │ │ │ │ ├── dropdown-menu-separator.svelte
│ │ │ │ │ ├── dropdown-menu-shortcut.svelte
│ │ │ │ │ ├── dropdown-menu-sub-content.svelte
│ │ │ │ │ ├── dropdown-menu-sub-trigger.svelte
│ │ │ │ │ ├── dropdown-menu-sub.svelte
│ │ │ │ │ ├── dropdown-menu-trigger.svelte
│ │ │ │ │ ├── dropdown-menu.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── empty/
│ │ │ │ │ ├── empty-content.svelte
│ │ │ │ │ ├── empty-description.svelte
│ │ │ │ │ ├── empty-header.svelte
│ │ │ │ │ ├── empty-media.svelte
│ │ │ │ │ ├── empty-title.svelte
│ │ │ │ │ ├── empty.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── field/
│ │ │ │ │ ├── field-content.svelte
│ │ │ │ │ ├── field-description.svelte
│ │ │ │ │ ├── field-error.svelte
│ │ │ │ │ ├── field-group.svelte
│ │ │ │ │ ├── field-label.svelte
│ │ │ │ │ ├── field-legend.svelte
│ │ │ │ │ ├── field-separator.svelte
│ │ │ │ │ ├── field-set.svelte
│ │ │ │ │ ├── field-title.svelte
│ │ │ │ │ ├── field.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── form/
│ │ │ │ │ ├── form-button.svelte
│ │ │ │ │ ├── form-description.svelte
│ │ │ │ │ ├── form-element-field.svelte
│ │ │ │ │ ├── form-field-errors.svelte
│ │ │ │ │ ├── form-field.svelte
│ │ │ │ │ ├── form-fieldset.svelte
│ │ │ │ │ ├── form-label.svelte
│ │ │ │ │ ├── form-legend.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── hover-card/
│ │ │ │ │ ├── hover-card-content.svelte
│ │ │ │ │ ├── hover-card-portal.svelte
│ │ │ │ │ ├── hover-card-trigger.svelte
│ │ │ │ │ ├── hover-card.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── input/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── input.svelte
│ │ │ │ ├── input-group/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── input-group-addon.svelte
│ │ │ │ │ ├── input-group-button.svelte
│ │ │ │ │ ├── input-group-input.svelte
│ │ │ │ │ ├── input-group-text.svelte
│ │ │ │ │ ├── input-group-textarea.svelte
│ │ │ │ │ └── input-group.svelte
│ │ │ │ ├── input-otp/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── input-otp-group.svelte
│ │ │ │ │ ├── input-otp-separator.svelte
│ │ │ │ │ ├── input-otp-slot.svelte
│ │ │ │ │ └── input-otp.svelte
│ │ │ │ ├── item/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── item-actions.svelte
│ │ │ │ │ ├── item-content.svelte
│ │ │ │ │ ├── item-description.svelte
│ │ │ │ │ ├── item-footer.svelte
│ │ │ │ │ ├── item-group.svelte
│ │ │ │ │ ├── item-header.svelte
│ │ │ │ │ ├── item-media.svelte
│ │ │ │ │ ├── item-separator.svelte
│ │ │ │ │ ├── item-title.svelte
│ │ │ │ │ └── item.svelte
│ │ │ │ ├── kbd/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── kbd-group.svelte
│ │ │ │ │ └── kbd.svelte
│ │ │ │ ├── label/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── label.svelte
│ │ │ │ ├── menubar/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── menubar-checkbox-item.svelte
│ │ │ │ │ ├── menubar-content.svelte
│ │ │ │ │ ├── menubar-group-heading.svelte
│ │ │ │ │ ├── menubar-group.svelte
│ │ │ │ │ ├── menubar-item.svelte
│ │ │ │ │ ├── menubar-label.svelte
│ │ │ │ │ ├── menubar-menu.svelte
│ │ │ │ │ ├── menubar-portal.svelte
│ │ │ │ │ ├── menubar-radio-group.svelte
│ │ │ │ │ ├── menubar-radio-item.svelte
│ │ │ │ │ ├── menubar-separator.svelte
│ │ │ │ │ ├── menubar-shortcut.svelte
│ │ │ │ │ ├── menubar-sub-content.svelte
│ │ │ │ │ ├── menubar-sub-trigger.svelte
│ │ │ │ │ ├── menubar-sub.svelte
│ │ │ │ │ ├── menubar-trigger.svelte
│ │ │ │ │ └── menubar.svelte
│ │ │ │ ├── native-select/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── native-select-opt-group.svelte
│ │ │ │ │ ├── native-select-option.svelte
│ │ │ │ │ └── native-select.svelte
│ │ │ │ ├── navigation-menu/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── navigation-menu-content.svelte
│ │ │ │ │ ├── navigation-menu-indicator.svelte
│ │ │ │ │ ├── navigation-menu-item.svelte
│ │ │ │ │ ├── navigation-menu-link.svelte
│ │ │ │ │ ├── navigation-menu-list.svelte
│ │ │ │ │ ├── navigation-menu-trigger.svelte
│ │ │ │ │ ├── navigation-menu-viewport.svelte
│ │ │ │ │ └── navigation-menu.svelte
│ │ │ │ ├── pagination/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── pagination-content.svelte
│ │ │ │ │ ├── pagination-ellipsis.svelte
│ │ │ │ │ ├── pagination-item.svelte
│ │ │ │ │ ├── pagination-link.svelte
│ │ │ │ │ ├── pagination-next-button.svelte
│ │ │ │ │ ├── pagination-next.svelte
│ │ │ │ │ ├── pagination-prev-button.svelte
│ │ │ │ │ ├── pagination-previous.svelte
│ │ │ │ │ └── pagination.svelte
│ │ │ │ ├── popover/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── popover-close.svelte
│ │ │ │ │ ├── popover-content.svelte
│ │ │ │ │ ├── popover-description.svelte
│ │ │ │ │ ├── popover-header.svelte
│ │ │ │ │ ├── popover-portal.svelte
│ │ │ │ │ ├── popover-title.svelte
│ │ │ │ │ ├── popover-trigger.svelte
│ │ │ │ │ └── popover.svelte
│ │ │ │ ├── progress/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── progress.svelte
│ │ │ │ ├── radio-group/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── radio-group-item.svelte
│ │ │ │ │ └── radio-group.svelte
│ │ │ │ ├── range-calendar/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── range-calendar-caption.svelte
│ │ │ │ │ ├── range-calendar-cell.svelte
│ │ │ │ │ ├── range-calendar-day.svelte
│ │ │ │ │ ├── range-calendar-grid-body.svelte
│ │ │ │ │ ├── range-calendar-grid-head.svelte
│ │ │ │ │ ├── range-calendar-grid-row.svelte
│ │ │ │ │ ├── range-calendar-grid.svelte
│ │ │ │ │ ├── range-calendar-head-cell.svelte
│ │ │ │ │ ├── range-calendar-header.svelte
│ │ │ │ │ ├── range-calendar-heading.svelte
│ │ │ │ │ ├── range-calendar-month-select.svelte
│ │ │ │ │ ├── range-calendar-month.svelte
│ │ │ │ │ ├── range-calendar-months.svelte
│ │ │ │ │ ├── range-calendar-nav.svelte
│ │ │ │ │ ├── range-calendar-next-button.svelte
│ │ │ │ │ ├── range-calendar-prev-button.svelte
│ │ │ │ │ ├── range-calendar-year-select.svelte
│ │ │ │ │ └── range-calendar.svelte
│ │ │ │ ├── resizable/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── resizable-handle.svelte
│ │ │ │ │ └── resizable-pane-group.svelte
│ │ │ │ ├── scroll-area/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── scroll-area-scrollbar.svelte
│ │ │ │ │ └── scroll-area.svelte
│ │ │ │ ├── select/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── select-content.svelte
│ │ │ │ │ ├── select-group-heading.svelte
│ │ │ │ │ ├── select-group.svelte
│ │ │ │ │ ├── select-item.svelte
│ │ │ │ │ ├── select-label.svelte
│ │ │ │ │ ├── select-portal.svelte
│ │ │ │ │ ├── select-scroll-down-button.svelte
│ │ │ │ │ ├── select-scroll-up-button.svelte
│ │ │ │ │ ├── select-separator.svelte
│ │ │ │ │ ├── select-trigger.svelte
│ │ │ │ │ └── select.svelte
│ │ │ │ ├── separator/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── separator.svelte
│ │ │ │ ├── sheet/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── sheet-close.svelte
│ │ │ │ │ ├── sheet-content.svelte
│ │ │ │ │ ├── sheet-description.svelte
│ │ │ │ │ ├── sheet-footer.svelte
│ │ │ │ │ ├── sheet-header.svelte
│ │ │ │ │ ├── sheet-overlay.svelte
│ │ │ │ │ ├── sheet-portal.svelte
│ │ │ │ │ ├── sheet-title.svelte
│ │ │ │ │ ├── sheet-trigger.svelte
│ │ │ │ │ └── sheet.svelte
│ │ │ │ ├── sidebar/
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── context.svelte.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── sidebar-content.svelte
│ │ │ │ │ ├── sidebar-footer.svelte
│ │ │ │ │ ├── sidebar-group-action.svelte
│ │ │ │ │ ├── sidebar-group-content.svelte
│ │ │ │ │ ├── sidebar-group-label.svelte
│ │ │ │ │ ├── sidebar-group.svelte
│ │ │ │ │ ├── sidebar-header.svelte
│ │ │ │ │ ├── sidebar-input.svelte
│ │ │ │ │ ├── sidebar-inset.svelte
│ │ │ │ │ ├── sidebar-menu-action.svelte
│ │ │ │ │ ├── sidebar-menu-badge.svelte
│ │ │ │ │ ├── sidebar-menu-button.svelte
│ │ │ │ │ ├── sidebar-menu-item.svelte
│ │ │ │ │ ├── sidebar-menu-skeleton.svelte
│ │ │ │ │ ├── sidebar-menu-sub-button.svelte
│ │ │ │ │ ├── sidebar-menu-sub-item.svelte
│ │ │ │ │ ├── sidebar-menu-sub.svelte
│ │ │ │ │ ├── sidebar-menu.svelte
│ │ │ │ │ ├── sidebar-provider.svelte
│ │ │ │ │ ├── sidebar-rail.svelte
│ │ │ │ │ ├── sidebar-separator.svelte
│ │ │ │ │ ├── sidebar-trigger.svelte
│ │ │ │ │ └── sidebar.svelte
│ │ │ │ ├── skeleton/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── skeleton.svelte
│ │ │ │ ├── slider/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── slider.svelte
│ │ │ │ ├── sonner/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── sonner.svelte
│ │ │ │ ├── spinner/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── spinner.svelte
│ │ │ │ ├── switch/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── switch.svelte
│ │ │ │ ├── table/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── table-body.svelte
│ │ │ │ │ ├── table-caption.svelte
│ │ │ │ │ ├── table-cell.svelte
│ │ │ │ │ ├── table-footer.svelte
│ │ │ │ │ ├── table-head.svelte
│ │ │ │ │ ├── table-header.svelte
│ │ │ │ │ ├── table-row.svelte
│ │ │ │ │ └── table.svelte
│ │ │ │ ├── tabs/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── tabs-content.svelte
│ │ │ │ │ ├── tabs-list.svelte
│ │ │ │ │ ├── tabs-trigger.svelte
│ │ │ │ │ └── tabs.svelte
│ │ │ │ ├── textarea/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── textarea.svelte
│ │ │ │ ├── toggle/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── toggle.svelte
│ │ │ │ ├── toggle-group/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── toggle-group-item.svelte
│ │ │ │ │ └── toggle-group.svelte
│ │ │ │ └── tooltip/
│ │ │ │ ├── index.ts
│ │ │ │ ├── tooltip-content.svelte
│ │ │ │ ├── tooltip-portal.svelte
│ │ │ │ ├── tooltip-provider.svelte
│ │ │ │ ├── tooltip-trigger.svelte
│ │ │ │ └── tooltip.svelte
│ │ │ ├── themes.ts
│ │ │ ├── user-config.svelte.ts
│ │ │ └── utils.ts
│ │ ├── params/
│ │ │ └── view.ts
│ │ └── routes/
│ │ ├── (app)/
│ │ │ ├── (layout)/
│ │ │ │ ├── (create)/
│ │ │ │ │ ├── +layout@(app).svelte
│ │ │ │ │ ├── components/
│ │ │ │ │ │ ├── action-menu.svelte
│ │ │ │ │ │ ├── base-color-picker.svelte
│ │ │ │ │ │ ├── copy-preset.svelte
│ │ │ │ │ │ ├── customizer-controls.svelte
│ │ │ │ │ │ ├── customizer.svelte
│ │ │ │ │ │ ├── example-wrapper.svelte
│ │ │ │ │ │ ├── example.svelte
│ │ │ │ │ │ ├── font-picker.svelte
│ │ │ │ │ │ ├── icon-library-picker.svelte
│ │ │ │ │ │ ├── initialize-dialog.svelte
│ │ │ │ │ │ ├── item-explorer.svelte
│ │ │ │ │ │ ├── lock-button.svelte
│ │ │ │ │ │ ├── main-menu.svelte
│ │ │ │ │ │ ├── menu-accent-picker.svelte
│ │ │ │ │ │ ├── menu-color-picker.svelte
│ │ │ │ │ │ ├── menu-icon-default.svelte
│ │ │ │ │ │ ├── menu-icon-inverted.svelte
│ │ │ │ │ │ ├── picker/
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ ├── picker-checkbox-item.svelte
│ │ │ │ │ │ │ ├── picker-content.svelte
│ │ │ │ │ │ │ ├── picker-group.svelte
│ │ │ │ │ │ │ ├── picker-item.svelte
│ │ │ │ │ │ │ ├── picker-label.svelte
│ │ │ │ │ │ │ ├── picker-radio-group.svelte
│ │ │ │ │ │ │ ├── picker-radio-item.svelte
│ │ │ │ │ │ │ ├── picker-separator.svelte
│ │ │ │ │ │ │ ├── picker-shortcut.svelte
│ │ │ │ │ │ │ ├── picker-trigger.svelte
│ │ │ │ │ │ │ └── picker.svelte
│ │ │ │ │ │ ├── preset-picker.svelte
│ │ │ │ │ │ ├── preview.svelte
│ │ │ │ │ │ ├── radius-picker.svelte
│ │ │ │ │ │ ├── random-button.svelte
│ │ │ │ │ │ ├── reset-button.svelte
│ │ │ │ │ │ ├── share.svelte
│ │ │ │ │ │ ├── style-picker.svelte
│ │ │ │ │ │ ├── theme-picker.svelte
│ │ │ │ │ │ └── welcome-dialog.svelte
│ │ │ │ │ ├── create/
│ │ │ │ │ │ ├── +layout.svelte
│ │ │ │ │ │ ├── +page.server.ts
│ │ │ │ │ │ └── [item]/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── +page.ts
│ │ │ │ │ └── lib/
│ │ │ │ │ ├── randomize-biases.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── +layout.svelte
│ │ │ │ ├── +page.svelte
│ │ │ │ ├── +page.ts
│ │ │ │ ├── blocks/
│ │ │ │ │ ├── +layout.svelte
│ │ │ │ │ ├── +page.svelte
│ │ │ │ │ ├── +page.ts
│ │ │ │ │ └── [category]/
│ │ │ │ │ ├── +page.server.ts
│ │ │ │ │ ├── +page.svelte
│ │ │ │ │ └── +page.ts
│ │ │ │ ├── charts/
│ │ │ │ │ ├── +layout.svelte
│ │ │ │ │ ├── +page.ts
│ │ │ │ │ ├── [t]/
│ │ │ │ │ │ ├── +page.server.ts
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ └── +page.ts
│ │ │ │ │ └── charts.ts
│ │ │ │ ├── colors/
│ │ │ │ │ ├── +layout.svelte
│ │ │ │ │ ├── +layout.ts
│ │ │ │ │ └── +page.svelte
│ │ │ │ ├── docs/
│ │ │ │ │ ├── +layout.server.ts
│ │ │ │ │ ├── +layout.svelte
│ │ │ │ │ └── [...slug]/
│ │ │ │ │ ├── +page.svelte
│ │ │ │ │ └── +page.ts
│ │ │ │ ├── examples/
│ │ │ │ │ ├── +layout.svelte
│ │ │ │ │ ├── +layout.ts
│ │ │ │ │ ├── +page.svelte
│ │ │ │ │ ├── +page.ts
│ │ │ │ │ ├── authentication/
│ │ │ │ │ │ ├── (components)/
│ │ │ │ │ │ │ └── user-auth-form.svelte
│ │ │ │ │ │ └── +page.svelte
│ │ │ │ │ ├── dashboard/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ ├── components/
│ │ │ │ │ │ │ ├── app-sidebar.svelte
│ │ │ │ │ │ │ ├── chart-area-interactive.svelte
│ │ │ │ │ │ │ ├── data-table-actions.svelte
│ │ │ │ │ │ │ ├── data-table-cell-viewer.svelte
│ │ │ │ │ │ │ ├── data-table-checkbox.svelte
│ │ │ │ │ │ │ ├── data-table-drag-handle.svelte
│ │ │ │ │ │ │ ├── data-table-header-limit.svelte
│ │ │ │ │ │ │ ├── data-table-header-target.svelte
│ │ │ │ │ │ │ ├── data-table-limit.svelte
│ │ │ │ │ │ │ ├── data-table-reviewer.svelte
│ │ │ │ │ │ │ ├── data-table-status.svelte
│ │ │ │ │ │ │ ├── data-table-target.svelte
│ │ │ │ │ │ │ ├── data-table-type.svelte
│ │ │ │ │ │ │ ├── data-table.svelte
│ │ │ │ │ │ │ ├── nav-documents.svelte
│ │ │ │ │ │ │ ├── nav-main.svelte
│ │ │ │ │ │ │ ├── nav-secondary.svelte
│ │ │ │ │ │ │ ├── nav-user.svelte
│ │ │ │ │ │ │ ├── schemas.ts
│ │ │ │ │ │ │ ├── section-cards.svelte
│ │ │ │ │ │ │ └── site-header.svelte
│ │ │ │ │ │ └── data.ts
│ │ │ │ │ ├── playground/
│ │ │ │ │ │ ├── (components)/
│ │ │ │ │ │ │ ├── code-viewer.svelte
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ ├── max-length-selector.svelte
│ │ │ │ │ │ │ ├── model-item.svelte
│ │ │ │ │ │ │ ├── model-selector.svelte
│ │ │ │ │ │ │ ├── preset-actions.svelte
│ │ │ │ │ │ │ ├── preset-save.svelte
│ │ │ │ │ │ │ ├── preset-selector.svelte
│ │ │ │ │ │ │ ├── preset-share.svelte
│ │ │ │ │ │ │ ├── temperature-selector.svelte
│ │ │ │ │ │ │ └── top-p-selector.svelte
│ │ │ │ │ │ ├── (data)/
│ │ │ │ │ │ │ ├── models.ts
│ │ │ │ │ │ │ └── presets.ts
│ │ │ │ │ │ └── +page.svelte
│ │ │ │ │ └── tasks/
│ │ │ │ │ ├── +page.svelte
│ │ │ │ │ ├── components/
│ │ │ │ │ │ ├── data-table-cell.svelte
│ │ │ │ │ │ ├── data-table-column-header.svelte
│ │ │ │ │ │ ├── data-table-faceted-filter.svelte
│ │ │ │ │ │ ├── data-table-priority-cell.svelte
│ │ │ │ │ │ ├── data-table-row-actions.svelte
│ │ │ │ │ │ ├── data-table-status-cell.svelte
│ │ │ │ │ │ ├── data-table-title-cell.svelte
│ │ │ │ │ │ ├── data-table-toolbar.svelte
│ │ │ │ │ │ ├── data-table-view-options.svelte
│ │ │ │ │ │ ├── data-table.svelte
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── user-nav.svelte
│ │ │ │ │ └── data/
│ │ │ │ │ ├── data.ts
│ │ │ │ │ ├── schemas.ts
│ │ │ │ │ └── tasks.ts
│ │ │ │ └── themes/
│ │ │ │ ├── +layout.svelte
│ │ │ │ ├── +layout.ts
│ │ │ │ └── +page.svelte
│ │ │ ├── +layout.server.ts
│ │ │ ├── +layout.svelte
│ │ │ ├── +layout.ts
│ │ │ └── preview/
│ │ │ └── [item]/
│ │ │ ├── +page.svelte
│ │ │ └── +page.ts
│ │ ├── (view)/
│ │ │ ├── +layout.svelte
│ │ │ └── view/
│ │ │ └── [view=view]/
│ │ │ ├── +page.svelte
│ │ │ └── +page.ts
│ │ ├── +error.svelte
│ │ ├── +layout.svelte
│ │ ├── api/
│ │ │ └── block/
│ │ │ └── [block]/
│ │ │ └── +server.ts
│ │ ├── init/
│ │ │ └── +server.ts
│ │ ├── og/
│ │ │ ├── +server.ts
│ │ │ ├── create/
│ │ │ │ └── +server.ts
│ │ │ └── og.ts
│ │ ├── registry/
│ │ │ └── +server.ts
│ │ └── repro/
│ │ └── +server.ts
│ ├── static/
│ │ ├── schema.json
│ │ └── site.webmanifest
│ ├── svelte.config.js
│ ├── tsconfig.json
│ ├── velite.config.js
│ ├── vite.config.ts
│ └── wrangler.jsonc
├── eslint.config.js
├── package.json
├── packages/
│ ├── cli/
│ │ ├── .gitignore
│ │ ├── .prettierignore
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── __mocks__/
│ │ │ ├── fs/
│ │ │ │ └── promises.cjs
│ │ │ └── fs.cjs
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── commands/
│ │ │ │ ├── add/
│ │ │ │ │ └── index.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── init/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── preflight.ts
│ │ │ │ ├── registry/
│ │ │ │ │ ├── build.ts
│ │ │ │ │ ├── deps-resolver.ts
│ │ │ │ │ └── index.ts
│ │ │ │ └── update/
│ │ │ │ └── index.ts
│ │ │ ├── constants.ts
│ │ │ ├── icons/
│ │ │ │ ├── index.ts
│ │ │ │ └── libraries.ts
│ │ │ ├── index.ts
│ │ │ ├── preset/
│ │ │ │ ├── index.ts
│ │ │ │ ├── preset.ts
│ │ │ │ └── presets.ts
│ │ │ ├── schema/
│ │ │ │ └── index.ts
│ │ │ └── utils/
│ │ │ ├── add-registry-items.ts
│ │ │ ├── auto-detect.ts
│ │ │ ├── colors.ts
│ │ │ ├── config/
│ │ │ │ ├── index.ts
│ │ │ │ ├── schema.ts
│ │ │ │ └── utils.ts
│ │ │ ├── css.ts
│ │ │ ├── errors.ts
│ │ │ ├── fonts.ts
│ │ │ ├── get-env-proxy.ts
│ │ │ ├── get-package-info.ts
│ │ │ ├── install-deps.ts
│ │ │ ├── preconditions.ts
│ │ │ ├── project.ts
│ │ │ ├── prompt-helpers.ts
│ │ │ ├── registry/
│ │ │ │ ├── index.ts
│ │ │ │ └── schema.ts
│ │ │ ├── resolve-imports.ts
│ │ │ ├── transform-css.ts
│ │ │ ├── transformers/
│ │ │ │ ├── index.ts
│ │ │ │ ├── transform-icons.ts
│ │ │ │ ├── transform-imports.ts
│ │ │ │ ├── transform-menu.ts
│ │ │ │ └── transform-strip-types.ts
│ │ │ ├── updaters/
│ │ │ │ ├── index.ts
│ │ │ │ ├── update-css-vars.ts
│ │ │ │ └── update-css.ts
│ │ │ └── utils.ts
│ │ ├── test/
│ │ │ ├── commands/
│ │ │ │ └── init.test.ts
│ │ │ ├── fixtures/
│ │ │ │ ├── colors/
│ │ │ │ │ ├── neutral.json
│ │ │ │ │ ├── slate.json
│ │ │ │ │ ├── stone.json
│ │ │ │ │ └── zinc.json
│ │ │ │ ├── config-custom-tsconfig/
│ │ │ │ │ ├── components.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── tsconfig.base.json
│ │ │ │ ├── config-full/
│ │ │ │ │ ├── components.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ └── app.css
│ │ │ │ │ └── tsconfig.json
│ │ │ │ ├── config-invalid/
│ │ │ │ │ ├── components.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── tsconfig.json
│ │ │ │ ├── config-jsconfig/
│ │ │ │ │ ├── components.json
│ │ │ │ │ ├── jsconfig.json
│ │ │ │ │ └── package.json
│ │ │ │ ├── config-none/
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── tsconfig.json
│ │ │ │ ├── config-partial/
│ │ │ │ │ ├── components.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── tsconfig.json
│ │ │ │ ├── config-trailing-slashes/
│ │ │ │ │ ├── components.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── tsconfig.json
│ │ │ │ ├── config-vite/
│ │ │ │ │ ├── components.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── tsconfig.json
│ │ │ │ ├── legacy/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── post-init-default/
│ │ │ │ │ │ ├── components.json
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ └── tsconfig.json
│ │ │ │ │ ├── post-init-new-york/
│ │ │ │ │ │ ├── components.json
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ └── tsconfig.json
│ │ │ │ │ ├── post-update-default/
│ │ │ │ │ │ ├── components.json
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ └── tsconfig.json
│ │ │ │ │ ├── post-update-new-york/
│ │ │ │ │ │ ├── components.json
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ └── tsconfig.json
│ │ │ │ │ └── pre-init/
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── tsconfig.json
│ │ │ │ ├── project-bun/
│ │ │ │ │ ├── bun.lockb
│ │ │ │ │ └── package.json
│ │ │ │ ├── project-npm/
│ │ │ │ │ └── package.json
│ │ │ │ ├── project-pnpm/
│ │ │ │ │ └── package.json
│ │ │ │ └── project-yarn/
│ │ │ │ └── package.json
│ │ │ ├── preset.test.ts
│ │ │ ├── registry-template.test.ts
│ │ │ └── utils/
│ │ │ ├── add-registry-items.test.ts
│ │ │ ├── auto-detect.test.ts
│ │ │ ├── deps-resolver.test.ts
│ │ │ ├── get-config.test.ts
│ │ │ ├── get-env-proxy.test.ts
│ │ │ ├── get-package-info.test.ts
│ │ │ ├── preconditions.test.ts
│ │ │ ├── preflight-init.test.ts
│ │ │ ├── project.test.ts
│ │ │ ├── registry.test.ts
│ │ │ ├── resolve-imports.test.ts
│ │ │ ├── test-helpers.ts
│ │ │ ├── transformers.test.ts
│ │ │ └── utils.test.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ └── registry/
│ ├── .gitignore
│ ├── .prettierignore
│ ├── CHANGELOG.md
│ ├── LICENSE.md
│ ├── README.md
│ ├── package.json
│ ├── src/
│ │ ├── index.ts
│ │ └── schemas.ts
│ ├── tsconfig.json
│ └── tsdown.config.ts
├── pnpm-workspace.yaml
├── registry-template/
│ ├── .gitignore
│ ├── .npmrc
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── README.md
│ ├── eslint.config.js
│ ├── package.json
│ ├── registry.json
│ ├── src/
│ │ ├── app.css
│ │ ├── app.d.ts
│ │ ├── app.html
│ │ ├── lib/
│ │ │ ├── index.ts
│ │ │ ├── registry/
│ │ │ │ ├── blocks/
│ │ │ │ │ ├── checkout-steps/
│ │ │ │ │ │ └── checkout-steps.svelte
│ │ │ │ │ ├── complex-component/
│ │ │ │ │ │ ├── +page.svelte
│ │ │ │ │ │ ├── components/
│ │ │ │ │ │ │ ├── pokemon-card.svelte
│ │ │ │ │ │ │ └── pokemon-image.svelte
│ │ │ │ │ │ ├── hooks/
│ │ │ │ │ │ │ └── use-pokemon.svelte.ts
│ │ │ │ │ │ └── lib/
│ │ │ │ │ │ └── pokemon.ts
│ │ │ │ │ ├── example-form/
│ │ │ │ │ │ └── example-form.svelte
│ │ │ │ │ ├── example-with-css/
│ │ │ │ │ │ ├── example-card.css
│ │ │ │ │ │ └── example-card.svelte
│ │ │ │ │ └── hello-world/
│ │ │ │ │ └── hello-world.svelte
│ │ │ │ └── ui/
│ │ │ │ ├── button/
│ │ │ │ │ ├── button.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── card/
│ │ │ │ │ ├── card-action.svelte
│ │ │ │ │ ├── card-content.svelte
│ │ │ │ │ ├── card-description.svelte
│ │ │ │ │ ├── card-footer.svelte
│ │ │ │ │ ├── card-header.svelte
│ │ │ │ │ ├── card-title.svelte
│ │ │ │ │ ├── card.svelte
│ │ │ │ │ └── index.ts
│ │ │ │ ├── input/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── input.svelte
│ │ │ │ ├── label/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── label.svelte
│ │ │ │ ├── stepper/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stepper-item.svelte
│ │ │ │ │ └── stepper.svelte
│ │ │ │ └── textarea/
│ │ │ │ ├── index.ts
│ │ │ │ └── input.svelte
│ │ │ └── utils.ts
│ │ └── routes/
│ │ ├── +layout.svelte
│ │ └── +page.svelte
│ ├── svelte.config.js
│ ├── tsconfig.json
│ └── vite.config.ts
└── repro/
├── .gitignore
├── .npmrc
├── README.md
├── components.json
├── package.json
├── src/
│ ├── app.css
│ ├── app.d.ts
│ ├── app.html
│ ├── lib/
│ │ ├── index.ts
│ │ └── utils.ts
│ └── routes/
│ ├── +layout.svelte
│ └── +page.svelte
├── static/
│ └── robots.txt
├── svelte.config.js
├── tsconfig.json
└── vite.config.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .changeset/README.md
================================================
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
================================================
FILE: .changeset/config.json
================================================
{
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
"changelog": ["@svitejs/changesets-changelog-github-compact", { "repo": "huntabyte/shadcn-svelte" }],
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [huntabyte, adriangonz97, ieedan]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: huntabyte
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/ISSUE_TEMPLATE/1-documentation_change.yml
================================================
name: Report Docs Issue
description: Suggest an addition or modification to the documentation
labels: [triage]
body:
- type: dropdown
attributes:
label: Change Type
description: What type of change are you proposing?
options:
- Addition
- Correction
- Removal
- Cleanup (formatting, typos, etc.)
validations:
required: true
- type: textarea
attributes:
label: Proposed Changes
description: Describe the proposed changes and why they are necessary
validations:
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/2-feature_request.yml
================================================
name: Feature request
description: Request a new feature
labels: [triage]
body:
- type: checkboxes
attributes:
label: Prerequisites
description: Please make sure you have checked all of the following.
options:
- label: This feature already exists in [shadcn/ui](https://github.com/shadcn/ui) - if not, it won't be considered here so don't continue with your issue.
required: true
- type: markdown
attributes:
value: |
This project's goal is to remain aligned with [shadcn/ui](https://github.com/shadcn-ui/ui). If the feature you are requesting is not in the original shadcn/ui, it will not be considered here.
- type: textarea
id: feature-description
attributes:
label: Describe the feature
description: A clear and concise description of the feature. If you intend to submit a PR for this feature, tell us how in the description. Thanks!
placeholder: Feature description
validations:
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/3-bug_report.yml
================================================
name: Bug report
description: Report an issue with shadcn-svelte
labels: [triage]
body:
- type: markdown
attributes:
value: |
### Thanks for taking the time to create an issue! Please search open/closed issues before submitting, as the issue may have already been reported/addressed.
- type: markdown
attributes:
value: |
#### If you aren't sure if something is a bug or not, please do not create an issue, instead ask in one of the following channels:
- [Discussions](https://github.com/huntabyte/shadcn-svelte/discussions/new?category=help)
- [Discord](https://discord.gg/fdXy3Sk8Gq)
- type: textarea
id: bug-description
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us how in the description. Thanks!
placeholder: Bug description
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction
description: |
Provide a minimal reproduction of the problem. Include a StackBlitz or link to a GitHub repository that we can easily run to recreate the issue. If a report is vague and does not have a reproduction, it will be closed without warning.
To get started, you can use the following StackBlitz template:
https://shadcn-svelte.com/repro
***Do not simply add a code snippet or a screenshot. We need a reproduction that we can easily run to recreate the issue.***
placeholder: Reproduction
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs
description: Please include browser console and server logs around the time this bug occurred. Optional if provided reproduction. Please try not to insert an image but copy paste the log text.
render: bash
- type: textarea
id: system-info
attributes:
label: System Info
description: Output of `npx envinfo --system --npmPackages svelte,shadcn-svelte,tailwindcss,bits-ui,vaul-svelte,sveltekit-superforms,@sveltejs/kit,mode-watcher,formsnap,cmdk-sv,svelte-radix,@lucide/svelte,svelte-sonner --binaries --browsers`
render: bash
placeholder: System, Binaries, Browsers
validations:
required: true
- type: dropdown
id: severity
attributes:
label: Severity
description: Select the severity of this issue
options:
- annoyance
- blocking an upgrade
- blocking all usage of shadcn-svelte
validations:
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Get Help
url: https://github.com/huntabyte/shadcn-svelte/discussions/new?category=help
about: If you can't get something to work the way you expect, open a question in our discussion forums.
- name: Discord
url: https://discord.gg/fdXy3Sk8Gq
about: If you need to have a back-and-forth conversation, join the Discord server.
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
================================================
FILE: .github/reproduire/needs-reproduction.md
================================================
Please provide a [reproduction](https://shadcn-svelte.com/repro).
More info
### Why do I need to provide a reproduction?
This project is maintained by a very small team, and we simply don't have the bandwidth to investigate issues that we can't easily replicate. Reproductions enable us to fix issues faster and more efficiently. If you care about getting your issue resolved, providing a reproduction is the best way to do that.
### I've provided a reproduction - what happens now?
Once a reproduction is provided, we'll remove the `needs reproduction` label and review the issue to determine how to resolve it. If we can confirm it's a bug, we'll label it as such and prioritize it based on its severity.
If `needs reproduction` labeled issues don't receive any activity (e.g., a comment with a reproduction link), they'll be closed. Feel free to comment with a reproduction at any time and the issue will be reopened.
### How can I create a reproduction?
You can use [this template](https://shadcn-svelte.com/repro) to create a minimal reproduction. You can also link to a GitHub repository with the reproduction.
Please ensure that the reproduction is as **minimal** as possible. If there is a ton of custom logic in your reproduction, it is difficult to determine if the issue is with your code or with the library. The more minimal the reproduction, the more likely it is that we'll be able to assist.
You might also find these other articles interesting and/or helpful:
- [The Importance of Reproductions](https://antfu.me/posts/why-reproductions-are-required)
- [How to Generate a Minimal, Complete, and Verifiable Example](https://stackoverflow.com/help/mcve)
================================================
FILE: .github/workflows/autoformat.yml
================================================
name: Auto-format PR on Comment
on:
issue_comment:
types: [created]
jobs:
format:
# only run on PR comments
if: github.event.issue.pull_request
runs-on: macos-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Check trigger and permissions
uses: actions/github-script@v7
id: check-permission
with:
script: |
const commentBody = context.payload.comment.body;
const hasTrigger = commentBody.includes('/format') || commentBody.includes('/autoformat');
if (!hasTrigger) {
console.log('Comment does not contain trigger phrase. Skipping.');
core.setOutput('should-continue', 'false');
return false;
}
const { data: perm } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: context.payload.comment.user.login
});
const hasWriteAccess = ['admin', 'write'].includes(perm.permission);
if (!hasWriteAccess) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: '❌ Sorry, you need write access to trigger auto-formatting.'
});
core.setOutput('should-continue', 'false');
return false;
}
core.setOutput('should-continue', 'true');
return true;
- name: Get PR details
if: steps.check-permission.outputs.should-continue == 'true'
uses: actions/github-script@v7
id: get-pr
with:
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});
core.setOutput('head-ref', pr.head.ref);
core.setOutput('head-sha', pr.head.sha);
core.setOutput('base-ref', pr.base.ref);
core.setOutput('pr-number', pr.number);
- name: React to comment
if: steps.check-permission.outputs.should-continue == 'true'
uses: actions/github-script@v7
with:
script: |
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: 'rocket'
});
- name: Checkout PR branch
if: steps.check-permission.outputs.should-continue == 'true'
uses: actions/checkout@v4
with:
ref: ${{ steps.get-pr.outputs.head-ref }}
- uses: pnpm/action-setup@v4
if: steps.check-permission.outputs.should-continue == 'true'
- uses: actions/setup-node@v4
if: steps.check-permission.outputs.should-continue == 'true'
with:
node-version: 20
cache: pnpm
- name: Install dependencies
if: steps.check-permission.outputs.should-continue == 'true'
run: pnpm install
- name: Run formatter
if: steps.check-permission.outputs.should-continue == 'true'
run: pnpm format .
- name: Check for changes
if: steps.check-permission.outputs.should-continue == 'true'
id: check-changes
run: |
if [[ -z $(git status --porcelain) ]]; then
echo "has-changes=false" >> $GITHUB_OUTPUT
else
echo "has-changes=true" >> $GITHUB_OUTPUT
fi
- name: Commit and push changes
if: steps.check-permission.outputs.should-continue == 'true' && steps.check-changes.outputs.has-changes == 'true'
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add .
git commit -m "chore: auto-format code via GitHub Action
Triggered by @${{ github.event.comment.user.login }} in PR #${{ steps.get-pr.outputs.pr-number }}"
git push origin HEAD:${{ steps.get-pr.outputs.head-ref }}
- name: Comment on PR with result
uses: actions/github-script@v7
if: always() && steps.check-permission.outputs.should-continue == 'true'
with:
script: |
const hasChanges = '${{ steps.check-changes.outputs.has-changes }}' === 'true';
const success = '${{ job.status }}' === 'success';
let body;
if (!success) {
body = '❌ Auto-formatting failed. Please check the workflow logs.';
} else if (hasChanges) {
body = '✅ Code has been auto-formatted and changes have been pushed to this PR.';
} else {
body = '✅ No formatting changes needed. Code is already properly formatted.';
}
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
================================================
FILE: .github/workflows/build-preview.yml
================================================
name: Build Preview Deployment
# cancel in-progress runs on new commits to same PR (github.event.number)
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
cancel-in-progress: true
on:
pull_request:
types: [opened, synchronize]
jobs:
build-preview:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Build site
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: preview-build
path: docs/.svelte-kit
include-hidden-files: true
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
cancel-in-progress: true
jobs:
check:
name: Type Check
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Run svelte-check
run: pnpm check
lint:
name: Lint
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install
- run: pnpm lint
cli-test:
name: CLI-Tests
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Build packages
run: pnpm build:cli
- name: Run tests
run: pnpm -F shadcn-svelte test
================================================
FILE: .github/workflows/deploy-preview.yml
================================================
name: Upload Preview Deployment
on:
workflow_run:
workflows: [Build Preview Deployment]
types:
- completed
permissions:
actions: read
deployments: write
contents: read
pull-requests: write
jobs:
deploy-preview:
runs-on: macos-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
id: preview-build-artifact
with:
name: preview-build
path: build
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Deploy to Cloudflare Pages
uses: AdrianGonz97/refined-cf-pages-action@v1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
githubToken: ${{ secrets.GITHUB_TOKEN }}
projectName: shadcn-svelte
deploymentName: Preview
directory: ${{ steps.preview-build-artifact.outputs.download-path }}/cloudflare
================================================
FILE: .github/workflows/deploy-prod.yml
================================================
name: Production Deployment
on:
push:
branches:
- main
paths:
- docs/**
- packages/registry/**
workflow_dispatch:
jobs:
deploy-production:
runs-on: macos-latest
permissions:
contents: read
deployments: write
name: Deploy Production Site to Cloudflare Pages
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Build site
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Deploy to Cloudflare
run: pnpm -F docs exec wrangler deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
================================================
FILE: .github/workflows/deploy-svelte-4.yml
================================================
name: Svelte 4 Deployment
on:
push:
branches:
- svelte-4
paths:
- sites/docs/**
workflow_dispatch:
jobs:
deploy-production:
runs-on: macos-latest
permissions:
contents: read
deployments: write
name: Deploy Production Site to Cloudflare Pages
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Build site
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Deploy to Cloudflare Pages
uses: AdrianGonz97/refined-cf-pages-action@v1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
githubToken: ${{ secrets.GITHUB_TOKEN }}
projectName: shadcn-svelte
directory: ./.svelte-kit/cloudflare
workingDirectory: sites/docs
branch: ${{ github.ref_name }}
================================================
FILE: .github/workflows/deploy-tailwind-3.yml
================================================
name: Tailwind 3 Deployment
on:
push:
branches:
- next-tailwind-3
paths:
- sites/docs/**
workflow_dispatch:
jobs:
deploy-production:
runs-on: macos-latest
permissions:
contents: read
deployments: write
name: Deploy Production Site to Cloudflare Pages
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Build site
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Deploy to Cloudflare Pages
uses: AdrianGonz97/refined-cf-pages-action@v1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
githubToken: ${{ secrets.GITHUB_TOKEN }}
projectName: shadcn-svelte-tw-3
directory: ./.svelte-kit/cloudflare
workingDirectory: sites/docs
deploymentName: Production Tailwind 3
================================================
FILE: .github/workflows/pr-guard.yml
================================================
name: PR guard
on:
pull_request_target:
types: [opened, reopened]
permissions:
pull-requests: write
issues: write
jobs:
guard:
uses: huntabyte/actions/.github/workflows/guard-fork-main.yml@main
================================================
FILE: .github/workflows/release.yml
================================================
name: Publish
on:
push:
branches:
- main
- next
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
permissions:
contents: write # to create release (changesets/action)
pull-requests: write # to create pull request (changesets/action)
id-token: write # Required for OIDC
name: Build & Publish Release
if: github.repository == 'huntabyte/shadcn-svelte'
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- run: npm install -g npm@latest
- name: Install dependencies
run: pnpm install
- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@v1
with:
commit: "chore(release): version package"
title: "chore(release): version package"
publish: pnpm ci:release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_CONFIG_PROVENANCE: true
NODE_ENV: production
================================================
FILE: .github/workflows/reproduire-close.yml
================================================
name: Close incomplete issues
on:
workflow_dispatch:
schedule:
- cron: "30 1 * * *" # run every day
permissions:
issues: write
jobs:
stale:
runs-on: macos-latest
steps:
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with:
days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
stale-issue-label: needs reproduction # Label that flags an issue as stale.
only-labels: needs reproduction # Only process these issues
days-before-issue-close: 7
ignore-updates: true
remove-stale-when-updated: false
close-issue-message: This issue was closed because it was open for 7 days without a reproduction.
close-issue-label: closed-by-bot
================================================
FILE: .github/workflows/reproduire.yml
================================================
name: Reproduire
on:
issues:
types: [labeled]
permissions:
issues: write
jobs:
reproduire:
runs-on: macos-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: Hebilicious/reproduire@4b686ae9cbb72dad60f001d278b6e3b2ce40a9ac # v0.0.9-mp
with:
label: needs reproduction
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
dist
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.turbo
**/.svelte-kit/**/*
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# JetBrains IDEs
.idea/
.velite
docs/static/registry
docs/static/themes.css
docs/static/schema/registry.json
docs/static/schema/registry-item.json
docs/src/__registry__
docs/static/docs
docs/static/llms.txt
docs/static/docs.md
registry-template/static/r
repro/src/lib/hooks
repro/src/lib/components/ui
!repro/src/lib/components/ui/light-switch
================================================
FILE: .npmrc
================================================
engine-strict=true # https://pnpm.io/npmrc#engine-strict
prefer-frozen-lockfile=false
supported-architecture-os=darwin,linux,win32
supported-architecture-cpu=x64,arm64
================================================
FILE: .nvmrc
================================================
v22.15.0
================================================
FILE: .prettierignore
================================================
.changeset
.DS_Store
node_modules
**/build
**/.svelte-kit
**/package
**/dist
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
CHANGELOG.md
.github/
registry-template
# docs site specific
docs/other/themes/dark.json
docs/other/themes/light.json
docs/static
docs/.velite
docs/src/__registry__
packages/cli/test/fixtures
playgrounds
registry-template/static
.svelte-kit
docs/src/routes/og/*-otf.json
**/__*__/**/*
================================================
FILE: .prettierrc
================================================
{
"useTabs": true,
"tabWidth": 4,
"singleQuote": false,
"trailingComma": "es5",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
},
{
"files": "*.md",
"options": {
"tabWidth": 2,
"useTabs": false,
"printWidth": 79
}
},
{
"files": ".github/**/*",
"options": {
"tabWidth": 2,
"useTabs": false
}
}
],
"tailwindFunctions": ["clsx", "cn", "tv"]
}
================================================
FILE: .vscode/settings.json
================================================
{
// Enable the ESlint flat config support
"eslint.useFlatConfig": true,
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never",
"source.removeUnusedImports": "never",
"source.removeUnused.ts": "never"
},
// Enable eslint for all supported languages
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"svelte",
"html",
"markdown",
"json",
"jsonc",
"yaml",
"toml",
"astro"
]
}
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to shadcn-svelte
We appreciate your interest in contributing. This guide will help you get started with the contribution process.
## Table of Contents
- [Contributing to shadcn-svelte](#contributing-to-shadcn-svelte)
- [Table of Contents](#table-of-contents)
- [Ways to contribute](#ways-to-contribute)
- [How to contribute](#how-to-contribute)
- [Questions](#questions)
- [License](#license)
## Ways to contribute
We welcome all kinds of contributions:
- **Feedback** - have suggestions or ideas? [Open a discussion](https://github.com/huntabyte/shadcn-svelte/discussions) to discuss it. Just note that this project is a port of [shadcn/ui](https://github.com/shadcn/ui), meaning we won't be adding new components to this project unless they are added to `shadcn/ui` first.
- **Help & Support** - if you enjoy helping others, join the [Discord](https://discord.gg/SRbSSrvXug) and help out in the `libs` -> `shadcn-support` channel, or answer questions asked in [Discussions](https://github.com/huntabyte/shadcn-svelte/discussions)
- **Bug reports** - please [open an issue](https://github.com/huntabyte/shadcn-svelte/issues/new) to report a bug.
- **Docs fixes** - spot a typo or broken link? Open a PR. If it's a larger change, please start a discussion first.
- **Code improvements** - For anything more involved than a quick fix, start a discussion first so we can align before you dive in.
## How to contribute
We try to keep the process simple to avoid wasted effort:
1. **Open an issue** for bugs
2. **Start a discussion** for feature ideas, improvements, or questions
3. A maintainer will review and tag it (e.g. help wanted, under review, etc.)
4. Want to work on something? Just comment on the thread or open a PR.
**Quick fix?** For typos or small tweaks, feel free to skip the discussion and just open a PR.
**Bigger change?** Open a discussion first so we can figure things out together.
## Questions
If you're looking to contribute and have questions about the process or the codebase in general, feel free to ask in the [Discord](https://hbyt.us/discord) in the `libs`->`shadcn-chat` channel!
## License
By contributing to this project, you agree that your contributions will be licensed under the [LICENSE](LICENSE.md) of the project.
================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) 2023 Hunter Johnston
Copyright (c) 2023 CokaKoala
Copyright (c) 2023 shadcn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
shadcn-svelte
[](https://discord.gg/fdXy3Sk8Gq)
[shadcn-svelte](https://www.shadcn-svelte.com/) is an unofficial community-led [Svelte](https://svelte.dev) port of [shadcn/ui](https://ui.shadcn.com/).
> **Note** **We are not affiliated with shadcn, but we did get his blessing prior to creating this project** This is a project born out of the need for a similar project for the Svelte ecosystem.
Accessible and customizable components that you can copy and paste into your apps. Free. Open Source. **Use this to build your own component library**.

## Documentation
Visit https://shadcn-svelte.com/docs to view the documentation.
## Sponsors
This project is supported by the following beautiful people/organizations:
## License
Published under the [MIT](https://github.com/huntabyte/shadcn-svelte/blob/main/LICENSE.md) license.
Built by [@huntabyte](https://github.com/huntabyte), [CokaKoala](https://github.com/adriangonz97),and [community](https://github.com/huntabyte/shadcn-svelte/graphs/contributors) 💛
## Community
Join the Discord server to ask questions, find collaborators, or just say hi!
================================================
FILE: docs/.gitignore
================================================
node_modules
# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/build
# OS
.DS_Store
Thumbs.db
# Env
.env
.env.*
!.env.example
!.env.test
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
================================================
FILE: docs/.npmrc
================================================
engine-strict=true
================================================
FILE: docs/README.md
================================================
# shadcn-svelte docs
================================================
FILE: docs/_headers
================================================
/*
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
================================================
FILE: docs/content/about.md
================================================
---
title: About
description: Powered by amazing open source projects.
---
## About
[shadcn-svelte](https://github.com/huntabyte/shadcn-svelte) is a port of [shadcn/ui](https://ui.shadcn.com) for Svelte/SvelteKit. It's maintained by [Huntabyte](https://x.com/huntabyte), [CokaKoala](https://github.com/adriangonz97), and [Aidan Bleser](https://x.com/ieeeedan) and has received countless contributions from the community.
## Credits
- [shadcn](https://twitter.com/shadcn) - The brilliant mind behind the designs, methodology, and implementation of the original [shadcn/ui](https://ui.shadcn.com).
- [Bits UI](https://bits-ui.com) - The headless components that power this project.
- [Formsnap](https://formsnap.dev) - The form components that power this project.
- [Paneforge](https://paneforge.com) - The resizable components that power this project.
- [Vaul Svelte](https://vaul-svelte.com) - The drawer components that power this project.
- [Radix UI](https://radix-ui.com) - The headless components and examples that the original [shadcn/ui](https://ui.shadcn.com) was built on.
- [Shu Ding](https://shud.in) - The typography style is adapted from his work on Nextra.
- [Cal](https://cal.com) - Where shad copied the styles for the first component: the `Button`.
## License
MIT © [shadcn](https://shadcn.com) & [huntabyte](https://twitter.com/huntabyte)
================================================
FILE: docs/content/changelog.md
================================================
---
title: Changelog
description: Latest updates and announcements.
---
## October 2025 - New Components
For this round of components, I looked at what we build every day, the boring stuff we rebuild over and over, and made reusable abstractions you can actually use.
- [Spinner](/docs/components/spinner): An indicator to show a loading state.
- [Kbd](/docs/components/kbd): Display a keyboard key or group of keys.
- [Button Group](/docs/components/button-group): A group of buttons for actions and split buttons.
- [Input Group](/docs/components/input-group): Input with icons, buttons, labels and more.
- [Field](/docs/components/field): One component. All your forms.
- [Item](/docs/components/item): Display lists of items, cards, and more.
- [Empty](/docs/components/empty): Use this one for empty states.
---
## June 2025
### New Calendar Components
We've completely overhauled the `Calendar` and `RangeCalendar` components to support dropdowns for the month and year selectors, and have added 30+ Calendar blocks to help you get started building your own calendar components.
Check out the [Calendar](/docs/components/calendar) docs page and the [Calendar Blocks](/blocks/calendar) page for more.
---
## May 2025
### Tailwind v4 Support
Tailwind v4 support has officially landed. You can see a full demo of the refreshed styles that come with it here: [https://v4.shadcn-svelte.com](https://v4.shadcn-svelte.com).
This release includes several key changes, all outlined in the [Tailwind v4 migration guide](/docs/migration/tailwind-v4). If you're still using Svelte v5 with Tailwind v3, your project and the CLI will continue to work as expected until you're ready to upgrade.
### Charts
Charts have been added as a preview component to the project. See the [Charts](/charts) page for examples.
If you're running Svelte v5 and Tailwind v4 you can add them to your project via the CLI.
### Custom Registry Support
We've added support for custom/remote registries - This means you can publish your own components and share them with the community via the `shadcn-svelte` CLI.
See the [Registry documentation](/docs/registry) for more information.
---
## March 2024
### Introducing Blocks
[Blocks](/blocks) are ready-made components that you can use to build your apps. They are fully responsive, accessible, and composable, meaning they are built using the same principles as the rest of the components in shadcn-svelte.
[v0](https://v0.dev) only supports React at the moment, so you can't customize them like you can the original from [shadcn/ui](https://ui.shadcn.com). However, if having support for Svelte interests you, I'm sure the v0 team would love to hear about it. :)
### New Component: Breadcrumb
We've added a new component to the project, [Breadcrumb](/docs/components/breadcrumb).
### New Component: Scroll Area
We've added a new component to the project, [Scroll Area](/docs/components/scroll-area), which is built on top of the [Scroll Area](https://bits-ui.com/docs/components/scroll-area) component from Bits UI.
It supports both vertical and horizontal scrolling, and is designed to provide a consistent experience across all browsers and platforms.
## February 2024
### New Component: Resizable
We've added a new component to the project, [Resizable](/docs/components/resizable), which is built on top of [PaneForge](https://paneforge.com). PaneForge is still in an early stage, so be sure to raise any issues you find with the library on the [PaneForge GitHub](https://github.com/svecosystem/paneforge).
### Updated Icon Imports
After some feedback about dev server performance, we've updated the way we import icons. With this change, we've decided to move away from the unmaintained `radix-icons-svelte` package to [svelte-radix](https://github.com/shinokada/svelte-radix) for the `new-york` style.
Instead of importing icons like so:
```ts
import { Check } from "@lucide/svelte";
```
We now import them directly:
```ts
import Check from "@lucide/svelte/icons/check";
```
With deep imports, we're preventing Vite from optimizing the entire icon collections, and instead only optimizing the icons that are actually used in your project. From what we've seen, this has a massive impact on dev server performance. Enjoy! 🚀
### Major Forms Update
Formsnap has been completely rewritten to be more flexible, easier to use, and less opinionated. This means we've had to make some changes to the way we use it in `shadcn-svelte`, but once you get the hang of it, you'll find it's much more powerful and less restrictive than the previous iteration.
Since the changes are so significant, there isn't a direct migration path from the old version to the new version. You'll need to update your components to use the new API, as well as ensure you're using the latest version of `formsnap` and `sveltekit-superforms`.
All of the `Form` components have been updated to use the new API, and you can see live examples of them on the [Forms Examples](/examples/forms) page.
Visit the [Formsnap](https://formsnap.dev) documentation (which has also been updated) to learn more about the new API and how its used.
## January 2024
We've added four new components to the project, [Carousel](/docs/components/carousel), [Drawer](/docs/components/drawer), [Sonner](/docs/components/sonner), & [Pagination](/docs/components/pagination).
### New Component: Carousel
We've added a new component to the project, [Carousel](/docs/components/carousel).
### New Component: Drawer
The Drawer is built on top of [vaul-svelte](https://vaul-svelte.com) and is a port of [vaul](https://vaul.emilkowalski.ski/), originally created by [Emil Kowalski](https://twitter.com/emilkowalski_) for React.
### New Component: Sonner
The Sonner component is provided by [svelte-sonner](https://svelte-sonner.vercel.app/), which is a Svelte port of [Sonner](https://sonner.emilkowal.ski/), originally created by [Emil Kowalski](https://twitter.com/emilkowalski_) for React.
### New Component: Pagination
Pagination leverages the [Pagination](https://bits-ui.com/docs/components/pagination) component from Bits UI.
## December 2023
We've added three new components to the project, [Calendar](/docs/components/calendar), [Range Calendar](/docs/components/range-calendar), & [Date Picker](/docs/components/date-picker).
## November 2023
### New Component: Toggle Group
We've added a new component to the library, [Toggle Group](/docs/components/toggle-group).
## October 2023
We've added two new components to the library, [Command](/docs/components/command) & [Combobox](/docs/components/combobox). We've also made some updates to the ` ` component that you'll want to be aware of.
### New Component: Command
Command is a component that allows you to create a command palette. It's built on top of [cmdk-sv](https://cmdk-sv.com), which is a Svelte port of [cmdk](https://cmdk.paco.me). The library is still in its infancy, but we're excited to see where it goes. If you notice any issues, please [open an issue](https://github.com/huntabyte/cmdk-sv) with the library.
Be sure to check out the [Command](/docs/components/command) docs for more information.
### New Component: Combobox
Combobox is a combination of the ` ` & ` ` components. It allows you to create a searchable dropdown menu.
Be sure to check out the [Combobox](/docs/components/combobox) docs for more information.
### Updates to Form
#### Form.Label Changes
Since we had to make some internal changes to formsnap to fix outstanding issues, there is a slight modification we have to make to the ` ` component. The `ids` returned from `getFormField()` is now a store, so we need to prefix it with `$` when we use it.
```svelte title="form-label.svelte" {2}
```
### Form.Control
Formsnap introduced a new component ` ` which wraps non-traditional form elements. This allows us to ensure the components are accessible, and work well with the rest of the form components. You'll need to define & export that control in your `form/index.ts` file.
```ts title="src/lib/ui/form/index.ts"
// ...rest
const Control = FormPrimitive.Control;
export {
// ...rest
Control,
Control as FormControl,
};
```
================================================
FILE: docs/content/cli.md
================================================
---
title: shadcn-svelte
description: Use the shadcn-svelte CLI to add components to your project.
---
## init
Use the `init` command to initialize dependencies for a new project.
The `init` command installs dependencies, adds the `cn` util, and creates CSS variables for the project.
You will be asked a few questions to configure `components.json`:
```txt showLineNumbers
Which base color would you like to use? › Slate
Where is your global CSS file? (this file will be overwritten) › src/routes/layout.css
Configure the import alias for lib: › $lib
Configure the import alias for components: › $lib/components
Configure the import alias for utils: › $lib/utils
Configure the import alias for hooks: › $lib/hooks
Configure the import alias for ui: › $lib/components/ui
```
**Options**
```bash
Usage: shadcn-svelte init [options]
initialize your project and install dependencies
Options:
-c, --cwd the working directory (default: the current directory)
-o, --overwrite overwrite existing files (default: false)
--no-deps disable adding & installing dependencies
--skip-preflight ignore preflight checks and continue (default: false)
--base-color the base color for the components (choices: "slate", "gray", "zinc",
"neutral", "stone")
--css path to the global CSS file
--components-alias import alias for components
--lib-alias import alias for lib
--utils-alias import alias for utils
--hooks-alias import alias for hooks
--ui-alias import alias for ui
--proxy fetch items from registry using a proxy
-h, --help display help for command
```
---
## add
Use the `add` command to add components and dependencies to your project.
**Options**
```bash
Usage: shadcn-svelte add [options] [components...]
add components to your project
Arguments:
components the components to add or a url to the component
Options:
-c, --cwd the working directory (default: the current directory)
--no-deps skips adding & installing package dependencies
--skip-preflight ignore preflight checks and continue (default: false)
-a, --all install all components to your project (default: false)
-y, --yes skip confirmation prompt (default: false)
-o, --overwrite overwrite existing files (default: false)
--proxy fetch components from registry using a proxy
-h, --help display help for command
```
---
## registry build
Use the `registry build` command to generate the registry JSON files.
This command reads the `registry.json` file and generates the registry JSON files into the `static/r` directory.
**Options**
```bash
Usage: shadcn-svelte registry build [options] [registry]
build components for a shadcn-svelte registry
Arguments:
registry path to registry.json file (default: ./registry.json)
Options:
-c, --cwd the working directory (default: the current directory)
-o, --output destination directory for json files (default: ./static/r)
-h, --help display help for command
```
---
## Outgoing Requests
### Proxy
This enables the use of a proxy when sending out requests to fetch from the `shadcn-svelte` registry. If the `HTTP_PROXY` or `http_proxy` environment variables have been set, the request library underneath will respect the proxy settings.
```bash
HTTP_PROXY="" npx shadcn-svelte@latest init
```
================================================
FILE: docs/content/components/accordion.md
================================================
---
title: Accordion
description: A vertically stacked set of interactive headings that each reveal a section of content.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/accordion
doc: https://bits-ui.com/docs/components/accordion
api: https://bits-ui.com/docs/components/accordion#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Is it accessible?
Yes. It adheres to the WAI-ARIA design pattern.
```
================================================
FILE: docs/content/components/alert-dialog.md
================================================
---
title: Alert Dialog
description: A modal dialog that interrupts the user with important content and expects a response.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/alert-dialog
doc: https://bits-ui.com/docs/components/alert-dialog
api: https://bits-ui.com/docs/components/alert-dialog#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbersw
```
```svelte showLineNumbers
Open
Are you absolutely sure?
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
Cancel
Continue
```
================================================
FILE: docs/content/components/alert.md
================================================
---
title: Alert
description: Displays a callout for user attention.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/alert
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Heads up!
You can add components to your app using the cli.
```
================================================
FILE: docs/content/components/aspect-ratio.md
================================================
---
title: Aspect Ratio
description: Displays content within a desired ratio.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/aspect-ratio
doc: https://bits-ui.com/docs/components/aspect-ratio
api: https://bits-ui.com/docs/components/aspect-ratio#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
```
================================================
FILE: docs/content/components/avatar.md
================================================
---
title: Avatar
description: An image element with a fallback for representing the user.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/avatar
doc: https://bits-ui.com/docs/components/avatar
api: https://bits-ui.com/docs/components/avatar#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
CN
```
================================================
FILE: docs/content/components/badge.md
================================================
---
title: Badge
description: Displays a badge or a component that looks like a badge.
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/badge
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
Badge
```
### Link
You can use the `badgeVariants` helper to create a link that looks like a badge.
```svelte
Badge
```
================================================
FILE: docs/content/components/breadcrumb.md
================================================
---
title: Breadcrumb
description: Displays the path to the current resource using a hierarchy of links.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/breadcrumb
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Home
Components
Breadcrumb
```
## Examples
### Custom separator
Use a custom component in the `` of ` ` to create a custom separator.
```svelte showLineNumbers {2,11-13}
Home
Components
```
---
### Dropdown
You can compose ` ` with a ` ` to create a dropdown in the breadcrumb.
```svelte showLineNumbers {2-5,11-22}
Components
Documentation
Themes
GitHub
```
---
### Collapsed
We provide a ` ` component to show a collapsed state when the breadcrumb is too long.
```svelte showLineNumbers {2,9}
{/* ... */}
{/* ... */}
```
---
### Link component
To use a link just add the `href` prop to ` `.
```svelte showLineNumbers {2,7-9}
Home
{/* ... */}
```
---
### Responsive
Here's an example of a responsive breadcrumb that composes ` ` with ` `, ` `, and ` `.
It displays a dropdown on desktop and a drawer on mobile.
================================================
FILE: docs/content/components/button-group.md
================================================
---
title: Button Group
description: A container that groups related buttons together with consistent styling.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/button-group
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
Button 1
Button 2
```
## Accessibility
- The `ButtonGroup` component has the `role` attribute set to `group`.
- Use `tabindex` to navigate between the buttons in the group.
- Use `aria-label` or `aria-labelledby` to label the button group.
```svelte showLineNumbers
Button 1
Button 2
```
## ButtonGroup vs ToggleGroup
- Use the `ButtonGroup` component when you want to group buttons that perform an action.
- Use the `ToggleGroup` component when you want to group buttons that toggle a state.
## Examples
### Orientation
Set the `orientation` prop to change the button group layout.
### Size
Control the size of buttons using the `size` prop on individual buttons.
### Nested
Nest `ButtonGroup` components to create button groups with spacing.
### Separator
The `ButtonGroupSeparator` component visually divides buttons within a group.
Buttons with variant `outline` do not need a separator since they have a border. For other variants, a separator is recommended to improve the visual hierarchy.
### Split
Create a split button group by adding two buttons separated by a `ButtonGroupSeparator`.
### Input
Wrap an `Input` component with buttons.
### Input Group
Wrap an `InputGroup` component to create complex input layouts.
### Dropdown Menu
Create a split button group with a `DropdownMenu` component.
### Select
Pair with a `Select` component.
### Popover
Use with a `Popover` component.
================================================
FILE: docs/content/components/button.md
================================================
---
title: Button
description: Displays a button or a component that looks like a button.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/button
api: https://bits-ui.com/docs/components/button#api-reference
---
**Updated:** We have updated the button component to add new sizes: `icon-sm` and `icon-lg`. See the
[changelog](/docs/components/button#changelog) for more details. Follow the
instructions to update your project.
```svelte showLineNumbers
Button
```
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
Button
```
## Examples
### Size
```svelte
Small
Default
Large
```
### Default
```svelte
Button
```
### Outline
```svelte
Outline
```
### Secondary
```svelte
Secondary
```
### Ghost
```svelte
Ghost
```
### Destructive
```svelte
Destructive
```
### Link
```svelte
Link
```
### Icon
```svelte
```
### With Icon
The spacing between the icon and the text is automatically adjusted based on the size of the button. You do not need any margin on the icon.
```svelte
New Branch
```
### Rounded
Use the `rounded-full` class to make the button rounded.
```svelte
```
### Spinner
```svelte showLineNumbers
Submit
```
### Button Group
To create a button group, use the `ButtonGroup` component. See the [Button Group](/docs/components/button-group) documentation for more details.
```svelte showLineNumbers
Archive
Report
Snooze
{#snippet child({ props })}
{/snippet}
Mark as Read
Archive
Snooze
Add to Calendar
Add to List
Label As...
Personal
Work
Other
Trash
```
### Link
You can convert the `` into an `` element by simply passing an `href` as a prop.
```svelte
Dashboard
```
Alternatively, you can use the `buttonVariants` helper to create a link that looks like a button.
```svelte
Dashboard
```
## Changelog
### 2025-09-24 New sizes
We have added two new sizes to the button component: `icon-sm` and `icon-lg`. These sizes are used to create icon buttons. To add them, edit `button.svelte` and add the following code under `size` in `buttonVariants`:
```ts showLineNumbers title="components/ui/button.svelte"
export const buttonVariants = tv({
// ...
variants: {
// ...
size: {
// ...
icon: "size-9",
"icon-sm": "size-8",
"icon-lg": "size-10",
},
},
});
```
================================================
FILE: docs/content/components/calendar.md
================================================
---
title: Calendar
description: A calendar component that allows users to select dates.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/calendar
doc: https://bits-ui.com/docs/components/calendar
api: https://bits-ui.com/docs/components/calendar#api-reference
---
## Blocks
We have built a collection of 30+ calendar blocks that you can use to build your own calendar components.
See call calendar blocks in the [Blocks Library](/blocks/calendar) page.
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui` and `@internationalized/date`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## About
The ` ` component is built on top of the [Bits UI Calendar](https://www.bits-ui.com/docs/components/calendar) component, which uses the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package to handle dates.
If you're looking for a range calendar, check out the [Range Calendar](/docs/components/range-calendar) component.
## Date Picker
You can use the ` ` component to build a date picker. See the [Date Picker](/docs/components/date-picker) page for more information.
## Examples
### Range Calendar
### Month and Year Selector
### Date of Birth Picker
### Date and Time Picker
### Natural Language Picker
This component uses the `chrono-node` library to parse natural language dates.
## Upgrade Guide
You can upgrade to the latest version of the ` ` component by running the following command:
When you're prompted to overwrite the existing files, select `Yes`. **If you have made any changes to the `Calendar` component, you will need to merge your changes with the new version.**
#### Installing Blocks
After upgrading the `Calendar` component, you can add the new blocks with the following:
This will add the latest version of the calendar blocks.
================================================
FILE: docs/content/components/card.md
================================================
---
title: Card
description: Displays a card with header, content, and footer.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/card
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Card Title
Card Description
Card Content
Card Footer
```
## Examples
================================================
FILE: docs/content/components/carousel.md
================================================
---
title: Carousel
description: A carousel with motion and swipe built using Embla.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/carousel
doc: https://www.embla-carousel.com/get-started/svelte
api: https://www.embla-carousel.com/api
---
## About
The carousel component is built using the [Embla Carousel](https://www.embla-carousel.com/get-started/svelte/) library.
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `embla-carousel-svelte`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
...
...
...
```
## Examples
### Sizes
To set the size of the items, you can use the `basis` utility class on the ` `.
```svelte showLineNumbers {4-6}
...
...
...
```
```svelte showLineNumbers {4-6}
...
...
...
```
### Spacing
To set the spacing between the items, we use a `ps-[VALUE]` utility on the ` ` and a negative `-ms-[VALUE]` on the ` `.
```svelte showLineNumbers /-ms-4/ /ps-4/
...
...
...
```
```svelte showLineNumbers /-ms-2/ /ps-2/ /md:-ms-4/ /md:ps-4/
...
...
...
```
### Orientation
Use the `orientation` prop to set the orientation of the carousel.
```svelte showLineNumbers /vertical | horizontal/
...
...
...
```
## Options
You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/api/options/) for more information.
```svelte showLineNumbers {2-5}
...
...
...
```
## API
Use reactive state and the `setApi` callback to get an instance of the carousel API.
```svelte showLineNumbers {2,5,19}
(api = emblaApi)}>
...
...
...
```
## Events
You can listen to events using the api instance from `bind:api`.
```svelte showLineNumbers {2,5,7-13,16}
(api = emblaApi)}>
...
...
...
```
## Plugins
You can use the `plugins` prop to add plugins to the carousel.
```svelte showLineNumbers {2,7-11}
```
See the [Embla Carousel docs](https://www.embla-carousel.com/api/plugins/) for more information on using plugins.
================================================
FILE: docs/content/components/chart.md
================================================
---
title: Chart
description: Beautiful charts. Built using LayerChart. Copy and paste into your apps.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/chart
---
**Important:** LayerChart v2 is still in pre-release and is actively evolving. Only use if you're comfortable with potential breaking changes before stable v2.
Your feedback will be invaluable in shaping the release and features. Current development status can be tracked [here](https://github.com/techniq/layerchart/pull/449).
Introducing **Charts**. A collection of chart components that you can copy and paste into your apps.
Charts are designed to look great out of the box. They work well with other components are are fully customizable to fit your project.
[Browse the Charts Library](/charts)
## Component
We use [LayerChart](https://next.layerchart.com) under the hood.
We designed the `Chart` component with composition in mind. **You build your charts using LayerChart components and only bring in custom components, such as `ChartTooltip`, when and where you need it**
```svelte showLineNumbers /Chart.Container/ /Chart.Tooltip/
{#snippet tooltip()}
{/snippet}
```
We do not wrap LayerChart. This means you're not locked into an abstraction. When a new LayerChart version is released, you can follow the official upgrade path to upgrade your charts.
**The components are yours**.
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `layerchart`:
Add the following colors to your CSS file
```css title="src/app.css" showLineNumbers
:root {
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
}
.dark {
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
}
@theme inline {
--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);
}
```
Copy and paste the following code into your project.
{/snippet}
## Your First Chart
Let's build your first chart. We'll build a bar chart with an axis, grid, tooltip, and legend.
### Start by defining your data
The following data represents the number of desktop and mobile users for each month.
**Note:** Your data can be in any shape. You are not limited to the shape of the data below. Use the `dataKey` prop to map your data to the chart.
```svelte title="lib/components/example-chart.svelte" showLineNumbers
```
### Define your chart config
The chart config holds configuration for the chart. This is where you place human-readable strings, such as labels, icons, and color tokens for theming.
```svelte title="lib/components/example-chart.svelte" showLineNumbers
```
### Build your chart
You can now build your chart using LayerChart components. We're using the `BarChart` component in this example, which is one of LayerChart's "Simplified Charts".
These components handle a lot of the common chart scaffolding for you, while allowing you to customize them to your liking.
{#if viewerData}
{/if}
We now have a group-stacked bar chart with an x axis and a grid.
### Adjusting the Axis Ticks
Our bar chart is currently displaying the full month name for each tick on the x axis. Let's shorten it to just the first three letters.
### Add a custom formatter to the x axis
The `props` prop is how you can pass custom props to the various components that make up the chart. Here we're passing a custom formatter to the x axis.
```svelte showLineNumbers {21-25}
d.slice(0, 3),
},
}}
/>
```
### Add Tooltip
So far we've only used the `BarChart` component from LayerChart. They look great out of the box thanks to some customizations in the `chart` component.
To add a tooltip, we'll use the custom `Chart.Tooltip` component from `chart`.
### Add the `Chart.Tooltip` component to the chart
We'll replace the `tooltip={false}` prop with the `tooltip` snippet where we'll place the `Chart.Tooltip` component.
```svelte showLineNumbers {26-28}
d.slice(0, 3),
},
}}
>
{#snippet tooltip()}
{/snippet}
```
### Add Legend
### Set the `legend` prop to `true`
The `legend` prop is used to show a legend for the chart. We are working with LayerChart to add a payload similar to the tooltip so we can more easily create a custom legend.
```svelte showLineNumbers {8}
d.slice(0, 3),
},
}}
>
{#snippet tooltip()}
{/snippet}
```
Done. You've built your first chart! What's next?
- [Themes and Colors](/docs/components/chart#theming)
- [Tooltip](/docs/components/chart#tooltip)
## Chart Config
The chart config is where you define the labels, icons and colors for a chart.
It is intentionally decoupled from chart data.
This allows you to share config and color tokens between charts. It can also works independently for cases where your data or color tokens live remotely or in a different format.
```svelte
```
## Theming
Charts has built-in support for theming. You can use css variables (recommended) or color values in any color format, such as hex, hsl, or oklch.
### CSS Variables
### Define your colors in your css file
```css {5-6,13-14} title="src/routes/layout.css" showLineNumbers
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
/* ... */
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
/* ... */
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
}
```
### Add the color to your `chartConfig`
```svelte {5,9} showLineNumbers
```
### hex, hsl or oklch
You can also define your colors directly in the chart config. Use the color format you prefer.
```svelte showLineNumbers
```
### Using Colors
To use the theme colors in your chart, reference the colors using the format `var(--color-KEY)`.
#### Components
```svelte
```
#### Chart Data
```ts showLineNumbers
const chartData = [
{ browser: "chrome", visitors: 275, color: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, color: "var(--color-safari)" },
];
```
#### Tailwind
```svelte
```
## Tooltip
A chart tooltip contains a label, name, indicator and value. You can use a combination of these to customize your tooltip.
You can turn on/off any of these using the `hideLabel`, `hideIndicator` props and customize the indicator style using the `indicator` prop.
Use `labelKey` and `nameKey` to use a custom key for the tooltip label and name.
Chart comes with the `` component. You can use this component to add custom tooltips to your chart.
### Props
Use the following props to customize the tooltip.
| Prop | Type | Description |
| :--------------- | :----------------------- | :------------------------------------------------------ |
| `labelKey` | string | The config or data key to use for the label. |
| `nameKey` | string | The config or data key to use for the name. |
| `indicator` | `dot` `line` or `dashed` | The indicator style for the tooltip. |
| `hideLabel` | boolean | Whether to hide the label. |
| `hideIndicator` | boolean | Whether to hide the indicator. |
| `label` | string | A custom label for the tooltip |
| `labelFormatter` | function | A function to format the label. |
| `formatter` | Snippet | A snippet to provide flexible rendering of the tooltip. |
### Colors
Colors are automatically referenced from the chart config.
### Custom
To use a custom key for tooltip label and names, use the `labelKey` and `nameKey` props.
```svelte showLineNumbers /browser/
```
This will use `Total Visitors` for label and `Chrome` and `Safari` for the tooltip names.
================================================
FILE: docs/content/components/checkbox.md
================================================
---
title: Checkbox
description: A control that allows the user to toggle between checked and not checked.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/checkbox
doc: https://bits-ui.com/docs/components/checkbox
api: https://bits-ui.com/docs/components/checkbox#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
```
================================================
FILE: docs/content/components/collapsible.md
================================================
---
title: Collapsible
description: An interactive component which expands/collapses a panel.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/collapsible
doc: https://bits-ui.com/docs/components/collapsible
api: https://bits-ui.com/docs/components/collapsible#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Can I use this in my project?
Yes. Free to use for personal and commercial projects. No attribution
required.
```
================================================
FILE: docs/content/components/combobox.md
================================================
---
title: Combobox
description: Autocomplete input and command palette with a list of suggestions.
component: true
---
## Installation
The Combobox is built using a composition of the ` ` and the ` ` components.
See installation instructions for the [Popover](/docs/components/popover#installation) and the [Command](/docs/components/command#installation) components.
## Usage
```svelte title="lib/components/example-combobox.svelte"
{#snippet child({ props })}
{selectedValue || "Select a framework..."}
{/snippet}
No framework found.
{#each frameworks as framework}
{
value = framework.value;
closeAndFocusTrigger();
}}
>
{framework.label}
{/each}
```
## Examples
### Combobox
### Popover
### Dropdown menu
### Responsive
You can create a responsive combobox by using the ` ` on desktop and the ` ` components on mobile.
================================================
FILE: docs/content/components/command.md
================================================
---
title: Command
description: Fast, composable, unstyled command menu for Svelte.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/command
doc: https://bits-ui.com/docs/components/command
api: https://bits-ui.com/docs/components/command#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
No results found.
Calendar
Search Emoji
Calculator
Profile
Billing
Settings
```
## Examples
### Dialog
To show the command menu in a dialog, use the ` ` component instead of ` `. It accepts props for both the ` ` and ` ` components.
```svelte title="lib/components/example-command-menu.svelte" showLineNumbers
No results found.
Calendar
Search Emoji
Calculator
```
### Combobox
You can use the ` ` component as a combobox. See the [Combobox](/docs/components/combobox) page for more information.
## Changelog
### 2024-10-30 Classes for icons
- Added `gap-2 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0` to the `` component to automatically style the icons inside.
================================================
FILE: docs/content/components/context-menu.md
================================================
---
title: Context Menu
description: Displays a menu to the user — such as a set of actions or functions — triggered by right click.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/context-menu
doc: https://bits-ui.com/docs/components/context-menu
api: https://bits-ui.com/docs/components/context-menu#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Right click
Profile
Billing
Team
Subscription
```
================================================
FILE: docs/content/components/data-table.md
================================================
---
title: Data Table
description: Powerful table and datagrids built using TanStack Table.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/data-table
doc: https://tanstack.com/table/v8/docs/introduction
---
## Introduction
Data tables are difficult to componentize because of the wide variety of features they support, and the uniqueness of every data set.
So instead of trying to create a one-size-fits-all solution, we've created a guide to help you build your own data tables.
We'll start with the basic `` component, and work our way up to a fully-featured data table.
Tip: If you find yourself using the same table in multiple places, you can always extract it into a reusable component.
## Table of Contents
This guide will show you how to use [TanStack Table](https://tanstack.com/table) and the `` component to build your own custom data table. We'll cover the following topics:
- [Basic Table](#basic-table)
- [Row Actions](#row-actions)
- [Pagination](#pagination)
- [Sorting](#sorting)
- [Filtering](#filtering)
- [Visibility](#visibility)
- [Row Selection](#row-selection)
- [Reusable Components](#reusable-components)
## Installation
1. Add the `` component to your project along with the `data-table` helpers. These helpers enable TanStack Table v8 to work with Svelte 5 Snippets, Components, etc.
2. Add `@tanstack/table-core` as a dependency:
## Prerequisites
We're going to build a table to show recent payments. Here's what our data looks like:
```ts showLineNumbers
type Payment = {
id: string;
amount: number;
status: "pending" | "processing" | "success" | "failed";
email: string;
};
export const data: Payment[] = [
{
id: "728ed52f",
amount: 100,
status: "pending",
email: "m@example.com",
},
{
id: "489e1d42",
amount: 125,
status: "processing",
email: "example@gmail.com",
},
// ...
];
```
## Project Structure
Start by creating a route where your data table will live (we'll call ours payments), along with the following files:
```txt
routes
└── payments
├── columns.ts
├── data-table.svelte
├── data-table-actions.svelte
├── data-table-checkbox.svelte
├── data-table-email-button.svelte
└── +page.svelte
```
- `columns.ts` will contain our column definitions.
- `data-table.svelte` will contain the `` component and the complete ` ` component.
- `data-table-actions.svelte` will contain the actions menu for each row.
- `data-table-checkbox.svelte` will contain the checkbox for each row.
- `data-table-email-button.svelte` will contain the sortable email header button.
- `+page.svelte` is where we'll render and access ` ` component.
## Basic Table
Let's start by building a basic table.
### Column Definitions
First, we'll define our columns.
```ts showLineNumbers {1,12-25} title="routes/payments/columns.ts"
import type { ColumnDef } from "@tanstack/table-core";
// This type is used to define the shape of our data.
// You can use a Zod schema here if you want.
export type Payment = {
id: string;
amount: number;
status: "pending" | "processing" | "success" | "failed";
email: string;
};
export const columns: ColumnDef[] = [
{
accessorKey: "status",
header: "Status",
},
{
accessorKey: "email",
header: "Email",
},
{
accessorKey: "amount",
header: "Amount",
},
];
```
**Note:** Columns are where you define the core of what your table will look like. They define the data that will be displayed, how it will be formatted, sorted and filtered.
### ` ` Component
Next, we'll create a ` ` component to render our table.
```svelte showLineNumbers title="routes/payments/data-table.svelte"
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
{#each headerGroup.headers as header (header.id)}
{#if !header.isPlaceholder}
{/if}
{/each}
{/each}
{#each table.getRowModel().rows as row (row.id)}
{#each row.getVisibleCells() as cell (cell.id)}
{/each}
{:else}
No results.
{/each}
```
**Tip**: If you find yourself using ` ` in multiple places, this is the component you could make reusable by extracting it to `components/ui/data-table.svelte`.
` `
### Render the table
Finally, we'll render our table in our page component.
```ts showLineNumbers title="routes/payments/+page.server.ts"
export async function load() {
// logic to fetch payments data here
const payments = await getPayments();
return {
payments,
};
}
```
```svelte showLineNumbers {8} title="routes/payments/+page.svelte"
```
## Cell Formatting
Let's format the amount cell to display the dollar amount. We'll also align the cell to the right.
### Update columns definition
Update the `header` and `cell` definitions for amount as follows:
```ts showLineNumbers title="routes/payments/columns.ts"
import type { ColumnDef } from "@tanstack/table-core";
import { createRawSnippet } from "svelte";
import { renderSnippet } from "$lib/components/ui/data-table/index.js";
export const columns: ColumnDef[] = [
{
accessorKey: "amount",
header: () => {
const amountHeaderSnippet = createRawSnippet(() => ({
render: () => `Amount
`,
}));
return renderSnippet(amountHeaderSnippet);
},
cell: ({ row }) => {
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
});
const amountCellSnippet = createRawSnippet<[{ amount: number }]>(
(getAmount) => {
const { amount } = getAmount();
const formatted = formatter.format(amount);
return {
render: () =>
`${formatted}
`,
};
}
);
return renderSnippet(amountCellSnippet, {
amount: row.original.amount,
});
},
},
];
```
We're using the `createRawSnippet` function to create a Svelte Snippet for rendering simple HTML elements that don't require full lifecycle and state capabilities like a component. We then use the `renderSnippet` helper function to render the snippet.
You can use the same approach to format other cells and headers.
## Row Actions
Let's add row actions to our table. We'll use the ` ` and the ` ` components for this, so you have install them if not done already:
### Create actions component
We'll start by defining the actions menu in our `data-table-actions.svelte` component.
```svelte showLineNumbers title="routes/payments/data-table-actions.svelte"
{#snippet child({ props })}
Open menu
{/snippet}
Actions
navigator.clipboard.writeText(id)}>
Copy payment ID
View customer
View payment details
```
### Update columns definition
Now that we've defined the ` ` component, let's update our `actions` column definition to use it.
```ts showLineNumbers title="routes/payments/columns.ts"
import type { ColumnDef } from "@tanstack/table-core";
import { renderComponent } from "$lib/components/ui/data-table/index.js";
import DataTableActions from "./data-table-actions.svelte";
export const columns: ColumnDef[] = [
// ...
{
id: "actions",
cell: ({ row }) => {
// You can pass whatever you need from `row.original` to the component
return renderComponent(DataTableActions, { id: row.original.id });
},
},
];
```
You can access the row data using `row.original` in the `cell` function. Use this to handle actions for your row eg. use the `id` to make a DELETE call to your API.
## Pagination
Next, we'll add pagination to our table.
### Update ` `
```svelte showLineNumbers title="routes/payments/data-table.svelte"
```
This will automatically paginate your rows into pages of 10. See the [pagination docs](https://tanstack.com/table/v8/docs/api/features/pagination) for more information on customizing page size and implementing manual pagination.
### Adding pagination controls
We can add pagination controls to our table using the ` ` component and the `table.previousPage()`, `table.nextPage()` API methods.
```svelte showLineNumbers title="routes/payments/data-table.svelte"
table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
```
See [Reusable Components](#reusable-components) section for a more advanced pagination component.
## Sorting
Let's make the email column sortable.
### Define ` ` component
We'll start by creating a component to render a sortable email header button.
```svelte showLineNumbers title="routes/payments/data-table-email-button.svelte"
Email
```
### Update ` `
```svelte showLineNumbers title="routes/payments/data-table.svelte"
```
### Make header cell sortable
We can now update the `email` header cell to add sorting controls.
```ts showLineNumbers title="src/routes/payments/columns.ts"
import type { ColumnDef } from "@tanstack/table-core";
import { renderComponent } from "$lib/components/ui/data-table/index.js";
import DataTableEmailButton from "./data-table-email-button.svelte";
export const columns: ColumnDef[] = [
// ...
{
accessorKey: "email",
header: ({ column }) =>
renderComponent(DataTableEmailButton, {
onclick: column.getToggleSortingHandler(),
}),
},
];
```
This will automatically sort the table (asc and desc) when the user toggles on the header cell.
## Filtering
Let's add a search input to filter emails in our table.
### Update ` `
```svelte showLineNumbers title="routes/payments/data-table.svelte"
```
Filtering is now enabled for the `email` column. You can add filters to other columns as well. See the [filtering docs](https://tanstack.com/table/v8/docs/guide/filters) for more information on customizing filters.
## Visibility
Adding column visibility is fairly simple using `@tanstack/table-core` visibility API.
### Update ` `
```svelte showLineNumbers title="routes/payments/data-table.svelte"
```
This adds a dropdown menu that you can use to toggle column visibility.
## Row Selection
Next, we're going to add row selection to our table.
### Define ` ` component
We'll start by defining the checkbox component in our `data-table-checkbox.svelte` component.
```svelte showLineNumbers title="routes/payments/data-table-checkbox.svelte"
checked, onCheckedChange} {...restProps} />
```
### Update columns definition
Now that we have a new component, we can add a `select` column definition to render a checkbox.
```ts showLineNumbers title="routes/payments/columns.ts"
import type { ColumnDef } from "@tanstack/table-core";
import { renderComponent } from "$lib/components/ui/data-table/index.js";
import { Checkbox } from "$lib/components/ui/checkbox/index.js";
export const columns: ColumnDef[] = [
// ...
{
id: "select",
header: ({ table }) =>
renderComponent(Checkbox, {
checked: table.getIsAllPageRowsSelected(),
indeterminate:
table.getIsSomePageRowsSelected() &&
!table.getIsAllPageRowsSelected(),
onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value),
"aria-label": "Select all",
}),
cell: ({ row }) =>
renderComponent(Checkbox, {
checked: row.getIsSelected(),
onCheckedChange: (value) => row.toggleSelected(!!value),
"aria-label": "Select row",
}),
enableSorting: false,
enableHiding: false,
},
];
```
### Update ` `
```svelte showLineNumbers title="routes/payments/data-table.svelte"
```
This adds a checkbox to each row and a checkbox in the header to select all rows.
### Show selected rows
You can show the number of selected rows using the `table.getFilteredSelectedRowModel()` API.
```svelte
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
```
## Reusable Components
Check out the [Tasks](/examples/tasks) example to learn about creating reusable components for your data tables.
================================================
FILE: docs/content/components/date-picker.md
================================================
---
title: Date Picker
description: A date picker component with range and presets.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/examples/date-picker-demo.svelte
---
## Installation
The Date Picker is built using a composition of the ` ` and either the ` ` or ` ` components.
See installations instructions for the [Popover](/docs/components/popover#installation), [Calendar](/docs/components/calendar#installation), and [Range Calendar](/docs/components/range-calendar#installation) components.
## Usage
```svelte showLineNumbers title="lib/components/example-date-picker.svelte"
{#snippet child({ props })}
{value ? df.format(value.toDate(getLocalTimeZone())) : "Select a date"}
{/snippet}
```
## Examples
### Date of Birth Picker
### Picker with Input
### Date and Time Picker
### Natural Language Picker
This component uses the `chrono-node` library to parse natural language dates.
================================================
FILE: docs/content/components/dialog.md
================================================
---
title: Dialog
description: A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/dialog
doc: https://bits-ui.com/docs/components/dialog
api: https://bits-ui.com/docs/components/dialog#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Open
Are you sure absolutely sure?
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
```
## Examples
### Custom close button
================================================
FILE: docs/content/components/drawer.md
================================================
---
title: Drawer
description: A drawer component for Svelte.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/drawer
doc: https://github.com/huntabyte/vaul-svelte
---
## About
Drawer is built on top of [Vaul Svelte](https://vaul-svelte.com), which is a Svelte port of [Vaul](https://vaul.emilkowal.ski) by [Emil Kowalski](https://twitter.com/emilkowalski_).
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `vaul-svelte`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Open
Are you sure absolutely sure?
This action cannot be undone.
Submit
Cancel
```
## Examples
### Responsive Dialog
You can combine the `Dialog` and `Drawer` components to create a responsive dialog. This renders a `Dialog` on desktop and a `Drawer` on mobile.
================================================
FILE: docs/content/components/dropdown-menu.md
================================================
---
title: Dropdown Menu
description: Displays a menu to the user — such as a set of actions or functions — triggered by a button.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/dropdown-menu
doc: https://bits-ui.com/docs/components/dropdown-menu
api: https://bits-ui.com/docs/components/dropdown-menu#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Open
My Account
Profile
Billing
Team
Subscription
```
## Examples
### Checkboxes
### Radio Group
### Dialog
This example shows how to open a dialog from a dropdown menu.
```svelte showLineNumbers
Actions
```
## Changelog
### 2024-10-30 Classes for DropdownMenu.SubTrigger
- Added `gap-2 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0` to the `` to automatically style icon inside the dropdown menu sub trigger.
- Removed `size-4` from the icon inside the `` since it is now handled by the parent ``.
================================================
FILE: docs/content/components/empty.md
================================================
---
title: Empty
description: Use the Empty component to display a empty state.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/empty
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
No data
No data found
Add data
```
## Examples
### Outline
Use the `border` utility class to create a outline empty state.
### Background
Use the `bg-*` and `bg-gradient-*` utilities to add a background to the empty state.
### Avatar
Use the `EmptyMedia` component to display an avatar in the empty state.
### Avatar Group
Use the `EmptyMedia` component to display an avatar group in the empty state.
### InputGroup
You can add an `InputGroup` component to the `EmptyContent` component.
================================================
FILE: docs/content/components/field.md
================================================
---
title: Field
description: Combine labels, controls, and help text to compose accessible form fields and grouped inputs.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/field
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Profile
This appears on invoices and emails.
Full name
This appears on invoices and emails.
Username
Choose another username.
Subscribe to the newsletter
```
## Anatomy
The `Field` family is designed for composing accessible forms. A typical field is structured as follows:
```svelte
Label
Optional helper text.
Validation message.
```
- `Field.Field` is the core wrapper for a single field.
- `Field.Content` is a flex column that groups label and description. Not required if you have no description.
- Wrap related fields with `Field.Group`, and use `Field.Set` with `Field.Legend` for semantic grouping.
## Examples
### Input
### Textarea
### Select
### Slider
### Fieldset
### Checkbox
### Radio
### Switch
### Choice Card
Wrap `Field` components inside `FieldLabel` to create selectable field groups. This works with `RadioItem`, `Checkbox` and `Switch` components.
### Field Group
Stack `Field` components with `Field.Group`. Add `Field.Separator` to divide them.
### Responsive Layout
- **Vertical fields:** Default orientation stacks label, control, and helper text—ideal for mobile-first layouts.
- **Horizontal fields:** Set `orientation="horizontal"` on `Field` to align the label and control side-by-side. Pair with `Field.Content` to keep descriptions aligned.
- **Responsive fields:** Set `orientation="responsive"` for automatic column layouts inside container-aware parents. Apply `@container/field-group` classes on `Field.Group` to switch orientations at specific breakpoints.
## Validation and Errors
- Add `data-invalid` to `Field` to switch the entire block into an error state.
- Add `aria-invalid` on the input itself for assistive technologies.
- Render `FieldError` immediately after the control or inside `FieldContent` to keep error messages aligned with the field.
Copy
```svelte
Email
Enter a valid email address.
```
## Accessibility
- `Field.Set` and `Field.Legend` keep related controls grouped for keyboard and assistive tech users.
- `Field` outputs `role="group"` so nested controls inherit labeling from `Field.Label` and `Field.Legend` when combined.
- Apply `Field.Separator` sparingly to ensure screen readers encounter clear section boundaries.
================================================
FILE: docs/content/components/form.md
================================================
---
title: Formsnap
description: Building forms with Formsnap, Superforms, & Zod.
links:
doc: https://formsnap.dev
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/form
---
Forms are tricky. They are one of the most common things you'll build in a web application, but also one of the most complex.
Well-designed HTML forms are:
- Well-structured and semantically correct.
- Easy to use and navigate (keyboard).
- Accessible with ARIA attributes and proper labels.
- Has support for client and server side validation.
- Well-styled and consistent with the rest of the application.
In this guide, we will take a look at building forms with [formsnap](https://formsnap.dev), [sveltekit-superforms](https://superforms.rocks) and [zod](https://zod.dev).
## Features
The `Form` components offered by `shadcn-svelte` are wrappers around `formsnap` & `sveltekit-superforms` which provide a few things:
- Composable components for building forms.
- Form field components for scoping form state.
- Form validation using [Zod](https://zod.dev) or any other validation library supported by [Superforms](https://superforms.rocks).
- Applies the correct `aria` attributes to form fields based on states.
- Enables you to easily use various components like [Select](/docs/components/select), [RadioGroup](/docs/components/radio-group), [Switch](/docs/components/switch), [Checkbox](/docs/components/checkbox) and other form components with forms.
If you aren't familiar with [Superforms](https://superforms.rocks) & [Formsnap](https://formsnap.dev), you should check out their documentation first, as this guide assumes you have a basic understanding of how they work together.
## Anatomy
```svelte showLineNumbers
```
## Example
```svelte showLineNumbers
{#snippet children({ props })}
Email
{/snippet}
```
## Installation
## Usage
### Create a form schema
Define the shape of your form using a Zod schema. You can read more about using Zod in the [Zod documentation](https://zod.dev). We're going to define it in a file called `schema.ts` in the same directory as our page component, but you can put it anywhere you like.
```ts title="src/routes/settings/schema.ts" showLineNumbers
import { z } from "zod";
export const formSchema = z.object({
username: z.string().min(2).max(50),
});
export type FormSchema = typeof formSchema;
```
### Setup the load function
```ts title="src/routes/settings/+page.server.ts" showLineNumbers
import type { PageServerLoad } from "./$types.js";
import { superValidate } from "sveltekit-superforms";
import { formSchema } from "./schema";
import { zod4 } from "sveltekit-superforms/adapters";
export const load: PageServerLoad = async () => {
return {
form: await superValidate(zod4(formSchema)),
};
};
```
### Create form component
For this example, we'll be passing the `form` returned from the load function as a prop to this component. To ensure it's typed properly, we'll use the `SuperValidated` type from `sveltekit-superforms`, and pass in the type of our form schema.
```svelte title="src/routes/settings/settings-form.svelte" showLineNumbers
{#snippet children({ props })}
Username
{/snippet}
This is your public display name.
Submit
```
The `name`, `id`, and all accessibility attributes are applied to the input by spreading the `attrs` object from the `Form.Control` component. The `Form.Label` will automatically be associated with the input using the `for` attribute, so you don't have to worry about that.
### Use the component
We'll pass the `form` from the data returned from the load function to the form component we created above.
```svelte title="src/routes/settings/+page.svelte" showLineNumbers
```
### Create an Action
```ts title="src/routes/settings/+page.server.ts" showLineNumbers {1-2,13-25}
import type { PageServerLoad, Actions } from "./$types.js";
import { fail } from "@sveltejs/kit";
import { superValidate } from "sveltekit-superforms";
import { zod4 } from "sveltekit-superforms/adapters";
import { formSchema } from "./schema";
export const load: PageServerLoad = async () => {
return {
form: await superValidate(zod4(formSchema)),
};
};
export const actions: Actions = {
default: async (event) => {
const form = await superValidate(event, zod4(formSchema));
if (!form.valid) {
return fail(400, {
form,
});
}
return {
form,
};
},
};
```
### Done
That's it. You now have a fully accessible form that is type-safe and has client & server side validation.
## Next Steps
Be sure to check out the [Formsnap](https://formsnap.dev) and [Superforms](https://superforms.rocks) documentation for more information on how to use them.
## Examples
See the following links for more examples on how to use the other `Form` components:
- [Checkbox](/docs/components/checkbox#form)
- [Date Picker](/docs/components/date-picker#form)
- [Input](/docs/components/input#form)
- [Radio Group](/docs/components/radio-group#form)
- [Select](/docs/components/select#form)
- [Switch](/docs/components/switch#form)
- [Textarea](/docs/components/textarea#form)
================================================
FILE: docs/content/components/hover-card.md
================================================
---
title: Hover Card
description: For sighted users to preview content available behind a link.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/link-preview
doc: https://bits-ui.com/docs/components/link-preview
api: https://bits-ui.com/docs/components/link-preview#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Hover
SvelteKit - Web development, streamlined
```
================================================
FILE: docs/content/components/index.md
================================================
---
title: Components
description: Here you can find all the components available in the library. We are working on adding more components.
---
================================================
FILE: docs/content/components/input-group.md
================================================
---
title: Input Group
description: Display additional information or actions to an input or textarea.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/input-group
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `@lucide/svelte`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Search
```
## Examples
### Icon
### Text
Display additional text information alongside inputs.
### Button
Add buttons to perform actions within the input group.
### Tooltip
Add tooltips to provide additional context or help.
### Textarea
Input groups also work with textarea components. Use `block-start` or `block-end` for alignment.
### Spinner
Show loading indicators while processing input.
### Label
Add labels within input groups to improve accessibility.
### Dropdown
Pair input groups with dropdown menus for complex interactions.
### Button Group
Wrap input groups with button groups to create prefixes and suffixes.
### Custom Input
Add the `data-slot="input-group-control"` attribute to your custom input for automatic behavior and focus state handling.
No style is applied to the custom input. Apply your own styles using the `class` prop.
================================================
FILE: docs/content/components/input-otp.md
================================================
---
title: Input OTP
description: Accessible one-time password component with copy paste functionality.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/input-otp
doc: https://bits-ui.com/docs/components/pin-input
api: https://bits-ui.com/docs/components/pin-input#api-reference
---
## About
Input OTP is built on top of Bits UI's [PinInput](https://bits-ui.com/docs/components/pin-input) which is inspired by [@guilherme_rodz](https://twitter.com/guilherme_rodz)'s Input OTP component.
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
{#snippet children({ cells })}
{#each cells.slice(0, 3) as cell}
{/each}
{#each cells.slice(3, 6) as cell}
{/each}
{/snippet}
```
## Examples
### Pattern
Use the `pattern` prop to define a custom pattern for the OTP input.
```svelte showLineNumbers {3,6}
```
### Separator
You can use the `InputOTP.Separator` component to add a separator between the groups of cells.
```svelte showLineNumbers {12}
{#snippet children({ cells })}
{#each cells.slice(0, 2) as cell}
{/each}
{#each cells.slice(2, 4) as cell}
{/each}
{/snippet}
```
### Controlled
### Form
================================================
FILE: docs/content/components/input.md
================================================
---
title: Input
description: Displays a form input field or a component that looks like an input field.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/input
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
```
## Examples
### Default
### File
### Disabled
### With Label
### With Button
================================================
FILE: docs/content/components/item.md
================================================
---
title: Item
description: A versatile component that you can use to display any content.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/item
---
The `Item` component is a straightforward flex container that can house nearly any type of content. Use it to display a title, description, and actions. Group it with the `ItemGroup` component to create a list of items.
You can pretty much achieve the same result with the `div` element and some classes, but **I've built this so many times** that I decided to create a component for it. Now I use it all the time.
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Item Header
Item
Item
Item Footer
```
## Item vs Field
Use Field if you need to display a form input such as a checkbox, input, radio, or select.
If you only need to display content such as a title, description, and actions, use `Item`.
## Examples
### Variants
### Size
The `Item` component has different sizes for different use cases. For example, you can use the `sm` size for a compact item or the default size for a standard item.
### Icon
### Avatar
### Image
### Group
### Header
### Link
To render an item as a link, use the the `child` snippet. The hover and focus states will be applied to the anchor element.
### Dropdown
================================================
FILE: docs/content/components/kbd.md
================================================
---
title: Kbd
description: Used to display textual user input from keyboard.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/kbd
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
B
```
## Examples
### Group
Use the `Kbd.Group` component to group keyboard keys together.
### Button
Use the `Kbd.Root` component inside a `Button` component to display a keyboard key inside a button.
### Tooltip
You can use the `Kbd.Root` component inside a `Tooltip` component to display a tooltip with a keyboard key.
### Input Group
You can use the `Kbd.Root` component inside a `InputGroup.Addon` component to display a keyboard key inside an input group.
================================================
FILE: docs/content/components/label.md
================================================
---
title: Label
description: Renders an accessible label associated with controls.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/label
doc: https://bits-ui.com/docs/components/label
api: https://bits-ui.com/docs/components/label#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
Your email address
```
================================================
FILE: docs/content/components/menubar.md
================================================
---
title: Menubar
description: A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/menubar
doc: https://bits-ui.com/docs/components/menubar
api: https://bits-ui.com/docs/components/menubar#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
File
New Tab
⌘T
New Window
Share
Print
```
================================================
FILE: docs/content/components/native-select.md
================================================
---
title: Native Select
description: A styled native HTML select element with consistent design system integration.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/native-select
---
For a styled select component, see the [Select](/docs/components/select) component.
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Select a fruit
Apple
Banana
Blueberry
Grapes
Pineapple
```
## Examples
### With Groups
Organize options using `NativeSelect.OptGroup` for better categorization.
```svelte showLineNumbers
Select a food
Apple
Banana
Blueberry
Carrot
Broccoli
Spinach
```
### Disabled State
Disable individual options or the entire select component.
### Invalid State
Show validation errors with the `aria-invalid` attribute and error styling.
```svelte showLineNumbers
Select a country
United States
United Kingdom
Canada
```
## Native Select vs Select
- Use `NativeSelect` when you need native browser behavior, better performance, or mobile-optimized dropdowns.
- Use `Select` when you need custom styling, animations, or complex interactions.
The `NativeSelect` component provides native HTML select functionality with consistent styling that matches your design system.
## Accessibility
- The component maintains all native HTML select accessibility features.
- Screen readers can navigate through options using arrow keys.
- The chevron icon is marked as `aria-hidden="true"` to avoid duplication.
- Use `aria-label` or `aria-labelledby` for additional context when needed.
```tsx showLineNumbers
English
Spanish
French
```
## API Reference
### NativeSelect.Root
The main select component that wraps the native HTML select element.
| Prop | Type | Default |
| ------- | -------- | ------- |
| `class` | `string` | |
All other props are passed through to the underlying `` element.
```svelte
Option 1
Option 2
```
### NativeSelect.Option
Represents an individual option within the select.
| Prop | Type | Default |
| ---------- | --------- | ------- |
| `value` | `string` | |
| `disabled` | `boolean` | `false` |
| `class` | `string` | |
All other props are passed through to the underlying `` element.
```svelte
Apple
Banana
```
### NativeSelect.OptGroup
Groups related options together for better organization.
| Prop | Type | Default |
| ---------- | --------- | ------- |
| `label` | `string` | |
| `disabled` | `boolean` | `false` |
| `class` | `string` | |
All other props are passed through to the underlying ` ` element.
```svelte
Apple
Banana
```
================================================
FILE: docs/content/components/navigation-menu.md
================================================
---
title: Navigation Menu
description: A collection of links for navigating websites.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/navigation-menu
doc: https://bits-ui.com/docs/components/navigation-menu
api: https://bits-ui.com/docs/components/navigation-menu#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Item One
Link
```
================================================
FILE: docs/content/components/pagination.md
================================================
---
title: Pagination
description: Pagination with page navigation, next and previous links.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/pagination
doc: https://bits-ui.com/docs/components/pagination
api: https://bits-ui.com/docs/components/pagination#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
{#snippet children({ pages, currentPage })}
{#each pages as page (page.key)}
{#if page.type === "ellipsis"}
{:else}
{page.value}
{/if}
{/each}
{/snippet}
```
================================================
FILE: docs/content/components/popover.md
================================================
---
title: Popover
description: Displays rich content in a portal, triggered by a button.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/popover
doc: https://bits-ui.com/docs/components/popover
api: https://bits-ui.com/docs/components/popover#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Open
Place content for the popover here.
```
================================================
FILE: docs/content/components/progress.md
================================================
---
title: Progress
description: Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/progress
doc: https://bits-ui.com/docs/components/progress
api: https://bits-ui.com/docs/components/progress#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
```
================================================
FILE: docs/content/components/radio-group.md
================================================
---
title: Radio Group
description: A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/radio-group
doc: https://bits-ui.com/docs/components/radio-group
api: https://bits-ui.com/docs/components/radio-group#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Option One
Option Two
```
================================================
FILE: docs/content/components/range-calendar.md
================================================
---
title: Range Calendar
description: A calendar component that allows users to select a range of dates.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/range-calendar
doc: https://bits-ui.com/docs/components/range-calendar
api: https://bits-ui.com/docs/components/range-calendar#api-reference
---
## About
The ` ` component is built on top of the [Bits Range Calendar](https://www.bits-ui.com/docs/components/range-calendar) component, which uses the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package to handle dates.
## Blocks
You can see the `RangeCalendar` component in action in the 30+ [Calendar Blocks](/blocks/calendar) we've built.
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui` and `@internationalized/date`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
================================================
FILE: docs/content/components/resizable.md
================================================
---
title: Resizable
description: Accessible resizable panel groups and layouts with keyboard support.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/resizable
doc: https://www.paneforge.com
api: https://www.paneforge.com/docs/components/pane-group
---
## About
The `Resizable` component is built on top of [PaneForge](https://github.com/svecosystem/paneforge) by [Huntabyte](https://github.com/huntabyte). Visit the [PaneForge documentation](https://paneforge.com) for all the available props and abilities of the `Resizable` component.
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `paneforge`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
One
Two
```
## Examples
### Vertical
Use the `direction` prop to set the direction of the resizable panels.
```svelte showLineNumbers {5}
One
Two
```
### Handle
You can set or hide the handle by using the `withHandle` prop on the `ResizableHandle` component.
```svelte showLineNumbers {7}
One
Two
```
================================================
FILE: docs/content/components/scroll-area.md
================================================
---
title: Scroll Area
description: Augments native scroll functionality for custom, cross-browser styling.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/scroll-area
doc: https://bits-ui.com/docs/components/scroll-area
api: https://bits-ui.com/docs/components/scroll-area#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Jokester began sneaking into the castle in the middle of the night and
leaving jokes all over the place: under the king's pillow, in his soup, even
in the royal toilet. The king was furious, but he couldn't seem to stop
Jokester. And then, one day, the people of the kingdom discovered that the
jokes left by Jokester were so funny that they couldn't help but laugh. And
once they started laughing, they couldn't stop.
```
## Examples
### Horizontal Scrolling
Set the `orientation` prop to `"horizontal"` to enable horizontal scrolling.
================================================
FILE: docs/content/components/select.md
================================================
---
title: Select
description: Displays a list of options for the user to pick from—triggered by a button.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/select
doc: https://bits-ui.com/docs/components/select
api: https://bits-ui.com/docs/components/select#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Light
Dark
System
```
## Examples
### Scrollable
================================================
FILE: docs/content/components/separator.md
================================================
---
title: Separator
description: Visually or semantically separates content.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/separator
doc: https://bits-ui.com/docs/components/separator
api: https://bits-ui.com/docs/components/separator#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
```
================================================
FILE: docs/content/components/sheet.md
================================================
---
title: Sheet
description: Extends the Dialog component to display content that complements the main content of the screen.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/sheet
doc: https://bits-ui.com/docs/components/dialog
api: https://bits-ui.com/docs/components/dialog#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Open
Are you sure absolutely sure?
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
```
## Examples
### Side
Pass the `side` property to ` ` to indicate the edge of the screen where the component will appear. The values can be `top`, `right`, `bottom` or `left`.
### Size
You can adjust the size of the sheet using CSS classes:
```svelte showLineNumbers {3}
Open
Are you absolutely sure?
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
```
================================================
FILE: docs/content/components/sidebar.md
================================================
---
title: Sidebar
description: A composable, themeable and customizable sidebar component.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/sidebar
---
Sidebars are one of the most complex components to build. They are central to any application and often contain a lot of moving parts.
Shad doesn't like building sidebars, so he built 30+ of them with all kinds of configurations. The core components have been extracted into `sidebar-*.svelte` files, and you can use them in your own projects.
We now have a solid foundation to build on top of. Composable. Themeable. Customizable.
[Browse the Blocks Library](/blocks).
## Installation
{#snippet cli()}
Run the following command to install the `sidebar` components:
Add the following colors to your CSS file
We'll go over the colors later in the [theming section](/docs/components/sidebar#theming).
```css title="src/routes/layout.css"
:root {
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.439 0 0);
}
```
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
Add the following colors to your CSS file
We'll go over the colors later in the [theming section](/docs/components/sidebar#theming).
```css title="src/routes/layout.css"
:root {
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.439 0 0);
}
```
{/snippet}
## Structure
A `Sidebar` component is composed of the following parts:
- `Sidebar.Provider` - Handles collapsible state.
- `Sidebar.Root` - The sidebar container.
- `Sidebar.Header` and `Sidebar.Footer` - Sticky at the top and bottom of the sidebar.
- `Sidebar.Content` - Scrollable content.
- `Sidebar.Group` - Section within the `Sidebar.Content`.
- `Sidebar.Trigger` - Trigger for the `Sidebar`.
## Usage
```svelte showLineNumbers title="src/routes/+layout.svelte"
{@render children?.()}
```
```svelte showLineNumbers title="src/lib/components/app-sidebar.svelte"
```
## Your First Sidebar
Let's start with the most basic sidebar. A collapsible sidebar with a menu.
Add a `Sidebar.Provider` and `Sidebar.Trigger` at the root of your application.
```svelte showLineNumbers title="src/routes/+layout.svelte"
{@render children?.()}
```
Create a new sidebar component at `src/lib/components/app-sidebar.svelte`.
```svelte showLineNumbers title="src/lib/components/app-sidebar.svelte"
```
Now, let's add a `Sidebar.Menu` to the sidebar.
We'll use the `Sidebar.Menu` component in a `Sidebar.Group`.
```svelte showLineNumbers title="src/lib/components/app-sidebar.svelte"
Application
{#each items as item (item.title)}
{#snippet child({ props })}
{item.title}
{/snippet}
{/each}
```
You've created your first sidebar.
## Components
The components in the `sidebar-*.svelte` files are built to be composable i.e you build your sidebar by putting the provided components together. They also compose well with other shadcn-svelte components such as `DropdownMenu`, `Collapsible`, `Dialog`, etc.
**If you need to change the code in the `sidebar-*.svelte` files, you are encouraged to do so. The code is yours. Use the provided components as a starting point to build your own**
In the next sections, we'll go over each component and how to use them.
## Sidebar.Provider
The `Sidebar.Provider` component is used to provide the sidebar context to the `Sidebar` component. You should always wrap your application in a `Sidebar.Provider` component.
### Props
| Name | Type | Description |
| -------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `open` | `boolean` | Open state of the sidebar (bindable). |
| `onOpenChange` | `(open: boolean) => void` | A callback fired _after_ the open state of the sidebar changes if uncontrolled, and _before_ the sidebar opens or closes if controlled. |
### Width
If you have a single sidebar in your application, you can use the `SIDEBAR_WIDTH` and `SIDEBAR_WIDTH_MOBILE` constants in `src/lib/components/ui/sidebar/constants.ts` to set the width of the sidebar.
```ts showLineNumbers title="src/lib/components/ui/sidebar/constants.ts"
export const SIDEBAR_WIDTH = "16rem";
export const SIDEBAR_WIDTH_MOBILE = "18rem";
```
For multiple sidebars in your application, you can use the `style` prop to set the width of the sidebar.
To set the width of the sidebar, you can use the `--sidebar-width` and `--sidebar-width-mobile` CSS variables in the `style` prop.
```svelte showLineNumbers
```
This will not only handle the width of the sidebar but also the layout spacing.
### Keyboard Shortcut
The `SIDEBAR_KEYBOARD_SHORTCUT` variable in `src/lib/components/ui/sidebar/constants.ts` is used to set the keyboard shortcut used to open and close the sidebar.
To trigger the sidebar, you use the `cmd+b` keyboard shortcut on Mac and `ctrl+b` on Windows.
You can change the keyboard shortcut by changing the value of the `SIDEBAR_KEYBOARD_SHORTCUT` variable.
```ts showLineNumbers title="src/lib/components/ui/sidebar/constants.ts"
export const SIDEBAR_KEYBOARD_SHORTCUT = "b";
```
## Sidebar.Root
The main `Sidebar` component used to render a collapsible sidebar.
```svelte showLineNumbers
```
### Props
| Property | Type | Description |
| ------------- | --------------------------------- | --------------------------------- |
| `side` | `left` or `right` | The side of the sidebar. |
| `variant` | `sidebar`, `floating`, or `inset` | The variant of the sidebar. |
| `collapsible` | `offcanvas`, `icon`, or `none` | Collapsible state of the sidebar. |
### side
Use the `side` prop to change the side of the sidebar.
Available options are `left` and `right`.
```svelte showLineNumbers
```
### variant
Use the `variant` prop to change the variant of the sidebar.
Available options are `sidebar`, `floating` and `inset`.
```svelte showLineNumbers
```
**Note:** If you use the `inset` variant, remember to wrap your main content
in a `SidebarInset` component.
```svelte showLineNumbers
```
### collapsible
Use the `collapsible` prop to make the sidebar collapsible.
Available options are `offcanvas`, `icon` and `none`.
```svelte showLineNumbers
```
| Prop | Description |
| ----------- | ------------------------------------------------------------ |
| `offcanvas` | A collapsible sidebar that slides in from the left or right. |
| `icon` | A sidebar that collapses to icons. |
| `none` | A non-collapsible sidebar. |
## useSidebar
The `useSidebar` function is used to hook into the sidebar context. It returns a reactive class instance, so it _cannot_ be destructured. Additionally, it must be called during the lifecycle of the component.
```svelte showLineNumbers
```
| Property | Type | Description |
| --------------- | ------------------------- | --------------------------------------------- |
| `state` | `expanded` or `collapsed` | The current state of the sidebar. |
| `open` | `boolean` | Whether the sidebar is open. |
| `setOpen` | `(open: boolean) => void` | Sets the open state of the sidebar. |
| `openMobile` | `boolean` | Whether the sidebar is open on mobile. |
| `setOpenMobile` | `(open: boolean) => void` | Sets the open state of the sidebar on mobile. |
| `isMobile` | `boolean` | Whether the sidebar is on mobile. |
| `toggle` | `() => void` | Toggles the sidebar. Desktop and mobile. |
## Sidebar.Header
Use the `Sidebar.Header` component to add a sticky header to the sidebar.
The following example adds a `` to the `Sidebar.Header`.
```svelte showLineNumbers title="src/lib/components/app-sidebar.svelte"
{#snippet child({ props })}
Select Workspace
{/snippet}
```
## Sidebar.Footer
Use the `Sidebar.Footer` component to add a sticky footer to the sidebar.
The following example adds a `` to the `Sidebar.Footer`.
```svelte showLineNumbers title="src/lib/components/app-sidebar.svelte"
{#snippet child({ props })}
{/snippet}
```
## Sidebar.Content
The `Sidebar.Content` component is used to wrap the content of the sidebar. This is where you add your `Sidebar.Group` components. It is scrollable.
```svelte showLineNumbers
```
## Sidebar.Group
Use the `Sidebar.Group` component to create a section within the sidebar.
A `Sidebar.Group` has a `Sidebar.GroupLabel`, a `Sidebar.GroupContent` and an optional `Sidebar.GroupAction`.
```svelte showLineNumbers
Application
Add Project
```
## Collapsible Sidebar.Group
To make a `Sidebar.Group` collapsible, wrap it in a `Collapsible`.
```svelte showLineNumbers
{#snippet child({ props })}
Help
{/snippet}
```
**Note:** We wrap the `Collapsible.Trigger` in a `Sidebar.GroupLabel` to render
a button.
## Sidebar.GroupAction
Use the `Sidebar.GroupAction` component to add an action to a `Sidebar.Group`.
```svelte showLineNumbers {3-5}
Projects
Add Project
```
## Sidebar.Menu
The `Sidebar.Menu` component is used for building a menu within a `Sidebar.Group`.
A `Sidebar.Menu` is composed of `Sidebar.MenuItem`, `Sidebar.MenuButton`, `Sidebar.MenuAction`, and `Sidebar.MenuSub` components.
Here's an example of a `Sidebar.Menu` component rendering a list of projects.
```svelte showLineNumbers
Projects
{#each projects as project}
{#snippet child({ props })}
{project.name}
{/snippet}
{/each}
```
## Sidebar.MenuButton
The `Sidebar.MenuButton` component is used to render a menu button within a `Sidebar.Menu`.
### Link or Anchor
By default, the `Sidebar.MenuButton` renders a button, but you can use the `child` snippet to render a different component such as an `` tag.
```svelte showLineNumbers
{#snippet child({ props })}
Home
{/snippet}
```
### Icon and Label
You can render an icon and a truncated label inside the button. Remember to wrap the label in a `` tag.
```svelte showLineNumbers
{#snippet child({ props })}
Home
{/snippet}
```
### isActive
Use the `isActive` prop to mark a menu item as active.
```svelte showLineNumbers
{#snippet child({ props })}
Home
{/snippet}
```
## Sidebar.MenuAction
The `Sidebar.MenuAction` component is used to render a menu action within a `Sidebar.Menu`.
This button works independently of the `Sidebar.MenuButton`, i.e. you can have the `Sidebar.MenuButton` as a clickable link and the `Sidebar.MenuAction` as a button.
```svelte showLineNumbers
{#snippet child({ props })}
Home
{/snippet}
Add Project
```
### DropdownMenu
Here's an example of a `Sidebar.MenuAction` that renders a `DropdownMenu`.
```svelte showLineNumbers
{#snippet child({ props })}
Home
{/snippet}
{#snippet child({ props })}
{/snippet}
Edit Project
Delete Project
```
## Sidebar.MenuSub
The `Sidebar.MenuSub` component is used to render a submenu within a `Sidebar.Menu`.
Use `Sidebar.MenuSubItem` and `Sidebar.MenuSubButton` to render a submenu item.
```svelte showLineNumbers
```
## Collapsible Sidebar.Menu
To make a `Sidebar.Menu` collapsible, wrap it and the `Sidebar.MenuSub` components in a `Collapsible`.
```svelte showLineNumbers
{#snippet child({ props })}
{/snippet}
```
## Sidebar.MenuBadge
The `Sidebar.MenuBadge` component is used to render a badge within a `Sidebar.MenuItem`.
```svelte showLineNumbers
24
```
## Sidebar.MenuSkeleton
The `Sidebar.MenuSkeleton` component is used to render a skeleton within a `Sidebar.MenuItem`. You can use this to show a loading state while waiting for data to load.
```svelte showLineNumbers
{#each Array.from({ length: 5 }) as _, index (index)}
{/each}
```
## Sidebar.Separator
The `Sidebar.Separator` component is used to render a separator within a `Sidebar`.
```svelte showLineNumbers
```
## Sidebar.Trigger
Use the `Sidebar.Trigger` component to render a button that toggles the sidebar.
The `Sidebar.Trigger` component must be used within a `Sidebar.Provider`.
```svelte showLineNumbers
```
## Custom Trigger
To create a custom trigger, you can use the `useSidebar` hook.
```svelte showLineNumbers
sidebar.toggle()}>Toggle Sidebar
```
## Sidebar.Rail
The `Sidebar.Rail` component is used to render a rail within a `Sidebar.Root`. This rail can be used to toggle the sidebar.
```svelte showLineNumbers
```
## Controlled Sidebar
Use Svelte's [Function Binding](https://svelte.dev/docs/svelte/bind#Function-bindings) to control the sidebar state.
```svelte showLineNumbers
myOpen, (newOpen) => (myOpen = newOpen)}>
```
## Theming
We use the following CSS variables to theme the sidebar.
```css
:root {
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.439 0 0);
}
```
**We intentionally use different variables for the sidebar and the rest of the application** to make it easy to have a sidebar that is styled differently from the rest of the application. Think a sidebar with a darker shade from the main application.
## Styling
Here are some tips for styling the sidebar based on different states.
- **Styling an element based on the sidebar collapsible state.** The following will hide the `Sidebar.Group` when the sidebar is in `icon` mode.
```svelte
```
- **Styling a menu action based on the menu button active state.** The following will force the menu action to be visible when the menu button is active.
```svelte
```
You can find more tips on using states for styling in this [Twitter thread](https://x.com/shadcn/status/1842329158879420864).
================================================
FILE: docs/content/components/skeleton.md
================================================
---
title: Skeleton
description: Use to show a placeholder while content is loading.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/skeleton
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
```
## Examples
## Card
================================================
FILE: docs/content/components/slider.md
================================================
---
title: Slider
description: An input where the user selects a value from within a given range.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/slider
doc: https://bits-ui.com/docs/components/slider
api: https://bits-ui.com/docs/components/slider#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
```
================================================
FILE: docs/content/components/sonner.md
================================================
---
title: Sonner
description: An opinionated toast component for Svelte.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/sonner
doc: https://svelte-sonner.vercel.app/
---
## About
The Sonner component is provided by [svelte-sonner](https://svelte-sonner.vercel.app/), which is a Svelte port of [Sonner](https://sonner.emilkowal.ski/), originally created by [Emil Kowalski](https://twitter.com/emilkowalski_) for React.
## Installation
Setup theme support
By default, Sonner will use the user's system preferences to determine whether to show the light or dark theme. To get around this, you can either pass in a custom `theme` prop to the component, or simply use [mode-watcher](https://github.com/svecosystem/mode-watcher) which you can hardcode to `dark` or `light` mode should you wish.
You can learn more about setting up Dark Mode support [here](/docs/dark-mode).
If you wish to opt out of Dark Mode support, you can uninstall `mode-watcher` and remove the `theme` prop from the component after installing via CLI, or manually install the component and don't include `mode-watcher`
{#snippet cli()}
Run the following command:
Add the Toaster component
```svelte showLineNumbers title="+layout.svelte" {2,6}
{@render children?.()}
```
{/snippet}
{#snippet manual()}
Install `svelte-sonner`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
Add the Toaster component
```svelte showLineNumbers title="+layout.svelte" {2,6}
{@render children?.()}
```
{/snippet}
## Usage
```svelte
```
```svelte
toast("Hello world")}>Show toast
```
## Examples
## Changelog
### 2025-12 Icons
We've updated the Sonner component to use icons from `lucide`. Update your `sonner.svelte` file to use the new icons.
```svelte showLineNumbers title="components/ui/sonner.svelte" {2-6,22-36}
{#snippet loadingIcon()}
{/snippet}
{#snippet successIcon()}
{/snippet}
{#snippet errorIcon()}
{/snippet}
{#snippet infoIcon()}
{/snippet}
{#snippet warningIcon()}
{/snippet}
```
================================================
FILE: docs/content/components/spinner.md
================================================
---
title: Spinner
description: An indicator that can be used to show a loading state.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/spinner
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `@lucide/svelte`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
```
## Customization
You can replace the default spinner icon with any other icon by editing the `Spinner` component.
## Examples
### Size
Use the `size-*` utility class to change the size of the spinner.
### Color
Use the `text-*` utility class to change the color of the spinner.
### Button
Add a spinner to a button to indicate a loading state. The ` ` will handle the spacing between the spinner and the text.
### Badge
You can also use a spinner inside a badge.
### Input Group
Input Group can have spinners inside ``.
### Empty
### Item
Use the spinner inside `` to indicate a loading state.
================================================
FILE: docs/content/components/switch.md
================================================
---
title: Switch
description: A control that allows the user to toggle between checked and not checked.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/switch
doc: https://bits-ui.com/docs/components/switch
api: https://bits-ui.com/docs/components/switch#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
```
================================================
FILE: docs/content/components/table.md
================================================
---
title: Table
description: A responsive table component.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/table
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
A list of your recent invoices.
Invoice
Status
Method
Amount
INV001
Paid
Credit Card
$250.00
```
## Data Table
You can use the `` component to build more complex data tables. Combine it with [@tanstack/table](https://tanstack.com/table) to create tables with sorting, filtering and pagination.
See the [Data Table](/docs/components/data-table) documentation for more information.
You can also see an example of a data table in the [Tasks](/examples/tasks) demo.
================================================
FILE: docs/content/components/tabs.md
================================================
---
title: Tabs
description: A set of layered sections of content—known as tab panels—that are displayed one at a time.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/tabs
doc: https://bits-ui.com/docs/components/tabs
api: https://bits-ui.com/docs/components/tabs#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte showLineNumbers
```
```svelte showLineNumbers
Account
Password
Make changes to your account here.
Change your password here.
```
================================================
FILE: docs/content/components/textarea.md
================================================
---
title: Textarea
description: Displays a form textarea or a component that looks like a textarea.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/textarea
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
```
## Examples
### Default
### Disabled
### With Label
### With Text
### With Button
================================================
FILE: docs/content/components/toggle-group.md
================================================
---
title: Toggle Group
description: A set of two-state buttons that can be toggled on or off.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/toggle-group
doc: https://bits-ui.com/docs/components/toggle-group
api: https://bits-ui.com/docs/components/toggle-group#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
A
B
C
```
## Examples
### Outline
### Single
### Small
### Large
### Disabled
### Spacing
Use `spacing={2}` to add spacing between toggle group items.
================================================
FILE: docs/content/components/toggle.md
================================================
---
title: Toggle
description: A two-state button that can be either on or off.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/toggle
doc: https://bits-ui.com/docs/components/toggle
api: https://bits-ui.com/docs/components/toggle#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
```svelte
```
```svelte
Toggle
```
## Examples
### Default
### Outline
### With Text
### Small
### Large
### Disabled
================================================
FILE: docs/content/components/tooltip.md
================================================
---
title: Tooltip
description: A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
component: true
links:
source: https://github.com/huntabyte/shadcn-svelte/tree/next/sites/docs/src/lib/registry/ui/tooltip
doc: https://bits-ui.com/docs/components/tooltip
api: https://bits-ui.com/docs/components/tooltip#api-reference
---
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
Install `bits-ui`:
Copy and paste the following code into your project.
{#if viewerData}
{/if}
{/snippet}
## Usage
The `Tooltip.Provider` component should be placed once in your root layout, wrapping all content that will contain tooltips. This ensures that only one tooltip within the provider can be open at a time.
```svelte title="src/routes/+layout.svelte" showLineNumbers
```
```svelte showLineNumbers
{@render children()}
```
Then use tooltips anywhere in your app:
```svelte
Hover
Add to library
```
### Nested Providers
You can nest providers to create groups with different settings. Tooltips use the closest ancestor provider. This is useful when you want instant tooltips in specific areas:
```svelte
```
---
## Changelog
### 2025-12 Update tooltip colors
We've updated the tooltip colors to use the foreground color for the background and the background color for the foreground.
Replace `bg-primary text-primary-foreground` with `bg-foreground text-background` for ` `.
================================================
FILE: docs/content/components/typography.md
================================================
---
title: Typography
description: Styles for headings, paragraphs, lists...etc
component: true
---
We do not ship any typography styles by default. This page is an example of how you can use utility classes to style your text.
## h1
## h2
## h3
## h4
## p
## blockquote
## table
## list
## Inline code
## Lead
## Large
## Small
## Muted
================================================
FILE: docs/content/components-json.md
================================================
---
title: components.json
description: Configuration for your project.
---
The `components.json` file holds configuration for your project.
We use it to understand how your project is set up and how to generate components customized for your project.
Note: The `components.json` file is optional and **only required if you're using the CLI** to add components to your project. If you're using the copy and paste method, you don't need this file.
You can create a `components.json` file in your project by running the following command:
See the [CLI section](/docs/cli) for more information.
## $schema
You can see the JSON Schema for `components.json` [here](https://shadcn-svelte.com/schema.json).
```json title="components.json"
{
"$schema": "https://shadcn-svelte.com/schema.json"
}
```
## tailwind
Configuration to help the CLI understand how Tailwind CSS is set up in your project.
See the [installation section](/docs/installation) for how to set up Tailwind CSS.
### tailwind.css
Path to the CSS file that imports Tailwind CSS into your project.
```json title="components.json"
{
"tailwind": {
"css": "src/app.{p,post}css"
}
}
```
### tailwind.baseColor
This is used to generate the default color palette for your components. **This cannot be changed after initialization.**
```json title="components.json"
{
"tailwind": {
"baseColor": "gray" | "neutral" | "slate" | "stone" | "zinc"
}
}
```
## aliases
The CLI uses these values and the `alias` config from your `svelte.config.js` file to place generated components in the correct location.
Path aliases have to be set up in your `svelte.config.js` file.
### aliases.lib
Import alias for your library, which is _typically_ where you store your components, utils, hooks, etc.
```json title="components.json"
{
"aliases": {
"lib": "$lib"
}
}
```
### aliases.utils
Import alias for your utility functions.
```json title="components.json"
{
"aliases": {
"utils": "$lib/utils"
}
}
```
### aliases.components
Import alias for your components.
```json title="components.json"
{
"aliases": {
"components": "$lib/components"
}
}
```
### aliases.ui
Import alias for your UI components.
```json title="components.json"
{
"aliases": {
"ui": "$lib/components/ui"
}
}
```
### aliases.hooks
Import alias for your hooks, which in Svelte 5 are reactive functions/classes whose files typically end in `.svelte.ts` or `.svelte.js`.
```json title="components.json"
{
"aliases": {
"hooks": "$lib/hooks"
}
}
```
## Typescript
Typescript can be enabled or disabled.
```json title="components.json"
{
"typescript": true | false
}
```
You can also specify a path to your own custom Typescript config file if it has a different name from `tsconfig.json` or `jsconfig.json`, or if it is located in a different directory:
```json title="components.json"
{
"typescript": {
"config": "path/to/tsconfig.custom.json"
}
}
```
## Registry
The registry URL tells the CLI where to fetch the shadcn-svelte components/registry from. You can pin this to a specific preview release or your own fork of the registry.
```json title="components.json"
{
"registry": "https://shadcn-svelte.com/registry"
}
```
================================================
FILE: docs/content/dark-mode/astro.md
================================================
---
title: Astro
description: Adding dark mode to your Astro site.
---
Just like in regular Svelte, we use the `class` strategy from Tailwind CSS to support dark mode toggling. See the [Tailwind CSS documentation](https://tailwindcss.com/docs/dark-mode#toggling-dark-mode-manually) for more information.
How you add the `dark` class to the `html` element is up to you. In this guide, we'll take a look at enabling dark mode toggling with [mode-watcher](https://github.com/svecosystem/mode-watcher).
## Usage
### Create an inline theme script
This script will, in part, keep and track the dark mode value in `localStorage` and prevent [FUOC](https://en.wikipedia.org/wiki/Flash_of_unstyled_content).
```astro title="src/pages/index.astro" {5-27} showLineNumbers
---
import "../styles/global.css";
---
Astro
```
### Install mode-watcher
### Add the ModeWatcher component
Import the `ModeWatcher` component and use it in your page with the `client:load` directive:
```astro title="src/pages/index.astro" {3,9} showLineNumbers
---
import "../styles/global.css";
import { ModeWatcher } from "mode-watcher";
---
Astro
```
### Create a mode toggle
Create a mode toggle on your site to toggle between light and dark mode:
#### Light switch
#### Dropdown menu
### Add mode toggle to page
Add the mode toggle to the page (also with the `client:load` directive):
```astro title="src/pages/index.astro" {4,12} showLineNumbers
---
import "../styles/global.css";
import { ModeWatcher } from "mode-watcher";
import ModeToggle from "$lib/components/mode-toggle.svelte";
---
Astro
```
================================================
FILE: docs/content/dark-mode/index.md
================================================
---
title: Dark Mode
description: Adding dark mode to your site.
---
================================================
FILE: docs/content/dark-mode/svelte.md
================================================
---
title: Svelte
description: Adding dark mode to your Svelte site.
---
## Install mode-watcher
Start by installing `mode-watcher`:
## Add the ModeWatcher component
Import the `ModeWatcher` component and use it in your root layout:
```svelte title="src/routes/+layout.svelte" showLineNumbers {3,7}
{@render children?.()}
```
## Add a mode toggle
Place a mode toggle on your site to toggle between light and dark mode.
================================================
FILE: docs/content/figma.md
================================================
---
title: Figma
description: Every component recreated in Figma. With customizable props, typography and icons.
---
The Figma UI Kit is open sourced by [Pietro Schirano](https://twitter.com/skirano).
## Grab a copy
https://www.figma.com/community/file/1203061493325953101
================================================
FILE: docs/content/index.md
================================================
---
title: Introduction
description: Re-usable components built with Bits UI and Tailwind CSS.
---
An unofficial, community-led [Svelte](https://svelte.dev) port of [shadcn/ui](https://ui.shadcn.com). We are not affiliated with [shadcn](https://x.com/shadcn), but we did get his blessing before creating a Svelte version of his work. This project was born out of the need for a similar project for the Svelte ecosystem.
**This is not a component library. It is how you build your component library.**
You know how most traditional component libraries work: you install a package from NPM, import the components, and use them in your app.
This approach works well until you need to customize a component to fit your design system or require one that isn’t included in the library. **Often, you end up wrapping library components, writing workarounds to override styles, or mixing components from different libraries with incompatible APIs.**
This is what shadcn-svelte aims to solve. It is built around the following principles:
- **Open Code:** The top layer of your component code is open for modification.
- **Composition:** Every component uses a common, composable interface, making them predictable.
- **Distribution:** A flat-file schema and command-line tool make it easy to distribute components.
- **Beautiful Defaults:** Carefully chosen default styles, so you get great design out-of-the-box.
- **AI-Ready:** Open code for LLMs to read, understand, and improve.
## Open Code
shadcn-svelte hands you the actual component code. You have full control to customize and extend the components to your needs. This means:
- **Full Transparency:** You see exactly how each component is built.
- **Easy Customization:** Modify any part of a component to fit your design and functionality requirements.
- **AI Integration:** Access to the code makes it straightforward for LLMs to read, understand, and even improve your components.
_In a typical library, if you need to change a button’s behavior, you have to override styles or wrap the component. With shadcn-svelte, you simply edit the button code directly._
How do I pull upstream updates in an Open Code approach?
shadcn-svelte follows a headless component architecture. This means the core of your app can receive fixes by updating your dependencies, for instance, bits-ui or paneforge.
The topmost layer, i.e., the one closest to your design system, is not
coupled with the implementation of the library. It stays open for
modification.
## Composition
Every component in shadcn-svelte shares a common, composable interface. **If a component does not exist, we bring it in, make it composable, and adjust its style to match and work with the rest of the design system.**
_A shared, composable interface means it's predictable for both your team and LLMs. You are not learning different APIs for every new component. Even for third-party ones._
## Distribution
shadcn-svelte is also a code distribution system. It defines a schema for components and a CLI to distribute them.
- **Schema:** A flat-file structure that defines the components, their dependencies, and properties.
- **CLI:** A command-line tool to distribute and install components across projects with cross-framework support.
_You can use the schema to distribute your components to other projects or have AI generate completely new components based on existing schema._
## Beautiful Defaults
shadcn-svelte comes with a large collection of components that have carefully chosen default styles. They are designed to look good on their own and to work well together as a consistent system:
- **Good Out-of-the-Box:** Your UI has a clean and minimal look without extra work.
- **Unified Design:** Components naturally fit with one another. Each component is built to match the others, keeping your UI consistent.
- **Easily Customizable:** If you want to change something, it's simple to override and extend the defaults.
## AI-Ready
The design of shadcn-svelte makes it easy for AI tools to work with your code. Its open code and consistent API allow AI models to read, understand, and even generate new components.
_An AI model can learn how your components work and suggest improvements or even create new components that integrate with your existing design._
================================================
FILE: docs/content/installation/astro.md
================================================
---
title: Astro
description: How to setup shadcn-svelte in an Astro project.
---
### Create project
Start by creating a new Astro project:
### Configure your Astro project
You will be asked a few questions to configure your project:
```bash showLineNumbers
- Where should we create your new project?
./your-app-name
- How would you like to start your new project?
Choose a starter template (or Empty)
- Install dependencies?
Yes
- Initialize a new git repository? (optional)
Yes/No
```
### Add Svelte to your project
Install Svelte using the Astro CLI:
Answer `Yes` to all the question prompted by the CLI when installing Svelte.
### Add TailwindCSS to your project
Add Tailwind CSS using the Astro CLI:
Answer `Yes` to all the question prompted by the CLI when installing TailwindCSS.
### Import the global CSS file
Import the `global.css` file in the `src/pages/index.astro` file:
```astro title="src/pages/index.astro" {2} showLineNumbers
---
import "../styles/global.css";
---
```
### Setup path aliases
Add the following code to the `tsconfig.json` file to resolve paths:
```json title="tsconfig.json" {2-10} showLineNumbers
{
"compilerOptions": {
// ...
"baseUrl": ".",
"paths": {
"$lib": ["./src/lib"],
"$lib/*": ["./src/lib/*"]
}
// ...
}
}
```
If needed, adapt the path aliases to your specific needs ([learn more about it](https://docs.astro.build/en/guides/aliases/)).
### Run the CLI
Run the `shadcn-svelte` init command to setup your project:
### Configure components.json
You will be asked a few questions to configure `components.json`:
```txt showLineNumbers
Which base color would you like to use? › Slate
Where is your global CSS file? (this file will be overwritten) › src/styles/global.css
Configure the import alias for lib: › $lib
Configure the import alias for components: › $lib/components
Configure the import alias for utils: › $lib/utils
Configure the import alias for hooks: › $lib/hooks
Configure the import alias for ui: › $lib/components/ui
```
### That's it
You can now start adding components to your project.
The command above will add the `Button` component to your project. You can then import it like this:
```astro title="index.astro" {2,10} showLineNumbers
---
import { Button } from "$lib/components/ui/button/index.js";
---
Astro
Hello World
```
Remember to use the `client` directives inside `.astro` files when dealing with interactive components ([learn more about it](https://docs.astro.build/en/reference/directives-reference/#client-directives)).
================================================
FILE: docs/content/installation/index.md
================================================
---
title: Installation
description: How to install dependencies and structure your app.
---
## Guides
## Imports
Unlike the original [shadcn/ui](https://ui.shadcn.com) for React, where the full components can exist in a single file, components in this port are split into multiple files. This is because Svelte doesn't support defining multiple components in a single file, so utilizing the CLI to add components will be the optimal approach.
The CLI will create a folder for _each_ component, which will sometimes just contain a single Svelte file, and in other times, multiple files. Within each folder, there will be an `index.ts` file that exports the component(s), so you can import them from a single file.
For example, the Accordion component is split into four `.svelte` files:
- `accordion.svelte`
- `accordion-content.svelte`
- `accordion-item.svelte`
- `accordion-trigger.svelte`
They can then be imported from the `accordion/index.ts` file like so:
```ts
import * as Accordion from '$lib/components/ui/accordion"
// or
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger
} from "$lib/components/ui/accordion"
```
Regardless of the import approach you take, the components will be tree-shaken by Rollup, so you don't have to worry about unused components being bundled into your app.
## VSCode extension
Install the shadcn-svelte [VSCode extension](https://marketplace.visualstudio.com/items?itemName=Selemondev.vscode-shadcn-svelte) by [@selemondev](https://github.com/selemondev) in Visual Studio Code to easily add Shadcn Svelte components to your project.
This extension offers a range of features:
- Ability to initialize the shadcn-svelte CLI
- Add components to your project
- Navigate to a specific component's documentation page directly from your IDE
- Handy snippets for quick component imports and markup
## JetBrains IDEs extension
Install the shadcn/ui Components Manager [JetBrains extension](https://plugins.jetbrains.com/plugin/23479-shadcn-ui-components-manager) by [@WarningImHack3r](https://github.com/WarningImHack3r) in any JetBrains IDE (IntelliJ IDEA, WebStorm...) to easily manage shadcn components within your project.
This extension offers a range of features, including:
- Automatically detect shadcn/ui components in your project
- Instantly add, remove, and update them with a single click
- Supports all shadcn/ui implementations: Svelte, React, Vue, and Solid
- Easily search for remote or existing components
================================================
FILE: docs/content/installation/manual.md
================================================
---
title: Manual Installation
description: How to setup shadcn-svelte manually.
---
### Add Tailwind
Use the `sv` CLI to add Tailwind CSS to your project.
### Add dependencies
Add the following dependencies to your project:
### Add icon library
Install `@lucide/svelte`:
### Configure path aliases
If you are using SvelteKit and are not using the default alias `$lib`, you'll need to update your `svelte.config.js` file to include those aliases.
```ts title="svelte.config.js" {6} showLineNumbers
const config = {
// ... other config
kit: {
// ... other config
alias: {
"@/*": "./path/to/lib/*",
},
},
};
```
If you are _not_ using SvelteKit, then you'll need to update your path aliases in your `tsconfig.json` and `vite.config.ts`.
```json title="tsconfig.json" {4-7} showLineNumbers
{
"compilerOptions": {
// ... other options
"paths": {
"$lib": ["./src/lib"],
"$lib/*": ["./src/lib/*"]
}
}
}
```
```ts title="vite.config.ts" {1, 5-9} showLineNumbers
import path from "path";
export default defineConfig({
// ... other options
resolve: {
alias: {
$lib: path.resolve("./src/lib"),
},
},
});
```
### Configure styles
Add the following to your global CSS file. You can learn more about using CSS variables for theming in the [theming section](/docs/theming).
```css title="src/routes/layout.css" showLineNumbers
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.269 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.371 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.439 0 0);
}
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--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-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);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
```
Feel free to add or modify as needed to suit your project.
### Configure utils
You'll want to create a `cn` helper to make it easier to conditionally add and merge Tailwind CSS classes.
```ts title="src/lib/utils.ts" showLineNumbers
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
```
### Import styles to your app
Create `src/routes/+layout.svelte` and import the styles:
```svelte title="src/routes/+layout.svelte" showLineNumbers
{@render children?.()}
```
### That's it
You can now start adding components to your project.
================================================
FILE: docs/content/installation/sveltekit.md
================================================
---
title: SvelteKit
description: How to setup shadcn-svelte in a SvelteKit project.
---
### Create project
Use the SvelteKit CLI to create a new project with TailwindCSS
### Setup path aliases
If you are not using the default alias `$lib`, you'll need to update your `svelte.config.js` file to include those aliases.
```ts title="svelte.config.js" {6} showLineNumbers
const config = {
// ... other config
kit: {
// ... other config
alias: {
"@/*": "./path/to/lib/*",
},
},
};
```
### Run the CLI
### Configure components.json
You will be asked a few questions to configure `components.json`:
```txt showLineNumbers
Which base color would you like to use? › Slate
Where is your global CSS file? (this file will be overwritten) › src/routes/layout.css
Configure the import alias for lib: › $lib
Configure the import alias for components: › $lib/components
Configure the import alias for utils: › $lib/utils
Configure the import alias for hooks: › $lib/hooks
Configure the import alias for ui: › $lib/components/ui
```
### That's it
You can now start adding components to your project.
The command above will add the `Button` component to your project. You can then import it like this:
```svelte {2,5} showLineNumbers
Click me
```
================================================
FILE: docs/content/installation/vite.md
================================================
---
title: Vite
description: How to setup shadcn-svelte in a Vite project.
---
### Add TailwindCSS
Use the Svelte CLI to add Tailwind CSS to your project.
### Edit tsconfig.json file
The current version of Vite splits TypeScript configuration into three files, two of which need to be edited.
Add the `baseUrl` and `paths` properties to the `compilerOptions` section of the `tsconfig.json` and
`tsconfig.app.json` files:
```json title="tsconfig.json" {7-13} showLineNumbers
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"$lib": ["./src/lib"],
"$lib/*": ["./src/lib/*"]
}
}
}
```
### Edit tsconfig.app.json file
Add the following code to the `tsconfig.app.json` file to resolve paths, for your IDE:
```json title="tsconfig.app.json" {4-8} showLineNumbers
{
"compilerOptions": {
// ...
"baseUrl": ".",
"paths": {
"$lib": ["./src/lib"],
"$lib/*": ["./src/lib/*"]
}
}
}
```
### Update vite.config.ts
Add the following code to the vite.config.ts so your app can resolve paths without error:
```ts title="vite.config.ts" {1, 5-9} showLineNumbers
import path from "path";
export default defineConfig({
// ... other options
resolve: {
alias: {
$lib: path.resolve("./src/lib"),
},
},
});
```
### Run the CLI
### Configure components.json
You will be asked a few questions to configure `components.json`:
```txt showLineNumbers
Which base color would you like to use? › Slate
Where is your global CSS file? (this file will be overwritten) › src/routes/layout.css
Configure the import alias for lib: › $lib
Configure the import alias for components: › $lib/components
Configure the import alias for utils: › $lib/utils
Configure the import alias for hooks: › $lib/hooks
Configure the import alias for ui: › $lib/components/ui
```
### That's it
You can now start adding components to your project.
The command above will add the `Button` component to your project. You can then import it like this:
```svelte {2,5} showLineNumbers
Click me
```
================================================
FILE: docs/content/javascript.md
================================================
---
title: JavaScript
description: How to use shadcn-svelte with JavaScript.
---
This project and the components are written in TypeScript. We recommend using TypeScript for your project as well.
However, we provide a JavaScript version of the components as well. The JavaScript version is _only_ available via the [CLI](/docs/cli).
To opt-out of TypeScript, you can use the `typescript` flag in your `components.json` file.
```json {6} title="components.json" showLineNumbers
{
"style": "default",
"tailwind": {
"css": "src/routes/layout.css"
},
"typescript": false,
"aliases": {
"utils": "$lib/utils",
"components": "$lib/components",
"hooks": "$lib/hooks",
"ui": "$lib/components/ui"
},
"registry": "https://shadcn-svelte.com/registry"
}
```
To configure import aliases, create a `jsconfig.json` file:
```json {4} title="jsconfig.json" showLineNumbers
{
"compilerOptions": {
"paths": {
"$lib/*": ["./src/lib/*"]
}
}
}
```
================================================
FILE: docs/content/legacy.md
================================================
---
title: Legacy Docs
description: View the legacy docs for shadcn-svelte and Tailwind v3.
---
You're looking at the docs for Svelte 5 + Tailwind v4.
If you're looking for older docs, you can find them below.
Svelte 5 + Tailwind v3 Docs
Svelte 4 + Tailwind v3 Docs
================================================
FILE: docs/content/migration/index.md
================================================
---
title: Migration
description: Learn how to update your project to the latest version of shadcn-svelte.
---
The latest version of shadcn-svelte expects you to be using Svelte v5 and Tailwind v4. The following guides will help you update your project to the latest version.
Svelte v5
Tailwind v4
================================================
FILE: docs/content/migration/svelte-5.md
================================================
---
title: Svelte 5
description: How to migrate from Svelte 4 and Tailwind 3 to Svelte 5.
---
**Note**: With Svelte 5 comes significant changes to this project, along with the headless UI library used [bits-ui](https://bits-ui.com). This guide is specifically focused on migrating the shadcn-svelte portions and does not cover the migration of `bits-ui`. See [Bits UI's migration guide](https://bits-ui.com/docs/migration-guide) for more information.
## Svelte 4 to Svelte 5
This first guide will take your project from Svelte 4 with Tailwind 3 to Svelte 5 and Tailwind 3.
Once you've completed this guide and you're comfortable everything is working, you can move on to the next guide to migrate to Tailwind 4.
## Prerequisites
1. Ensure you have read up on the changes from Svelte 4 to Svelte 5. Svelte provides a comprehensive guide for this on their [website](https://svelte.dev/docs/svelte/v5-migration-guide).
2. Commit any pending changes to your repository.
3. Determine which of your components have custom behavior/styles so that you can reimplement those after updating.
4. Use [`sv-migrate`](https://svelte.dev/docs/cli/sv-migrate) to help you migrate your project to Svelte 5.
## Update Configs
The `components.json`, `utils`, and the global CSS file have changed for Svelte 5.
### Update `components.json`
Add the `registry` to the root object, and add `hooks`, `ui`, and `lib` keys under `aliases`.
```diff
{
"$schema": "https://shadcn-svelte.com/schema.json",
"style": "default",
"tailwind": {
"css": "src/routes/layout.css",
"baseColor": "slate"
},
"aliases": {
"components": "$lib/components",
"utils": "$lib/utils",
+ "ui": "$lib/components/ui",
+ "hooks": "$lib/hooks",
+ "lib": "$lib"
},
"typescript": true,
+ "registry": "https://shadcn-svelte.com/registry"
}
```
### Update `tailwind.config.js`
Add `tailwindcss-animate`.
Add the `tailwindcss-animate` plugin, sidebar colors, and animations config.
```ts title="tailwind.config.js"
import type { Config } from "tailwindcss";
import tailwindcssAnimate from "tailwindcss-animate";
const config: Config = {
darkMode: ["class"],
content: ["./src/**/*.{html,js,svelte,ts}"],
safelist: ["dark"],
theme: {
container: {
// unchanged ...
},
extend: {
colors: {
// unchanged ...
sidebar: {
DEFAULT: "hsl(var(--sidebar-background))",
foreground: "hsl(var(--sidebar-foreground))",
primary: "hsl(var(--sidebar-primary))",
"primary-foreground": "hsl(var(--sidebar-primary-foreground))",
accent: "hsl(var(--sidebar-accent))",
"accent-foreground": "hsl(var(--sidebar-accent-foreground))",
border: "hsl(var(--sidebar-border))",
ring: "hsl(var(--sidebar-ring))",
},
},
borderRadius: {
// unchanged ...
},
fontFamily: {
// unchanged ...
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--bits-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--bits-accordion-content-height)" },
to: { height: "0" },
},
"caret-blink": {
"0%,70%,100%": { opacity: "1" },
"20%,50%": { opacity: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
"caret-blink": "caret-blink 1.25s ease-out infinite",
},
},
},
plugins: [tailwindcssAnimate],
};
export default config;
```
### Update `utils.ts`
**Note**: You may not want to do this step until after you've updated your components, as some components may rely on the now removed `flyAndScale` function.
`utils.ts` now only exports the `cn` function and a few utility types.
```ts title="src/lib/utils.ts"
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type WithoutChild = T extends { child?: any } ? Omit : T;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type WithoutChildren = T extends { children?: any }
? Omit
: T;
export type WithoutChildrenOrChild = WithoutChildren>;
export type WithElementRef = T & {
ref?: U | null;
};
```
## Upgrade Components
### Alias Dependencies (optional)
If you plan to slowly migrate components, it's recommended to alias the old versions of the major dependencies, like `bits-ui`, in your `package.json` file so that you can use both versions of the library in your project while you migrate.
```diff title="package.json"
{
"devDependencies": {
- "bits-ui": "^0.22.0",
+ "bits-ui-old": "npm:bits-ui@0.22.0",
}
}
```
You'll then want to replace all the imports used in your project to `bits-ui-old`.
```diff title="src/lib/components/ui/dialog-content.svelte"
```
You can do the same for any of the other dependencies that you're using in your project.
### Update Dependencies
The following dependencies have been updated to support Svelte 5:
- `bits-ui` - `^1.0.0`
- `svelte-sonner` - `^1.0.0`
- `@lucide/svelte` - `^0.482.0`
- `paneforge` - `^1.0.0-next.5`
- `vaul-svelte` - `^1.0.0-next.7`
- `mode-watcher` - `^1.0.0`
- `cmdk-sv` - deprecated in favor of Bits UI's `Command` component
- `svelte-headless-table` - deprecated in favor of `@tanstack/table-core`
- `svelte-radix` - icons deprecated in favor of `@lucide/svelte`
- `lucide-svelte` - replaced with `@lucide/svelte`
You can update your dependencies by running the following command:
### Start Migrating Components
Now you're ready to begin updating your components to their new versions. The CLI doesn't actually _update_ your components, it simply replaces them with the new versions, so be sure to commit your changes before running the CLI.
```bash
git add .
git commit -m 'before migration'
```
Now you can run the `add` command to start migrating your components.
Review the diff to see what was updated and make any necessary adjustments. Rinse and repeat for each component you want to migrate.
## Remove Unused Dependencies
Once you've updated all your components, you can remove the old dependencies from your `package.json` file.
### cmdk-sv
`cmdk-sv` has been replaced with Bits UI's `Command` component.
### svelte-headless-table
`svelte-headless-table` has been replaced with `@tanstack/table-core`.
### svelte-radix
`svelte-radix` has been replaced with `@lucide/svelte`.
### lucide-svelte
`lucide-svelte` has been replaced with `@lucide/svelte`.
## Next Steps
Once you've completed this guide and you're comfortable everything is working as expected, you can move on to the [Tailwind 4 Guide](/docs/migration/tailwind-v4).
================================================
FILE: docs/content/migration/tailwind-v4.md
================================================
---
title: Tailwind v4
description: How to use shadcn-svelte with Tailwind v4 and Svelte 5.
---
This documentation site is now running Tailwind v4. If you're looking for the old Tailwind v3 docs, you can find them here: [https://tw3.shadcn-svelte.com](https://tw3.shadcn-svelte.com).
## What's New
- The `@latest` CLI can now initialize projects with Tailwind v4 and Svelte 5.
- Full support for the new `@theme` directive and `@theme inline` option.
- All components are updated for Tailwind v4 and Svelte 5.
- Every primitive that renders an element now has a `data-slot` attribute for styling.
- We've fixed and cleaned up the style of the components.
- Buttons now use the default cursor.
- We're deprecating the `default` style. New projects will use `new-york`.
- HSL colors are now converted to OKLCH.
**Note: this is non-breaking. Your existing apps with Tailwind v3 will continue to work. When you add new components, they'll still be in Tailwind v3 with the style configured in `components.json` until you upgrade. Only new projects start with Tailwind v4.**
## See it Live
This documentation site is now using Tailwind v4 and Svelte 5, but for a more complete example, checkout the demo site here: [https://v4.shadcn-svelte.com](https://v4.shadcn-svelte.com).
If you find any bugs, please us know on [GitHub](https://github.com/huntabyte/shadcn-svelte/issues).
## Try It Out
You can start using Tailwind v4 and Svelte 5 today using the `@latest` CLI. See the specific install docs
## Upgrade Your Project
**Note**: This guide assumes you are coming from a Svelte 5 and Tailwind 3 project. If you are coming from a Svelte 4 project, you should first follow the [Svelte 4 and Tailwind 3 to Svelte 5](./svelte-5) guide.
**Important:** Before upgrading, please read the [Tailwind v4 Compatibility
Docs](https://tailwindcss.com/docs/compatibility) and make sure your project
is ready for the upgrade. Tailwind v4 uses bleeding-edge browser features and
is designed for modern browsers.
One of the major advantages of using `shadcn-svelte` is that the code you end up with is exactly what you'd write yourself. There are no hidden abstractions.
This means when a dependency has a new release, you can just follow the official upgrade paths.
Here's how to upgrade your existing projects:
### 1. Follow the Tailwind v4 Upgrade Guide
- Upgrade to Tailwind v4 by following the official upgrade guide: https://tailwindcss.com/docs/upgrade-guide
- Use the `@tailwindcss/upgrade` codemod to remove deprecated utility classes and update the tailwind config.
### 2. Replace PostCSS with Vite
The upgrade script will automatically migrate your project to the latest PostCSS configuration of Tailwind v4, but the Tailwind team recommends using Vite instead, so we'll use that instead.
#### Delete `postcss.config.js`
```diff title="postcss.config.js"
- export default {
- plugins: {
- '@tailwindcss/postcss': {},
- }
- };
```
#### Uninstall `@tailwindcss/postcss`
#### Install `@tailwindcss/vite`
#### Update `vite.config.ts`
```diff title="vite.config.ts"
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
+ import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
- plugins: [sveltekit()],
+ plugins: [tailwindcss(), sveltekit()],
});
```
#### Verify the upgrade
Start your dev server and verify that all your styles are working as expected.
### 2. Update your `app.css` file
The codemod will update your `app.css` file to look something like this, where it's defining the colors as CSS variables and importing your existing `tailwind.config.ts` file:
```css showLineNumbers
@import "tailwindcss";
@config "../tailwind.config.ts";
/*
The default border color has changed to `currentcolor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentcolor);
}
}
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 72.2% 50.6%;
--destructive-foreground: 0 0% 98%;
--ring: 240 10% 3.9%;
--radius: 0.5rem;
--sidebar: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--ring: 240 4.9% 83.9%;
--sidebar: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
```
In the following steps, we'll update this to completely remove the `tailwind.config.ts` and adopt the CSS-based config.
#### Replace `tailwind-css-animate` with `tw-animate-css`
We've deprecated `tailwindcss-animate` in favor of `tw-animate-css`, which has support for Tailwind v4.
#### Import `tw-animate-css`
```diff title="app.css"
@import "tailwindcss";
+ @import "tw-animate-css";
/* ... */
```
#### Add the custom variant for dark mode
```diff title="app.css"
@import "tailwindcss";
@import "tw-animate-css";
+@custom-variant dark (&:is(.dark *));
/* ... */
```
#### Remove the compatibility styles
We override the styles applied here so this is just dead code.
```diff title="app.css"
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
- /*
- The default border color has changed to `currentcolor` in Tailwind CSS v4,
- so we've added these compatibility styles to make sure everything still
- looks the same as it did with Tailwind CSS v3.
-
- If we ever want to remove these styles, we need to add an explicit border
- color utility to any element that depends on these defaults.
- */
- @layer base {
- *,
- ::after,
- ::before,
- ::backdrop,
- ::file-selector-button {
- border-color: var(--color-gray-200, currentcolor);
- }
- }
```
#### CSS Variables and Theme Config
We'll move the CSS variables to the `:root` and `.dark` selectors, wrap the colors values in `hsl()`, and set up an `@theme inline` directive to replace our Tailwind v3 config.
Once complete, your `app.css` file should look something like this (the color values will differ depending on your theme):
```css title="app.css"
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
:root {
--background: hsl(0 0% 100%) /* <- Wrap in HSL */;
--foreground: hsl(240 10% 3.9%);
--muted: hsl(240 4.8% 95.9%);
--muted-foreground: hsl(240 3.8% 46.1%);
--popover: hsl(0 0% 100%);
--popover-foreground: hsl(240 10% 3.9%);
--card: hsl(0 0% 100%);
--card-foreground: hsl(240 10% 3.9%);
--border: hsl(240 5.9% 90%);
--input: hsl(240 5.9% 90%);
--primary: hsl(240 5.9% 10%);
--primary-foreground: hsl(0 0% 98%);
--secondary: hsl(240 4.8% 95.9%);
--secondary-foreground: hsl(240 5.9% 10%);
--accent: hsl(240 4.8% 95.9%);
--accent-foreground: hsl(240 5.9% 10%);
--destructive: hsl(0 72.2% 50.6%);
--destructive-foreground: hsl(0 0% 98%);
--ring: hsl(240 10% 3.9%);
--sidebar: hsl(0 0% 98%);
--sidebar-foreground: hsl(240 5.3% 26.1%);
--sidebar-primary: hsl(240 5.9% 10%);
--sidebar-primary-foreground: hsl(0 0% 98%);
--sidebar-accent: hsl(240 4.8% 95.9%);
--sidebar-accent-foreground: hsl(240 5.9% 10%);
--sidebar-border: hsl(220 13% 91%);
--sidebar-ring: hsl(217.2 91.2% 59.8%);
--radius: 0.5rem;
}
.dark {
--background: hsl(240 10% 3.9%);
--foreground: hsl(0 0% 98%);
--muted: hsl(240 3.7% 15.9%);
--muted-foreground: hsl(240 5% 64.9%);
--popover: hsl(240 10% 3.9%);
--popover-foreground: hsl(0 0% 98%);
--card: hsl(240 10% 3.9%);
--card-foreground: hsl(0 0% 98%);
--border: hsl(240 3.7% 15.9%);
--input: hsl(240 3.7% 15.9%);
--primary: hsl(0 0% 98%);
--primary-foreground: hsl(240 5.9% 10%);
--secondary: hsl(240 3.7% 15.9%);
--secondary-foreground: hsl(0 0% 98%);
--accent: hsl(240 3.7% 15.9%);
--accent-foreground: hsl(0 0% 98%);
--destructive: hsl(0 62.8% 30.6%);
--destructive-foreground: hsl(0 0% 98%);
--ring: hsl(240 4.9% 83.9%);
--sidebar: hsl(240 5.9% 10%);
--sidebar-foreground: hsl(240 4.8% 95.9%);
--sidebar-primary: hsl(224.3 76.3% 48%);
--sidebar-primary-foreground: hsl(0 0% 100%);
--sidebar-accent: hsl(240 3.7% 15.9%);
--sidebar-accent-foreground: hsl(240 4.8% 95.9%);
--sidebar-border: hsl(240 3.7% 15.9%);
--sidebar-ring: hsl(217.2 91.2% 59.8%);
}
@theme inline {
/* Radius (for rounded-*) */
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
/* Colors */
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-ring: var(--ring);
--color-radius: var(--radius);
--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);
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
```
#### Verify the update
Restart your dev server and verify that all your styles are working as expected.
#### Remove the `tailwind.config` file
Once you've verified that your styles are working as expected, you can remove the `tailwind.config.ts` file.
### 3. Use new `size-*` utility
The new `size-*` utility (added in Tailwind v3.4), is now fully supported by `tailwind-merge`. You can replace `w-* h-*` with the new `size-*` utility:
```diff
- w-4 h-4
+ size-4
```
### 4. Update your dependencies
### 5. Update your utils (optional)
If you're planning on adding additional components in the future or plan to update your existing components to the latest versions, you'll need to update your `utils.ts` file.
Previously, we were depending on `bits-ui` for some simple type helpers that required you to have `bits-ui` installed, regardless if you were using components that depend on it.
These helpers have been moved into the `utils.ts` file:
```diff title="utils.ts"
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ export type WithoutChild = T extends { child?: any } ? Omit : T;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ export type WithoutChildren = T extends { children?: any } ? Omit : T;
+ export type WithoutChildrenOrChild = WithoutChildren>;
+ export type WithElementRef = T & { ref?: U | null };
```
And then you can incrementally replace these imports in your existing components:
```diff title="card.svelte"
```
### 6. Update Your Colors (optional)
The dark mode colors have been revisited and updated to be more accessible, as you can see in these docs as well as the [v4.shadcn-svelte.com](https://v4.shadcn-svelte.com) demo site.
You can update your components to use the new dark mode colors by re-adding your components using the CLI[^1].
Commit any changes
**The CLI will overwrite your existing components.** It's recommended to commit the changes you've made to your components before running the CLI.
```bash
git add .
git commit -m '..."
```
Update components
Update colors
Update the dark mode colors in your `app.css` file to the new OKLCH values. See the [Base Colors](/docs/theming#base-colors) reference for a list of colors.
Review Changes
Review and re-apply any changes you've made to your components using the git diffs.
[^1]: Updating your components will overwrite your existing components.
================================================
FILE: docs/content/registry/examples.md
================================================
---
title: Examples
description: "Examples of registry items: styles, components, css vars, etc."
---
## registry:style
### Custom style that extends shadcn-svelte
The following registry item is a custom style that extends shadcn/ui. On `npx shadcn-svelte@latest init`, it will:
- Install `phosphor-svelte` icons as a dependency.
- Add the `login-01` block and `calendar` component to the project.
- Add the `editor` from a remote registry.
- Set the `font-sans` variable to `Inter, sans-serif`.
- Install a `brand` color in light and dark mode.
```json title="example-style.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "example-style",
"type": "registry:style",
"dependencies": ["phosphor-svelte"],
"registryDependencies": [
"login-01",
"calendar",
"https://example.com/r/editor.json"
],
"cssVars": {
"theme": {
"font-sans": "Inter, sans-serif"
},
"light": {
"brand": "oklch(0.145 0 0)"
},
"dark": {
"brand": "oklch(0.145 0 0)"
}
}
}
```
### Custom style from scratch
The following registry item is a custom style that _doesn't_ extend shadcn-svelte. See the `extends: none` field.
It can be used to create a new style from scratch i.e. custom components, css vars, dependencies, etc.
On `npx shadcn-svelte@latest add`, the following will:
- Install `tailwind-merge` and `clsx` as dependencies.
- Add the `utils` registry item from the shadcn-svelte registry.
- Add the `button`, `input`, `label`, and `select` components from a remote registry.
- Install new css vars: `main`, `bg`, `border`, `text`, `ring`.
```json title="example-style.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"extends": "none",
"name": "new-style",
"type": "registry:style",
"dependencies": ["tailwind-merge", "clsx"],
"registryDependencies": [
"utils",
"https://example.com/r/button.json",
"https://example.com/r/input.json",
"https://example.com/r/label.json",
"https://example.com/r/select.json"
],
"cssVars": {
"theme": {
"font-sans": "Inter, sans-serif",
}
"light": {
"main": "#88aaee",
"bg": "#dfe5f2",
"border": "#000",
"text": "#000",
"ring": "#000",
},
"dark": {
"main": "#88aaee",
"bg": "#272933",
"border": "#000",
"text": "#e6e6e6",
"ring": "#fff",
}
}
}
```
## registry:theme
### Custom theme
```json title="example-theme.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-theme",
"type": "registry:theme",
"cssVars": {
"light": {
"background": "oklch(1 0 0)",
"foreground": "oklch(0.141 0.005 285.823)",
"primary": "oklch(0.546 0.245 262.881)",
"primary-foreground": "oklch(0.97 0.014 254.604)",
"ring": "oklch(0.746 0.16 232.661)",
"sidebar-primary": "oklch(0.546 0.245 262.881)",
"sidebar-primary-foreground": "oklch(0.97 0.014 254.604)",
"sidebar-ring": "oklch(0.746 0.16 232.661)"
},
"dark": {
"background": "oklch(1 0 0)",
"foreground": "oklch(0.141 0.005 285.823)",
"primary": "oklch(0.707 0.165 254.624)",
"primary-foreground": "oklch(0.97 0.014 254.604)",
"ring": "oklch(0.707 0.165 254.624)",
"sidebar-primary": "oklch(0.707 0.165 254.624)",
"sidebar-primary-foreground": "oklch(0.97 0.014 254.604)",
"sidebar-ring": "oklch(0.707 0.165 254.624)"
}
}
}
```
### Custom colors
The following style will init using shadcn-svelte defaults and then add a custom `brand` color.
```json title="example-style.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-style",
"type": "registry:style",
"cssVars": {
"light": {
"brand": "oklch(0.99 0.00 0)"
},
"dark": {
"brand": "oklch(0.14 0.00 286)"
}
}
}
```
## registry:block
### Custom block
This blocks installs the `login-01` block from the shadcn-svelte registry.
```json title="login-01.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "login-01",
"type": "registry:block",
"description": "A simple login form.",
"registryDependencies": ["button", "card", "input", "label"],
"files": [
{
"path": "blocks/login-01/page.svelte",
"content": "import { LoginForm } ...",
"type": "registry:page",
"target": "src/routes/login/+page.svelte"
},
{
"path": "blocks/login-01/components/login-form.svelte",
"content": "...",
"type": "registry:component"
}
]
}
```
### Install a block and override primitives
You can install a block from the shadcn-svelte registry and override the primitives using your custom ones.
On `npx shadcn-svelte@latest add`, the following will:
- Add the `login-01` block from the shadcn-svelte registry.
- Override the `button`, `input`, and `label` primitives with the ones from the remote registry.
```json title="example-style.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-login",
"type": "registry:block",
"registryDependencies": [
"login-01",
"https://example.com/r/button.json",
"https://example.com/r/input.json",
"https://example.com/r/label.json"
]
}
```
## CSS Variables
### Custom Theme Variables
Add custom theme variables to the `theme` object.
```json title="example-theme.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-theme",
"type": "registry:theme",
"cssVars": {
"theme": {
"font-heading": "Inter, sans-serif",
"shadow-card": "0 0 0 1px rgba(0, 0, 0, 0.1)"
}
}
}
```
### Override Tailwind CSS variables
```json title="example-theme.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-theme",
"type": "registry:theme",
"cssVars": {
"theme": {
"spacing": "0.2rem",
"breakpoint-sm": "640px",
"breakpoint-md": "768px",
"breakpoint-lg": "1024px",
"breakpoint-xl": "1280px",
"breakpoint-2xl": "1536px"
}
}
}
```
## Add custom CSS
### Base styles
```json title="example-base.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-style",
"type": "registry:style",
"css": {
"@layer base": {
"h1": {
"font-size": "var(--text-2xl)"
},
"h2": {
"font-size": "var(--text-xl)"
}
}
}
}
```
### Components
```json title="example-card.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-card",
"type": "registry:component",
"css": {
"@layer components": {
"card": {
"background-color": "var(--color-white)",
"border-radius": "var(--rounded-lg)",
"padding": "var(--spacing-6)",
"box-shadow": "var(--shadow-xl)"
}
}
}
}
```
## Add custom utilities
### Simple utility
```json title="example-component.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-component",
"type": "registry:component",
"css": {
"@utility content-auto": {
"content-visibility": "auto"
}
}
}
```
### Complex utility
```json title="example-utility.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-component",
"type": "registry:component",
"css": {
"@utility scrollbar-hidden": {
"scrollbar-hidden": {
"&::-webkit-scrollbar": {
"display": "none"
}
}
}
}
}
```
### Functional utilities
```json title="example-functional.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-component",
"type": "registry:component",
"css": {
"@utility tab-*": {
"tab-size": "var(--tab-size-*)"
}
}
}
```
## Add custom animations
Note: you need to define both `@keyframes` in css and `theme` in cssVars to use animations.
```json title="example-component.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "custom-component",
"type": "registry:component",
"cssVars": {
"theme": {
"--animate-wiggle": "wiggle 1s ease-in-out infinite"
}
},
"css": {
"@keyframes wiggle": {
"0%, 100%": {
"transform": "rotate(-3deg)"
},
"50%": {
"transform": "rotate(3deg)"
}
}
}
}
```
================================================
FILE: docs/content/registry/faq.md
================================================
---
title: FAQ
description: Frequently asked questions about running a registry.
---
## Frequently asked questions
### What does a complex component look like?
Here's an example of a complex component that installs a page, two components, a hook, a format-date utils and a config file.
```json showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A complex hello world component",
"files": [
{
"path": "registry/hello-world/page.svelte",
"type": "registry:page",
"target": "src/routes/hello/+page.svelte"
},
{
"path": "registry/hello-world/components/hello-world.svelte",
"type": "registry:component"
},
{
"path": "registry/hello-world/components/formatted-message.svelte",
"type": "registry:component"
},
{
"path": "registry/hello-world/hooks/use-hello.svelte.ts",
"type": "registry:hook"
},
{
"path": "registry/hello-world/lib/format-date.ts",
"type": "registry:utils"
},
{
"path": "registry/hello-world/hello.config.ts",
"type": "registry:file",
"target": "hello.config.ts"
}
]
}
```
### How do I add a new Tailwind color?
To add a new color you need to add it to `cssVars` under `light` and `dark` keys.
```json showLineNumbers {10-18}
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A complex hello world component",
"files": [
// ...
],
"cssVars": {
"light": {
"brand-background": "20 14.3% 4.1%",
"brand-accent": "20 14.3% 4.1%"
},
"dark": {
"brand-background": "20 14.3% 4.1%",
"brand-accent": "20 14.3% 4.1%"
}
}
}
```
The CLI will update the project CSS file. Once updated, the new colors will be available to be used as utility classes: `bg-brand` and `text-brand-accent`.
### How do I add or override a Tailwind theme variable?
To add or override a theme variable you add it to `cssVars.theme` under the key you want to add or override.
```json showLineNumbers {10-15}
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A complex hello world component",
"files": [
// ...
],
"cssVars": {
"theme": {
"text-base": "3rem",
"ease-in-out": "cubic-bezier(0.4, 0, 0.2, 1)",
"font-heading": "Poppins, sans-serif"
}
}
}
```
================================================
FILE: docs/content/registry/getting-started.md
================================================
---
title: Getting Started
description: Learn how to get setup and run your own component registry.
---
This guide will walk you through the process of setting up your own component registry.
It assumes you already have a project with components and would like to turn it into a registry.
If you're starting a new registry project, you can use the [registry template](https://github.com/huntabyte/shadcn-svelte/tree/main/registry-template) as a starting point. It's already configured for you.
## registry.json
The `registry.json` file is only required if you're using the `shadcn-svelte` CLI to build your registry.
If you're using a different build system, you can skip this step as long as your build system produces valid JSON files that conform to the [registry-item schema specification](/docs/registry/registry-item-json).
### Add a registry.json file
Create a `registry.json` file in the root of your project.
```json title="registry.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"items": [
// ...
]
}
```
This `registry.json` file must conform to the [registry schema specification](/docs/registry/registry-json).
## Add a registry item
### Create your component
Add your first component. Here's an example of a simple ` ` component:
```svelte title="registry/hello-world/hello-world.svelte" showLineNumbers
Hello World
```
**Note:** This example places the component in the `registry/`
directory. You can place it anywhere in your project as long as you set the
correct path in the `registry.json` file and you follow the `registry/[NAME]`
directory structure.
```txt
registry
└── hello-world
└── hello-world.svelte
```
**Important:** If you're placing your component in a custom directory, make sure it can be detected by Tailwind CSS.
```css showLineNumbers title="src/routes/layout.css"
@source "./registry/@acmecorp/ui-lib";
```
### Add your component to the registry
To add your component to the registry, you need to add your component definition to `registry.json`.
```json title="registry.json" showLineNumbers {6-17}
{
"$schema": "https://shadcn-svelte.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "./src/lib/hello-world/hello-world.svelte",
"type": "registry:component"
}
]
}
]
}
```
You define your registry item by adding a `name`, `type`, `title`, `description` and `files`.
For every file you add, you must specify the `path` and `type` of the file. The `path` is the relative path to the file from the root of your project. The `type` is the type of the file.
You can read more about the registry item schema and file types in the [registry item schema docs](/docs/registry/registry-item-json).
## Build your registry
### Install the shadcn-svelte CLI
### Add a build script
Add a `registry:build` script to your `package.json` file.
```json title="package.json" showLineNumbers
{
"scripts": {
"registry:build": "pnpm shadcn-svelte registry build"
}
}
```
### Run the build script
Run the build script to generate the registry JSON files.
**Note:** By default, the build script will generate the registry JSON files in `static/r` e.g `static/r/hello-world.json`.
You can change the output directory by passing the `--output` option. See the [shadcn-svelte registry build command](/docs/cli#registry-build) for more information.
## Serve your registry
You can serve your registry by running the dev server.
Your files will now be served at `http://localhost:5173/r/[NAME].json` eg. `http://localhost:5173/r/hello-world.json`.
## Publish your registry
To make your registry available to other developers, you can publish it by deploying your project to a public URL.
## Adding Auth
The `shadcn-svelte` CLI does not offer a built-in way to add auth to your registry. We recommend handling authorization on your registry server.
A common simple approach is to use a `token` query parameter to authenticate requests to your registry. e.g. `http://localhost:5173/r/hello-world.json?token=[SECURE_TOKEN_HERE]`.
Use the secure token to authenticate requests and return a 401 Unauthorized response if the token is invalid. The `shadcn-svelte` CLI will handle the 401 response and display a message to the user.
**Note:** Make sure to encrypt and expire tokens.
## Guidelines
Here are some guidelines to follow when building components for a registry.
- The following properties are required for the block definition: `name`, `description`, `type` and `files`.
- Make sure to list all registry dependencies in `registryDependencies`. A registry dependency is the name of the component in the registry eg. `input`, `button`, `card`, etc or a URL to a registry item eg. `http://localhost:5173/r/editor.json`
- Ideally, place your files within a registry item in `components`, `hooks`, `lib` directories.
## Install using the CLI
To install a registry item using the `shadcn-svelte` CLI, use the `add` command followed by the URL of the registry item.
================================================
FILE: docs/content/registry/index.md
================================================
---
title: Registry
description: Run your own component registry.
---
**Note:** This feature is currently experimental. Help us improve it by
testing it out and sending feedback. If you have any questions, please [reach
out to us](https://github.com/huntabyte/shadcn-svelte/discussions).
You can use the `shadcn-svelte` CLI to create your own component registry. Creating your own registry allows you to distribute your own custom components, hooks, pages, and other files to any Svelte project.
Registry items are automatically compatible with the `shadcn-svelte` CLI.
## Requirements
You are free to design and host your custom registry as you see fit. The only requirement is that your registry items must be valid JSON files that conform to the [registry-item schema specification](/docs/registry/registry-item-json).
If you'd like to see an example of a registry, we have a [template project](https://github.com/huntabyte/shadcn-svelte/tree/main/registry-template) for you to use as a starting point.
You can clone it using `degit`
================================================
FILE: docs/content/registry/registry-item-json.md
================================================
---
title: registry-item.json
description: Specification for registry items.
---
The `registry-item.json` schema is used to define your custom registry items.
```json title="registry-item.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/hello-world/hello-world.svelte",
"type": "registry:component"
},
{
"path": "registry/hello-world/use-hello-world.svelte.ts",
"type": "registry:hook"
}
],
"cssVars": {
"theme": {
"font-heading": "Poppins, sans-serif"
},
"light": {
"brand": "20 14.3% 4.1%"
},
"dark": {
"brand": "20 14.3% 4.1%"
}
}
}
```
[See more examples](/docs/registry/examples)
## Definitions
You can see the JSON Schema for `registry-item.json` [here](/schema/registry-item.json).
### $schema
The `$schema` property is used to specify the schema for the `registry-item.json` file.
```json title="registry-item.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry-item.json"
}
```
### name
The name of the item. This is used to identify the item in the registry. It should be unique for your registry.
```json title="registry-item.json" showLineNumbers
{
"name": "hello-world"
}
```
### title
A human-readable title for your registry item. Keep it short and descriptive.
```json title="registry-item.json" showLineNumbers
{
"title": "Hello World"
}
```
### description
A description of your registry item. This can be longer and more detailed than the `title`.
```json title="registry-item.json" showLineNumbers
{
"description": "A simple hello world component."
}
```
### type
The `type` property is used to specify the type of your registry item. This is used to determine the type and target path of the item when resolved for a project.
```json title="registry-item.json" showLineNumbers
{
"type": "registry:block"
}
```
The following types are supported:
| Type | Description |
| -------------------- | ------------------------------------------------ |
| `registry:block` | Use for complex components with multiple files. |
| `registry:component` | Use for simple components. |
| `registry:lib` | Use for lib and utils. |
| `registry:hook` | Use for hooks. |
| `registry:ui` | Use for UI components and single-file primitives |
| `registry:page` | Use for page or file-based routes. |
| `registry:file` | Use for miscellaneous files. |
| `registry:style` | Use for registry styles. eg. `new-york` |
| `registry:theme` | Use for themes. |
### author
The `author` property is used to specify the author of the registry item.
It can be unique to the registry item or the same as the author of the registry.
```json title="registry-item.json" showLineNumbers
{
"author": "John Doe "
}
```
### dependencies
The `dependencies` property is used to specify the dependencies of your registry item. This is for `npm` packages.
Use `@version` to specify the version of your registry item.
```json title="registry-item.json" showLineNumbers
{
"dependencies": ["bits-ui", "zod", "@lucide/svelte", "name@1.0.2"]
}
```
### registryDependencies
Defines other registry items that this item depends on.
Each entry may be one of the following:
#### shadcn-svelte Registry Item
The name of a shadcn-svelte registry item (e.g., `'button'`, `'input'`, `'select'`), which will resolve to that item in the shadcn-svelte registry.
```json title="registry-item.json" showLineNumbers
{
"registryDependencies": ["button", "input", "select"]
}
```
#### Remote URL
A full URL to a custom registry item (e.g. `https://example.com/r/hello-world.json`)
```json title="registry-item.json" showLineNumbers
{
"registryDependencies": ["https://example.com/r/hello-world.json"]
}
```
#### Local alias (when building with the CLI)
If you're defining the item in `registry.json` and using the CLI to build the registry, you can use a name prefixed with `local:` (e.g. `local:stepper`) to reference an item in the current registry. The CLI will convert this to a relative path (e.g. `./stepper.json`) in the output `registry-item.json` file.
```json title="registry.json" showLineNumbers
{
"items": [
{
"name": "hello-world",
"registryDependencies": ["local:stepper"]
}
]
}
```
Which the CLI will convert to the following in the output `registry-item.json` file:
```json title="registry-item.json" showLineNumbers
{
"registryDependencies": ["./stepper.json"]
}
```
#### Relative Path
If you're not using the CLI and defining the item directly in its `registry-item.json` file, you can specify a relative path, which is relative to the current item, to reference another item in the registry (e.g. `./stepper.json`).
```json title="registry-item.json" showLineNumbers
{
"registryDependencies": ["./stepper.json"]
}
```
### files
The `files` property is used to specify the files of your registry item. Each file has a `path`, `type` and `target` (optional) property.
**The `target` property is required for `registry:page` and `registry:file` types.**
```json title="registry-item.json" showLineNumbers
{
"files": [
{
"path": "registry/hello-world/page.svelte",
"type": "registry:page",
"target": "src/routes/hello/+page.svelte"
},
{
"path": "registry/hello-world/hello-world.svelte",
"type": "registry:component"
},
{
"path": "registry/hello-world/use-hello-world.svelte.ts",
"type": "registry:hook"
},
{
"path": "registry/hello-world/.env",
"type": "registry:file",
"target": ".env"
}
]
}
```
#### path
The `path` property is used to specify the path to the file in your registry. This path is used by the build script to parse, transform and build the registry JSON payload.
#### type
The `type` property is used to specify the type of the file. See the [type](#type) section for more information.
#### target
The `target` property is used to indicate where the file should be placed in a project. This is optional and only required for `registry:page` and `registry:file` types.
By default, the `shadcn-svelte` cli will read a project's `components.json` file to determine the target path. For some files, such as routes or config you can specify the target path manually.
Use `~` to refer to the root of the project e.g `~/foo.config.js`.
### cssVars
Use to define CSS variables for your registry item.
```json title="registry-item.json" showLineNumbers
{
"cssVars": {
"theme": {
"font-heading": "Poppins, sans-serif"
},
"light": {
"brand": "20 14.3% 4.1%",
"radius": "0.5rem"
},
"dark": {
"brand": "20 14.3% 4.1%"
}
}
}
```
### css
Use `css` to add new rules to the project's CSS file eg. `@layer base`, `@layer components`, `@utility`, `@keyframes`, etc.
```json title="registry-item.json" showLineNumbers
{
"css": {
"@layer base": {
"body": {
"font-size": "var(--text-base)",
"line-height": "1.5"
}
},
"@layer components": {
"button": {
"background-color": "var(--color-primary)",
"color": "var(--color-white)"
}
},
"@utility text-magic": {
"font-size": "var(--text-base)",
"line-height": "1.5"
},
"@keyframes wiggle": {
"0%, 100%": {
"transform": "rotate(-3deg)"
},
"50%": {
"transform": "rotate(3deg)"
}
}
}
}
```
### docs
Use `docs` to show custom documentation or message when installing your registry item via the CLI.
```json title="registry-item.json" showLineNumbers
{
"docs": "Remember to add the FOO_BAR environment variable to your .env file."
}
```
### categories
Use `categories` to organize your registry item.
```json title="registry-item.json" showLineNumbers
{
"categories": ["sidebar", "dashboard"]
}
```
### meta
Use `meta` to add additional metadata to your registry item. You can add any key/value pair that you want to be available to the registry item.
```json title="registry-item.json" showLineNumbers
{
"meta": { "foo": "bar" }
}
```
================================================
FILE: docs/content/registry/registry-json.md
================================================
---
title: registry.json
description: Schema for running your own component registry.
---
The `registry.json` schema is used to define your custom component registry.
```json title="registry.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry.json",
"name": "shadcn-svelte",
"homepage": "https://shadcn-svelte.com",
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "src/lib/registry/blocks/hello-world/hello-world.svelte",
"type": "registry:component"
}
]
}
]
}
```
## Definitions
You can see the JSON Schema for `registry.json` [here](/schema/registry.json).
### $schema
The `$schema` property is used to specify the schema for the `registry.json` file.
```json title="registry.json" showLineNumbers
{
"$schema": "https://shadcn-svelte.com/schema/registry.json"
}
```
### name
The `name` property is used to specify the name of your registry. This is used for data attributes and other metadata.
```json title="registry.json" showLineNumbers
{
"name": "acme"
}
```
### homepage
The homepage of your registry. This is used for data attributes and other metadata.
```json title="registry.json" showLineNumbers
{
"homepage": "https://acme.com"
}
```
### items
The `items` in your registry. Each item must implement the [registry-item schema specification](/schema/registry-item.json).
```json title="registry.json" showLineNumbers
{
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "src/lib/registry/blocks/hello-world/hello-world.svelte",
"type": "registry:component"
}
]
}
]
}
```
See the [registry-item schema documentation](/docs/registry/registry-item-json) for more information.
### aliases
`aliases` define how your registry's internal import paths will be transformed when users install your components. These should match how you import components within your registry code.
For example, if your registry's component has:
```svelte
```
Then your `registry.json` should have matching aliases:
```json title="registry.json" showLineNumbers
{
"aliases": {
"lib": "@/lib", // Matches your internal imports
"ui": "@/lib/registry/ui", // Matches your internal imports
"components": "@/lib/registry/components", // Matches your internal imports
"utils": "@/lib/utils", // Matches your internal imports
"hooks": "@/lib/hooks" // Matches your internal imports
}
}
```
When users install your component, these paths will be transformed according to their `components.json` configuration. The aliases you define here are the "source" paths that will be replaced.
Default aliases (if you don't specify any):
```json title="registry.json" showLineNumbers
{
"aliases": {
"lib": "$lib/registry/lib", // For internal library code
"ui": "$lib/registry/ui", // For UI components
"components": "$lib/registry/components", // For component-specific code
"utils": "$lib/utils", // For utility functions
"hooks": "$lib/registry/hooks" // For reactive state and logic (.svelte.js|ts)
}
}
```
### overrideDependencies
`overrideDependencies` lets you force specific version ranges for dependencies, overriding what `shadcn-svelte registry build` detects in your `package.json`.
Common use cases:
- Using latest pre-release versions: `"overrideDependencies": ["paneforge@next"]`
- Pinning to specific versions: `"overrideDependencies": ["dep@1.5.0"]`
**Warning**: Overriding dependencies can lead to version conflicts if not carefully managed. This option should be used sparingly.
Example transformation:
```json
// Your registry's package.json
{
"dependencies": {
"paneforge": "1.0.0-next.1"
}
}
```
When the user installs your component, the latest `@next` version will be used instead of `1.0.0-next.1`
```json
{
"dependencies": {
"paneforge": "1.0.0-next.1", // overrideDependencies: []
"paneforge": "1.0.0-next.5" // overrideDependencies: ["paneforge@next"]
}
}
```
================================================
FILE: docs/content/theming.md
================================================
---
title: Theming
description: Use CSS Variables to customize the look and feel of your application.
---
We use CSS variables for styling. This allows you to easily change the colors of components without having to update class names.
## Convention
We use a simple `background` and `foreground` convention for colors. The `background` variable is used for the background color of the component and the `foreground` variable is used for the text color.
The `background` suffix is omitted when the variable is used for the background color of the component.
Given the following CSS variables:
```css
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
```
The `background` color of the following component will be `var(--primary)` and the `foreground` color will be `var(--primary-foreground)`.
```svelte
Hello
```
## List of variables
Here's the list of variables available for customization:
```css title="src/routes/layout.css" showLineNumbers
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.269 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.371 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.439 0 0);
}
```
## Adding new colors
To add new colors, you need to add them to your CSS file.
```css title="src/routes/layout.css" showLineNumbers
:root {
--warning: oklch(0.84 0.16 84);
--warning-foreground: oklch(0.28 0.07 46);
}
.dark {
--warning: oklch(0.41 0.11 46);
--warning-foreground: oklch(0.99 0.02 95);
}
@theme inline {
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
}
```
You can now use the `warning` utility class in your components.
```svelte /bg-warning/ /text-warning-foreground/
```
## Other color formats
See the [Tailwind CSS documentation](https://tailwindcss.com/docs/colors) for more information on using colors in Tailwind CSS.
## Base Colors
For reference, here's a list of the base colors that are available.
### Neutral
```css title="src/routes/layout.css" showLineNumbers
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
}
```
### Stone
```css title="src/routes/layout.css" showLineNumbers
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.147 0.004 49.25);
--card: oklch(1 0 0);
--card-foreground: oklch(0.147 0.004 49.25);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.147 0.004 49.25);
--primary: oklch(0.216 0.006 56.043);
--primary-foreground: oklch(0.985 0.001 106.423);
--secondary: oklch(0.97 0.001 106.424);
--secondary-foreground: oklch(0.216 0.006 56.043);
--muted: oklch(0.97 0.001 106.424);
--muted-foreground: oklch(0.553 0.013 58.071);
--accent: oklch(0.97 0.001 106.424);
--accent-foreground: oklch(0.216 0.006 56.043);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.923 0.003 48.717);
--input: oklch(0.923 0.003 48.717);
--ring: oklch(0.709 0.01 56.259);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0.001 106.423);
--sidebar-foreground: oklch(0.147 0.004 49.25);
--sidebar-primary: oklch(0.216 0.006 56.043);
--sidebar-primary-foreground: oklch(0.985 0.001 106.423);
--sidebar-accent: oklch(0.97 0.001 106.424);
--sidebar-accent-foreground: oklch(0.216 0.006 56.043);
--sidebar-border: oklch(0.923 0.003 48.717);
--sidebar-ring: oklch(0.709 0.01 56.259);
}
.dark {
--background: oklch(0.147 0.004 49.25);
--foreground: oklch(0.985 0.001 106.423);
--card: oklch(0.216 0.006 56.043);
--card-foreground: oklch(0.985 0.001 106.423);
--popover: oklch(0.216 0.006 56.043);
--popover-foreground: oklch(0.985 0.001 106.423);
--primary: oklch(0.923 0.003 48.717);
--primary-foreground: oklch(0.216 0.006 56.043);
--secondary: oklch(0.268 0.007 34.298);
--secondary-foreground: oklch(0.985 0.001 106.423);
--muted: oklch(0.268 0.007 34.298);
--muted-foreground: oklch(0.709 0.01 56.259);
--accent: oklch(0.268 0.007 34.298);
--accent-foreground: oklch(0.985 0.001 106.423);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.553 0.013 58.071);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.216 0.006 56.043);
--sidebar-foreground: oklch(0.985 0.001 106.423);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0.001 106.423);
--sidebar-accent: oklch(0.268 0.007 34.298);
--sidebar-accent-foreground: oklch(0.985 0.001 106.423);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.553 0.013 58.071);
}
```
### Zinc
```css title="src/routes/layout.css" showLineNumbers
:root {
--radius: 0.625rem;
--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);
--border: oklch(0.92 0.004 286.32);
--input: oklch(0.92 0.004 286.32);
--ring: oklch(0.705 0.015 286.067);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.141 0.005 285.823);
--sidebar-primary: oklch(0.21 0.006 285.885);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.967 0.001 286.375);
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.705 0.015 286.067);
}
.dark {
--background: oklch(0.141 0.005 285.823);
--foreground: oklch(0.985 0 0);
--card: oklch(0.21 0.006 285.885);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.21 0.006 285.885);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.92 0.004 286.32);
--primary-foreground: oklch(0.21 0.006 285.885);
--secondary: oklch(0.274 0.006 286.033);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.274 0.006 286.033);
--muted-foreground: oklch(0.705 0.015 286.067);
--accent: oklch(0.274 0.006 286.033);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.552 0.016 285.938);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.21 0.006 285.885);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.274 0.006 286.033);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.552 0.016 285.938);
}
```
### Gray
```css title="src/routes/layout.css" showLineNumbers
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.13 0.028 261.692);
--card: oklch(1 0 0);
--card-foreground: oklch(0.13 0.028 261.692);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.13 0.028 261.692);
--primary: oklch(0.21 0.034 264.665);
--primary-foreground: oklch(0.985 0.002 247.839);
--secondary: oklch(0.967 0.003 264.542);
--secondary-foreground: oklch(0.21 0.034 264.665);
--muted: oklch(0.967 0.003 264.542);
--muted-foreground: oklch(0.551 0.027 264.364);
--accent: oklch(0.967 0.003 264.542);
--accent-foreground: oklch(0.21 0.034 264.665);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.928 0.006 264.531);
--input: oklch(0.928 0.006 264.531);
--ring: oklch(0.707 0.022 261.325);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0.002 247.839);
--sidebar-foreground: oklch(0.13 0.028 261.692);
--sidebar-primary: oklch(0.21 0.034 264.665);
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
--sidebar-accent: oklch(0.967 0.003 264.542);
--sidebar-accent-foreground: oklch(0.21 0.034 264.665);
--sidebar-border: oklch(0.928 0.006 264.531);
--sidebar-ring: oklch(0.707 0.022 261.325);
}
.dark {
--background: oklch(0.13 0.028 261.692);
--foreground: oklch(0.985 0.002 247.839);
--card: oklch(0.21 0.034 264.665);
--card-foreground: oklch(0.985 0.002 247.839);
--popover: oklch(0.21 0.034 264.665);
--popover-foreground: oklch(0.985 0.002 247.839);
--primary: oklch(0.928 0.006 264.531);
--primary-foreground: oklch(0.21 0.034 264.665);
--secondary: oklch(0.278 0.033 256.848);
--secondary-foreground: oklch(0.985 0.002 247.839);
--muted: oklch(0.278 0.033 256.848);
--muted-foreground: oklch(0.707 0.022 261.325);
--accent: oklch(0.278 0.033 256.848);
--accent-foreground: oklch(0.985 0.002 247.839);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.551 0.027 264.364);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.21 0.034 264.665);
--sidebar-foreground: oklch(0.985 0.002 247.839);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
--sidebar-accent: oklch(0.278 0.033 256.848);
--sidebar-accent-foreground: oklch(0.985 0.002 247.839);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.551 0.027 264.364);
}
```
### Slate
```css title="src/routes/layout.css" showLineNumbers
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.129 0.042 264.695);
--card: oklch(1 0 0);
--card-foreground: oklch(0.129 0.042 264.695);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.129 0.042 264.695);
--primary: oklch(0.208 0.042 265.755);
--primary-foreground: oklch(0.984 0.003 247.858);
--secondary: oklch(0.968 0.007 247.896);
--secondary-foreground: oklch(0.208 0.042 265.755);
--muted: oklch(0.968 0.007 247.896);
--muted-foreground: oklch(0.554 0.046 257.417);
--accent: oklch(0.968 0.007 247.896);
--accent-foreground: oklch(0.208 0.042 265.755);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.929 0.013 255.508);
--input: oklch(0.929 0.013 255.508);
--ring: oklch(0.704 0.04 256.788);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.984 0.003 247.858);
--sidebar-foreground: oklch(0.129 0.042 264.695);
--sidebar-primary: oklch(0.208 0.042 265.755);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.968 0.007 247.896);
--sidebar-accent-foreground: oklch(0.208 0.042 265.755);
--sidebar-border: oklch(0.929 0.013 255.508);
--sidebar-ring: oklch(0.704 0.04 256.788);
}
.dark {
--background: oklch(0.129 0.042 264.695);
--foreground: oklch(0.984 0.003 247.858);
--card: oklch(0.208 0.042 265.755);
--card-foreground: oklch(0.984 0.003 247.858);
--popover: oklch(0.208 0.042 265.755);
--popover-foreground: oklch(0.984 0.003 247.858);
--primary: oklch(0.929 0.013 255.508);
--primary-foreground: oklch(0.208 0.042 265.755);
--secondary: oklch(0.279 0.041 260.031);
--secondary-foreground: oklch(0.984 0.003 247.858);
--muted: oklch(0.279 0.041 260.031);
--muted-foreground: oklch(0.704 0.04 256.788);
--accent: oklch(0.279 0.041 260.031);
--accent-foreground: oklch(0.984 0.003 247.858);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.551 0.027 264.364);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.208 0.042 265.755);
--sidebar-foreground: oklch(0.984 0.003 247.858);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.279 0.041 260.031);
--sidebar-accent-foreground: oklch(0.984 0.003 247.858);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.551 0.027 264.364);
}
```
================================================
FILE: docs/mdsx.config.js
================================================
// @ts-check
import { readFileSync } from "node:fs";
import process from "node:process";
import { join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import prettier from "@prettier/sync";
import rehypePrettyCode from "rehype-pretty-code";
import rehypeSlug from "rehype-slug";
import { codeImport } from "remark-code-import";
import remarkGfm from "remark-gfm";
import { visit } from "unist-util-visit";
import { u } from "unist-builder";
import { createHighlighterCore } from "shiki/core";
import { createJavaScriptRegexEngine } from "shiki/engine/javascript";
import { defineConfig } from "mdsx";
import { Index } from "./src/__registry__/index.js";
/** @type {import('prettier').Config} */
const codeBlockPrettierConfig = {
useTabs: false,
tabWidth: 2,
singleQuote: false,
trailingComma: "none",
printWidth: 80,
endOfLine: "lf",
parser: "svelte",
plugins: ["prettier-plugin-svelte"],
overrides: [
{
files: "*.svelte",
options: {
parser: "svelte",
},
},
],
bracketSameLine: false,
};
const __dirname = fileURLToPath(new URL(".", import.meta.url));
const jsEngine = createJavaScriptRegexEngine();
export async function createHighlighter() {
if (!globalThis.__shikiHighlighter) {
globalThis.__shikiHighlighter = await createHighlighterCore({
themes: [
import("@shikijs/themes/github-dark"),
import("@shikijs/themes/github-light-default"),
],
langs: [
import("@shikijs/langs/typescript"),
import("@shikijs/langs/svelte"),
import("@shikijs/langs/css"),
import("@shikijs/langs/json"),
import("@shikijs/langs/bash"),
import("@shikijs/langs/astro"),
import("@shikijs/langs/diff"),
],
engine: jsEngine,
});
}
return globalThis.__shikiHighlighter;
}
/**
* @typedef {import('mdast').Root} MdastRoot
* @typedef {import('hast').Root} HastRoot
* @typedef {import('unified').Transformer} HastTransformer
* @typedef {import('unified').Transformer} MdastTransformer
*/
/**
* @type {import('rehype-pretty-code').Options}
*/
const prettyCodeOptions = {
theme: {
dark: "github-dark",
light: "github-light-default",
},
keepBackground: false,
// @ts-expect-error - shh
getHighlighter: createHighlighter,
onVisitLine(node) {
// Prevent lines from collapsing in `display: grid` mode, and allow empty
// lines to be copy/pasted
if (node.children.length === 0) {
node.children = [{ type: "text", value: " " }];
}
},
onVisitHighlightedLine(node) {
node.properties.className = ["line--highlighted"];
},
onVisitHighlightedChars(node) {
node.properties.className = ["chars--highlighted"];
},
};
export const mdsxConfig = defineConfig({
extensions: [".md"],
remarkPlugins: [remarkGfm, codeImport, remarkRemovePrettierIgnore],
rehypePlugins: [
rehypeSlug,
rehypeComponentExample,
rehypePreData,
[rehypePrettyCode, prettyCodeOptions],
rehypeHandleMetadata,
],
blueprints: {
default: {
path: resolve(__dirname, "./src/lib/components/mdsx/blueprint.svelte"),
},
},
});
/**
* Removes `` and `// prettier-ignore` from code blocks
* before they are converted to HTML for syntax highlighting.
*
* We do this because sometimes we want to force a line break in code blocks, but
* prettier removes them, however, we don't want to include the ignore statement
* in the final code block.
*
* One caveat is that if you did want to include the ignore statement in the final
* code block, you'd have to do some hacky stuff like including it in the comment
* itself and checking for it in the code block, but that's not something we need
* at the moment.
*
* @returns {MdastTransformer} - Unified Transformer
*/
function remarkRemovePrettierIgnore() {
return async (tree) => {
visit(tree, "code", (node) => {
node.value = node.value
.replaceAll("\n", "")
.replaceAll("// prettier-ignore\n", "");
});
};
}
/**
* @returns {HastTransformer} - Unified Transformer
*/
function rehypePreData() {
return (tree) => {
visit(tree, (node) => {
if (node?.type === "element" && node?.tagName === "pre") {
const [codeEl] = node.children;
if (codeEl.type !== "element") return;
if (codeEl.tagName !== "code") return;
if (
codeEl.data &&
"meta" in codeEl.data &&
codeEl.data.meta &&
typeof codeEl.data.meta === "string"
) {
// Extract event from meta and pass it down the tree.
const regex = /event="([^"]*)"/;
const match = codeEl.data?.meta.match(regex);
if (match) {
// @ts-expect-error - this is fine
node.__event__ = match ? match[1] : null;
codeEl.data.meta = codeEl.data.meta.replace(regex, "");
}
}
// @ts-expect-error - this is fine
node.__rawString__ = codeEl.children?.[0].value;
// @ts-expect-error - this is fine
node.__src__ = node.properties?.__src__;
// @ts-expect-error - this is fine
node.__style__ = node.properties?.__style__;
}
});
};
}
/**
*
* @returns {HastTransformer} - Unified Transformer
*/
export function rehypeComponentExample() {
return (tree) => {
const nameRegex = /name="([^"]+)"/;
const titleRegex = /title="([^"]+)"/;
visit(tree, (node, index, parent) => {
if (
node?.type === "raw" &&
(node?.value?.startsWith("` elements that contain a ``.
* We use this to style elements within the `` differently if a ``
* is present.
*
* @returns {HastTransformer} - Unified Transformer
*/
function rehypeHandleMetadata() {
return async (tree) => {
visit(tree, (node) => {
if (node?.type === "element" && node?.tagName === "figure") {
if (!("data-rehype-pretty-code-figure" in node.properties)) {
return;
}
const preElement = node.children.at(-1);
if (preElement && "tagName" in preElement && preElement.tagName !== "pre") {
return;
}
const firstChild = node.children.at(0);
if (firstChild && "tagName" in firstChild && firstChild.tagName === "figcaption") {
node.properties["data-metadata"] = "";
const lastChild = node.children.at(-1);
if (lastChild && "properties" in lastChild) {
lastChild.properties["data-metadata"] = "";
}
}
}
});
};
}
function getComponentSourceFileContent(src = "") {
const newSrc = src.replace("../", "./");
if (!newSrc) return null;
// Read the source file.
const filePath = join(process.cwd(), newSrc);
const formattedSource = prettier.format(
readFileSync(filePath, "utf-8"),
/** @type {any} */ (codeBlockPrettierConfig)
);
return formattedSource.trim();
}
================================================
FILE: docs/package.json
================================================
{
"name": "docs",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "pnpm --reporter append-only --color \"/dev:/\"",
"dev:content": "velite dev --watch",
"dev:icons": "tsx scripts/build-icons.ts --watch",
"dev:svelte": "vite dev",
"build": "pnpm build:icons && pnpm build:content && pnpm build:llm-placeholders && pnpm build:svelte && pnpm build:llms",
"build:content": "velite && tsx scripts/velite/velite-update-json.ts",
"build:svelte": "vite build",
"build:registry": "tsx scripts/build-registry.ts build-registry",
"build:screenshots": "tsx scripts/capture-registry.ts",
"build:icons": "tsx scripts/build-icons.ts",
"build:llms": "tsx scripts/build-llms.ts",
"build:llm-placeholders": "tsx scripts/build-llm-placeholders.ts",
"pull:styles": "tsx scripts/pull-styles.ts",
"replace:velite": "tsx scripts/velite/velite-watch-output.ts",
"sync": "pnpm build:registry && pnpm build:content && svelte-kit sync",
"preview": "vite preview",
"check": "svelte-check --fail-on-warnings --tsconfig ./tsconfig.json",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20260317.1",
"@dnd-kit-svelte/svelte": "^0.1.5",
"@dnd-kit/abstract": "^0.1.21",
"@dnd-kit/collision": "^0.1.21",
"@dnd-kit/helpers": "^0.1.21",
"@fontsource-variable/dm-sans": "^5.2.8",
"@fontsource-variable/figtree": "^5.2.10",
"@fontsource-variable/geist": "^5.2.8",
"@fontsource-variable/geist-mono": "^5.2.7",
"@fontsource-variable/inter": "^5.2.8",
"@fontsource-variable/jetbrains-mono": "^5.2.8",
"@fontsource-variable/noto-sans": "^5.2.10",
"@fontsource-variable/noto-serif": "^5.2.9",
"@fontsource-variable/nunito-sans": "^5.2.7",
"@fontsource-variable/lora": "^5.2.8",
"@fontsource-variable/merriweather": "^5.2.6",
"@fontsource-variable/playfair-display": "^5.2.8",
"@fontsource-variable/roboto-slab": "^5.2.8",
"@fontsource-variable/outfit": "^5.2.8",
"@fontsource-variable/public-sans": "^5.2.7",
"@fontsource-variable/raleway": "^5.2.8",
"@fontsource-variable/roboto": "^5.2.10",
"@hugeicons/core-free-icons": "^4.0.0",
"@hugeicons/svelte": "^1.1.2",
"@internationalized/date": "^3.12.0",
"@lucide/svelte": "^0.577.0",
"@prettier/sync": "0.6.1",
"@shikijs/langs": "^3.20.0",
"@shikijs/themes": "^3.20.0",
"@sveltejs/acorn-typescript": "^1.0.9",
"@sveltejs/adapter-cloudflare": "^7.2.8",
"@sveltejs/enhanced-img": "^0.10.4",
"@sveltejs/kit": "^2.55.0",
"@sveltejs/vite-plugin-svelte": "^7.0.0",
"@tabler/icons-svelte": "^3.40.0",
"@tailwindcss/vite": "^4.2.1",
"@tanstack/table-core": "^8.21.3",
"@types/d3-scale": "^4.0.9",
"@types/d3-shape": "^3.1.8",
"@types/hast": "^3.0.4",
"@types/jsdom": "^27.0.0",
"@types/lodash.template": "^4.5.3",
"@types/mdast": "^4.0.4",
"acorn": "^8.16.0",
"bits-ui": "^2.16.3",
"chrono-node": "^2.9.0",
"clsx": "^2.1.1",
"consola": "^3.4.2",
"d3-scale": "^4.0.2",
"d3-shape": "^3.2.0",
"embla-carousel-autoplay": "^8.6.0",
"embla-carousel-svelte": "^8.6.0",
"estree-walker": "^3.0.3",
"formsnap": "^2.0.1",
"globby": "^16.0.0",
"hast-util-to-html": "^9.0.5",
"jsdom": "^27.3.0",
"layerchart": "2.0.0-next.43",
"little-date": "^1.2.1",
"magic-string": "^0.30.21",
"mdsx": "^0.0.7",
"mode-watcher": "^1.1.0",
"package-manager-detector": "^1.6.0",
"paneforge": "^1.0.2",
"phosphor-svelte": "^3.0.1",
"postcss": "^8.5.8",
"rehype-parse": "^9.0.1",
"rehype-pretty-code": "^0.14.1",
"rehype-remark": "^10.0.1",
"rehype-slug": "^6.0.0",
"remark-code-import": "^1.2.0",
"remark-gfm": "^4.0.1",
"remark-stringify": "^11.0.0",
"remixicon-svelte": "^0.0.5",
"rimraf": "^6.1.3",
"rollup-plugin-visualizer": "^6.0.5",
"runed": "^0.37.1",
"shadcn-svelte": "workspace:*",
"shiki": "^3.20.0",
"svelte": "^5.54.0",
"svelte-check": "^4.4.5",
"svelte-sonner": "^1.1.0",
"svelte-toolbelt": "^0.10.6",
"sveltekit-superforms": "^2.30.0",
"tailwind-merge": "^3.5.0",
"tailwind-variants": "^3.2.2",
"tailwindcss": "^4.2.1",
"tsx": "^4.21.0",
"tw-animate-css": "^1.4.0",
"typescript": "^5.9.3",
"unified": "^11.0.5",
"unist-builder": "^4.0.0",
"unist-util-visit": "^5.0.0",
"vaul-svelte": "1.0.0-next.7",
"velite": "^0.3.1",
"vite": "^8.0.0",
"zod": "catalog:"
},
"dependencies": {
"@types/lodash": "^4.17.24",
"lodash": "^4.17.23"
}
}
================================================
FILE: docs/scripts/build-icons.ts
================================================
#!/usr/bin/env tsx
import * as fs from "fs/promises";
import { watch } from "fs";
import * as path from "path";
import { iconLibraries, type IconLibraryName } from "shadcn-svelte/icons";
const SEARCH_BASE = "src/";
const REGISTRY_BASE = "src/lib/registry";
type IconUsage = Record>;
async function findSvelteFiles(dir: string) {
const files: string[] = [];
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
files.push(...(await findSvelteFiles(fullPath)));
} else if (entry.isFile() && entry.name.endsWith(".svelte")) {
files.push(fullPath);
}
}
return files;
}
async function scanIconUsage() {
const iconUsage = Object.fromEntries(
Object.keys(iconLibraries).map((key) => [key, new Set()])
) as IconUsage;
const searchBasesDir = path.join(process.cwd(), SEARCH_BASE);
const files = await findSvelteFiles(searchBasesDir);
for (const file of files) {
const content = await fs.readFile(file, "utf-8");
for (const [libraryName, config] of Object.entries(iconLibraries)) {
const regex = new RegExp(`${config.name}=["']([^"']+)["']`, "g");
let match;
while ((match = regex.exec(content)) !== null) {
iconUsage[libraryName as IconLibraryName].add(match[1]);
}
}
}
return iconUsage;
}
async function generateIconFiles(iconUsage: IconUsage) {
const outputDir = path.join(process.cwd(), REGISTRY_BASE, "icons");
const completedLibraries: { name: IconLibraryName; icons: string[] }[] = [];
for (const [lib, config] of Object.entries(iconLibraries)) {
const libraryName = lib as IconLibraryName;
const icons = Array.from(iconUsage[libraryName]).sort();
if (icons.length === 0) {
continue;
}
const typeName = `${config.title.replace(/\s/g, "")}IconName`;
const typeUnion = icons.map((icon) => `"${icon}"`).join(" | ");
const indexFileContent = `// Auto-generated by scripts/build-icons.ts
export type ${typeName} = ${typeUnion};
`;
const dirname = `__${libraryName}__`;
const iconDir = path.join(outputDir, dirname);
const iconOutputDir = path.join(outputDir, dirname);
const iconFiles = icons.map((icon) => {
const iconExport = iconLibraries[libraryName].export({ name: icon });
const fileName = `${icon}.ts`;
return {
name: icon,
fileName,
path: path.join(iconOutputDir, fileName),
content: `// Auto-generated by scripts/build-icons.ts\n${iconExport}\n`,
};
});
await fs.mkdir(iconDir, { recursive: true });
await fs.mkdir(outputDir, { recursive: true });
await fs.writeFile(path.join(iconOutputDir, "index.ts"), indexFileContent);
for (const iconFile of iconFiles) {
await fs.writeFile(iconFile.path, iconFile.content);
}
// clean unused icon files
const iconFileSet = new Set([
"index.ts",
...iconFiles.map((iconFile) => iconFile.fileName),
]);
for (const existingIconFile of await fs.readdir(iconOutputDir)) {
if (!iconFileSet.has(existingIconFile)) {
await fs.rm(path.join(iconOutputDir, existingIconFile));
}
}
completedLibraries.push({ name: libraryName, icons });
}
console.log("✓ Generated icon files:");
for (const library of completedLibraries) {
console.log(` - ${library.name}: ${library.icons.length} icons`);
}
}
async function main() {
const iconUsage = await scanIconUsage();
await generateIconFiles(iconUsage);
}
const isWatchMode = process.argv.includes("--watch");
if (isWatchMode) {
const SEARCH_DIR = path.join(process.cwd(), SEARCH_BASE);
await main();
watch(SEARCH_DIR, { recursive: true }, (_, filename) => {
if (!filename?.endsWith(".svelte")) return;
if (filename.includes("registry/icons/__")) return;
if (filename.includes("components/icon-placeholder")) return;
main().catch((error) => {
console.error("❌ Icons build failed:", error);
});
});
} else {
await main();
}
================================================
FILE: docs/scripts/build-llm-placeholders.ts
================================================
/**
* Creates empty markdown files so that they are loaded into the manifest for
* the cloudflare build and we can manually update them after we build so we don't
* need to build twice or try to manipulate the manifest post build.
*/
import { globby } from "globby";
import { mkdir, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
async function main() {
try {
const files = (await globby(["content/**/*.md"])).map((filePath) => {
const newPath = filePath.replace("content/", "docs/");
if (newPath.endsWith("/index.md")) return newPath.replace("/index.md", ".md");
return newPath;
});
for (const file of files) {
const outputPath = join(__dirname, "../static", file);
const outputDir = dirname(outputPath);
await mkdir(outputDir, { recursive: true });
await writeFile(outputPath, "\n", "utf-8");
}
await writeFile(join(__dirname, "../static/llms.txt"), "\n", "utf-8");
} catch (error) {
console.error("Error building LLM placeholder files:", error);
}
}
main();
================================================
FILE: docs/scripts/build-llms.ts
================================================
import { unified } from "unified";
import rehypeParse from "rehype-parse";
import rehypeRemark from "rehype-remark";
import remarkStringify from "remark-stringify";
import remarkGfm from "remark-gfm";
import { basename, dirname, join, relative } from "node:path";
import { fileURLToPath } from "node:url";
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
import { JSDOM } from "jsdom";
import consola from "consola";
import type { Plugin } from "unified";
import type { Root, Link, Node, Paragraph, Text } from "mdast";
import {
components,
installation,
gettingStarted,
migration,
darkMode,
registry,
} from "../.velite";
consola.wrapConsole();
const __dirname = dirname(fileURLToPath(import.meta.url));
/**
* Replaces relative links with complete URLs
*/
const remarkRelativeLinks: Plugin<[], Root> = () => {
return (tree: Root) => {
const visit = (node: Node) => {
if (node.type === "link" && "url" in node) {
const link = node as Link;
if (link.url.startsWith("/")) {
link.url = `https://shadcn-svelte.com${link.url}`;
}
}
if ("children" in node && Array.isArray(node.children)) {
for (const child of node.children) {
visit(child);
}
}
};
visit(tree);
};
};
/**
* Removes paragraphs that contain only the word "Copy"
*/
const remarkRemoveCopyLines: Plugin<[], Root> = () => {
return (tree: Root) => {
if ("children" in tree && Array.isArray(tree.children)) {
tree.children = tree.children.filter((node: Node) => {
if (node.type === "paragraph") {
const paragraph = node as Paragraph;
if (paragraph.children.length === 1 && paragraph.children[0].type === "text") {
const text = paragraph.children[0] as Text;
return text.value.trim() !== "Copy";
}
}
return true;
});
}
};
};
export type FileMap = Record;
export async function collectFiles(currentDir: string, baseDir: string): Promise {
try {
const entries = await readdir(currentDir, { withFileTypes: true });
const files: FileMap = {};
for (const entry of entries) {
const fullPath = join(currentDir, entry.name);
const relPath = relative(baseDir, fullPath);
if (entry.isDirectory()) {
const subFiles = await collectFiles(fullPath, baseDir);
Object.assign(files, subFiles);
} else if (entry.isFile()) {
if (fullPath.includes("figma")) continue;
const content = await readFile(fullPath, "utf-8");
files[relPath] = content;
}
}
return files;
} catch (error) {
throw new Error(
`Failed to collect files from ${currentDir}: ${error instanceof Error ? error.message : String(error)}`,
{
cause: error,
}
);
}
}
type LinkData = {
name: string;
path: string;
description?: string;
title?: string;
};
type VeliteData =
| (typeof components)[number]
| (typeof installation)[number]
| (typeof gettingStarted)[number]
| (typeof migration)[number]
| (typeof darkMode)[number]
| (typeof registry)[number];
type CategorizedLinks = {
overview: LinkData[];
installation: LinkData[];
components: {
formInput: LinkData[];
layoutNavigation: LinkData[];
overlaysDialogs: LinkData[];
feedbackStatus: LinkData[];
displayMedia: LinkData[];
misc: LinkData[];
};
darkMode: LinkData[];
migration: LinkData[];
registry: LinkData[];
other: LinkData[];
};
const REGEX_PATTERNS = {
multipleNewlines: /\n{3,}/g,
bulletSpacing: /- \n\s+/g,
multiLineBullets: /(- [^\n]*)(?:\n\s+([^\n-][^\n]*))/g,
startLineSpaces: /(\n|^)[ \t]+\n/g,
endLineSpaces: /\n[ \t]+($|\n)/g,
inlineCodeBefore: /(\S+)\s*\n\s*(`[^`]+?`)/g,
inlineCodeAfter: /(`[^`]+?`)\s*\n\s*(\S+)/g,
parenCodeStart: /\(\s*\n\s*(`[^`]+?`)/g,
parenCodeEnd: /(`[^`]+?`)\s*\n\s*\)/g,
escapedBackticks: /\\`([^`]+?)\\`/g,
codeBlockIndent: /```([a-z]*)\n\t/g,
htmlComments: //gs,
trailingLinkSpaces: /\[([^\]]+)\s+\]/g,
} as const;
async function toMarkdown(rawHtml: string) {
const dom = new JSDOM(rawHtml);
const document = dom.window.document;
const codeTags = document?.querySelectorAll("code");
if (codeTags) {
for (const code of codeTags) {
const language = code.getAttribute("data-language");
if (language) {
code.className = `${code.className || ""} language-${language}`.trim();
}
}
}
const targetElement = document.getElementById("main-content");
const elementsToRemove = Array.from(
document.querySelectorAll("[data-llm-ignore], [aria-hidden='true']")
);
for (const element of elementsToRemove) {
element.remove();
}
const html = targetElement ? targetElement.innerHTML : "";
const file = await unified()
.use(rehypeParse)
.use(rehypeRemark)
.use(remarkGfm)
.use(remarkRelativeLinks)
.use(remarkRemoveCopyLines)
.use(remarkStringify, {
bullet: "-",
listItemIndent: "one",
tightDefinitions: true,
fences: true,
})
.process(html);
const sanitizedFile = String(file)
.replace(REGEX_PATTERNS.htmlComments, "")
.replace(REGEX_PATTERNS.multipleNewlines, "\n\n")
.replace(REGEX_PATTERNS.bulletSpacing, "- ")
.replace(REGEX_PATTERNS.multiLineBullets, "$1 $2")
.replace(REGEX_PATTERNS.startLineSpaces, "$1")
.replace(REGEX_PATTERNS.endLineSpaces, "$1")
.replace(REGEX_PATTERNS.inlineCodeBefore, "$1 $2")
.replace(REGEX_PATTERNS.inlineCodeAfter, "$1 $2")
.replace(REGEX_PATTERNS.parenCodeStart, "($1")
.replace(REGEX_PATTERNS.parenCodeEnd, "$1)")
.replace(REGEX_PATTERNS.escapedBackticks, "`$1`")
.replace(REGEX_PATTERNS.codeBlockIndent, "```$1\n")
.replace(REGEX_PATTERNS.trailingLinkSpaces, "[$1]")
.replace(/\u00C2/g, "") // Â
.replace(/\u2014/g, "") // â€"
// eslint-disable-next-line no-control-regex
.replace(/[^\u0000-\u007F\u2019]/g, "") // preserve fancy apostrophe
.replaceAll("\t", " ")
.trim();
return sanitizedFile;
}
function findVeliteData(veliteData: Record, path: string): VeliteData | null {
// search through all velite data arrays for matching path
for (const dataArray of Object.values(veliteData)) {
const found = dataArray.find((item) => item.path === path);
if (found) return found;
}
return null;
}
async function createLLMsIndex(files: FileMap) {
const veliteData = {
components,
installation,
gettingStarted,
migration,
darkMode,
registry,
};
const categorizedLinks: CategorizedLinks = {
overview: [],
installation: [],
components: {
formInput: [],
layoutNavigation: [],
overlaysDialogs: [],
feedbackStatus: [],
displayMedia: [],
misc: [],
},
darkMode: [],
migration: [],
registry: [],
other: [],
};
const componentCategories = {
formInput: [
"form",
"field",
"button",
"button-group",
"input",
"input-group",
"input-otp",
"textarea",
"checkbox",
"radio-group",
"select",
"switch",
"slider",
"calendar",
"date-picker",
"combobox",
"label",
"native-select",
],
layoutNavigation: [
"accordion",
"breadcrumb",
"navigation-menu",
"sidebar",
"tabs",
"separator",
"scroll-area",
"resizable",
],
overlaysDialogs: [
"dialog",
"alert-dialog",
"sheet",
"drawer",
"popover",
"tooltip",
"hover-card",
"context-menu",
"dropdown-menu",
"menubar",
"command",
],
feedbackStatus: ["alert", "sonner", "progress", "spinner", "skeleton", "badge", "empty"],
displayMedia: [
"avatar",
"card",
"table",
"data-table",
"chart",
"carousel",
"aspect-ratio",
"typography",
"item",
"kbd",
],
misc: ["collapsible", "toggle", "toggle-group", "pagination"],
};
for (const fileName of Object.keys(files)) {
if (!fileName.endsWith(".html")) continue;
const baseName = basename(fileName, ".html");
const dirPath = dirname(fileName);
const outputName =
baseName === "index" ? (dirPath === "." ? "docs" : basename(dirPath)) : baseName;
const relativePath =
baseName === "index" ? `${outputName}.md` : join(dirPath, `${outputName}.md`);
const veliteItem =
findVeliteData(veliteData, baseName) ||
findVeliteData(veliteData, join(dirPath, baseName).replace(/\\/g, "/")) ||
findVeliteData(veliteData, dirPath.replace(/\\/g, "/") + "/" + baseName);
const linkData: LinkData = {
name: outputName,
path: `https://shadcn-svelte.com/docs/${relativePath}`,
title: veliteItem?.title,
description: veliteItem?.description,
};
if (
outputName === "index" ||
outputName === "about" ||
outputName === "changelog" ||
outputName === "cli" ||
outputName === "components-json" ||
outputName === "theming" ||
outputName === "javascript" ||
outputName === "legacy"
) {
categorizedLinks.overview.push(linkData);
} else if (dirPath.includes("installation")) {
categorizedLinks.installation.push(linkData);
} else if (dirPath.includes("dark-mode")) {
categorizedLinks.darkMode.push(linkData);
} else if (dirPath.includes("migration")) {
categorizedLinks.migration.push(linkData);
} else if (dirPath.includes("registry")) {
categorizedLinks.registry.push(linkData);
} else if (dirPath.includes("components")) {
let categorized = false;
if (componentCategories.formInput.includes(outputName)) {
categorizedLinks.components.formInput.push(linkData);
categorized = true;
} else if (componentCategories.layoutNavigation.includes(outputName)) {
categorizedLinks.components.layoutNavigation.push(linkData);
categorized = true;
} else if (componentCategories.overlaysDialogs.includes(outputName)) {
categorizedLinks.components.overlaysDialogs.push(linkData);
categorized = true;
} else if (componentCategories.feedbackStatus.includes(outputName)) {
categorizedLinks.components.feedbackStatus.push(linkData);
categorized = true;
} else if (componentCategories.displayMedia.includes(outputName)) {
categorizedLinks.components.displayMedia.push(linkData);
categorized = true;
} else if (componentCategories.misc.includes(outputName)) {
categorizedLinks.components.misc.push(linkData);
categorized = true;
}
if (!categorized) {
categorizedLinks.components.misc.push(linkData);
}
} else {
categorizedLinks.other.push(linkData);
}
}
categorizedLinks.overview.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.installation.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.darkMode.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.migration.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.registry.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.other.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.components.formInput.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.components.layoutNavigation.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.components.overlaysDialogs.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.components.feedbackStatus.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.components.displayMedia.sort((a, b) => a.name.localeCompare(b.name));
categorizedLinks.components.misc.sort((a, b) => a.name.localeCompare(b.name));
const llmsContent = `# shadcn-svelte
> shadcn-svelte is a collection of beautifully-designed, accessible components for Svelte and SvelteKit. It is built with TypeScript, Tailwind CSS, and Bits UI primitives. Open Source. Open Code. AI-Ready. It also comes with a command-line tool to install and manage components and a registry system to publish and distribute code.
## Overview
${categorizedLinks.overview
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
## Installation
${categorizedLinks.installation
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
## Components
### Form & Input
${categorizedLinks.components.formInput
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
### Layout & Navigation
${categorizedLinks.components.layoutNavigation
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
### Overlays & Dialogs
${categorizedLinks.components.overlaysDialogs
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
### Feedback & Status
${categorizedLinks.components.feedbackStatus
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
### Display & Media
${categorizedLinks.components.displayMedia
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
### Misc
${categorizedLinks.components.misc
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
## Dark Mode
${categorizedLinks.darkMode
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
## Migration
${categorizedLinks.migration
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
## Registry
${categorizedLinks.registry
.map((link) => `- [${link.title || formatName(link.name)}](${link.path}): ${link.description}`)
.join("\n")}
`;
const createFile = async (destinationFile: string) => {
const outputPath = join(__dirname, destinationFile);
const outputDir = dirname(outputPath);
await mkdir(outputDir, { recursive: true });
await writeFile(outputPath, llmsContent);
};
await createFile("../.svelte-kit/cloudflare/llms.txt");
consola.info("Created llms.txt index file!");
}
function formatName(name: string): string {
return name
.split("-")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
}
async function main() {
try {
consola.info("Starting to build LLM files...");
const rootPath = join(__dirname, "../.svelte-kit/cloudflare/docs");
console.info("Collecting files from", rootPath);
const files = await collectFiles(rootPath, rootPath);
const fileNames = Object.keys(files).filter((fileName) => fileName.endsWith(".html"));
// build individual llms.txt files and collect content
for (const fileName of fileNames) {
console.info("Processing", fileName);
if (!fileName.endsWith(".html")) continue;
const fileContent = files[fileName];
const cleanedContent = await toMarkdown(fileContent);
const baseName = basename(fileName, ".html");
const dirPath = dirname(fileName);
const outputName =
baseName === "index" ? (dirPath === "." ? "docs" : basename(dirPath)) : baseName;
const createFile = async (destinationDir: string) => {
const outputPath =
baseName === "index" && dirPath === "."
? join(__dirname, destinationDir.replace("/docs", ""), `${outputName}.md`)
: baseName === "index"
? join(__dirname, destinationDir, `${outputName}.md`)
: join(__dirname, destinationDir, dirPath, `${outputName}.md`);
const outputDir = dirname(outputPath);
await mkdir(outputDir, { recursive: true });
await writeFile(outputPath, cleanedContent);
};
await createFile("../.svelte-kit/cloudflare/docs");
}
await createLLMsIndex(files);
} catch (error) {
console.error("Error building LLM files:", error);
}
}
main();
================================================
FILE: docs/scripts/build-registry.ts
================================================
import fs from "node:fs";
import { execSync } from "node:child_process";
import path from "node:path";
import postcss from "postcss";
import prettier from "prettier";
import { rimraf } from "rimraf";
import {
componentsJsonSchema,
registryItemSchema,
registrySchema,
type Registry,
type RegistryItemType,
} from "shadcn-svelte/schema";
import { PRESET_STYLES, type PresetConfig } from "shadcn-svelte/preset";
interface BuildRegistryItem {
name: string;
type: string;
files: Array<{
path: string;
}>;
}
import { buildRegistry } from "./registry.js";
import { THEMES } from "../src/lib/registry/themes.js";
import { getColorsData } from "../src/lib/components/colors/colors.js";
import { toJSONSchema } from "zod";
const prettierConfig = await prettier.resolveConfig(import.meta.url);
if (!prettierConfig) throw new Error("Failed to resolve prettier config.");
const INTERNAL_REGISTRY_PATH = path.resolve("src", "lib", "registry");
const REGISTRY_PATH = path.resolve("static", "registry");
const STYLE_TEMP_BASE = path.join(REGISTRY_PATH, "temp", "style");
function writeFileWithDirs(
filePath: string,
data: string,
options: Parameters[2] = {}
): void {
// Create directory path if it doesn't exist
const dirname = path.dirname(filePath);
fs.mkdirSync(dirname, { recursive: true });
// Write the file
fs.writeFileSync(filePath, data, options);
}
function log(message: string) {
console.log(`[registry]: ${message}`);
}
export async function build(): Promise {
log("📦 Starting...");
log("🔍 Crawling registry (UI, examples, blocks, hooks, lib, fonts)...");
const registry = await buildRegistry();
log(`✨ Found ${registry.length} registry items`);
log("✅ Validating registry...");
validateRegistry(registry);
// build registry styles (each style gets its own temp dir with cn-* classes resolved)
log("🎨 Building registry styles...");
await Promise.all(
PRESET_STYLES.map(async (style) => {
log(` 📐 Processing style: ${style}`);
const styleTempDir = path.join(STYLE_TEMP_BASE, style);
try {
fs.mkdirSync(styleTempDir, { recursive: true });
const styleRegistry = await rewriteRegistryForStyle(registry, style, styleTempDir);
await buildRegistryJson(styleRegistry, style);
await runRegistryBuild(style);
} finally {
rimraf.sync(styleTempDir);
const registryJsonPath = path.resolve(`registry-${style}.json`);
if (fs.existsSync(registryJsonPath)) {
fs.rmSync(registryJsonPath);
}
}
log(`✅ Style ${style} built`);
})
);
log("✅ Registry styles built");
log("🧹 Cleaning up style temp directory...");
rimraf.sync(STYLE_TEMP_BASE);
// ----------------------------------------------------------------------------
// Build __registry__/blocks.ts
// ----------------------------------------------------------------------------
log("🧩 Building __registry__/blocks.ts...");
rimraf.sync(path.resolve("src", "__registry__"));
let blocksIndex = `
// This file is autogenerated by scripts/build-registry.ts
// Do not edit this file directly.
export const blocks = [
`; // Creates block index files
for (const block of registry) {
if (block.type !== "registry:block" || block.name.startsWith("chart-")) continue;
blocksIndex += `"${block.name}",`;
}
blocksIndex += "\n] as const;\n";
const blocksPath = path.resolve("src", "__registry__", "blocks.ts");
writeFileWithDirs(blocksPath, blocksIndex);
// ----------------------------------------------------------------------------
// Build __registry__/index.js.
// ----------------------------------------------------------------------------
let index = `
// This file is autogenerated by scripts/build-registry.ts
// Do not edit this file directly.
export const Index = {`;
// TODO: fix later - we should either add these calendar examples to
// the `lib/registry/examples` dir, or... do something else?
const CALENDAR_EXAMPLES = ["02", "13", "22", "24", "29"].map((n) => `calendar-${n}`);
for (const item of registry as BuildRegistryItem[]) {
if (item.type !== "registry:example" && !CALENDAR_EXAMPLES.includes(item.name)) {
continue;
}
const resolveFiles = item.files.map((file: BuildRegistryItem["files"][0]) =>
file.path.replace("src/", "../")
);
index += `
"${item.name}": {
files: [${resolveFiles.map((filePath: string) => `"${filePath.replaceAll(path.sep, "/")}"`)}],
},`;
}
index += `
}
`;
// Write style index.
const registryPath = path.resolve("src", "__registry__", "index.js");
rimraf.sync(registryPath);
writeFileWithDirs(registryPath, index);
// ----------------------------------------------------------------------------
// Build registry/colors/index.json.
// ----------------------------------------------------------------------------
log("🎨 Building registry/colors...");
const colorsTargetPath = path.join(REGISTRY_PATH, "colors");
rimraf.sync(colorsTargetPath);
if (!fs.existsSync(colorsTargetPath)) {
fs.mkdirSync(colorsTargetPath, { recursive: true });
}
const colorsData = getColorsData();
writeFileWithDirs(
path.join(colorsTargetPath, "index.json"),
JSON.stringify(colorsData, null, "\t"),
"utf-8"
);
// ----------------------------------------------------------------------------
// Build registry/colors/[theme].json
// ----------------------------------------------------------------------------
for (const theme of THEMES) {
writeFileWithDirs(
path.join(REGISTRY_PATH, "colors", `${theme.name}.json`),
JSON.stringify(theme, null, "\t"),
"utf-8"
);
}
// ----------------------------------------------------------------------------
// Build static/schema.json
// ----------------------------------------------------------------------------
log("📋 Writing schema files...");
const componentsJSON = toJSONSchema(componentsJsonSchema);
writeFileWithDirs(
path.resolve("static", "schema.json"),
JSON.stringify(componentsJSON, null, "\t")
);
const SCHEMA_DIR = path.resolve("static", "schema");
writeFileWithDirs(
path.resolve(SCHEMA_DIR, "registry.json"),
JSON.stringify(toJSONSchema(registrySchema), null, "\t")
);
writeFileWithDirs(
path.resolve(SCHEMA_DIR, "registry-item.json"),
JSON.stringify(toJSONSchema(registryItemSchema), null, "\t")
);
log("🎉 Done!");
}
const CN_CLASS_SELECTOR = /^\.(cn-[\w-]+)$/;
/**
* Parse style-