diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..78fe3d9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,100 @@ +name: 🐛 Bug Report +description: Found a bug? Let us help you fix it! +title: 'bug: ' +labels: ['bug'] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug! Let's fix it together. + + - type: dropdown + id: component + attributes: + label: Component Category + description: Which component type has the issue? + options: + - Inputs + - Buttons + - Accordions + - Alerts + - Avatars + - Badges + - Banners + - Checkboxes + - Dialogs + - Dropdowns + - 'Hover Cards' + - Notifications + - Popovers + - Radios + - Sliders + - Switches + - Textareas + - Tooltips + - Base UI Components + - Other + validations: + required: true + + - type: input + id: component-id + attributes: + label: Component ID + description: Which specific component? (e.g., input-01, button-02) + placeholder: 'input-01' + + - type: textarea + id: current-behavior + attributes: + label: Current Behavior + description: What's happening that shouldn't be? + placeholder: 'When I click the button...' + validations: + required: true + + - type: textarea + id: expected-behavior + attributes: + label: Expected Behavior + description: What should happen instead? + placeholder: 'The button should...' + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to Reproduce + description: Help us find the bug + value: | + 1. Go to '...' + 2. Click on '...' + 3. See error + validations: + required: true + + - type: dropdown + id: browsers + attributes: + label: Affected Browsers + multiple: true + options: + - Firefox + - Chrome + - Safari + - Edge + - Other + + - type: textarea + id: logs + attributes: + label: Error Logs + description: Any error messages in the console? + render: shell + + - type: markdown + attributes: + value: | + > [!TIP] + > Include screenshots or screen recordings if possible - they're super helpful! diff --git a/.github/ISSUE_TEMPLATE/component_request.yml b/.github/ISSUE_TEMPLATE/component_request.yml new file mode 100644 index 0000000..799b80a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/component_request.yml @@ -0,0 +1,105 @@ +name: 🧩 Component Request +description: Have an idea for a new component? Let's build it! +title: 'component: ' +labels: ['component'] +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a new component! Let's make something awesome together. + + > [!NOTE] + > This project is a copy of the original Origin UI, reimplemented in Svelte. New components should aim to match the original Origin UI's design and functionality. + + - type: dropdown + id: component-type + attributes: + label: Request Type + description: What kind of component are you looking for? + options: + - New Component Category + - New Component in Existing Category + - Variation of Existing Component + validations: + required: true + + - type: dropdown + id: category + attributes: + label: Component Category + description: Where should this component live? + options: + - Inputs + - Buttons + - Accordions + - Alerts + - Avatars + - Badges + - Banners + - Checkboxes + - Dialogs + - Dropdowns + - 'Hover Cards' + - Notifications + - Popovers + - Radios + - Sliders + - Switches + - Textareas + - Tooltips + - New Category (describe below) + validations: + required: true + + - type: input + id: new-category + attributes: + label: New Category Name + description: If you selected "New Category", what should we call it? + placeholder: 'Date Pickers' + + - type: textarea + id: description + attributes: + label: Component Description + description: What should this component do? + placeholder: 'A component that...' + validations: + required: true + + - type: textarea + id: use-cases + attributes: + label: Use Cases + description: When would someone use this component? + value: | + 1. When users need to... + 2. In situations where... + validations: + required: true + + - type: textarea + id: features + attributes: + label: Key Features + description: What features should it have? + value: | + - [ ] Feature 1 + - [ ] Feature 2 + validations: + required: true + + - type: textarea + id: examples + attributes: + label: Examples & Inspiration + description: Share links to similar components + placeholder: | + - Design inspiration: ... + - Similar component: ... + + - type: markdown + attributes: + value: | + > [!TIP] + > Add mockups or sketches if you have them - they help us understand your vision! diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..0b831bf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: 📚 Documentation + url: https://originui-svelte.pages.dev/ + about: Check our documentation for guides and examples + - name: 💬 Discussions + url: https://github.com/max-got/originui-svelte/discussions + about: Ask questions and share ideas + - name: 🎨 Original Origin UI + url: https://originui.com/ + about: View the original components we're recreating diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..3d983a3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,96 @@ +name: 💡 Feature Request +description: Got an idea to make Origin UI - Svelte better? Share it here! +title: 'feat: ' +labels: ['enhancement'] +body: + - type: markdown + attributes: + value: | + Thanks for helping make Origin UI - Svelte better! Let's hear your idea. + + > [!NOTE] + > This project is a copy of the original Origin UI, reimplemented in Svelte. New features should align with and complement the original Origin UI's functionality. + + - type: dropdown + id: feature-type + attributes: + label: Feature Type + description: What area would this improve? + options: + - Developer Experience + - Component Enhancement + - Documentation + - Performance + - Accessibility + - Other + validations: + required: true + + - type: dropdown + id: component + attributes: + label: Related Component + description: Does this affect a specific component type? + options: + - Not Component Specific + - Inputs + - Buttons + - Accordions + - Alerts + - Avatars + - Badges + - Banners + - Checkboxes + - Dialogs + - Dropdowns + - 'Hover Cards' + - Notifications + - Popovers + - Radios + - Sliders + - Switches + - Textareas + - Tooltips + - Base UI Components + validations: + required: true + + - type: textarea + id: problem + attributes: + label: Current Limitation + description: What's missing or could be better? + placeholder: 'It would be great if...' + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: How could we solve this? + placeholder: 'We could...' + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternative Approaches + description: Are there other ways to solve this? + placeholder: 'Another way could be...' + + - type: textarea + id: examples + attributes: + label: Examples & References + description: Share any examples or references + placeholder: | + - Similar feature in other libraries: ... + - Reference implementation: ... + + - type: markdown + attributes: + value: | + > [!TIP] + > Not sure if this is the right approach? Open a discussion first - we're happy to brainstorm together! diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..968c57b --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,47 @@ +## Description + + + +## Type of Change + + + +- [ ] New component(s) +- [ ] Enhancement to existing component +- [ ] Bug fix +- [ ] Documentation +- [ ] Other: + +## Component Details + + + +**Category:** +**Component Name(s):** + +## Checklist + + + +- [ ] Matches original design (or improves it) +- [ ] Uses Svelte 5 runes +- [ ] Follows project structure +- [ ] Ran `pnpm generate:registry` +- [ ] Added route config (if new category) +- [ ] Added dependencies to `constants.ts` (if needed) +- [ ] Added placeholder content (if .todo/.soon) +- [ ] Tested in light/dark mode +- [ ] Checked accessibility + +## Screenshots + + + +## Related Issues + + + +--- + +> [!TIP] +> Need help? Check our [Contributing Guide](../README.md#contributing) or open a Draft PR for early feedback! diff --git a/README.md b/README.md index 92dfa0f..c34e9d1 100644 --- a/README.md +++ b/README.md @@ -6,19 +6,48 @@ > [!NOTE] > This is a work in progress. For some components the necessary libraries are coming soon (e.g. [Bits UI](https://next.bits-ui.com/docs/introduction)) or are just not available yet (e.g. [React Payment Inputs](https://github.com/medipass/react-payment-inputs)). Maybe i will add them in the future myself. -Origin UI - Svelte is a collection of copy-and-paste components for quickly building app UIs using Svelte. The collection currently features 90+ components and is updated with new examples if the original library is updated. +Origin UI - Svelte is a collection of copy-and-paste components for quickly building app UIs using Svelte. + +## Table of Contents + +- [Features](#features) +- [Demo](#demo) +- [Acknowledgements](#acknowledgements) +- [Differences from the original](#differences-from-the-original) +- [Getting Started](#getting-started) + - [Prerequisites](#prerequisites) + - [Development](#development) +- [Usage](#usage) + - [Utils](#utils) + - [Base Components](#base-components) + - [CSS Variables](#css-variables) +- [Contributing](#contributing) + - [Project Structure](#project-structure) + - [Component Registry System](#component-registry-system) + - [Dependency Detection System](#dependency-detection-system) + - [Code Collapsing System](#code-collapsing-system) + - [Component Guidelines](#component-guidelines) + - [Pull Request Process](#pull-request-process) +- [Need Help?](#need-help) +- [Terms of Use](#terms-of-use) +- [Contact](#contact) +- [Notes](#notes) ## Demo [originui-svelte.pages.dev/](https://originui-svelte.pages.dev/) -## Features +## Acknowledgements + +- [Origin UI](https://originui.com/) - The original project that this Svelte version is copied from +- [Svelte](https://svelte.dev) +- [TailwindCSS](https://tailwindcss.com) +- [Lucide Icons](https://lucide.dev) +- [Bits UI](https://next.bits-ui.com) -- Built with Svelte and TailwindCSS -- Fully customizable -- Responsive design +## Differences from the original -## Differences from the original [Origin UI](https://originui.com/) +The Original [Origin UI](https://originui.com/) is built with Next.js. This is a built with Svelte. - [x] [Svelte](https://svelte.dev) instead of ~~Next.js~~ - [x] [Lucide Svelte](https://lucide.dev/guide/packages/lucide-svelte) instead of ~~Lucide React~~ @@ -26,48 +55,54 @@ Origin UI - Svelte is a collection of copy-and-paste components for quickly buil ## Getting Started +### Prerequisites + +If you want to use the components in your project, you need to setup the following: + +- [Svelte](https://svelte.dev) +- [TailwindCSS](https://tailwindcss.com) +- [Bits UI (Next)](https://next.bits-ui.com/docs/introduction) +- or other dependencies (see [src/lib/constants.ts](src/lib/constants.ts)) + ### Development > [!NOTE] > This project uses [pnpm](https://pnpm.io/) as package manager. -1. Clone the repository: +1. **Setup** - ``` + ```bash git clone https://github.com/max-got/originui-svelte.git - ``` - -2. Install dependencies: - - ``` + cd originui-svelte pnpm install ``` -3. Run the development server: +2. **Development** - ``` + ```bash pnpm dev ``` -4. Open [http://localhost:5173](http://localhost:5173) with your browser to see the result. + - Components are previewed at `http://localhost:5173` -### Usage - -You can copy and use the components in your Svelte project. Note that some components may require additional libraries - refer to the code comments at the top of each file for specific requirements. +3. **Code Quality** + ```bash + pnpm lint # Run ESLint + pnpm format # Run Prettier + ``` -### Prerequisites +### Usage -If you want to use the components in your project, you need to setup the following: - -- [Svelte](https://svelte.dev) -- [TailwindCSS](https://tailwindcss.com) -- [Lucide Icons](https://lucide.dev) -- [Bits UI (Next)](https://next.bits-ui.com/docs/introduction) +You can copy and use the components in your Svelte project. Note that some components may require additional libraries - refer to the listed dependencies in the component preview. #### Utils In the `src/lib/utils.ts` folder you will find the common `cn` function for tailwindcss class merging. +In the `src/lib/hooks` folder you will find the common hooks. + +In the `src/lib/actions` folder you will find the common actions. + #### Base Components You need to copy the base components from the `src/lib/components/ui` folder to your project and adjust the imports accordingly. @@ -124,27 +159,500 @@ Import the CSS in your `src/lib/app.css` file (the following is based on tailwin } ``` -## Components +## Contributing -- Inputs -- Buttons -- (More categories to be added) +We welcome contributions to Origin UI - Svelte! -## Contributing +This guide will help you understand our project structure and contribution workflow. -Contributions are welcome! Please feel free to submit a Pull Request. +### Project Structure -## Terms of Use +``` +src/ +├── lib/ +│ ├── components/ # UI Components organized by type +│ │ ├── ui/ # Base UI components +│ │ │ ├── badge.svelte # one component +│ │ │ ├── button.svelte # one component +│ │ │ ├── accordion.svelte # needs multiple components +│ │ │ │ │── accordion-item.svelte # Base component Accordion Item +│ │ │ │ │── accordion-trigger.svelte # Base component Accordion Trigger +│ │ │ │ │── ... +│ │ │ └── ... +│ │ ├── inputs/ # Input components +│ │ │ ├── input-01.svelte +│ │ │ ├── input-02.svelte +│ │ │ └── ... +│ │ ├── buttons/ # Button components +│ │ │ ├── button-01.svelte +│ │ │ ├── button-02.svelte +│ │ │ └── ... +│ │ └─ ... # Other component categories +│ ├── utils/ # Utility functions +│ ├── types/ # TypeScript type definitions +│ ├── hooks/ # Svelte hooks +│ ├── actions/ # Svelte actions +│ └── config/ # Configuration files +``` -Feel free to use these components in personal and commercial projects. However, while the tutorials and demos are available for your use as-is, they cannot be redistributed or resold. +### Component Registry System -## Acknowledgements +The project uses an automated component registry system that connects your components to the routing system. Here's how it works: -- [Origin UI](https://originui.com/) - The original project that this Svelte version is copied from -- [Svelte](https://svelte.dev) -- [TailwindCSS](https://tailwindcss.com) -- [Lucide Icons](https://lucide.dev) -- [Bits UI](https://next.bits-ui.com) +1. **Registry Generation** + + ```bash + pnpm generate:registry + ``` + + This script automatically: + + - Scans the `src/lib/components/` directory + - Generates `src/lib/componentRegistry.types.ts` with component mappings + - Updates component type definitions and directory structures + +2. **Registry Architecture** + + ``` + src/ + ├── lib/ + │ ├── componentRegistry.types.ts # Auto-generated types + │ ├── componentRegistry.ts # Registry implementation + │ └── data/api/ + │ ├── components.ts # API endpoints + │ ├── components.handler.ts # Request handlers + │ └── components.route.ts # Route definitions + ├── routes/ + │ └── (components)/ + │ └── [path=componentsPath]/ + │ ├── +page.server.ts # Dynamic route handling + │ └── [directory]/[id]/ + │ └── +page.server.ts # Component page handling + └── params/ + ├── componentDirectory.ts # Directory parameter validation + ├── componentId.ts # Component ID validation + └── componentsPath.ts # Path parameter validation + ``` + +3. **How It Works** + + - The registry system creates a type-safe mapping between: + - Component files in your directories + - URL routes and parameters + - API endpoints + - SvelteKit param matchers use these types to validate URLs + - The system enables dynamic routing while maintaining type safety + +4. **When to Run Registry Generation** + Run `pnpm generate:registry` when you: + - Add new component files + - Create new component categories + - Rename components or directories + - Update component structure + +> [!IMPORTANT] +> Always run `pnpm generate:registry` after making changes to component files or structure. This ensures the routing system stays in sync with your components. + +### Dependency Detection System + +The project includes an automated dependency detection system that analyzes component source code and manages dependencies. + +1. **Dependency Configuration** + + Dependencies must be registered in `src/lib/constants.ts`: + + ```typescript + export const POSSIBLE_DEPENDENCIES = [ + { + dev: false, // Whether it's a dev dependency + name: 'bits-ui', // Import name to detect + packageName: 'bits-ui@next', // NPM package name + url: 'https://github.com/huntabyte/bits-ui' // Reference URL + } + // ... other dependencies + ] as const; + ``` + +> [!IMPORTANT] +> When using a new dependency in your component, you MUST add it to `POSSIBLE_DEPENDENCIES` first. +> This ensures the dependency detection system can find and document it correctly. + +2. **Adding New Dependencies** + + To add a new dependency: + + 1. Open `src/lib/constants.ts` + 2. Add an entry to `POSSIBLE_DEPENDENCIES`: + ```typescript + { + dev: boolean, // true for devDependencies, false for dependencies + name: string, // The import path to detect (e.g., 'your-package') + packageName: string, // The exact package name with version (e.g., 'your-package@1.0.0') + url: string // Package repository or documentation URL + } + ``` + 3. Commit the change before adding components that use this dependency + +3. **How It Works** + + The system (`src/lib/utils/handleComponentSource.ts`): + + - Scans component source code for imports + - Matches imports against `POSSIBLE_DEPENDENCIES` + - Generates installation commands + - Adds dependency information to component metadata + +4. **Example Output** + + When a component uses dependencies: + + ```svelte + + ``` + + The system automatically: + + ```markdown + + ``` + +5. **Special Cases** + + - Enhanced Images: + + ```typescript + // Automatically detects and adds @sveltejs/enhanced-img + const enhancedImageMatch = source.match(ENHANCED_IMAGE_REGEX); + ``` + + - Multiple Dependencies: + ```bash + # Combines dev and runtime dependencies + pnpm i -D @iconify-json/ri unplugin-icons && pnpm i bits-ui@next + ``` + +6. **Integration** + + The system integrates with: + + - Component API endpoints + - Documentation generation + - Development tooling + +> [!TIP] +> When adding new components that use external packages: +> +> 1. First add the dependency to `POSSIBLE_DEPENDENCIES` +> 2. Then create your component with the imports +> 3. The system will automatically detect and document the dependencies + +### Code Collapsing System + +The project includes an automatic code collapsing system for better readability in the documentation. This feature is implemented in `src/lib/utils/shiki-transformer/collapsible.ts`. + +1. **How to Use** + + Add collapse markers in your component code: + + ```svelte + + ``` + +2. **Supported Comment Types** + + The system recognizes collapse markers, like this: + + ```typescript + // JavaScript/TypeScript style + // [!code collapse-start] + // long code + // [!code collapse-end] + ``` + +3. **How It Works** + + The system: + + - Detects collapse markers in source code + - Wraps the content in a collapsible section + - Adds an "Expand/Collapse" button + - Preserves code highlighting and formatting + +4. **Example Use Case** + + Perfect for: + + - Large data arrays + - Configuration objects + - Repetitive code sections + - Long utility functions + + ```svelte + + + + ``` + +5. **Best Practices** + + - Use for non-essential code sections + - Keep critical implementation details visible + - Collapse large data structures + - Use in documentation and examples + +> [!TIP] +> Use code collapsing to improve the readability of your components in the documentation while keeping all code accessible when needed. + +### Component Guidelines + +- 1\. **Component Organization** + + - 1.1\. **Base (`/ui`) components** + + Base components are in the `src/lib/components/ui` folder. + + Each component should be in its own directory if it needs multiple components. + + ``` + component-category/ + ├── index.ts # Exports + ├── component.svelte # Main component + ``` + + If a component is a simple one, it can be placed in the `src/lib/components/ui` folder. + + ``` + component-category/ + └── component.svelte # Main component + ``` + + - 1.2\. **Origin UI components** + + Origin UI components are in the `src/lib/components` folder. + + Each component should be in its own desired category (e.g. `inputs`,`buttons`, etc.) + + ``` + component-category/ + ├── category-01.svelte + ├── category-02.svelte + └── ... + ``` + + If a component isn't achievable (e.g. not the necessary libraries available, not enough time to implement, etc.) you need to add a placeholder component in the `src/lib/components` folder. In this case the component should be named `category-03.todo.svelte`. + + ``` + component-category/ + └── category-03.todo.svelte + ``` + + If a component is just waiting for a library to be implemented, you need to add a placeholder component in the `src/lib/components` folder. In this case the component should be named `category-04.soon.svelte`. + + ``` + component-category/ + └── category-04.soon.svelte + ``` + + > [!NOTE] + > The component should have content. For example: + > + > ```html + >

+ > waiting for + > class="underline hover:text-foreground" + > href="https://github.com/huntabyte/bits-ui/pull/582" + > >Bits UI TimeField > + >

+ > ``` + + - 1.3\. **Route Configuration** + + When adding a new component category, you must configure its routing in `src/lib/config/routes.ts`: + + ```typescript + { + componentDirectory: ['your-category'], // Directory name(s) containing components + header: { + description: 'A growing collection of ${count} components built with Svelte and TailwindCSS.', + title: 'Your Category' + }, + label: 'Your Category', // Navigation label + order: 12, // Navigation order (increment from last) + path: 'your-category', // URL path + seo: { + description: 'An extensive collection of copy-and-paste components built with Svelte and TailwindCSS.', + keywords: 'your, keywords, component, svelte, tailwindcss', + title: 'Your Category', + twitterDescription: 'An extensive collection of copy-and-paste components built with Svelte and TailwindCSS.', + twitterTitle: 'Your Category' + } + } + ``` + + For combined categories (like inputs/textareas), use multiple directories: + + ```typescript + componentDirectory: ['category1', 'category2'], + path: 'combined-category' + ``` + +> [!NOTE] +> The `order` property determines the navigation menu order. Check existing routes for the next available number. + +2. **Component Requirements** + + - Resemble the original component as closely as possible + - If there is a "better" way to implement the component, use that + - Use Svelte 5 runes for state management + - Include TypeScript types for props and events + - Implement proper ARIA attributes for accessibility + +3. **Styling Guidelines** + - Use Tailwind CSS for all styling + - Follow the project's color scheme using CSS variables + - Implement responsive design using Tailwind breakpoints + - Use semantic HTML elements + - Maintain dark mode support + +### Pull Request Process + +1. **Before Starting** + + - Check existing issues and PRs to avoid duplicate work + - For new features, open an issue for discussion first + - Fork the repository and create a feature branch: + ```bash + git checkout -b feature/your-feature-name + ``` + +2. **Component Development** + + - Follow the component organization guidelines + - Place components in appropriate directories + - Use the correct naming convention: + ``` + component-category/ + ├── category-XX.svelte # Regular component + ├── category-XX.todo.svelte # Not yet possible + └── category-XX.soon.svelte # Waiting for dependency + ``` + - Run `pnpm generate:registry` after adding/modifying components + +3. **Quality Checklist** + + - [ ] Component matches original design + - [ ] Svelte 5 runes used correctly + - [ ] TypeScript types are complete + - [ ] ARIA attributes implemented + - [ ] Dark mode works correctly + - [ ] Responsive design tested + - [ ] No console errors/warnings + - [ ] Code formatted (`pnpm format`) + - [ ] Linting passes (`pnpm lint`) + +4. **Route Configuration** + + - If adding a new category: + - Add entry to `src/lib/config/routes.ts` + - Configure SEO metadata + - Set correct navigation order + - For existing categories: + - Ensure component follows naming pattern + - Update component count in route description + +5. **Documentation** + + - Include example usage + - Document any required props + - Note any dependencies + - Add placeholder content for `.todo` and `.soon` components + +6. **Submitting the PR** + + ```bash + git add . + git commit -m "feat: add new component category" + git push origin feature/your-feature-name + ``` + + - Use conventional commit messages: + - `feat:` for new components/features + - `fix:` for bug fixes + - `docs:` for documentation + - `refactor:` for code improvements + - `chore:` for maintenance + +7. **PR Description Template** + + ```markdown + ## Description + + Brief description of changes + + ## Type of change + + - [ ] New component(s) + - [ ] Bug fix + - [ ] Documentation update + - [ ] Refactoring + + ## Checklist + + - [ ] Run `pnpm generate:registry` + - [ ] Tested in light/dark mode + - [ ] Responsive design verified + - [ ] Accessibility checked + - [ ] Documentation updated + ``` + +8. **After Submission** + - Respond to review comments promptly + - Keep the PR focused and small + - Update your branch if needed: + ```bash + git fetch origin + git rebase origin/main + ``` + +> [!NOTE] +> Large PRs are harder to review. Consider breaking big changes into smaller, focused PRs. + +### Need Help? + +- Check existing issues and pull requests +- Join our discussions in the repository +- Open an issue for questions + +We appreciate your contributions to the Svelte Community and to this project! + +## Terms of Use + +Feel free to use these components in personal and commercial projects. However, while the tutorials and demos are available for your use as-is, they cannot be redistributed or resold. ## Contact