create-baton 1.0.0 → 1.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.
@@ -0,0 +1,270 @@
1
+ ---
2
+ name: shadcn
3
+ description: >-
4
+ shadcn/ui component library patterns — installation, customization,
5
+ form integration, and accessible component usage. Load at Session 1-3
6
+ when using shadcn/ui. Use when building UI components or forms.
7
+ ---
8
+
9
+ # shadcn/ui Skill
10
+
11
+ > Copy-paste components you own. Not a dependency — it's YOUR code.
12
+
13
+ ---
14
+
15
+ ## What shadcn/ui Is
16
+
17
+ - NOT an npm package you install
18
+ - A collection of components you copy into your project
19
+ - Built on Radix UI (accessible primitives) + Tailwind CSS
20
+ - You own the code — customize freely
21
+
22
+ ---
23
+
24
+ ## Setup (Session 1)
25
+
26
+ ```bash
27
+ npx shadcn@latest init
28
+ ```
29
+
30
+ This creates:
31
+ - `components/ui/` — where components live
32
+ - `lib/utils.ts` — the `cn()` helper
33
+ - Updates `tailwind.config.ts` with CSS variables
34
+
35
+ ### Adding Components
36
+
37
+ ```bash
38
+ # Add individual components as needed
39
+ npx shadcn@latest add button
40
+ npx shadcn@latest add input
41
+ npx shadcn@latest add card
42
+ npx shadcn@latest add dialog
43
+ npx shadcn@latest add dropdown-menu
44
+ npx shadcn@latest add table
45
+ ```
46
+
47
+ **Rule:** Only add components you're about to use. Don't add the entire library upfront.
48
+
49
+ ---
50
+
51
+ ## Most Used Components
52
+
53
+ ### Essential (Add Session 1)
54
+
55
+ | Component | Use For |
56
+ |-----------|---------|
57
+ | `button` | All clickable actions |
58
+ | `input` | Text inputs |
59
+ | `label` | Form labels |
60
+ | `card` | Content containers |
61
+
62
+ ### Common (Add When Needed)
63
+
64
+ | Component | Use For |
65
+ |-----------|---------|
66
+ | `dialog` | Modals, confirmations |
67
+ | `dropdown-menu` | Action menus, user menus |
68
+ | `table` | Data display |
69
+ | `select` | Dropdown selections |
70
+ | `textarea` | Multi-line input |
71
+ | `badge` | Status indicators |
72
+ | `toast` | Notifications |
73
+ | `skeleton` | Loading states |
74
+ | `avatar` | User images |
75
+ | `tabs` | Content sections |
76
+
77
+ ---
78
+
79
+ ## Form Pattern (Session 2-3)
80
+
81
+ ### With react-hook-form + zod
82
+
83
+ ```bash
84
+ npx shadcn@latest add form
85
+ npm install react-hook-form zod @hookform/resolvers
86
+ ```
87
+
88
+ ```tsx
89
+ 'use client'
90
+ import { useForm } from 'react-hook-form';
91
+ import { zodResolver } from '@hookform/resolvers/zod';
92
+ import { z } from 'zod';
93
+ import { Button } from '@/components/ui/button';
94
+ import { Input } from '@/components/ui/input';
95
+ import {
96
+ Form, FormControl, FormField, FormItem,
97
+ FormLabel, FormMessage,
98
+ } from '@/components/ui/form';
99
+
100
+ const schema = z.object({
101
+ name: z.string().min(1, 'Name is required'),
102
+ email: z.string().email('Invalid email'),
103
+ });
104
+
105
+ export function CreateForm() {
106
+ const form = useForm({
107
+ resolver: zodResolver(schema),
108
+ defaultValues: { name: '', email: '' },
109
+ });
110
+
111
+ async function onSubmit(values: z.infer<typeof schema>) {
112
+ // Server action or API call
113
+ }
114
+
115
+ return (
116
+ <Form {...form}>
117
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
118
+ <FormField
119
+ control={form.control}
120
+ name="name"
121
+ render={({ field }) => (
122
+ <FormItem>
123
+ <FormLabel>Name</FormLabel>
124
+ <FormControl>
125
+ <Input {...field} />
126
+ </FormControl>
127
+ <FormMessage />
128
+ </FormItem>
129
+ )}
130
+ />
131
+ <Button type="submit">Create</Button>
132
+ </form>
133
+ </Form>
134
+ );
135
+ }
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Customization
141
+
142
+ ### Changing Colors
143
+
144
+ Edit `globals.css` CSS variables:
145
+
146
+ ```css
147
+ @layer base {
148
+ :root {
149
+ --primary: 222.2 47.4% 11.2%; /* Dark blue */
150
+ --primary-foreground: 210 40% 98%;
151
+ --destructive: 0 84.2% 60.2%; /* Red */
152
+ }
153
+ }
154
+ ```
155
+
156
+ ### Changing Border Radius
157
+
158
+ ```css
159
+ :root {
160
+ --radius: 0.5rem; /* Change this one value */
161
+ }
162
+ ```
163
+
164
+ ### Extending a Component
165
+
166
+ Since you own the code, just edit the file:
167
+
168
+ ```tsx
169
+ // components/ui/button.tsx
170
+ // Add a new variant
171
+ const buttonVariants = cva(
172
+ "...",
173
+ {
174
+ variants: {
175
+ variant: {
176
+ default: "...",
177
+ destructive: "...",
178
+ outline: "...",
179
+ // Add your own
180
+ brand: "bg-brand-600 text-white hover:bg-brand-700",
181
+ },
182
+ },
183
+ }
184
+ );
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Layout Patterns
190
+
191
+ ### Page with Sidebar
192
+
193
+ ```tsx
194
+ <div className="flex h-screen">
195
+ <aside className="hidden w-64 border-r lg:block">
196
+ <nav className="space-y-1 p-4">{/* Nav items */}</nav>
197
+ </aside>
198
+ <main className="flex-1 overflow-y-auto p-6">
199
+ {children}
200
+ </main>
201
+ </div>
202
+ ```
203
+
204
+ ### Dashboard Header
205
+
206
+ ```tsx
207
+ <header className="flex items-center justify-between border-b px-6 py-4">
208
+ <h1 className="text-lg font-semibold">{title}</h1>
209
+ <div className="flex items-center gap-3">
210
+ <Button variant="outline" size="sm">Settings</Button>
211
+ <Avatar />
212
+ </div>
213
+ </header>
214
+ ```
215
+
216
+ ### Data Table with Actions
217
+
218
+ ```tsx
219
+ <Table>
220
+ <TableHeader>
221
+ <TableRow>
222
+ <TableHead>Name</TableHead>
223
+ <TableHead>Status</TableHead>
224
+ <TableHead className="w-[50px]" />
225
+ </TableRow>
226
+ </TableHeader>
227
+ <TableBody>
228
+ {items.map(item => (
229
+ <TableRow key={item.id}>
230
+ <TableCell>{item.name}</TableCell>
231
+ <TableCell><Badge>{item.status}</Badge></TableCell>
232
+ <TableCell>
233
+ <DropdownMenu>
234
+ <DropdownMenuTrigger asChild>
235
+ <Button variant="ghost" size="sm">...</Button>
236
+ </DropdownMenuTrigger>
237
+ <DropdownMenuContent>
238
+ <DropdownMenuItem>Edit</DropdownMenuItem>
239
+ <DropdownMenuItem className="text-destructive">Delete</DropdownMenuItem>
240
+ </DropdownMenuContent>
241
+ </DropdownMenu>
242
+ </TableCell>
243
+ </TableRow>
244
+ ))}
245
+ </TableBody>
246
+ </Table>
247
+ ```
248
+
249
+ ---
250
+
251
+ ## Best Practices
252
+
253
+ ### Do
254
+
255
+ - Add components one at a time as you need them
256
+ - Use the `Form` component for all forms (handles validation, accessibility)
257
+ - Use `toast` for success/error feedback
258
+ - Use `skeleton` for loading states
259
+ - Keep customizations in CSS variables when possible
260
+
261
+ ### Don't
262
+
263
+ - Don't add all components at once
264
+ - Don't wrap shadcn components in your own wrappers (unnecessary abstraction)
265
+ - Don't fight the styling — if you need something very different, build custom
266
+ - Don't use `dialog` for simple confirmations (use browser `confirm()` for MVP)
267
+
268
+ ---
269
+
270
+ *Last updated: Baton Protocol v3.1*
@@ -0,0 +1,242 @@
1
+ ---
2
+ name: tailwind
3
+ description: >-
4
+ Tailwind CSS patterns — utility-first styling, responsive design, dark mode,
5
+ custom configuration, and component composition. Load at Session 1-2 when
6
+ using Tailwind. Use when styling components or discussing CSS approach.
7
+ ---
8
+
9
+ # Tailwind CSS Skill
10
+
11
+ > Utility-first means every style decision is visible in the markup. No mystery CSS files.
12
+
13
+ ---
14
+
15
+ ## Setup (Session 1)
16
+
17
+ ### With Next.js
18
+
19
+ Tailwind comes pre-configured with `create-next-app`. If not installed:
20
+
21
+ ```bash
22
+ npm install -D tailwindcss @tailwindcss/postcss postcss
23
+ ```
24
+
25
+ ### Essential Config
26
+
27
+ ```typescript
28
+ // tailwind.config.ts
29
+ import type { Config } from 'tailwindcss';
30
+
31
+ const config: Config = {
32
+ content: ['./src/**/*.{ts,tsx}'],
33
+ theme: {
34
+ extend: {
35
+ colors: {
36
+ brand: {
37
+ 50: '#eff6ff',
38
+ 500: '#3b82f6',
39
+ 600: '#2563eb',
40
+ 700: '#1d4ed8',
41
+ },
42
+ },
43
+ },
44
+ },
45
+ plugins: [],
46
+ };
47
+
48
+ export default config;
49
+ ```
50
+
51
+ **Rules:**
52
+ - Extend the theme, don't override it
53
+ - Define brand colors once in config
54
+ - Use `content` to point to your source files only
55
+
56
+ ---
57
+
58
+ ## Core Patterns
59
+
60
+ ### Spacing
61
+
62
+ Use Tailwind's spacing scale consistently:
63
+
64
+ ```
65
+ p-1 = 4px p-2 = 8px p-3 = 12px p-4 = 16px
66
+ p-6 = 24px p-8 = 32px p-12 = 48px p-16 = 64px
67
+ ```
68
+
69
+ **Rule:** Stick to `4, 8, 12, 16, 24, 32, 48, 64`. Skip odd values.
70
+
71
+ ### Layout
72
+
73
+ ```tsx
74
+ // Centered container with max width
75
+ <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
76
+
77
+ // Flex row with gap
78
+ <div className="flex items-center gap-4">
79
+
80
+ // Grid
81
+ <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
82
+ ```
83
+
84
+ ### Typography
85
+
86
+ ```tsx
87
+ // Heading
88
+ <h1 className="text-3xl font-bold tracking-tight text-gray-900">
89
+
90
+ // Body
91
+ <p className="text-base text-gray-600 leading-relaxed">
92
+
93
+ // Small/caption
94
+ <span className="text-sm text-gray-500">
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Responsive Design
100
+
101
+ ### Mobile-First (Default)
102
+
103
+ Tailwind is mobile-first. No prefix = mobile. Prefixes add larger breakpoints:
104
+
105
+ ```tsx
106
+ // Stack on mobile, row on desktop
107
+ <div className="flex flex-col sm:flex-row gap-4">
108
+
109
+ // Full width mobile, half on tablet, third on desktop
110
+ <div className="w-full sm:w-1/2 lg:w-1/3">
111
+
112
+ // Hide on mobile, show on desktop
113
+ <nav className="hidden lg:block">
114
+ ```
115
+
116
+ ### Breakpoints
117
+
118
+ ```
119
+ sm: 640px (tablet portrait)
120
+ md: 768px (tablet landscape)
121
+ lg: 1024px (desktop)
122
+ xl: 1280px (large desktop)
123
+ 2xl: 1536px (wide desktop)
124
+ ```
125
+
126
+ **Rule:** Only use `sm:`, `lg:`, and `xl:`. Three breakpoints cover 95% of layouts.
127
+
128
+ ---
129
+
130
+ ## Dark Mode
131
+
132
+ ### Setup
133
+
134
+ ```typescript
135
+ // tailwind.config.ts
136
+ const config: Config = {
137
+ darkMode: 'class', // or 'media' for system preference
138
+ // ...
139
+ };
140
+ ```
141
+
142
+ ### Usage
143
+
144
+ ```tsx
145
+ <div className="bg-white dark:bg-gray-900">
146
+ <h1 className="text-gray-900 dark:text-white">
147
+ <p className="text-gray-600 dark:text-gray-400">
148
+ </div>
149
+ ```
150
+
151
+ **Rule:** Don't add dark mode until the user asks. It doubles your styling work.
152
+
153
+ ---
154
+
155
+ ## Component Patterns
156
+
157
+ ### Button
158
+
159
+ ```tsx
160
+ // Base button styles
161
+ const buttonBase = "inline-flex items-center justify-center rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2";
162
+
163
+ // Variants
164
+ const variants = {
165
+ primary: "bg-brand-600 text-white hover:bg-brand-700 focus:ring-brand-500",
166
+ secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200 focus:ring-gray-500",
167
+ ghost: "text-gray-600 hover:bg-gray-100 hover:text-gray-900",
168
+ };
169
+
170
+ // Sizes
171
+ const sizes = {
172
+ sm: "px-3 py-1.5 text-sm",
173
+ md: "px-4 py-2 text-sm",
174
+ lg: "px-6 py-3 text-base",
175
+ };
176
+ ```
177
+
178
+ ### Card
179
+
180
+ ```tsx
181
+ <div className="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
182
+ <h3 className="text-lg font-semibold text-gray-900">{title}</h3>
183
+ <p className="mt-2 text-sm text-gray-600">{description}</p>
184
+ </div>
185
+ ```
186
+
187
+ ### Input
188
+
189
+ ```tsx
190
+ <input
191
+ className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm
192
+ placeholder:text-gray-400
193
+ focus:border-brand-500 focus:outline-none focus:ring-1 focus:ring-brand-500"
194
+ placeholder="Enter value..."
195
+ />
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Best Practices
201
+
202
+ ### Do
203
+
204
+ - Use `gap` instead of margins between flex/grid children
205
+ - Use `max-w-prose` for text content (65ch)
206
+ - Use `truncate` for text that might overflow
207
+ - Use `sr-only` for screen-reader-only text
208
+ - Group hover states: `group hover:group-hover:text-blue-500`
209
+
210
+ ### Don't
211
+
212
+ - Don't use `@apply` in CSS files (defeats the purpose of utility-first)
213
+ - Don't create utility classes that match existing Tailwind classes
214
+ - Don't nest more than 3 responsive prefixes on one element
215
+ - Don't use arbitrary values `[13px]` when a scale value exists
216
+
217
+ ---
218
+
219
+ ## cn() Helper (Conditional Classes)
220
+
221
+ ```typescript
222
+ // lib/utils.ts
223
+ import { clsx, type ClassValue } from 'clsx';
224
+ import { twMerge } from 'tailwind-merge';
225
+
226
+ export function cn(...inputs: ClassValue[]) {
227
+ return twMerge(clsx(inputs));
228
+ }
229
+
230
+ // Usage
231
+ <div className={cn(
232
+ "rounded-lg p-4",
233
+ isActive && "bg-brand-50 border-brand-500",
234
+ !isActive && "bg-gray-50 border-gray-200"
235
+ )}>
236
+ ```
237
+
238
+ Install: `npm install clsx tailwind-merge`
239
+
240
+ ---
241
+
242
+ *Last updated: Baton Protocol v3.1*