@ldsui/components
v1.0.0
Published
Modern Web Components library built with Lit - A lightweight, accessible design system
Downloads
3
Maintainers
Readme
LDS Components
Modern Web Components library built with Lit - A lightweight, accessible design system.
📋 About
LDS Components (Lightweight Design System) is a collection of reusable, framework-agnostic Web Components designed for building modern web applications. The library prioritizes:
- Performance: Minimal bundle size with tree-shaking and lazy loading
- Accessibility: WCAG 2.1 compliant with full keyboard navigation
- Developer Experience: TypeScript-first with comprehensive documentation
- Flexibility: Works with React, Vue, Angular, or vanilla JavaScript
This project was created as a portfolio demonstration of advanced Web Components knowledge, showcasing modern patterns like Shadow DOM encapsulation, CSS custom properties for theming, and reactive property systems.
🛠️ Tech Stack
| Category | Technology | |----------|------------| | Core | Lit 3.x - Fast, lightweight Web Components | | Language | TypeScript 5.x with strict mode | | Build | Vite 7.x with ES modules output | | Testing | Vitest + Playwright (browser testing) | | Documentation | Storybook 10.x | | Package Manager | pnpm | | Linting | ESLint 9.x + Prettier |
🤔 Why Lit? (vs Stencil vs CELLS)
While I have extensive experience with Stencil, I chose Lit for this project for specific reasons:
| Aspect | Lit | Stencil | CELLS (BBVA) | |--------|-----|---------|--------------| | Philosophy | Minimal abstraction over platform APIs | Compiler-based, framework-like | Enterprise framework on Stencil | | Bundle Size | ~5KB (core) | ~13KB (runtime) | Larger (enterprise features) | | Learning Curve | Low - close to vanilla WC | Medium - JSX, decorators | High - proprietary patterns | | Toolchain | Flexible (Vite, Rollup, etc.) | Custom CLI required | Custom CLI + internal tools | | Community | Google-backed, growing fast | Ionic team, stable | Internal/enterprise only | | Standards | Closest to native APIs | Some abstractions | Heavy abstractions |
Key Reasons for Choosing Lit:
Industry Adoption: Lit has become the de-facto standard for Web Components in 2024-2025, used by Google, Adobe, ING, and many others.
Transferable Skills: Knowledge of Lit translates directly to understanding native Web Components APIs, unlike framework-specific patterns.
Modern DX: First-class TypeScript support, reactive properties, and excellent Vite integration without a custom CLI.
Portfolio Value: Demonstrating proficiency in both Stencil (professional experience) and Lit (modern standard) shows adaptability and comprehensive Web Components expertise.
💡 Note: My Stencil experience provided a strong foundation in Web Components concepts (Shadow DOM, slots, events, lifecycle), making the transition to Lit straightforward while gaining exposure to a different approach in the ecosystem.
✨ Features
- 🎨 5 Core Components: Button, Badge, Input, Card, Modal
- 🌗 Dark/Light Theme Support: Built-in theming with CSS custom properties
- ♿ Accessible: ARIA attributes and keyboard navigation
- 🌳 Tree-Shakable: Import only what you need
- 📦 Lazy Loading: Components load on demand
- 🔧 Framework Agnostic: Works with any framework or vanilla JS
- 💪 TypeScript: Full type definitions included
📦 Installation
npm install @ldsui/components
# or
pnpm add @ldsui/components
# or
yarn add @ldsui/components🚀 Quick Start (Basic Usage)
1. Import and register components
// Option A: Register all components at once
import '@ldsui/components/define';
// Option B: Register only what you need (recommended for production)
import { defineLdsButton, defineLdsBadge } from '@ldsui/components';
defineLdsButton();
defineLdsBadge();2. Import design tokens (optional but recommended)
import '@ldsui/components/tokens.css';3. Use in HTML
<!DOCTYPE html>
<html data-theme="light">
<head>
<script type="module" src="your-app.js"></script>
</head>
<body>
<lds-button variant="primary" size="md">Click me</lds-button>
<lds-badge variant="success">Online</lds-badge>
<lds-card elevation="md" padding="lg">
<h2>Welcome</h2>
<lds-input label="Email" type="email" placeholder="[email protected]"></lds-input>
</lds-card>
</body>
</html>Framework Integration
React:
import '@ldsui/components/define';
function App() {
return <lds-button variant="primary">React Button</lds-button>;
}Vue:
<script setup>
import '@ldsui/components/define';
</script>
<template>
<lds-button variant="primary">Vue Button</lds-button>
</template>Angular:
// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@ldsui/components/define';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {}📚 Import Options
Option 1: Import all components
// Register all components at once
import '@ldsui/components/define';
// Import CSS tokens (optional, for theming)
import '@ldsui/components/tokens.css';<lds-button variant="primary">Click me</lds-button>
<lds-badge variant="success">New</lds-badge>Option 2: Import individual components (Tree-Shaking)
// Only import what you need
import { defineLdsButton } from '@ldsui/components/button';
import { defineLdsBadge } from '@ldsui/components/badge';
// Register the components
defineLdsButton();
defineLdsBadge();Option 3: Import classes for extension
import { LdsButton } from '@ldsui/components';
class MyCustomButton extends LdsButton {
// Extend the component
}🧩 Components
Button
A customizable button with variants, sizes, and states.
<lds-button variant="primary" size="md">Primary</lds-button>
<lds-button variant="secondary">Secondary</lds-button>
<lds-button variant="ghost">Ghost</lds-button>
<lds-button variant="danger">Danger</lds-button>
<lds-button disabled>Disabled</lds-button>
<lds-button loading>Loading...</lds-button>| Property | Type | Default | Description |
|----------|------|---------|-------------|
| variant | 'primary' \| 'secondary' \| 'ghost' \| 'danger' | 'primary' | Visual style variant |
| size | 'sm' \| 'md' \| 'lg' | 'md' | Button size |
| disabled | boolean | false | Disable the button |
| loading | boolean | false | Show loading state |
Badge
Status indicators and labels.
<lds-badge variant="primary">New</lds-badge>
<lds-badge variant="success">Active</lds-badge>
<lds-badge variant="warning">Pending</lds-badge>
<lds-badge variant="error">Error</lds-badge>| Property | Type | Default | Description |
|----------|------|---------|-------------|
| variant | 'primary' \| 'secondary' \| 'success' \| 'warning' \| 'error' | 'primary' | Visual style variant |
Input
Form input with label, helper text, and error states.
<lds-input
label="Email"
type="email"
placeholder="Enter your email"
helper-text="We'll never share your email"
></lds-input>
<lds-input
label="Password"
type="password"
error="Password is required"
></lds-input>| Property | Type | Default | Description |
|----------|------|---------|-------------|
| label | string | '' | Label text |
| type | 'text' \| 'email' \| 'password' \| 'number' \| 'tel' \| 'url' | 'text' | Input type |
| value | string | '' | Current value |
| placeholder | string | '' | Placeholder text |
| disabled | boolean | false | Disable the input |
| error | string | undefined | Error message |
| helperText | string | '' | Helper text |
Events:
lds-input-input- Fired on inputlds-input-change- Fired on change
Card
Container with elevation and padding options.
<lds-card elevation="md" padding="lg">
<h3>Card Title</h3>
<p>Card content goes here</p>
</lds-card>
<lds-card interactive>
<p>Clickable card</p>
</lds-card>| Property | Type | Default | Description |
|----------|------|---------|-------------|
| elevation | 'none' \| 'sm' \| 'md' | 'sm' | Shadow elevation |
| padding | 'none' \| 'sm' \| 'md' \| 'lg' | 'md' | Internal padding |
| interactive | boolean | false | Enable hover/focus styles |
Slots:
- Default slot - Card body content
header- Card header contentfooter- Card footer content
Modal
Dialog with focus management and accessibility.
<lds-modal open title="Confirm Action">
<p>Are you sure you want to proceed?</p>
<div slot="footer">
<lds-button variant="ghost">Cancel</lds-button>
<lds-button variant="primary">Confirm</lds-button>
</div>
</lds-modal>| Property | Type | Default | Description |
|----------|------|---------|-------------|
| open | boolean | false | Show/hide the modal |
| title | string | '' | Modal title |
| closeOnEsc | boolean | true | Close on Escape key |
| closeOnBackdropClick | boolean | true | Close on backdrop click |
Events:
lds-modal-close- Fired when modal closes (detail:{ reason: 'backdrop' | 'esc' | 'programmatic' })
Slots:
- Default slot - Modal body content
footer- Modal footer (typically buttons)
🎨 Design Tokens & Theming
LDS Components uses a comprehensive design token system built with CSS custom properties, enabling consistent styling and easy theme customization.
Available Tokens
/* Colors */
--lds-color-primary: #3b82f6;
--lds-color-primary-contrast: #ffffff;
--lds-color-secondary: #64748b;
--lds-color-success: #22c55e;
--lds-color-warning: #f59e0b;
--lds-color-error: #ef4444;
/* Spacing */
--lds-spacing-1: 0.25rem;
--lds-spacing-2: 0.5rem;
--lds-spacing-3: 0.75rem;
--lds-spacing-4: 1rem;
--lds-spacing-6: 1.5rem;
/* Typography */
--lds-font-size-sm: 0.875rem;
--lds-font-size-md: 1rem;
--lds-font-size-lg: 1.125rem;
/* Border Radius */
--lds-radius-md: 0.375rem;
--lds-radius-lg: 0.5rem;
/* Shadows */
--lds-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--lds-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);Using Tokens
Import the tokens CSS file:
@import '@ldsui/components/tokens.css';
/* Override tokens for your brand */
:root {
--lds-color-primary: #8b5cf6; /* Purple brand color */
}Light/Dark Theme Support
LDS Components supports automatic theme switching using the data-theme attribute:
<!-- Light theme (default) -->
<html data-theme="light">
<!-- Dark theme -->
<html data-theme="dark">JavaScript toggle:
// Toggle theme
const toggleTheme = () => {
const current = document.documentElement.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
};
// Respect system preference
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.setAttribute('data-theme', prefersDark ? 'dark' : 'light');CSS media query approach:
@media (prefers-color-scheme: dark) {
:root {
--lds-color-primary: #60a5fa;
--lds-color-primary-contrast: #0f172a;
/* ... other dark mode overrides */
}
}The token system ensures:
- ✅ Consistency across all components
- ✅ Easy customization without touching component internals
- ✅ Theme switching with a single attribute change
- ✅ CSS-in-JS compatibility (tokens work with any styling solution)
📖 Storybook
View all components and their variations in Storybook:
pnpm storybook🏗️ Development
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Run tests
pnpm test
# Build for production
pnpm build
# Run Storybook
pnpm storybook📄 License
MIT © Keiner Pajaro
🤝 Contributing
Contributions are welcome! Please read our contributing guidelines before submitting a PR.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
