Skip to content

Commit 5fbda20

Browse files
authored
Feat/custome themes (#12)
* feat(theming): implement custom theme system with teal theme * fix(select): add missing underline on items hover and focus * fix(sidebar): add missing underline on items hover and focus * docs: update readme * chore: bump version to 0.2.0
1 parent 0f00bd0 commit 5fbda20

85 files changed

Lines changed: 499 additions & 335 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 136 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,116 @@
11
# @nipsys/shadcn-lsd
22

3-
A React component library implementing the Logos Design System (LSD) using shadcn / Radix UI and Tailwind CSS.
4-
5-
## Overview
6-
7-
@nipsys/shadcn-lsd follows a minimalist design system. The library offers a comprehensive set of UI components with built-in light and dark theme support.
3+
A React component library implementing the Logos Design System (LSD). Built with Radix UI primitives and Tailwind CSS, following the shadcn/ui patterns.
84

95
## Installation
106

117
```bash
12-
npm install @nipsys/shadcn-lsd
13-
# or
148
pnpm add @nipsys/shadcn-lsd
159
```
1610

17-
## Quick Start
11+
## Usage
12+
13+
### Import the CSS
14+
15+
First, import the stylesheet in your application entry point:
1816

1917
```tsx
20-
import { Button, Input, Card } from '@nipsys/shadcn-lsd';
2118
import '@nipsys/shadcn-lsd/css';
19+
```
20+
21+
### Import Components
22+
23+
```tsx
24+
import { Button, Dialog, DialogTrigger, DialogContent } from '@nipsys/shadcn-lsd';
2225

2326
function App() {
2427
return (
25-
<div className="min-h-screen bg-background text-foreground">
26-
<Card className="p-6">
27-
<h1 className="text-2xl mb-4">Welcome to LSD React</h1>
28-
<Input placeholder="Enter your name" className="mb-4" />
29-
<Button>Submit</Button>
30-
</Card>
31-
</div>
28+
<Dialog>
29+
<DialogTrigger>Open</DialogTrigger>
30+
<DialogContent>
31+
<p>Dialog content here</p>
32+
</DialogContent>
33+
</Dialog>
3234
);
3335
}
3436
```
3537

36-
## Theming
38+
### Theming
3739

38-
LSD React uses CSS custom properties for theming. The theme can be switched by adding/removing the `.dark` class on the root element (or any container).
40+
The library supports light and dark themes out of the box. Add the `dark` class to your root element to enable dark mode:
3941

40-
### Light Theme (Default)
42+
```html
43+
<html class="dark">
44+
<!-- your app -->
45+
</html>
46+
```
4147

42-
```css
43-
:root {
44-
--lsd-text: 0 0 0; /* Black */
45-
--lsd-border: 0 0 0; /* Black */
46-
--lsd-surface-primary: 255 255 255; /* White */
47-
--lsd-surface-secondary: 255 255 255; /* White */
48-
}
48+
### Theme Variants
49+
50+
A teal theme variant is also available:
51+
52+
```html
53+
<html class="theme-teal">
54+
<!-- light teal theme -->
55+
</html>
56+
57+
<html class="dark theme-teal">
58+
<!-- dark teal theme -->
59+
</html>
4960
```
5061

51-
### Dark Theme
62+
### CSS Variables
63+
64+
The design system uses CSS custom properties that you can override:
5265

5366
```css
54-
.dark {
55-
--lsd-text: 255 255 255; /* White */
56-
--lsd-border: 255 255 255; /* White */
57-
--lsd-surface-primary: 0 0 0; /* Black */
58-
--lsd-surface-secondary: 0 0 0; /* Black */
67+
:root {
68+
--lsd-primary: #000000;
69+
--lsd-text-primary: #000000;
70+
--lsd-text-secondary: #808080;
71+
--lsd-border: #000000;
72+
--lsd-surface: #ffffff;
73+
--lsd-destructive: #b91c1c;
74+
--lsd-success: #15803d;
75+
--lsd-warning: #f59e0b;
76+
--lsd-info: #2563eb;
5977
}
6078
```
6179

6280
## Components
6381

64-
LSD React provides a comprehensive set of UI components:
65-
66-
### Form Components
67-
- **Input**: Text input with size variants
68-
- **Autocomplete**: Searchable dropdown with async support
69-
- **Select**: Native select with custom styling
70-
- **Checkbox**: Accessible checkbox component
71-
- **Switch**: Toggle switch component
72-
- **Label**: Form label with variants
73-
74-
### Navigation Components
75-
- **Tabs**: Tabbed interface with size variants
76-
- **Sidebar**: Collapsible sidebar with submenus
77-
- **Breadcrumb**: Navigation breadcrumb (coming soon)
78-
79-
### Layout Components
80-
- **Card**: Container with header, content, and footer
81-
- **Sheet**: Slide-out panel component
82-
- **Separator**: Visual divider
83-
- **ScrollArea**: Custom scrollable area
84-
85-
### Data Display Components
86-
- **Badge**: Status and label badges
87-
- **Typography**: Text components with variants
88-
- **Skeleton**: Loading placeholder
89-
- **Progress**: Progress bar with indeterminate state
90-
91-
### Feedback Components
92-
- **Dialog**: Modal dialog component
93-
- **AlertDialog**: Confirmation dialog
94-
- **Popover**: Popup content component
95-
- **Tooltip**: Hover tooltip
96-
- **Sonner**: Toast notifications
97-
98-
### Input Components
99-
- **Button**: Versatile button with variants and sizes
100-
- **ButtonGroup**: Grouped buttons
101-
- **Toggle**: Toggle button component
102-
- **ToggleGroup**: Grouped toggle buttons
82+
| Component | Description |
83+
|-----------|-------------|
84+
| Accordion | Vertically stacked collapsible sections |
85+
| AlertDialog | Modal dialog for critical confirmations |
86+
| Autocomplete | Input with async suggestion fetching |
87+
| Badge | Small label for status or categorization |
88+
| Button | Interactive button with multiple variants |
89+
| ButtonGroup | Grouped buttons with optional separators |
90+
| Card | Container for related content |
91+
| Checkbox | Boolean input control |
92+
| Command | Command palette for keyboard navigation |
93+
| Dialog | Modal overlay for focused content |
94+
| Input | Text input field |
95+
| Label | Form field label |
96+
| Popover | Floating content anchored to trigger |
97+
| Progress | Visual indicator of completion |
98+
| ScrollArea | Custom scrollbar container |
99+
| Select | Dropdown selection input |
100+
| Separator | Visual divider between sections |
101+
| Sheet | Slide-out panel overlay |
102+
| Sidebar | Navigation sidebar component |
103+
| Skeleton | Loading placeholder |
104+
| Sonner | Toast notifications |
105+
| Switch | Toggle switch input |
106+
| Tabs | Tabbed content navigation |
107+
| Toggle | Two-state button |
108+
| ToggleGroup | Group of toggle buttons |
109+
| Tooltip | Hover information popup |
110+
| Typography | Text styling components |
103111

104112
## Development
105-
113+
M
106114
### Prerequisites
107115

108116
- Node.js >= 24.0.0
@@ -111,20 +119,70 @@ LSD React provides a comprehensive set of UI components:
111119
### Setup
112120

113121
```bash
122+
# Clone the repository
114123
git clone https://github.com/nipsysdev/shadcn-lsd.git
115124
cd shadcn-lsd
125+
126+
# Install dependencies
116127
pnpm install
117128
```
118129

119130
### Scripts
120131

121-
- `pnpm dev` - Start development server
122-
- `pnpm build` - Build the library
123-
- `pnpm cosmos` - Start React Cosmos dev server
124-
- `pnpm cosmos:export` - Export Cosmos site
125-
- `pnpm lint` - Run linting
132+
```bash
133+
# Start component playground
134+
pnpm cosmos
126135

136+
# Build the library
137+
pnpm build
138+
139+
# Run tests
140+
pnpm test
141+
142+
# Run tests in watch mode
143+
pnpm test:watch
144+
145+
# Run tests with coverage
146+
pnpm test:coverage
147+
148+
# Lint code
149+
pnpm lint
150+
151+
# Format code
152+
pnpm format
153+
```
154+
155+
### Component Playground
156+
157+
The project uses React Cosmos for component development. Run `pnpm cosmos` to start the playground at `http://localhost:5000`.
158+
159+
To export a static build for deployment:
160+
161+
```bash
162+
pnpm cosmos-export
163+
```
164+
165+
## Tech Stack
166+
167+
- **React 19** - UI library
168+
- **TypeScript** - Type safety
169+
- **Tailwind CSS 4** - Utility-first styling
170+
- **Radix UI** - Accessible primitives
171+
- **Vite** - Build tooling
172+
- **Vitest** - Testing framework
173+
- **React Cosmos** - Component playground
174+
175+
## Peer Dependencies
176+
177+
Make sure your project has these installed:
178+
179+
```json
180+
{
181+
"react": "^19.2.4",
182+
"react-dom": "^19.2.4"
183+
}
184+
```
127185

128186
## License
129187

130-
Licensed under GNU GPL v3+
188+
[GPL-3.0-or-later](LICENSE)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"publishConfig": {
66
"access": "public"
77
},
8-
"version": "0.1.0",
8+
"version": "0.2.0",
99
"type": "module",
1010
"module": "./dist/main.js",
1111
"exports": {

src/__cosmos__/code-block.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export function CodeBlock({ className, code, ...props }: CodeBlockProps) {
99
return (
1010
<pre
1111
className={cn(
12-
'lsd:overflow-x-auto lsd:rounded-md lsd:bg-lsd-surface-secondary lsd:p-4 lsd:text-sm lsd:text-lsd-text-primary',
12+
'lsd:overflow-x-auto lsd:rounded-md lsd:bg-lsd-surface lsd:p-4 lsd:text-sm lsd:text-lsd-text-primary',
1313
className,
1414
)}
1515
{...props}

src/__cosmos__/fixtures/Accordion.fixture.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ import {
66
} from '@/components/ui/accordion';
77
import { CodeExample } from '../code-example';
88
import { FontToggle } from '../font-toggle';
9-
import { ThemeToggle } from '../theme-toggle';
9+
import { ThemeAccentToggle, ThemeToggle } from '../theme-toggle';
1010

1111
export default function AccordionFixture() {
1212
return (
1313
<div className="lsd:p-8 lsd:w-full lsd:space-y-8">
1414
<div className="lsd:flex lsd:justify-end lsd:gap-4">
1515
<ThemeToggle />
16+
<ThemeAccentToggle />
1617
<FontToggle />
1718
</div>
1819

src/__cosmos__/fixtures/AlertDialog.fixture.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
import { Button } from '@/components/ui/button';
1414
import { CodeExample } from '../code-example';
1515
import { FontToggle } from '../font-toggle';
16-
import { ThemeToggle } from '../theme-toggle';
16+
import { ThemeAccentToggle, ThemeToggle } from '../theme-toggle';
1717

1818
export default function AlertDialogFixture() {
1919
const [showBasicDialog, setShowBasicDialog] = useState(false);
@@ -24,6 +24,7 @@ export default function AlertDialogFixture() {
2424
<div className="lsd:p-8 lsd:w-full lsd:space-y-8">
2525
<div className="lsd:flex lsd:justify-end lsd:gap-4">
2626
<ThemeToggle />
27+
<ThemeAccentToggle />
2728
<FontToggle />
2829
</div>
2930

src/__cosmos__/fixtures/Autocomplete.fixture.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Autocomplete } from '@/components/ui/autocomplete';
44
import { Button } from '@/components/ui/button';
55
import { CodeExample } from '../code-example';
66
import { FontToggle } from '../font-toggle';
7-
import { ThemeToggle } from '../theme-toggle';
7+
import { ThemeAccentToggle, ThemeToggle } from '../theme-toggle';
88

99
const frameworks = [
1010
{ value: '1', label: 'React' },
@@ -19,6 +19,7 @@ export default () => (
1919
<div className="lsd:p-8 lsd:w-full lsd:space-y-8">
2020
<div className="lsd:flex lsd:justify-end lsd:gap-4">
2121
<ThemeToggle />
22+
<ThemeAccentToggle />
2223
<FontToggle />
2324
</div>
2425

src/__cosmos__/fixtures/Badge.fixture.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useState } from 'react';
22
import { Badge } from '@/components/ui/badge';
33
import { CodeExample } from '../code-example';
44
import { FontToggle } from '../font-toggle';
5-
import { ThemeToggle } from '../theme-toggle';
5+
import { ThemeAccentToggle, ThemeToggle } from '../theme-toggle';
66

77
export default function BadgeFixture() {
88
const [dismissedBadges, setDismissedBadges] = useState<Set<number>>(
@@ -77,6 +77,7 @@ export default function BadgeFixture() {
7777
<div className="lsd:p-8 lsd:w-full lsd:space-y-8">
7878
<div className="lsd:flex lsd:justify-end lsd:gap-4">
7979
<ThemeToggle />
80+
<ThemeAccentToggle />
8081
<FontToggle />
8182
</div>
8283

src/__cosmos__/fixtures/Button.fixture.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ import { Plus } from 'lucide-react';
22
import { Button } from '@/components/ui/button';
33
import { CodeExample } from '../code-example';
44
import { FontToggle } from '../font-toggle';
5-
import { ThemeToggle } from '../theme-toggle';
5+
import { ThemeAccentToggle, ThemeToggle } from '../theme-toggle';
66

77
export default function ButtonFixture() {
88
return (
99
<div className="lsd:p-8 lsd:w-full lsd:space-y-8">
1010
<div className="lsd:flex lsd:justify-end lsd:gap-4">
1111
<ThemeToggle />
12+
<ThemeAccentToggle />
1213
<FontToggle />
1314
</div>
1415

src/__cosmos__/fixtures/ButtonGroup.fixture.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ import { Button } from '@/components/ui/button';
22
import { ButtonGroup, ButtonGroupText } from '@/components/ui/button-group';
33
import { CodeExample } from '../code-example';
44
import { FontToggle } from '../font-toggle';
5-
import { ThemeToggle } from '../theme-toggle';
5+
import { ThemeAccentToggle, ThemeToggle } from '../theme-toggle';
66

77
export default function ButtonGroupFixture() {
88
return (
99
<div className="lsd:p-8 lsd:w-full lsd:space-y-8">
1010
<div className="lsd:flex lsd:justify-end lsd:gap-4">
1111
<ThemeToggle />
12+
<ThemeAccentToggle />
1213
<FontToggle />
1314
</div>
1415

src/__cosmos__/fixtures/Card.fixture.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import {
1010
} from '@/components/ui/card';
1111
import { CodeExample } from '../code-example';
1212
import { FontToggle } from '../font-toggle';
13-
import { ThemeToggle } from '../theme-toggle';
13+
import { ThemeAccentToggle, ThemeToggle } from '../theme-toggle';
1414

1515
export default function CardFixture() {
1616
return (
1717
<div className="lsd:p-8 lsd:w-full lsd:space-y-8">
1818
<div className="lsd:flex lsd:justify-end lsd:gap-4">
1919
<ThemeToggle />
20+
<ThemeAccentToggle />
2021
<FontToggle />
2122
</div>
2223

0 commit comments

Comments
 (0)