@zoop-svelte/svelte-components
v0.1.9
Published
Zoop UI component library built with Svelte 5, TypeScript, and Tailwind CSS
Maintainers
Readme
✨ Features
🚀 Installation
Package Manager
# npm
npm install @zoop-svelte/svelte-components
# yarn
yarn add @zoop-svelte/svelte-components
# pnpm
pnpm add @zoop-svelte/svelte-componentsDependencies
# Install required peer dependencies
npm install -D tailwindcss @tailwindcss/vite🎯 Quick Start
1. Configure Tailwind CSS
Update your tailwind.config.js:
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./src/**/*.{html,js,svelte,ts}',
'./node_modules/@zoop-svelte/svelte-components/**/*.{html,js,svelte,ts}'
],
theme: {
extend: {
colors: {
// Component color tokens
primary: 'rgb(251 91 36)',
'primary-dark': 'rgb(234 88 12)',
secondary: 'rgb(243 244 246)',
destructive: 'rgb(239 68 68)'
// Add more as needed...
}
}
},
plugins: []
};2. Import Styles
Add to your main CSS file:
@import 'tailwindcss';
@import '@zoop-svelte/svelte-components/dist/styles.css';
@source "/@zoop-svelte/svelte-components/dist";3. Start Using Components
<script>
import { Button, Accordion, Progress } from '@zoop-svelte/svelte-components';
import { Plus } from 'lucide-svelte';
</script>
<Button leadingIcon={Plus}>Add Item</Button>
<Accordion.Root type="single">
<Accordion.Item value="item-1">
<Accordion.Trigger>
<Accordion.Title>What is Zoop UI?</Accordion.Title>
</Accordion.Trigger>
<Accordion.Content>A beautiful component library for Svelte applications.</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
<Progress value={50} max={100} />🧩 Components
Available Components
<!-- Variants -->
<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Delete</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<!-- Sizes -->
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
<!-- With Icons -->
<Button leadingIcon={Save}>Save Changes</Button>
<Button trailingIcon={ArrowRight}>Continue</Button>
<Button variant="icon"><Settings /></Button>
<!-- States -->
<Button loading>Processing...</Button>
<Button disabled>Disabled</Button>
<!-- Interactive Loading -->
<script>
let isLoading = false;
async function handleClick() {
isLoading = true;
await doSomething();
isLoading = false;
}
</script>
<Button loading={isLoading} on:click={handleClick}>
Submit
</Button> </details>
</td>
<td width="50%">
<h4>📂 Accordion</h4>
<p>Collapsible content panels with smooth animations and single/multiple expansion modes.</p>
<details>
<summary><strong>View Examples</strong></summary>
<br />
<!-- Single Mode -->
<Accordion.Root type="single" value="item-1">
<Accordion.Item value="item-1">
<Accordion.Trigger>
<Accordion.Title>Section 1</Accordion.Title>
<Accordion.Description>
Optional description text
</Accordion.Description>
</Accordion.Trigger>
<Accordion.Content>
Content for section 1
</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
<!-- Multiple Mode -->
<Accordion.Root type="multiple">
<Accordion.Item value="faq-1">
<Accordion.Trigger>
<Accordion.Title>FAQ Question 1</Accordion.Title>
</Accordion.Trigger>
<Accordion.Content>
Answer to question 1
</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="faq-2">
<Accordion.Trigger>
<Accordion.Title>FAQ Question 2</Accordion.Title>
</Accordion.Trigger>
<Accordion.Content>
Answer to question 2
</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
</details>
</td><!-- Basic Progress -->
<Progress value={33} />
<Progress value={66} />
<Progress value={100} />
<!-- Custom Colors -->
<Progress
value={75}
class="[&>div]:bg-gradient-to-r [&>div]:from-purple-500 [&>div]:to-pink-500"
/>
<!-- Different Sizes -->
<Progress value={50} class="h-1" />
<Progress value={50} class="h-2" />
<Progress value={50} class="h-4" />
<!-- With Labels -->
<div class="space-y-2">
<div class="flex justify-between text-sm">
<span>Uploading...</span>
<span>{progress}%</span>
</div>
<Progress value={progress} />
</div> </details>
</td>
<td width="50%">
<h4>📝 Input</h4>
<p>Text input fields with consistent styling and validation states.</p>
<details>
<summary><strong>View Examples</strong></summary>
<br /><!-- Basic Input -->
<Label for="email">Email</Label>
<Input id="email" type="email" placeholder="[email protected]" />
<!-- Password Input -->
<Input type="password" placeholder="Enter password" />
<!-- With Error State -->
<Input class="border-red-500" placeholder="Invalid input" />
<!-- Disabled State -->
<Input disabled placeholder="Disabled input" /> </details>
</td><script>
let checked = false;
let terms = false;
</script>
<!-- Basic Checkbox -->
<div class="flex items-center space-x-2">
<Checkbox id="check1" bind:checked />
<Label for="check1">Enable notifications</Label>
</div>
<!-- Required Checkbox -->
<div class="flex items-center space-x-2">
<Checkbox id="terms" bind:checked={terms} required />
<Label for="terms">
I agree to the terms and conditions
</Label>
</div>
<!-- Disabled State -->
<Checkbox disabled checked /> </details>
</td>
<td width="50%">
<h4>📄 Sheet</h4>
<p>Slide-out panels for forms and additional content.</p>
<details>
<summary><strong>View Examples</strong></summary>
<br />
<script>
let open = false;
</script>
<Button on:click={() => open = true}>
Open Sheet
</Button>
<Sheet.Root bind:open>
<Sheet.Overlay />
<Sheet.Content>
<Sheet.Header>
<Sheet.Title>Edit Profile</Sheet.Title>
<Sheet.Description>
Make changes to your profile here.
</Sheet.Description>
</Sheet.Header>
<div class="py-4 space-y-4">
<div>
<Label for="name">Name</Label>
<Input id="name" />
</div>
<div>
<Label for="email">Email</Label>
<Input id="email" type="email" />
</div>
</div>
<Sheet.Footer>
<Button variant="secondary" on:click={() => open = false}>
Cancel
</Button>
<Button>Save Changes</Button>
</Sheet.Footer>
</Sheet.Content>
</Sheet.Root>
</details>
</td><script>
let plan = 'free';
</script>
<RadioGroup.Root bind:value={plan}>
<div class="space-y-2">
<div class="flex items-center space-x-2">
<RadioGroup.Item value="free" id="free" />
<Label for="free">Free Plan</Label>
</div>
<div class="flex items-center space-x-2">
<RadioGroup.Item value="pro" id="pro" />
<Label for="pro">Pro Plan ($9/mo)</Label>
</div>
<div class="flex items-center space-x-2">
<RadioGroup.Item value="enterprise" id="enterprise" />
<Label for="enterprise">Enterprise</Label>
</div>
</div>
</RadioGroup.Root> </details>
</td>
<td width="50%">
<h4>💬 Textarea</h4>
<p>Multi-line text input with auto-resize options.</p>
<details>
<summary><strong>View Examples</strong></summary>
<br /><!-- Basic Textarea -->
<Label for="message">Message</Label>
<Textarea id="message" placeholder="Type your message..." rows={4} />
<!-- With Character Count -->
<div class="space-y-2">
<Textarea bind:value={message} maxlength={200} />
<p class="text-sm text-gray-500">
{message.length}/200 characters
</p>
</div>
<!-- Auto-resize -->
<Textarea placeholder="Auto-resizing textarea" class="resize-none" on:input={handleAutoResize} /> </details>
</td>🎨 Theming
CSS Variables
Customize the look and feel by overriding CSS variables: Below are the examples of the variables. Please keep these variables only.
:root {
/* Colors */
--vr-color-primary: #16b46b;
--vr-color-primary-dark: #128a56;
--vr-color-primary-foreground: #052e1f;
--vr-color-secondary: #c6eedd;
--vr-color-stroke: #8fcfad;
--vr-color-muted: #a6dfc6;
--vr-color-muted-medium: #6dbb9a;
--vr-color-muted-dark: #4a9778;
--vr-color-foreground-primary: #062417;
--vr-color-foreground-secondary: #2d6e57;
--vr-color-foreground-tertiary: #51997c;
--vr-color-background-primary: #ffffff;
--vr-color-background-secondary: #eaf9f2;
--vr-color-distructive: #e74452;
--vr-color-distructive-dark: #c33541;
--vr-color-distructive-foreground: #a62d39;
--vr-color-success: #16b46b;
--vr-color-warning: #ffc933;
/* Spacing */
--vr-radius: 7px;
--vr-spacing: 4px;
/* Typography */
--font-sans: system-ui, -apple-system, sans-serif;
}Tailwind Configuration
Extend your theme with custom values:
theme: {
extend: {
animation: {
'fade-in': 'fadeIn 0.5s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out'
},
borderRadius: {
'zoop': '0.625rem'
}
}
}🛠️ Development
Prerequisites
- Node.js 18+
- pnpm (recommended) or npm
Setup
# Clone the repository
git clone https://github.com/zoop/zoop-svelte-components.git
cd zoop-svelte-components
# Install dependencies
pnpm install
# Start development server
pnpm devProject Structure
zoop-svelte-components/
├── src/
│ ├── lib/
│ │ ├── components/
│ │ │ └── ui/ # Component implementations
│ │ │ ├── button/
│ │ │ ├── accordion/
│ │ │ ├── progress/
│ │ │ └── ...
│ │ ├── utils.ts # Utility functions
│ │ └── index.ts # Public exports
│ └── routes/ # Demo pages
│ ├── +page.svelte # Home page
│ ├── button/ # Button examples
│ ├── accordion/ # Accordion examples
│ └── ...
├── static/
├── tests/
└── package.jsonScripts
# Development
pnpm dev # Start dev server
pnpm build # Build for production
pnpm preview # Preview production build
# Testing
pnpm test # Run tests
pnpm test:watch # Watch mode
# Code Quality
pnpm lint # Run ESLint
pnpm format # Format with Prettier
pnpm check # Type checking
# Package
pnpm package # Build component library🤝 Contributing
We love contributions! Please see our Contributing Guide for details.
Quick Contribution Guide
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Guidelines
- ✅ Write tests for new components
- ✅ Update documentation
- ✅ Follow the existing code style
- ✅ Ensure TypeScript types are exported
- ✅ Add examples to demo pages
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Built on top of Bits UI - Headless components for Svelte
- Styled with Tailwind CSS - Utility-first CSS framework
- Icons from Lucide Icons - Beautiful & consistent icons
- Created with ❤️ by the Innovation Team
📞 Support
- 📧 Email: [email protected]
- 💬 Discord: Join our community
- 🐛 Issues: GitHub Issues
- 📖 Docs: Documentation
