@fr0mpy/component-system 2.0.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.
Files changed (43) hide show
  1. package/bin/cli.js +283 -0
  2. package/index.js +12 -0
  3. package/package.json +45 -0
  4. package/templates/commands/component-harness.md +116 -0
  5. package/templates/commands/setup-styling.md +111 -0
  6. package/templates/component-recipes/accordion.md +153 -0
  7. package/templates/component-recipes/alert.md +145 -0
  8. package/templates/component-recipes/avatar.md +165 -0
  9. package/templates/component-recipes/badge.md +126 -0
  10. package/templates/component-recipes/breadcrumb.md +220 -0
  11. package/templates/component-recipes/button.md +90 -0
  12. package/templates/component-recipes/card.md +130 -0
  13. package/templates/component-recipes/carousel.md +277 -0
  14. package/templates/component-recipes/checkbox.md +117 -0
  15. package/templates/component-recipes/collapsible.md +201 -0
  16. package/templates/component-recipes/combobox.md +193 -0
  17. package/templates/component-recipes/context-menu.md +254 -0
  18. package/templates/component-recipes/dialog.md +193 -0
  19. package/templates/component-recipes/drawer.md +196 -0
  20. package/templates/component-recipes/dropdown-menu.md +263 -0
  21. package/templates/component-recipes/hover-card.md +230 -0
  22. package/templates/component-recipes/input.md +113 -0
  23. package/templates/component-recipes/label.md +259 -0
  24. package/templates/component-recipes/modal.md +155 -0
  25. package/templates/component-recipes/navigation-menu.md +310 -0
  26. package/templates/component-recipes/pagination.md +223 -0
  27. package/templates/component-recipes/popover.md +156 -0
  28. package/templates/component-recipes/progress.md +185 -0
  29. package/templates/component-recipes/radio.md +148 -0
  30. package/templates/component-recipes/select.md +154 -0
  31. package/templates/component-recipes/separator.md +124 -0
  32. package/templates/component-recipes/skeleton.md +186 -0
  33. package/templates/component-recipes/slider.md +114 -0
  34. package/templates/component-recipes/spinner.md +225 -0
  35. package/templates/component-recipes/switch.md +100 -0
  36. package/templates/component-recipes/table.md +161 -0
  37. package/templates/component-recipes/tabs.md +145 -0
  38. package/templates/component-recipes/textarea.md +234 -0
  39. package/templates/component-recipes/toast.md +209 -0
  40. package/templates/component-recipes/toggle-group.md +216 -0
  41. package/templates/component-recipes/tooltip.md +115 -0
  42. package/templates/hooks/triggers.d/styling.json +23 -0
  43. package/templates/skills/styling.md +173 -0
package/bin/cli.js ADDED
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
7
+ const TARGET_DIR = path.join(process.cwd(), '.claude');
8
+ const args = process.argv.slice(2);
9
+
10
+ // Parse flags
11
+ const hasFlag = (...flags) => flags.some((f) => args.includes(f));
12
+ const forceMode = hasFlag('--force', '-f');
13
+ const mergeMode = hasFlag('--merge', '-m');
14
+ const removeMode = hasFlag('--remove', '--uninstall', '-r');
15
+ const helpMode = hasFlag('--help', '-h');
16
+ const updateSkills = hasFlag('--update-skills');
17
+ const updateRecipes = hasFlag('--update-recipes');
18
+ const updateCommands = hasFlag('--update-commands');
19
+ const updateMode = updateSkills || updateRecipes || updateCommands;
20
+
21
+ function copyDir(src, dest) {
22
+ fs.mkdirSync(dest, { recursive: true });
23
+
24
+ const entries = fs.readdirSync(src, { withFileTypes: true });
25
+
26
+ for (const entry of entries) {
27
+ const srcPath = path.join(src, entry.name);
28
+ const destPath = path.join(dest, entry.name);
29
+
30
+ if (entry.isDirectory()) {
31
+ copyDir(srcPath, destPath);
32
+ } else {
33
+ fs.copyFileSync(srcPath, destPath);
34
+ }
35
+ }
36
+ }
37
+
38
+ function copySubdir(subdir) {
39
+ const src = path.join(TEMPLATES_DIR, subdir);
40
+ const dest = path.join(TARGET_DIR, subdir);
41
+
42
+ if (!fs.existsSync(src)) {
43
+ console.error(`❌ Source directory not found: ${subdir}`);
44
+ return false;
45
+ }
46
+
47
+ if (fs.existsSync(dest)) {
48
+ fs.rmSync(dest, { recursive: true });
49
+ }
50
+
51
+ copyDir(src, dest);
52
+ return true;
53
+ }
54
+
55
+ function injectStylingTrigger() {
56
+ const triggersDDir = path.join(TARGET_DIR, 'hooks', 'triggers.d');
57
+ const stylingTriggerSrc = path.join(TEMPLATES_DIR, 'hooks', 'triggers.d', 'styling.json');
58
+ const stylingTriggerDest = path.join(triggersDDir, 'styling.json');
59
+
60
+ if (fs.existsSync(triggersDDir) && fs.existsSync(stylingTriggerSrc)) {
61
+ fs.copyFileSync(stylingTriggerSrc, stylingTriggerDest);
62
+ return true;
63
+ }
64
+ return false;
65
+ }
66
+
67
+ function removeStylingTrigger() {
68
+ const stylingTrigger = path.join(TARGET_DIR, 'hooks', 'triggers.d', 'styling.json');
69
+ if (fs.existsSync(stylingTrigger)) {
70
+ fs.unlinkSync(stylingTrigger);
71
+ return true;
72
+ }
73
+ return false;
74
+ }
75
+
76
+ async function init() {
77
+ console.log('🎨 Initializing Claude Code component system...\n');
78
+
79
+ const promptSystemExists = fs.existsSync(path.join(TARGET_DIR, 'hooks'));
80
+ const componentSystemExists = fs.existsSync(path.join(TARGET_DIR, 'skills')) ||
81
+ fs.existsSync(path.join(TARGET_DIR, 'component-recipes'));
82
+
83
+ if (componentSystemExists && !forceMode && !mergeMode) {
84
+ console.log('⚠️ Component system already exists in .claude/');
85
+ console.log(' Use --force to overwrite, --merge to update, or use selective updates:');
86
+ console.log(' --update-skills, --update-recipes, --update-commands\n');
87
+ process.exit(1);
88
+ }
89
+
90
+ if (!fs.existsSync(TEMPLATES_DIR)) {
91
+ console.error('❌ Templates directory not found. Package may be corrupted.');
92
+ process.exit(1);
93
+ }
94
+
95
+ // Create .claude if it doesn't exist
96
+ fs.mkdirSync(TARGET_DIR, { recursive: true });
97
+
98
+ if (forceMode && componentSystemExists) {
99
+ // Only remove component-system specific dirs
100
+ const componentDirs = ['skills', 'component-recipes'];
101
+ for (const dir of componentDirs) {
102
+ const dirPath = path.join(TARGET_DIR, dir);
103
+ if (fs.existsSync(dirPath)) {
104
+ fs.rmSync(dirPath, { recursive: true });
105
+ }
106
+ }
107
+ console.log('🗑️ Removed existing component system files.\n');
108
+ }
109
+
110
+ // Copy component system templates
111
+ copyDir(path.join(TEMPLATES_DIR, 'skills'), path.join(TARGET_DIR, 'skills'));
112
+ copyDir(path.join(TEMPLATES_DIR, 'component-recipes'), path.join(TARGET_DIR, 'component-recipes'));
113
+
114
+ // Copy styling commands
115
+ const commandsDir = path.join(TARGET_DIR, 'commands');
116
+ fs.mkdirSync(commandsDir, { recursive: true });
117
+ fs.copyFileSync(
118
+ path.join(TEMPLATES_DIR, 'commands', 'setup-styling.md'),
119
+ path.join(commandsDir, 'setup-styling.md')
120
+ );
121
+ fs.copyFileSync(
122
+ path.join(TEMPLATES_DIR, 'commands', 'component-harness.md'),
123
+ path.join(commandsDir, 'component-harness.md')
124
+ );
125
+
126
+ console.log('✅ Created component system files:');
127
+ console.log(' 📁 skills/ - Styling skill for UI generation');
128
+ console.log(' 📁 component-recipes/ - 36 component templates');
129
+ console.log(' 📄 commands/setup-styling.md');
130
+ console.log(' 📄 commands/component-harness.md\n');
131
+
132
+ // Inject styling trigger if prompt-system is installed
133
+ if (promptSystemExists) {
134
+ if (injectStylingTrigger()) {
135
+ console.log('✅ Injected styling trigger into prompt system.');
136
+ console.log(' Styling-related prompts will now auto-trigger the styling skill.\n');
137
+ }
138
+ } else {
139
+ console.log('ℹ️ Prompt system not detected.');
140
+ console.log(' For auto-triggering styling rules, also install:');
141
+ console.log(' npx @fr0mpy/prompt-system\n');
142
+ }
143
+
144
+ console.log('🚀 Ready! Use /setup-styling to configure your design system.\n');
145
+ }
146
+
147
+ async function update() {
148
+ if (!fs.existsSync(TARGET_DIR)) {
149
+ console.error('❌ .claude directory not found. Run without flags to initialize first.');
150
+ process.exit(1);
151
+ }
152
+
153
+ console.log('🔄 Updating selected components...\n');
154
+
155
+ const updates = [];
156
+
157
+ if (updateSkills && copySubdir('skills')) updates.push('skills');
158
+ if (updateRecipes && copySubdir('component-recipes')) updates.push('component-recipes');
159
+ if (updateCommands) {
160
+ const commandsDir = path.join(TARGET_DIR, 'commands');
161
+ fs.mkdirSync(commandsDir, { recursive: true });
162
+ fs.copyFileSync(
163
+ path.join(TEMPLATES_DIR, 'commands', 'setup-styling.md'),
164
+ path.join(commandsDir, 'setup-styling.md')
165
+ );
166
+ fs.copyFileSync(
167
+ path.join(TEMPLATES_DIR, 'commands', 'component-harness.md'),
168
+ path.join(commandsDir, 'component-harness.md')
169
+ );
170
+ updates.push('commands');
171
+ }
172
+
173
+ if (updates.length > 0) {
174
+ console.log(`✅ Updated: ${updates.join(', ')}\n`);
175
+ } else {
176
+ console.log('⚠️ No components updated.\n');
177
+ }
178
+ }
179
+
180
+ function remove() {
181
+ if (!fs.existsSync(TARGET_DIR)) {
182
+ console.log('ℹ️ .claude directory does not exist. Nothing to remove.\n');
183
+ return;
184
+ }
185
+
186
+ // Check if prompt-system exists - if so, only remove component-system files
187
+ const hasHooks = fs.existsSync(path.join(TARGET_DIR, 'hooks'));
188
+
189
+ const componentDirs = ['skills', 'component-recipes'];
190
+ const componentCommands = ['setup-styling.md', 'component-harness.md'];
191
+
192
+ for (const dir of componentDirs) {
193
+ const dirPath = path.join(TARGET_DIR, dir);
194
+ if (fs.existsSync(dirPath)) {
195
+ fs.rmSync(dirPath, { recursive: true });
196
+ }
197
+ }
198
+
199
+ // Remove styling commands
200
+ const commandsDir = path.join(TARGET_DIR, 'commands');
201
+ if (fs.existsSync(commandsDir)) {
202
+ for (const cmd of componentCommands) {
203
+ const cmdPath = path.join(commandsDir, cmd);
204
+ if (fs.existsSync(cmdPath)) {
205
+ fs.unlinkSync(cmdPath);
206
+ }
207
+ }
208
+ }
209
+
210
+ // Remove styling trigger
211
+ removeStylingTrigger();
212
+
213
+ // Remove styling-config.json if it exists
214
+ const stylingConfig = path.join(TARGET_DIR, 'styling-config.json');
215
+ if (fs.existsSync(stylingConfig)) {
216
+ fs.unlinkSync(stylingConfig);
217
+ }
218
+
219
+ if (hasHooks) {
220
+ console.log('✅ Removed component system files. Prompt system preserved.\n');
221
+ } else {
222
+ // If nothing else remains, remove .claude entirely
223
+ const remaining = fs.readdirSync(TARGET_DIR);
224
+ if (remaining.length === 0 || (remaining.length === 1 && remaining[0] === 'commands')) {
225
+ fs.rmSync(TARGET_DIR, { recursive: true });
226
+ console.log('✅ Removed .claude directory.\n');
227
+ } else {
228
+ console.log('✅ Removed component system files.\n');
229
+ }
230
+ }
231
+ }
232
+
233
+ function showHelp() {
234
+ console.log(`
235
+ @fr0mpy/component-system - Claude Code UI styling and component system
236
+
237
+ Usage:
238
+ npx @fr0mpy/component-system Initialize in current directory
239
+ npx @fr0mpy/component-system --merge Add to existing .claude (default behavior)
240
+ npx @fr0mpy/component-system --force Overwrite existing component files
241
+ npx @fr0mpy/component-system --remove Remove component system files
242
+
243
+ Selective updates:
244
+ --update-skills Update only skills/
245
+ --update-recipes Update only component-recipes/
246
+ --update-commands Update only styling commands
247
+
248
+ Options:
249
+ -h, --help Show this help message
250
+ -f, --force Overwrite existing component system files
251
+ -m, --merge Merge with existing .claude directory
252
+ -r, --remove Remove component system (alias: --uninstall)
253
+
254
+ What's included:
255
+ • skills/ Styling skill for consistent UI generation
256
+ • component-recipes/ 36 pre-built component templates
257
+ • commands/ /setup-styling, /component-harness
258
+
259
+ Getting started:
260
+ 1. Run: npx @fr0mpy/component-system
261
+ 2. Use: /setup-styling to configure your design system
262
+ 3. Use: /component-harness to preview components
263
+
264
+ For prompt injection and agents:
265
+ npx @fr0mpy/prompt-system
266
+
267
+ Learn more: https://github.com/fr0mpy/claude-base-setup
268
+ `);
269
+ }
270
+
271
+ async function main() {
272
+ if (helpMode) {
273
+ showHelp();
274
+ } else if (removeMode) {
275
+ remove();
276
+ } else if (updateMode) {
277
+ await update();
278
+ } else {
279
+ await init();
280
+ }
281
+ }
282
+
283
+ main();
package/index.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @claude-tools/component-system
3
+ *
4
+ * Claude Code UI styling system with design tokens, component recipes, and visual preview harness.
5
+ */
6
+
7
+ const path = require('path');
8
+
9
+ module.exports = {
10
+ name: '@claude-tools/component-system',
11
+ templatesDir: path.join(__dirname, 'templates'),
12
+ };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@fr0mpy/component-system",
3
+ "version": "2.0.0",
4
+ "description": "Claude Code UI styling system with design tokens, 36 component recipes, and visual harness",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "fromp-component-system": "./bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Tests not yet configured\""
11
+ },
12
+ "keywords": [
13
+ "claude",
14
+ "claude-code",
15
+ "ui",
16
+ "components",
17
+ "tailwind",
18
+ "design-tokens",
19
+ "styling",
20
+ "react"
21
+ ],
22
+ "author": "fr0mpy",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/fr0mpy/claude-base-setup.git",
27
+ "directory": "packages/component-system"
28
+ },
29
+ "files": [
30
+ "bin/",
31
+ "templates/",
32
+ "index.js"
33
+ ],
34
+ "engines": {
35
+ "node": ">=16.0.0"
36
+ },
37
+ "peerDependencies": {
38
+ "@fr0mpy/prompt-system": ">=2.0.0"
39
+ },
40
+ "peerDependenciesMeta": {
41
+ "@fr0mpy/prompt-system": {
42
+ "optional": true
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,116 @@
1
+ Launch the visual component harness to preview and iterate on your design system components.
2
+
3
+ ## Prerequisites
4
+ - Run `/setup-styling` first to generate styling config and component recipes
5
+ - Node.js 18+ installed
6
+
7
+ ## Workflow
8
+
9
+ 1. **Check for styling config**
10
+ - If `.claude/styling-config.json` doesn't exist, prompt to run `/setup-styling` first
11
+
12
+ 2. **Check if component-harness exists**
13
+ - Look for `component-harness/` directory in project root
14
+ - If not found, scaffold it from templates
15
+
16
+ 3. **Scaffold component-harness** (if needed)
17
+ Create the following structure:
18
+ ```
19
+ component-harness/
20
+ ├── index.html
21
+ ├── main.tsx
22
+ ├── App.tsx
23
+ ├── Gallery.tsx
24
+ ├── ComponentPreview.tsx
25
+ ├── components/ # Generated components go here
26
+ │ ├── Button.tsx
27
+ │ ├── Card.tsx
28
+ │ └── ...
29
+ ├── lib/
30
+ │ └── utils.ts # cn() utility
31
+ ├── vite.config.ts
32
+ ├── tailwind.config.ts
33
+ ├── postcss.config.js
34
+ ├── tsconfig.json
35
+ └── package.json
36
+ ```
37
+
38
+ 4. **Generate components from recipes (resumable)**
39
+ - List all `.claude/component-recipes/*.md` files
40
+ - For each recipe, check if matching `.tsx` component exists
41
+ - Only generate missing components (skip existing ones)
42
+ - Use tokens from `.claude/styling-config.json`
43
+ - Update `components/index.ts` to export all components
44
+
45
+ 5. **Validate completeness**
46
+ - Count recipes vs generated components
47
+ - If any missing, loop back to step 4
48
+ - Only proceed when: `✓ [N]/[N] components generated`
49
+
50
+ 6. **Install dependencies** (if package.json is new)
51
+ ```bash
52
+ cd component-harness && npm install
53
+ ```
54
+
55
+ 7. **Start dev server**
56
+ ```bash
57
+ cd component-harness && npm run dev
58
+ ```
59
+
60
+ 8. **Open browser**
61
+ - Open `http://localhost:5173` (or configured port)
62
+
63
+ ## Harness Features
64
+
65
+ ### Navigation
66
+ - Left/right chevron buttons to cycle through components
67
+ - Component name displayed in header
68
+ - Variant selector for components with multiple variants
69
+
70
+ ### Live Preview
71
+ - Component rendered in isolated preview area
72
+ - Props can be adjusted in real-time
73
+ - Dark/light mode toggle
74
+
75
+ ### Change Requests
76
+ - "Request Change" button that:
77
+ 1. Prompts user to describe desired change
78
+ 2. Claude updates the recipe and regenerates component
79
+ 3. HMR updates the preview instantly
80
+
81
+ ## Generated Gallery.tsx Structure
82
+
83
+ ```tsx
84
+ // Core navigation and preview
85
+ - useState for currentComponentIndex
86
+ - Array of all components with their variants
87
+ - Left/Right chevron navigation
88
+ - Component name + variant display
89
+ - Isolated preview area
90
+ - "Request Change" button
91
+ ```
92
+
93
+ ## package.json Dependencies
94
+
95
+ ```json
96
+ {
97
+ "dependencies": {
98
+ "react": "^18.2.0",
99
+ "react-dom": "^18.2.0",
100
+ "clsx": "^2.0.0",
101
+ "tailwind-merge": "^2.0.0",
102
+ "lucide-react": "^0.300.0",
103
+ "@radix-ui/react-slot": "^1.0.0"
104
+ },
105
+ "devDependencies": {
106
+ "vite": "^5.0.0",
107
+ "@vitejs/plugin-react": "^4.0.0",
108
+ "typescript": "^5.0.0",
109
+ "tailwindcss": "^3.4.0",
110
+ "postcss": "^8.0.0",
111
+ "autoprefixer": "^10.0.0"
112
+ }
113
+ }
114
+ ```
115
+
116
+ $ARGUMENTS
@@ -0,0 +1,111 @@
1
+ Define your unique UI aesthetic for consistent component generation.
2
+
3
+ This command creates a personalized styling system. Once configured, the `styling` skill will automatically apply these tokens and recipes when generating UI components.
4
+
5
+ ## Workflow
6
+
7
+ 1. **Check for existing tokens** - Look for `tailwind.config.*` or existing `.claude/styling-config.json`
8
+ 2. **Ask aesthetic questions** using AskUserQuestion tool:
9
+
10
+ **Q1: Import existing?**
11
+ - If `tailwind.config.*` found: "Found tailwind config. Import colors/spacing from it?"
12
+ - Options: [Yes, import] [No, start fresh]
13
+
14
+ **Q2: Overall aesthetic feel**
15
+ - Options: [Minimal - clean, lots of whitespace] [Bold - strong colors, high contrast] [Playful - rounded, colorful, fun] [Enterprise - professional, structured] [Custom - I'll describe it]
16
+
17
+ **Q3: Color philosophy**
18
+ - Options: [Monochrome - shades of one color] [Vibrant - bright, saturated colors] [Muted pastels - soft, calm colors] [Earth tones - natural, warm colors] [Custom - I'll provide hex values]
19
+ - If Custom: Ask for primary, secondary, background, surface, text colors
20
+
21
+ **Q4: Typography**
22
+ - Options: [Modern sans (Inter/system)] [Classic serif] [Monospace/technical] [Custom font family]
23
+
24
+ **Q5: Component personality**
25
+ - Corners: [Sharp (rounded-none)] [Subtle (rounded-sm)] [Rounded (rounded-lg)] [Pill (rounded-full)]
26
+ - Shadows: [Flat (no shadows)] [Subtle (shadow-sm)] [Pronounced (shadow-lg)] [Glassmorphism]
27
+ - Density: [Compact (tight spacing)] [Comfortable (normal)] [Spacious (generous padding)]
28
+
29
+ 3. **Generate `.claude/styling-config.json`** with structure:
30
+ ```json
31
+ {
32
+ "aesthetic": "minimal",
33
+ "tokens": {
34
+ "colors": {
35
+ "primary": "#0066FF",
36
+ "primary-foreground": "#FFFFFF",
37
+ "secondary": "#6C5CE7",
38
+ "secondary-foreground": "#FFFFFF",
39
+ "background": "#FFFFFF",
40
+ "foreground": "#1A1A1A",
41
+ "surface": "#F5F5F5",
42
+ "muted": "#6B7280",
43
+ "muted-foreground": "#9CA3AF",
44
+ "border": "#E5E7EB",
45
+ "destructive": "#EF4444",
46
+ "destructive-foreground": "#FFFFFF"
47
+ },
48
+ "radius": "rounded-lg",
49
+ "shadow": "shadow-sm",
50
+ "spacing": {
51
+ "tight": "2",
52
+ "normal": "4",
53
+ "loose": "6"
54
+ },
55
+ "typography": {
56
+ "family": "font-sans",
57
+ "heading": "font-semibold tracking-tight",
58
+ "body": "font-normal"
59
+ }
60
+ },
61
+ "personality": {
62
+ "corners": "rounded",
63
+ "depth": "subtle-shadows",
64
+ "density": "comfortable"
65
+ }
66
+ }
67
+ ```
68
+
69
+ 4. **Generate `.claude/component-recipes/`** directory with recipes for each component type:
70
+ - button.md, card.md, input.md, modal.md, select.md
71
+ - checkbox.md, radio.md, badge.md, alert.md, avatar.md
72
+ - tooltip.md, table.md, tabs.md, accordion.md, dialog.md, toast.md
73
+
74
+ Each recipe should reference `{tokens.*}` from the config and follow the aesthetic choices.
75
+
76
+ 5. **Ask about component-harness**: "Want me to scaffold the visual component-harness for previewing?"
77
+
78
+ ## Recipe Template
79
+
80
+ When generating each recipe, follow this structure:
81
+ ```markdown
82
+ # [Component] Component Recipe
83
+
84
+ ## Structure
85
+ - HTML element to use
86
+ - Supported variants
87
+ - Supported sizes
88
+ - Required states (loading, disabled, etc.)
89
+
90
+ ## Tailwind Classes
91
+ - Base: [base classes that apply to all variants]
92
+ - [Variant]: [classes for this variant using {tokens.*} references]
93
+ - Sizes: [size-specific classes]
94
+ - States: [hover, focus, disabled classes]
95
+
96
+ ## Props Interface
97
+ - variant: [list of variants]
98
+ - size: [list of sizes]
99
+ - [other props]
100
+
101
+ ## Do
102
+ - [best practices]
103
+
104
+ ## Don't
105
+ - [anti-patterns]
106
+
107
+ ## Example
108
+ [code example]
109
+ ```
110
+
111
+ $ARGUMENTS