Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Migration Guide: SCL 0.2.x → 0.3.0

This guide documents breaking changes when upgrading from SCL 0.2.x to 0.3.0.

## Overview

SCL 0.3.0 is a complete rebuild using pure Radix primitives and vanilla CSS. All Tailwind CSS dependencies have been removed.

## Breaking Changes

### 1. Button Variant Rename

The `default` variant has been renamed to `primary`.

**Before (0.2.x):**
```tsx
<Button variant="default">Click me</Button>
```

**After (0.3.0):**
```tsx
<Button variant="primary">Click me</Button>
```

**Migration:** Find and replace all instances of `variant="default"` with `variant="primary"` in your Button components.

### 2. CSS Class Names

All components now use BEM-like CSS class names prefixed with `scl-`.

**Before (0.2.x):** Tailwind utility classes
```html
<button class="bg-primary text-primary-foreground h-10 px-4">
```

**After (0.3.0):** SCL CSS classes
```html
<button class="scl-button scl-button--primary scl-button--default">
```

### 3. Removed Components

The following components have been removed in 0.3.0:

| Component | Reason |
|-----------|--------|
| `AlertDialog` | Depended on removed dependencies |
| `Command` | Depended on `cmdk` package |
| `Combobox` | Depended on `cmdk` package |
| `DropdownMenu` | Depended on `lucide-react` |
| `Form` | Depended on `react-hook-form` |
| `Sheet` | Depended on `vaul` and `lucide-react` |
| `DitheredImage` | Custom component removed |
| `Statusline` | Custom component removed |
| `TerminalTextarea` | Custom component removed |

### 4. Removed Exports

The following exports have been removed:

- `buttonVariants` → Use `ButtonVariant` type instead
- `badgeVariants` → Use `BadgeVariant` type instead
- `toggleVariants` → Use `ToggleSize` type instead

### 5. CSS Import

You must import the global CSS file for components to render correctly:

```tsx
import '@drjoshcsimmons/scl/dist/globals.css';
```

### 6. Removed Dependencies

The following peer dependencies are no longer required:

- `tailwindcss`
- `postcss`
- `autoprefixer`
- `class-variance-authority`
- `tailwind-merge`
- `clsx`
- `lucide-react`
- `cmdk`
- `react-hook-form`
- `@hookform/resolvers`
- `zod`
- `vaul`

## New Features

### CSS Custom Properties

All design tokens are now available as CSS custom properties:

```css
:root {
--scl-primary: hsl(120, 100%, 50%);
--scl-secondary: hsl(300, 100%, 50%);
--scl-destructive: hsl(0, 100%, 50%);
--scl-space-4: 1rem;
/* ... */
}
```

### Theme Classes

Apply theme variants using CSS classes:

```tsx
<div className="scl-theme-yellow">
{/* Components use yellow as primary color */}
</div>
```

Available themes: `scl-theme-yellow`, `scl-theme-blue`, `scl-theme-white`, `scl-theme-amber`, `scl-theme-hotpink`, `scl-theme-cyan`

## Full Component List (0.3.0)

The following 25 components are available:

- Accordion
- Alert
- Avatar
- Badge
- Button
- Card
- Checkbox
- Collapsible
- Dialog
- Input
- Label
- Popover
- Progress
- RadioGroup
- ScrollArea
- Select
- Separator
- Skeleton
- Slider
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Tooltip
391 changes: 1 addition & 390 deletions bun.lock

Large diffs are not rendered by default.

51 changes: 5 additions & 46 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
{
"name": "@drjoshcsimmons/scl",
"version": "0.2.8",
"description": "A retro terminal-themed React component library built on Radix and Tailwind",
"version": "0.3.0",
"description": "A retro terminal-themed React component library built on Radix primitives with vanilla CSS",
"keywords": [
"react",
"components",
"ui",
"terminal",
"retro",
"radix",
"tailwind",
"shadcn"
"radix"
],
"homepage": "https://jcpsimmons.github.io/scl/",
"author": "Josh Simmons",
Expand Down Expand Up @@ -48,28 +46,22 @@
"format": "biome format --write src",
"check": "biome check --write src",
"typecheck": "tsc --noEmit",
"prepublishOnly": "npm run build"
"prepublishOnly": "bun run build"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
"@hookform/resolvers": "^3.9.0",
"@radix-ui/react-accordion": "^1.2.0",
"@radix-ui/react-alert-dialog": "^1.1.0",
"@radix-ui/react-aspect-ratio": "^1.1.0",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-checkbox": "^1.1.0",
"@radix-ui/react-collapsible": "^1.1.0",
"@radix-ui/react-context-menu": "^2.2.0",
"@radix-ui/react-dialog": "^1.1.0",
"@radix-ui/react-dropdown-menu": "^2.1.0",
"@radix-ui/react-hover-card": "^1.1.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-menubar": "^1.1.0",
"@radix-ui/react-navigation-menu": "^1.2.0",
"@radix-ui/react-popover": "^1.1.0",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-radio-group": "^1.2.0",
Expand All @@ -80,9 +72,7 @@
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-switch": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-toast": "^1.2.0",
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-toggle-group": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.0",
"@storybook/addon-a11y": "8.6.15",
"@storybook/addon-essentials": "8.6.15",
Expand All @@ -100,47 +90,16 @@
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.0",
"@vitest/coverage-v8": "^2.1.0",
"autoprefixer": "^10.4.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cmdk": "^1.0.0",
"date-fns": "^3.6.0",
"embla-carousel-react": "^8.3.0",
"input-otp": "^1.4.0",
"jsdom": "^25.0.0",
"lucide-react": "^0.460.0",
"postcss": "^8.4.0",
"react": "^18.3.0",
"react-day-picker": "^9.3.0",
"react-dom": "^18.3.0",
"react-hook-form": "^7.54.0",
"react-resizable-panels": "^2.1.0",
"recharts": "^2.13.0",
"sonner": "^1.7.0",
"storybook": "8.6.15",
"tailwind-merge": "^2.5.0",
"tailwindcss": "^3.4.0",
"tailwindcss-animate": "^1.0.0",
"typescript": "^5.6.0",
"vaul": "^1.1.0",
"vite": "^5.4.0",
"vite-plugin-dts": "^4.3.0",
"vitest": "^2.1.0",
"zod": "^3.24.0"
"vitest": "^2.1.0"
},
"dependencies": {
"@codemirror/basic-setup": "^0.20.0",
"@codemirror/commands": "^6.10.1",
"@codemirror/lang-css": "^6.3.1",
"@codemirror/lang-html": "^6.4.11",
"@codemirror/lang-javascript": "^6.2.4",
"@codemirror/lang-json": "^6.0.2",
"@codemirror/lang-markdown": "^6.5.0",
"@codemirror/language": "^6.11.3",
"@codemirror/state": "^6.5.2",
"@codemirror/view": "^6.39.4",
"@lezer/highlight": "^1.2.3",
"@replit/codemirror-vim": "^6.3.0",
"@vercel/analytics": "^1.6.1"
}
}
6 changes: 0 additions & 6 deletions postcss.config.js

This file was deleted.

58 changes: 58 additions & 0 deletions src/components/ui/accordion/accordion.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* Accordion Component Styles */

.scl-accordion-item {
border-bottom: 2px solid var(--scl-primary);
width: 100%;
}

.scl-accordion-header {
display: flex;
}

.scl-accordion-trigger {
display: flex;
flex: 1;
align-items: center;
justify-content: space-between;
padding: var(--scl-space-4) 0;
font-size: var(--scl-text-sm);
font-weight: 500;
font-family: var(--scl-font-mono);
text-align: left;
background: none;
border: none;
color: var(--scl-primary);
cursor: pointer;
}

.scl-accordion-trigger:hover {
text-decoration: underline;
}

.scl-accordion-trigger__icon {
width: 1rem;
height: 1rem;
flex-shrink: 0;
color: var(--scl-muted-foreground);
transition: transform var(--scl-duration-normal);
}

.scl-accordion-trigger[data-state="open"] .scl-accordion-trigger__icon {
transform: rotate(180deg);
}

.scl-accordion-content {
overflow: hidden;
font-size: var(--scl-text-sm);
color: var(--scl-primary);
}

.scl-accordion-content[data-state="closed"] {
height: 0;
visibility: hidden;
}

.scl-accordion-content__inner {
padding-bottom: var(--scl-space-4);
padding-top: 0;
}
37 changes: 26 additions & 11 deletions src/components/ui/accordion/accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,48 @@
import * as AccordionPrimitive from '@radix-ui/react-accordion';
import { ChevronDown } from 'lucide-react';
import * as React from 'react';
import { cn } from '@/lib/utils';
import { cx } from '@/lib/utils';
import './accordion.css';

const Accordion = AccordionPrimitive.Root;

const ChevronIcon = () => (
<svg
className="scl-accordion-trigger__icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="square"
aria-hidden="true"
>
<polyline points="6 9 12 15 18 9" />
</svg>
);

const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item ref={ref} className={cn('border-b-2 w-full', className)} {...props} />
<AccordionPrimitive.Item
ref={ref}
className={cx('scl-accordion-item', className)}
{...props}
/>
));
AccordionItem.displayName = 'AccordionItem';

const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Header className="scl-accordion-header">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
'flex flex-1 items-center justify-between py-4 text-sm font-medium hover:underline text-left [&[data-state=open]>svg]:rotate-180',
className
)}
className={cx('scl-accordion-trigger', className)}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground" />
<ChevronIcon />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
));
Expand All @@ -39,10 +54,10 @@ const AccordionContent = React.forwardRef<
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className="overflow-hidden text-sm data-[state=closed]:h-0 data-[state=closed]:invisible"
className="scl-accordion-content"
{...props}
>
<div className={cn('pb-4 pt-0', className)}>{children}</div>
<div className={cx('scl-accordion-content__inner', className)}>{children}</div>
</AccordionPrimitive.Content>
));
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
Expand Down
Loading