cooterlabs 1.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +228 -45
- package/bin/index.js +376 -22
- package/package.json +12 -4
- package/templates/_lib/utils.ts +28 -0
- package/templates/action-sheet/action-sheet.tsx +108 -0
- package/templates/alert/alert.tsx +146 -0
- package/templates/avatar/avatar.tsx +20 -8
- package/templates/badge/badge.tsx +114 -25
- package/templates/breadcrumb/breadcrumb.tsx +108 -0
- package/templates/button/button.tsx +39 -6
- package/templates/button-group/button-group.tsx +88 -0
- package/templates/card/card.tsx +31 -24
- package/templates/checkbox/checkbox.tsx +5 -9
- package/templates/context-menu/context-menu.tsx +172 -0
- package/templates/dialog/dialog.tsx +122 -0
- package/templates/dropdown/dropdown.tsx +175 -0
- package/templates/input/input.tsx +80 -14
- package/templates/label/label.tsx +2 -7
- package/templates/list/list.tsx +91 -0
- package/templates/loader/loader.tsx +33 -0
- package/templates/navbar-bottom/navbar-bottom.tsx +71 -0
- package/templates/navbar-top/navbar-top.tsx +79 -0
- package/templates/page-control/page-control.tsx +50 -0
- package/templates/pagination/pagination.tsx +104 -0
- package/templates/progress/progress.tsx +64 -0
- package/templates/radio/radio.tsx +36 -0
- package/templates/select/select.tsx +113 -0
- package/templates/stepper/stepper.tsx +88 -0
- package/templates/tabs/tabs.tsx +52 -0
- package/templates/textarea/textarea.tsx +2 -7
- package/templates/toggle/toggle.tsx +22 -0
- package/templates/tooltip/tooltip.tsx +32 -0
package/README.md
CHANGED
|
@@ -1,80 +1,263 @@
|
|
|
1
1
|
# CooterLabs UI Library CLI
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A standalone CLI for scaffolding the **Aeon Product Design System** — beautiful, accessible, highly customizable React components — directly into your React, Vite, or Next.js project.
|
|
4
4
|
|
|
5
|
-
It brings components directly to you.
|
|
5
|
+
It brings components directly to you. This is **not** an importable NPM package: the actual React TS/JS source is scaffolded straight into your `src/components/ui` folder, so you completely own the implementation, styles, and markup. Think shadcn/ui, but for the Aeon design system.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx cooterlabs init # set up the theme
|
|
9
|
+
npx cooterlabs add button # scaffold a component
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Table of contents
|
|
15
|
+
|
|
16
|
+
- [Features](#features)
|
|
17
|
+
- [Requirements](#requirements)
|
|
18
|
+
- [Commands](#commands)
|
|
19
|
+
- [`init` — theme setup](#init--theme-setup)
|
|
20
|
+
- [`add` — scaffold components](#add--scaffold-components)
|
|
21
|
+
- [The shared `cn()` utility](#the-shared-cn-utility)
|
|
22
|
+
- [The Aeon theme](#the-aeon-theme)
|
|
23
|
+
- [Semantic colors](#semantic-colors)
|
|
24
|
+
- [Primitive color scales](#primitive-color-scales)
|
|
25
|
+
- [Typography ramp](#typography-ramp)
|
|
26
|
+
- [Radius, elevation & focus ring](#radius-elevation--focus-ring)
|
|
27
|
+
- [Component reference](#component-reference)
|
|
28
|
+
- [How it works under the hood](#how-it-works-under-the-hood)
|
|
29
|
+
- [Changelog](#changelog)
|
|
30
|
+
- [License](#license)
|
|
31
|
+
|
|
32
|
+
---
|
|
6
33
|
|
|
7
34
|
## Features
|
|
8
35
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
36
|
+
- **Project detection** — auto-detects your ecosystem: Next.js (App router or Pages router), Vite, or Create React App, plus your package manager (`npm`, `pnpm`, `yarn`, `bun`) from lockfiles.
|
|
37
|
+
- **TypeScript vs. JavaScript** — installs `.tsx` component files when TypeScript is detected (via `typescript` dependency or `tsconfig.json`), falling back to `.jsx` otherwise.
|
|
38
|
+
- **Tailwind awareness** — warns if Tailwind CSS isn't detected, since all components are styled with Tailwind utilities.
|
|
39
|
+
- **Dependency auto-install** — each component's runtime dependencies (`@radix-ui/*`, `lucide-react`, `clsx`, `tailwind-merge`) are resolved and installed automatically, collectively, in one pass.
|
|
40
|
+
- **Component dependencies** — components that build on other components (e.g. `select` reuses `input`'s variant styles) automatically pull in what they need.
|
|
41
|
+
- **Shared `cn()` helper** — a single `src/lib/utils.ts` is scaffolded once and shared by every component, with a tailwind-merge config that understands the Aeon type ramp (see [below](#the-shared-cn-utility)).
|
|
42
|
+
- **Prettier formatting** — components are formatted with *your* project's Prettier config before being written, so they match your code style from the first commit.
|
|
43
|
+
- **Interactive interface** — run without arguments to get an autocomplete multi-select of every available component.
|
|
15
44
|
|
|
16
|
-
##
|
|
45
|
+
## Requirements
|
|
17
46
|
|
|
18
|
-
|
|
19
|
-
|
|
47
|
+
- **React 18+** project (Vite, Next.js, or CRA).
|
|
48
|
+
- **Tailwind CSS v4** for the default `aeon` theme (it's emitted as a v4 `@theme` block). The legacy `zinc` / `slate` themes target Tailwind v3 / shadcn-style HSL variables.
|
|
49
|
+
- Node 18+ (the CLI is an ES module).
|
|
20
50
|
|
|
21
|
-
|
|
51
|
+
---
|
|
22
52
|
|
|
23
|
-
|
|
53
|
+
## Commands
|
|
54
|
+
|
|
55
|
+
### `init` — theme setup
|
|
56
|
+
|
|
57
|
+
Sets up the design-system CSS variables in your base stylesheet (`src/index.css`, `app/globals.css`, or `styles/globals.css` — resolved automatically per framework):
|
|
24
58
|
|
|
25
59
|
```bash
|
|
26
|
-
npx cooterlabs init
|
|
60
|
+
npx cooterlabs init # interactive theme picker
|
|
61
|
+
npx cooterlabs init aeon # non-interactive, applies the default theme
|
|
27
62
|
```
|
|
28
63
|
|
|
29
|
-
|
|
64
|
+
What it does:
|
|
65
|
+
|
|
66
|
+
1. Locates (or creates) your base CSS file.
|
|
67
|
+
2. Ensures the Tailwind entry point exists — `@import "tailwindcss";` for v4 themes, the classic `@tailwind base/components/utilities` trio for legacy themes.
|
|
68
|
+
3. Appends the theme block. For **aeon** this is a Tailwind v4 `@theme static { … }` block plus the `alert-timer` keyframes used by the Alert component's auto-dismiss countdown.
|
|
69
|
+
4. If theme variables already exist in the file, it prints the block for you to merge manually instead of clobbering your file.
|
|
30
70
|
|
|
31
|
-
|
|
71
|
+
Available themes:
|
|
32
72
|
|
|
33
|
-
|
|
73
|
+
| Theme | Format | Description |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `aeon` *(default)* | Tailwind v4 `@theme` | The full Aeon Product Design System — colors, type ramp, radii, elevation, focus ring. |
|
|
76
|
+
| `zinc` | v3 / shadcn HSL `:root` vars | Legacy neutral theme. |
|
|
77
|
+
| `slate` | v3 / shadcn HSL `:root` vars | Legacy cool-grey theme. |
|
|
78
|
+
|
|
79
|
+
### `add` — scaffold components
|
|
34
80
|
|
|
35
81
|
```bash
|
|
36
|
-
npx cooterlabs add
|
|
82
|
+
npx cooterlabs add # interactive multi-select
|
|
83
|
+
npx cooterlabs add button # one component
|
|
84
|
+
npx cooterlabs add card badge # ⚠️ one at a time — run twice, or use the picker
|
|
85
|
+
npx cooterlabs add --all # everything
|
|
37
86
|
```
|
|
38
87
|
|
|
39
|
-
|
|
88
|
+
What it does, per run:
|
|
40
89
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
90
|
+
1. Detects framework, TypeScript, Tailwind, and package manager.
|
|
91
|
+
2. Expands component requirements — e.g. `add select` also scaffolds `input`, because `select.tsx` imports its shared variant styles from `./input`.
|
|
92
|
+
3. Scaffolds `src/lib/utils.ts` (the shared `cn()` helper) if it doesn't exist yet.
|
|
93
|
+
4. Copies each component into `src/components/ui/` (or `components/ui/` for Next.js without `src/`), formatted with your Prettier config.
|
|
94
|
+
5. Installs the union of all required runtime dependencies in a single package-manager invocation.
|
|
95
|
+
|
|
96
|
+
Existing files with the same name are overwritten — re-running `add` is also how you *update* a component to the latest version (diff your local changes first if you've customized it).
|
|
44
97
|
|
|
45
|
-
|
|
46
|
-
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## The shared `cn()` utility
|
|
101
|
+
|
|
102
|
+
Every component imports one helper:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { cn } from "../../lib/utils"
|
|
47
106
|
```
|
|
48
107
|
|
|
49
|
-
|
|
108
|
+
The CLI scaffolds this file once, at `src/lib/utils.ts` (or `lib/utils.js`). It is **not** the stock shadcn two-liner — it uses `extendTailwindMerge` to teach tailwind-merge the Aeon font-size ramp:
|
|
50
109
|
|
|
51
|
-
|
|
110
|
+
```ts
|
|
111
|
+
import { clsx, type ClassValue } from "clsx"
|
|
112
|
+
import { extendTailwindMerge } from "tailwind-merge"
|
|
52
113
|
|
|
53
|
-
|
|
54
|
-
|
|
114
|
+
const twMerge = extendTailwindMerge({
|
|
115
|
+
extend: {
|
|
116
|
+
classGroups: {
|
|
117
|
+
"font-size": [{ text: ["h1", …, "b4", …, "btn-tiny"] }],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
export function cn(...inputs: ClassValue[]) {
|
|
123
|
+
return twMerge(clsx(inputs))
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Why this matters:** without it, tailwind-merge treats custom utilities like `text-b4` as text *colors* and silently drops real color classes like `text-white` when they appear together. If you already have your own `lib/utils`, the CLI won't overwrite it — but make sure it includes this classGroups extension or component styles will subtly break.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## The Aeon theme
|
|
132
|
+
|
|
133
|
+
Running `npx cooterlabs init aeon` gives you the complete design system as CSS variables, which Tailwind v4 turns into utilities automatically.
|
|
134
|
+
|
|
135
|
+
### Semantic colors
|
|
136
|
+
|
|
137
|
+
`background`, `foreground`, `card`, `popover`, `primary` (deep teal `#0d3435`), `secondary`, `muted`, `accent`, `destructive`, `border`, `input`, `ring` — plus status colors `success`, `info`, `warning`, `error`, each with a `-foreground` pair. Use them as `bg-primary`, `text-muted-foreground`, `border-border`, etc.
|
|
138
|
+
|
|
139
|
+
### Primitive color scales
|
|
140
|
+
|
|
141
|
+
Full 50–900 scales for `primary-*`, `grey-*`, `success-*`, `error-*`, `warning-*`, and `info-*` — e.g. `bg-primary-50`, `text-grey-500`, `border-error-200`. Components use these for hover/active/disabled states, so keep them if you retheme.
|
|
142
|
+
|
|
143
|
+
### Typography ramp
|
|
144
|
+
|
|
145
|
+
The entire Aeon type ramp ships as `--text-*` variables, each with size, line-height, **and weight** baked in:
|
|
146
|
+
|
|
147
|
+
| Utilities | Role |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `text-h1` … `text-h5` | Headings (48px/600 → 24px/600) |
|
|
150
|
+
| `text-s1`, `text-s2` | Subtitles |
|
|
151
|
+
| `text-b1` … `text-b4` | Body (regular & medium, 16px & 14px) |
|
|
152
|
+
| `text-c1` … `text-c3` | Captions (12px & 10px) |
|
|
153
|
+
| `text-label` | Form labels |
|
|
154
|
+
| `text-btn-giant` … `text-btn-tiny` | Button text sizes |
|
|
155
|
+
|
|
156
|
+
Font family: **Inter** (`--font-sans`). Load the font yourself (e.g. via Google Fonts or `@fontsource/inter`) — the theme only declares the stack.
|
|
157
|
+
|
|
158
|
+
### Radius, elevation & focus ring
|
|
159
|
+
|
|
160
|
+
- **Radius:** `rounded-xxs` (4px) → `rounded-xl` (24px).
|
|
161
|
+
- **Elevation:** `shadow-100` → `shadow-800`.
|
|
162
|
+
- **Focus ring:** `--shadow-focus` (a 3px `#c2f5f6` halo) — every interactive component uses `focus-visible:shadow-focus` for a consistent, accessible focus style.
|
|
163
|
+
- **`@keyframes alert-timer`:** powers the Alert component's auto-dismiss countdown bar; emitted alongside the theme block.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Component reference
|
|
168
|
+
|
|
169
|
+
All components live in `components/ui/`, are fully typed, and follow the Aeon size ramp (`giant / large / medium / small / tiny`) where applicable. Radix-based components keep the full Radix composition API.
|
|
170
|
+
|
|
171
|
+
### Form controls
|
|
172
|
+
|
|
173
|
+
| Component | Exports | Key props / notes |
|
|
174
|
+
|---|---|---|
|
|
175
|
+
| `button` | `Button` | `variant`: `filled` \| `outline` \| `clear` · `size`: giant→tiny · `iconOnly` · `asChild` (Radix `Slot`). |
|
|
176
|
+
| `button-group` | `ButtonGroup`, `ButtonGroupItem` | Segmented control matching the button size ramp. |
|
|
177
|
+
| `input` | `Input` (+ exported style maps reused by `select`) | `variant`: `outline` \| `filled` · `size`: `large` \| `medium` · `status`: success/info/warning/error · `helperText` · `icon`. |
|
|
178
|
+
| `textarea` | `Textarea` | Multiline input matching `input` styling. |
|
|
179
|
+
| `select` | `Select`, `SelectTrigger`, `SelectContent`, `SelectItem`, `SelectValue`, `SelectGroup`, … | Radix select styled as an Aeon input; **requires `input`** (auto-installed). |
|
|
180
|
+
| `label` | `Label` | Radix label. |
|
|
181
|
+
| `checkbox` | `Checkbox` | Radix checkbox with indeterminate support. |
|
|
182
|
+
| `radio` | `RadioGroup`, `RadioGroupItem` | Radix radio group. |
|
|
183
|
+
| `toggle` | `Toggle` | Radix switch. |
|
|
184
|
+
|
|
185
|
+
### Feedback
|
|
186
|
+
|
|
187
|
+
| Component | Exports | Key props / notes |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| `alert` | `Alert`, `AlertTitle`, `AlertDescription`, `AlertActions` | `severity`: default/success/info/warning/error · `variant`: `filled` \| `outline` · `position` (fixed placements) · `duration` (auto-dismiss seconds, pauses on hover, animated countdown) · `onDismiss`. |
|
|
190
|
+
| `badge` | `Badge` | `type`: `badge` \| `chip` (chips are dismissible/selectable) · `variant`: `filled` \| `outline` · `color`: default/success/info/warning/error · `size`: medium/small/tiny · `iconOnly`. |
|
|
191
|
+
| `avatar` | `Avatar`, `AvatarImage`, `AvatarFallback` | Radix avatar, `size`: giant→tiny. |
|
|
192
|
+
| `progress` | `Progress` | Radix progress; `label`: `left` \| `right` percentage label · `disabled`. |
|
|
193
|
+
| `loader` | `Loader` | CSS spinner, `size`: giant→tiny. |
|
|
194
|
+
| `tooltip` | `TooltipProvider`, `Tooltip`, `TooltipTrigger`, `TooltipContent` | Radix dark tooltip. |
|
|
195
|
+
|
|
196
|
+
### Overlays
|
|
197
|
+
|
|
198
|
+
| Component | Exports | Key props / notes |
|
|
199
|
+
|---|---|---|
|
|
200
|
+
| `dialog` | `Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader`, `DialogFooter`, … | Radix dialog (Pop-Up). |
|
|
201
|
+
| `action-sheet` | `ActionSheet`, `ActionSheetTrigger`, `ActionSheetContent`, … | Mobile bottom sheet built on Radix dialog. |
|
|
202
|
+
| `context-menu` | `ContextMenu`, `ContextMenuTrigger`, `ContextMenuContent`, `ContextMenuItem`, checkbox/radio items, … | Radix context menu. |
|
|
203
|
+
| `dropdown` | `DropdownMenu`, `DropdownMenuTrigger`, `DropdownMenuContent`, `DropdownMenuItem`, … | Radix dropdown menu. |
|
|
204
|
+
|
|
205
|
+
### Navigation
|
|
206
|
+
|
|
207
|
+
| Component | Exports | Key props / notes |
|
|
208
|
+
|---|---|---|
|
|
209
|
+
| `tabs` | `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent` | Radix tabs. |
|
|
210
|
+
| `breadcrumb` | `Breadcrumb`, `BreadcrumbList`, `BreadcrumbItem`, `BreadcrumbLink`, `BreadcrumbPage`, `BreadcrumbSeparator`, … | Accessible breadcrumb trail. |
|
|
211
|
+
| `pagination` | `Pagination`, `PaginationContent`, `PaginationItem`, `PaginationLink`, `PaginationPrevious`, `PaginationNext`, … | Page navigation. |
|
|
212
|
+
| `page-control` | `PageControl` | Mobile page-indicator dots. |
|
|
213
|
+
| `stepper` | `Stepper`, `StepperItem`, `StepperSeparator` | Horizontal step indicator. |
|
|
214
|
+
| `navbar-top` | `NavbarTop`, `NavbarTopLeft`, `NavbarTopTitle`, `NavbarTopRight` | Mobile top app bar. |
|
|
215
|
+
| `navbar-bottom` | `NavbarBottom`, `NavbarBottomItem` | Mobile bottom tab bar. |
|
|
216
|
+
| `list` | `List`, `ListHeader`, `ListItem` | Mobile list rows with leading/trailing slots. |
|
|
217
|
+
|
|
218
|
+
### Layout
|
|
219
|
+
|
|
220
|
+
| Component | Exports | Key props / notes |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| `card` | `Card`, `CardImage`, `CardHeader`, `CardFooter`, `CardTitle`, `CardDescription`, … | Composable card wrappers. |
|
|
223
|
+
|
|
224
|
+
### Example
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
import { Button } from "@/components/ui/button"
|
|
228
|
+
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert"
|
|
229
|
+
|
|
230
|
+
export function Example() {
|
|
231
|
+
return (
|
|
232
|
+
<>
|
|
233
|
+
<Button variant="filled" size="large">Save changes</Button>
|
|
234
|
+
<Alert severity="success" duration={5} onDismiss={() => {}}>
|
|
235
|
+
<AlertTitle>Saved</AlertTitle>
|
|
236
|
+
<AlertDescription>Your changes are live.</AlertDescription>
|
|
237
|
+
</Alert>
|
|
238
|
+
</>
|
|
239
|
+
)
|
|
240
|
+
}
|
|
55
241
|
```
|
|
56
242
|
|
|
57
|
-
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## How it works under the hood
|
|
58
246
|
|
|
59
|
-
|
|
247
|
+
1. `npx cooterlabs add [component]` inspects your filesystem: lockfiles for the package manager, `package.json` deps for the framework, `tsconfig.json` for TypeScript, and Tailwind config/deps for styling support.
|
|
248
|
+
2. Component requirements are expanded (`select` → `input`), then the shared `lib/utils` helper is scaffolded if missing.
|
|
249
|
+
3. Templates are copied from the CLI package into `src/components/ui/` (or `components/ui/`), run through your Prettier config, and written with the right extension.
|
|
250
|
+
4. The union of every selected component's runtime dependencies is installed in one package-manager call, so you only get libraries the components actually use.
|
|
60
251
|
|
|
61
|
-
|
|
62
|
-
- `badge` - Tiny status badge elements relying on standard `variant` mappings.
|
|
63
|
-
- `button` - A highly stylized native HTML button leveraging Radix UI primitives (`Slot`).
|
|
64
|
-
- `card` - Content display wrappers comprising headers, footers, body content, and titles.
|
|
65
|
-
- `checkbox` - Robust implementation for accessible `<input type="checkbox"/>` mappings.
|
|
66
|
-
- `input` - Your standard customized HTML `<input />`.
|
|
67
|
-
- `label` - An accessible Radix-backed `<label />`.
|
|
68
|
-
- `textarea` - A matching multiline input variation styling perfectly with standard inputs.
|
|
252
|
+
## Changelog
|
|
69
253
|
|
|
70
|
-
|
|
254
|
+
### 2.1.0
|
|
71
255
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
5. Child dependencies (e.g., `lucide-react`, Radix UI dependencies) required *exclusively* for that component are installed so the codebase isn't overwhelmed with useless imported libraries.
|
|
256
|
+
- **Synced all 28 component templates** with the latest Aeon implementations (updated button/badge/alert variants, refined focus states using `shadow-focus`, tailwind-merge-safe type-ramp classes).
|
|
257
|
+
- **New component: `select`** — Radix select styled as an Aeon input; auto-installs `input`, whose variant styles it reuses.
|
|
258
|
+
- **Shared `cn()` helper** — components now import from `lib/utils` instead of inlining `cn` per file; the CLI scaffolds it (with the type-ramp-aware tailwind-merge config) on first `add`.
|
|
259
|
+
- **Theme update** — the `aeon` theme now ships `--shadow-focus` (shared focus ring) and the `alert-timer` keyframes for Alert auto-dismiss.
|
|
77
260
|
|
|
78
261
|
## License
|
|
79
262
|
|
|
80
|
-
MIT
|
|
263
|
+
MIT — Grab it, use it, scale it!
|