@archetypeai/ds-cli 0.3.7
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/LICENSE +21 -0
- package/README.md +123 -0
- package/bin.js +77 -0
- package/commands/add.js +42 -0
- package/commands/create.js +238 -0
- package/commands/init.js +199 -0
- package/files/AGENTS.md +63 -0
- package/files/CLAUDE.md +63 -0
- package/files/LICENSE +21 -0
- package/files/rules/accessibility.md +219 -0
- package/files/rules/charts.md +352 -0
- package/files/rules/components.md +267 -0
- package/files/rules/design-principles.md +56 -0
- package/files/rules/linting.md +31 -0
- package/files/rules/state.md +405 -0
- package/files/rules/styling.md +245 -0
- package/files/skills/apply-ds/SKILL.md +117 -0
- package/files/skills/apply-ds/scripts/setup.sh +271 -0
- package/files/skills/build-pattern/SKILL.md +202 -0
- package/files/skills/create-dashboard/SKILL.md +189 -0
- package/files/skills/deploy-worker/SKILL.md +231 -0
- package/files/skills/deploy-worker/references/wrangler-commands.md +327 -0
- package/files/skills/fix-accessibility/SKILL.md +184 -0
- package/files/skills/fix-metadata/SKILL.md +118 -0
- package/files/skills/fix-metadata/assets/favicon.ico +0 -0
- package/files/skills/setup-chart/SKILL.md +225 -0
- package/files/skills/setup-chart/data/embedding.csv +42 -0
- package/files/skills/setup-chart/data/timeseries.csv +173 -0
- package/files/skills/setup-chart/references/scatter-chart.md +229 -0
- package/files/skills/setup-chart/references/sensor-chart.md +156 -0
- package/lib/add-ds-config-codeagent.js +154 -0
- package/lib/add-ds-ui-svelte.js +93 -0
- package/lib/scaffold-ds-svelte-project.js +272 -0
- package/lib/use-package-manager.js +65 -0
- package/lib/use-shadcn-svelte-registry.js +26 -0
- package/lib/validate-url.js +31 -0
- package/package.json +34 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: apply-ds
|
|
3
|
+
description: Sets up an existing SvelteKit project with the Archetype AI design system (@archetypeai/ds-lib-tokens). Use when initializing a new project with the design system by adding tokens to an existing project, configuring Tailwind v4 CSS imports, setting up shadcn-svelte, installing design system components and configuring eslint/prettier for Svelte projects.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Applying the Design System
|
|
7
|
+
|
|
8
|
+
Setup involves these steps:
|
|
9
|
+
|
|
10
|
+
1. Install tokens package
|
|
11
|
+
2. Install and configure Tailwind CSS
|
|
12
|
+
3. Initialize shadcn-svelte
|
|
13
|
+
4. Install design system components
|
|
14
|
+
5. Configure CSS imports
|
|
15
|
+
6. Set up linting and formatting
|
|
16
|
+
|
|
17
|
+
## Automated Setup
|
|
18
|
+
|
|
19
|
+
Run the setup script from the project root:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bash scripts/setup.sh
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The script requires:
|
|
26
|
+
|
|
27
|
+
- A global CSS file at `src/app.css`, `src/routes/layout.css`, or `src/app.pcss`
|
|
28
|
+
|
|
29
|
+
## Manual Setup
|
|
30
|
+
|
|
31
|
+
### Step 1: Install Tokens
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm i @archetypeai/ds-lib-tokens
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Step 2: Install and Configure Tailwind CSS
|
|
38
|
+
|
|
39
|
+
Install Tailwind CSS v4 and its Vite plugin:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm i -D tailwindcss @tailwindcss/vite
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then add the `@tailwindcss/vite` plugin to your `vite.config.js`:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
49
|
+
|
|
50
|
+
export default defineConfig({
|
|
51
|
+
plugins: [svelte(), tailwindcss()]
|
|
52
|
+
// ...
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The setup script handles this automatically — it detects your vite config file, adds the import, and inserts `tailwindcss()` into the plugins array.
|
|
57
|
+
|
|
58
|
+
### Step 3: Initialize shadcn-svelte
|
|
59
|
+
|
|
60
|
+
The `--css` flag should point to your project's global CSS file:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx shadcn-svelte@latest init \
|
|
64
|
+
--base-color slate \
|
|
65
|
+
--css src/app.css \
|
|
66
|
+
--components-alias '$lib/components' \
|
|
67
|
+
--lib-alias '$lib' \
|
|
68
|
+
--utils-alias '$lib/utils' \
|
|
69
|
+
--hooks-alias '$lib/hooks' \
|
|
70
|
+
--ui-alias '$lib/components/ui' \
|
|
71
|
+
--skip-preflight \
|
|
72
|
+
--no-deps
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Step 4: Install Components
|
|
76
|
+
|
|
77
|
+
Install all components:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npx @archetypeai/ds-cli add ds-ui-svelte
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Or install individually:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx shadcn-svelte@latest add https://design-system.archetypeai.workers.dev/r/button.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Step 5: Configure CSS Imports
|
|
90
|
+
|
|
91
|
+
Replace the contents of your global CSS file with:
|
|
92
|
+
|
|
93
|
+
```css
|
|
94
|
+
@import '@archetypeai/ds-lib-tokens/theme.css';
|
|
95
|
+
@import 'tailwindcss';
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Step 6: Set Up Linting
|
|
99
|
+
|
|
100
|
+
Install dependencies:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm i -D eslint prettier eslint-plugin-svelte eslint-config-prettier prettier-plugin-svelte prettier-plugin-tailwindcss globals
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The setup script creates `eslint.config.js`, `.prettierrc`, and `.prettierignore` automatically. See `@rules/linting.md` for details.
|
|
107
|
+
|
|
108
|
+
## Verification
|
|
109
|
+
|
|
110
|
+
Confirm setup is complete:
|
|
111
|
+
|
|
112
|
+
- [ ] `@archetypeai/ds-lib-tokens` in package.json
|
|
113
|
+
- [ ] `tailwindcss` and `@tailwindcss/vite` in package.json devDependencies
|
|
114
|
+
- [ ] `vite.config.js` includes `import tailwindcss from '@tailwindcss/vite'` and `tailwindcss()` in plugins
|
|
115
|
+
- [ ] `components.json` exists
|
|
116
|
+
- [ ] Components in `$lib/components/ui/`
|
|
117
|
+
- [ ] CSS file contains correct imports
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Archetype AI Design System Setup Script
|
|
4
|
+
#
|
|
5
|
+
# Sets up a SvelteKit project with @archetypeai/ds-lib-tokens and design system components.
|
|
6
|
+
# Fully non-interactive.
|
|
7
|
+
#
|
|
8
|
+
# Usage: bash setup.sh
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
set -e
|
|
12
|
+
|
|
13
|
+
echo "═══════════════════════════════════════════════════"
|
|
14
|
+
echo " Archetype AI Design System Setup"
|
|
15
|
+
echo "═══════════════════════════════════════════════════"
|
|
16
|
+
echo ""
|
|
17
|
+
|
|
18
|
+
# ─────────────────────────────────────────────────────────
|
|
19
|
+
# Prerequisites Check
|
|
20
|
+
# ─────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
if ! command -v node &> /dev/null; then
|
|
23
|
+
echo "✗ Error: Node.js is not installed"
|
|
24
|
+
echo " Install Node.js 18+ and try again"
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
|
|
29
|
+
if [ "$NODE_VERSION" -lt 18 ]; then
|
|
30
|
+
echo "✗ Error: Node.js 18+ required (found v$NODE_VERSION)"
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [ ! -f "package.json" ]; then
|
|
35
|
+
echo "✗ Error: No package.json found"
|
|
36
|
+
echo " Run this script from your project root directory"
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Detect global CSS file
|
|
41
|
+
CSS_FILE=""
|
|
42
|
+
if [ -f "src/app.css" ]; then
|
|
43
|
+
CSS_FILE="src/app.css"
|
|
44
|
+
elif [ -f "src/routes/layout.css" ]; then
|
|
45
|
+
CSS_FILE="src/routes/layout.css"
|
|
46
|
+
elif [ -f "src/app.pcss" ]; then
|
|
47
|
+
CSS_FILE="src/app.pcss"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
if [ -z "$CSS_FILE" ]; then
|
|
51
|
+
echo "✗ Error: No global CSS file found"
|
|
52
|
+
echo " Checked: src/app.css, src/routes/layout.css, src/app.pcss"
|
|
53
|
+
echo " Create a global CSS file and run again."
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
echo "✓ Prerequisites OK (Node v$NODE_VERSION, CSS: $CSS_FILE)"
|
|
58
|
+
echo ""
|
|
59
|
+
|
|
60
|
+
# ─────────────────────────────────────────────────────────
|
|
61
|
+
# Step 1: Install Tokens
|
|
62
|
+
# ─────────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
echo "Step 1/6: Installing @archetypeai/ds-lib-tokens..."
|
|
65
|
+
|
|
66
|
+
if grep -q '"@archetypeai/ds-lib-tokens"' package.json 2>/dev/null; then
|
|
67
|
+
echo " → Already installed, skipping"
|
|
68
|
+
else
|
|
69
|
+
npm i @archetypeai/ds-lib-tokens || {
|
|
70
|
+
echo ""
|
|
71
|
+
echo "✗ Installation failed."
|
|
72
|
+
exit 1
|
|
73
|
+
}
|
|
74
|
+
echo " ✓ Tokens installed"
|
|
75
|
+
fi
|
|
76
|
+
echo ""
|
|
77
|
+
|
|
78
|
+
# ─────────────────────────────────────────────────────────
|
|
79
|
+
# Step 2: Install & Configure Tailwind CSS
|
|
80
|
+
# ─────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
echo "Step 2/6: Installing and configuring Tailwind CSS..."
|
|
83
|
+
|
|
84
|
+
# Install tailwindcss + vite plugin if not present
|
|
85
|
+
if grep -q '"tailwindcss"' package.json 2>/dev/null && grep -q '"@tailwindcss/vite"' package.json 2>/dev/null; then
|
|
86
|
+
echo " → tailwindcss already installed, skipping"
|
|
87
|
+
else
|
|
88
|
+
npm i -D tailwindcss @tailwindcss/vite || {
|
|
89
|
+
echo ""
|
|
90
|
+
echo "✗ Failed to install tailwindcss"
|
|
91
|
+
exit 1
|
|
92
|
+
}
|
|
93
|
+
echo " ✓ tailwindcss and @tailwindcss/vite installed"
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
# Configure vite.config.js with @tailwindcss/vite plugin
|
|
97
|
+
VITE_CONFIG=""
|
|
98
|
+
if [ -f "vite.config.js" ]; then
|
|
99
|
+
VITE_CONFIG="vite.config.js"
|
|
100
|
+
elif [ -f "vite.config.ts" ]; then
|
|
101
|
+
VITE_CONFIG="vite.config.ts"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
if [ -z "$VITE_CONFIG" ]; then
|
|
105
|
+
echo " ⚠ No vite.config found — create one and add tailwindcss() to plugins manually"
|
|
106
|
+
elif grep -q "@tailwindcss/vite" "$VITE_CONFIG" 2>/dev/null; then
|
|
107
|
+
echo " → @tailwindcss/vite already configured in $VITE_CONFIG, skipping"
|
|
108
|
+
else
|
|
109
|
+
# Add import after the last import statement
|
|
110
|
+
LAST_IMPORT_LINE=$(grep -n '^import ' "$VITE_CONFIG" | tail -1 | cut -d: -f1)
|
|
111
|
+
if [ -n "$LAST_IMPORT_LINE" ]; then
|
|
112
|
+
sed -i.bak "${LAST_IMPORT_LINE}a\\
|
|
113
|
+
import tailwindcss from '@tailwindcss/vite';" "$VITE_CONFIG"
|
|
114
|
+
else
|
|
115
|
+
sed -i.bak "1i\\
|
|
116
|
+
import tailwindcss from '@tailwindcss/vite';" "$VITE_CONFIG"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# Add tailwindcss() to plugins array
|
|
120
|
+
if grep -q 'plugins.*svelte()' "$VITE_CONFIG"; then
|
|
121
|
+
sed -i.bak 's/svelte()/svelte(), tailwindcss()/' "$VITE_CONFIG"
|
|
122
|
+
elif grep -q 'plugins.*\[' "$VITE_CONFIG"; then
|
|
123
|
+
sed -i.bak 's/plugins:[[:space:]]*\[/plugins: [tailwindcss(), /' "$VITE_CONFIG"
|
|
124
|
+
else
|
|
125
|
+
echo " ⚠ Could not find plugins array — add tailwindcss() to plugins manually"
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
rm -f "${VITE_CONFIG}.bak"
|
|
129
|
+
echo " ✓ @tailwindcss/vite configured in $VITE_CONFIG"
|
|
130
|
+
fi
|
|
131
|
+
echo ""
|
|
132
|
+
|
|
133
|
+
# ─────────────────────────────────────────────────────────
|
|
134
|
+
# Step 3: Initialize shadcn-svelte
|
|
135
|
+
# ─────────────────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
echo "Step 3/6: Initializing shadcn-svelte..."
|
|
138
|
+
|
|
139
|
+
if [ -f "components.json" ]; then
|
|
140
|
+
echo " → components.json exists, skipping init"
|
|
141
|
+
else
|
|
142
|
+
npx shadcn-svelte@latest init \
|
|
143
|
+
--base-color slate \
|
|
144
|
+
--css "$CSS_FILE" \
|
|
145
|
+
--components-alias '$lib/components' \
|
|
146
|
+
--lib-alias '$lib' \
|
|
147
|
+
--utils-alias '$lib/utils' \
|
|
148
|
+
--hooks-alias '$lib/hooks' \
|
|
149
|
+
--ui-alias '$lib/components/ui' \
|
|
150
|
+
--skip-preflight \
|
|
151
|
+
--no-deps
|
|
152
|
+
echo " ✓ shadcn-svelte initialized"
|
|
153
|
+
fi
|
|
154
|
+
echo ""
|
|
155
|
+
|
|
156
|
+
# ─────────────────────────────────────────────────────────
|
|
157
|
+
# Step 4: Install Components
|
|
158
|
+
# ─────────────────────────────────────────────────────────
|
|
159
|
+
|
|
160
|
+
echo "Step 4/6: Installing design system components..."
|
|
161
|
+
npx @archetypeai/ds-cli add ds-ui-svelte
|
|
162
|
+
echo " ✓ Components installed"
|
|
163
|
+
echo ""
|
|
164
|
+
|
|
165
|
+
# ─────────────────────────────────────────────────────────
|
|
166
|
+
# Step 5: Configure CSS Imports
|
|
167
|
+
# ─────────────────────────────────────────────────────────
|
|
168
|
+
|
|
169
|
+
echo "Step 5/6: Configuring CSS imports..."
|
|
170
|
+
|
|
171
|
+
cat > "$CSS_FILE" << 'EOF'
|
|
172
|
+
@import '@archetypeai/ds-lib-tokens/theme.css';
|
|
173
|
+
@import 'tailwindcss';
|
|
174
|
+
EOF
|
|
175
|
+
|
|
176
|
+
echo " ✓ CSS imports written to $CSS_FILE"
|
|
177
|
+
echo ""
|
|
178
|
+
|
|
179
|
+
# ─────────────────────────────────────────────────────────
|
|
180
|
+
# Step 6: Set Up Linting & Formatting
|
|
181
|
+
# ─────────────────────────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
echo "Step 6/6: Setting up linting and formatting..."
|
|
184
|
+
|
|
185
|
+
npm i -D eslint prettier eslint-plugin-svelte eslint-config-prettier prettier-plugin-svelte prettier-plugin-tailwindcss globals 2>/dev/null || true
|
|
186
|
+
echo " ✓ Linting dependencies installed"
|
|
187
|
+
|
|
188
|
+
# Create eslint.config.js if it doesn't exist
|
|
189
|
+
if [ ! -f "eslint.config.js" ]; then
|
|
190
|
+
cat > eslint.config.js << 'ESLINT_EOF'
|
|
191
|
+
import js from '@eslint/js';
|
|
192
|
+
import svelte from 'eslint-plugin-svelte';
|
|
193
|
+
import globals from 'globals';
|
|
194
|
+
import svelteConfig from './svelte.config.js';
|
|
195
|
+
|
|
196
|
+
export default [
|
|
197
|
+
js.configs.recommended,
|
|
198
|
+
...svelte.configs.recommended,
|
|
199
|
+
...svelte.configs['flat/prettier'],
|
|
200
|
+
{
|
|
201
|
+
languageOptions: {
|
|
202
|
+
globals: { ...globals.browser, ...globals.node }
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
files: ['**/*.svelte', '**/*.svelte.js'],
|
|
207
|
+
languageOptions: {
|
|
208
|
+
parserOptions: { svelteConfig }
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
ignores: ['.svelte-kit/', 'build/', 'dist/', 'node_modules/']
|
|
213
|
+
}
|
|
214
|
+
];
|
|
215
|
+
ESLINT_EOF
|
|
216
|
+
echo " ✓ eslint.config.js created"
|
|
217
|
+
else
|
|
218
|
+
echo " → eslint.config.js exists, skipping"
|
|
219
|
+
fi
|
|
220
|
+
|
|
221
|
+
# Create .prettierrc if it doesn't exist
|
|
222
|
+
if [ ! -f ".prettierrc" ]; then
|
|
223
|
+
cat > .prettierrc << PRETTIER_EOF
|
|
224
|
+
{
|
|
225
|
+
"useTabs": true,
|
|
226
|
+
"singleQuote": true,
|
|
227
|
+
"trailingComma": "none",
|
|
228
|
+
"printWidth": 100,
|
|
229
|
+
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
|
|
230
|
+
"tailwindStylesheet": "./$CSS_FILE"
|
|
231
|
+
}
|
|
232
|
+
PRETTIER_EOF
|
|
233
|
+
echo " ✓ .prettierrc created"
|
|
234
|
+
else
|
|
235
|
+
echo " → .prettierrc exists, skipping"
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
# Create .prettierignore if it doesn't exist
|
|
239
|
+
if [ ! -f ".prettierignore" ]; then
|
|
240
|
+
cat > .prettierignore << 'IGNORE_EOF'
|
|
241
|
+
.svelte-kit
|
|
242
|
+
.claude
|
|
243
|
+
.cursor
|
|
244
|
+
build
|
|
245
|
+
dist
|
|
246
|
+
node_modules
|
|
247
|
+
package-lock.json
|
|
248
|
+
IGNORE_EOF
|
|
249
|
+
echo " ✓ .prettierignore created"
|
|
250
|
+
else
|
|
251
|
+
echo " → .prettierignore exists, skipping"
|
|
252
|
+
fi
|
|
253
|
+
|
|
254
|
+
# Add lint/format scripts to package.json
|
|
255
|
+
npm pkg set scripts.lint="eslint ." 2>/dev/null || true
|
|
256
|
+
npm pkg set scripts.lint:fix="eslint . --fix" 2>/dev/null || true
|
|
257
|
+
npm pkg set scripts.format="prettier --write ." 2>/dev/null || true
|
|
258
|
+
npm pkg set scripts.format:check="prettier --check ." 2>/dev/null || true
|
|
259
|
+
echo " ✓ Lint/format scripts added to package.json"
|
|
260
|
+
echo ""
|
|
261
|
+
|
|
262
|
+
# ─────────────────────────────────────────────────────────
|
|
263
|
+
# Complete
|
|
264
|
+
# ─────────────────────────────────────────────────────────
|
|
265
|
+
|
|
266
|
+
echo "═══════════════════════════════════════════════════"
|
|
267
|
+
echo " Setup Complete"
|
|
268
|
+
echo "═══════════════════════════════════════════════════"
|
|
269
|
+
echo ""
|
|
270
|
+
echo " Components are in \$lib/components/ui/"
|
|
271
|
+
echo ""
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-pattern
|
|
3
|
+
description: Creates composite UI patterns by assembling design system primitives. Use when building reusable components that combine multiple primitives (Card, Button, Input, etc.), creating dashboard widgets, form groups, sensor cards, data displays, or any complex component from existing design system primitives. Also use when the user asks to create a "component" or "widget" that should follow design system conventions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Building Patterns
|
|
7
|
+
|
|
8
|
+
Patterns are composite components assembled from design system primitives.
|
|
9
|
+
|
|
10
|
+
## Decision: Pattern vs Extension
|
|
11
|
+
|
|
12
|
+
**Build a pattern when:**
|
|
13
|
+
|
|
14
|
+
- Combining 3+ primitives into a reusable unit
|
|
15
|
+
- The combination will be used in multiple places
|
|
16
|
+
- The component has its own props/state logic
|
|
17
|
+
|
|
18
|
+
**Extend a primitive instead when:**
|
|
19
|
+
|
|
20
|
+
- Adding variants to a single primitive
|
|
21
|
+
- Customizing styling without composition
|
|
22
|
+
|
|
23
|
+
## Pattern Structure
|
|
24
|
+
|
|
25
|
+
```svelte
|
|
26
|
+
<script>
|
|
27
|
+
import { cn } from '$lib/utils.js';
|
|
28
|
+
import { Card, CardHeader, CardTitle, CardContent } from '$lib/components/ui/card/index.js';
|
|
29
|
+
import { Button } from '$lib/components/ui/button/index.js';
|
|
30
|
+
|
|
31
|
+
let { title, class: className, children, ...restProps } = $props();
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<Card class={cn('p-4', className)} {...restProps}>
|
|
35
|
+
<CardHeader>
|
|
36
|
+
<CardTitle>{title}</CardTitle>
|
|
37
|
+
</CardHeader>
|
|
38
|
+
<CardContent>
|
|
39
|
+
{@render children?.()}
|
|
40
|
+
</CardContent>
|
|
41
|
+
</Card>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Key Conventions
|
|
45
|
+
|
|
46
|
+
### Props Pattern
|
|
47
|
+
|
|
48
|
+
Always use this structure:
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
let {
|
|
52
|
+
ref = $bindable(null), // optional DOM reference
|
|
53
|
+
class: className, // rename to avoid reserved word
|
|
54
|
+
children, // snippet for slot content
|
|
55
|
+
...restProps // pass-through attributes
|
|
56
|
+
} = $props();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Class Merging
|
|
60
|
+
|
|
61
|
+
Always use `cn()` for classes:
|
|
62
|
+
|
|
63
|
+
```svelte
|
|
64
|
+
<div class={cn('bg-card p-4', className)}>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Never concatenate strings directly.
|
|
68
|
+
|
|
69
|
+
### Spreading restProps
|
|
70
|
+
|
|
71
|
+
Always spread on the root element:
|
|
72
|
+
|
|
73
|
+
```svelte
|
|
74
|
+
<Card class={cn('p-4', className)} {...restProps}>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This ensures aria attributes, data attributes, and event handlers pass through.
|
|
78
|
+
|
|
79
|
+
### Rendering Children
|
|
80
|
+
|
|
81
|
+
Use `{@render}` for slot content:
|
|
82
|
+
|
|
83
|
+
```svelte
|
|
84
|
+
{@render children?.()}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Available Primitives
|
|
88
|
+
|
|
89
|
+
Import from `$lib/components/ui/`. Before building, list `$lib/components/ui/` to discover all installed primitives.
|
|
90
|
+
|
|
91
|
+
### Layout & Structure
|
|
92
|
+
|
|
93
|
+
- **card** - Card, CardHeader, CardTitle, CardContent, CardFooter, CardAction, CardDescription
|
|
94
|
+
- **separator** - Separator
|
|
95
|
+
- **resizable** - ResizablePane, ResizablePaneGroup, ResizableHandle
|
|
96
|
+
- **scroll-area** - ScrollArea
|
|
97
|
+
- **aspect-ratio** - AspectRatio
|
|
98
|
+
- **skeleton** - Skeleton
|
|
99
|
+
- **collapsible** - Collapsible.Root, Collapsible.Trigger, Collapsible.Content
|
|
100
|
+
|
|
101
|
+
### Forms & Inputs
|
|
102
|
+
|
|
103
|
+
- **button** - Button (with variants via `buttonVariants`)
|
|
104
|
+
- **input** - Input
|
|
105
|
+
- **textarea** - Textarea
|
|
106
|
+
- **label** - Label
|
|
107
|
+
- **checkbox** - Checkbox
|
|
108
|
+
- **switch** - Switch
|
|
109
|
+
- **select** - Select.Root, Select.Trigger, Select.Content, Select.Item
|
|
110
|
+
- **native-select** - NativeSelect
|
|
111
|
+
- **radio-group** - RadioGroup.Root, RadioGroup.Item
|
|
112
|
+
- **slider** - Slider
|
|
113
|
+
- **toggle** - Toggle
|
|
114
|
+
- **toggle-group** - ToggleGroup.Root, ToggleGroup.Item
|
|
115
|
+
- **input-otp** - InputOTP
|
|
116
|
+
- **input-group** - InputGroup
|
|
117
|
+
- **field** - Field, FieldSet, FieldGroup, FieldLabel, FieldDescription, FieldError, FieldContent
|
|
118
|
+
|
|
119
|
+
### Data Display
|
|
120
|
+
|
|
121
|
+
- **table** - Table, TableHeader, TableBody, TableRow, TableCell, TableHead, TableFooter, TableCaption
|
|
122
|
+
- **data-table** - createSvelteTable, FlexRender
|
|
123
|
+
- **chart** - Chart.Container, Chart.Tooltip
|
|
124
|
+
- **badge** - Badge
|
|
125
|
+
- **avatar** - Avatar, AvatarImage, AvatarFallback
|
|
126
|
+
- **kbd** - Kbd
|
|
127
|
+
- **empty** - Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent
|
|
128
|
+
- **item** - Item, ItemGroup, ItemHeader, ItemContent, ItemTitle, ItemDescription, ItemActions, ItemMedia
|
|
129
|
+
- **spinner** - Spinner
|
|
130
|
+
- **progress** - Progress
|
|
131
|
+
- **carousel** - Carousel
|
|
132
|
+
|
|
133
|
+
### Overlays & Dialogs
|
|
134
|
+
|
|
135
|
+
- **dialog** - Dialog.Root, Dialog.Trigger, Dialog.Content, Dialog.Header, Dialog.Title, Dialog.Description, Dialog.Footer, Dialog.Close
|
|
136
|
+
- **alert-dialog** - AlertDialog.Root, AlertDialog.Trigger, AlertDialog.Content, AlertDialog.Header, AlertDialog.Title, AlertDialog.Description, AlertDialog.Footer, AlertDialog.Action, AlertDialog.Cancel
|
|
137
|
+
- **sheet** - Sheet.Root, Sheet.Trigger, Sheet.Content, Sheet.Header, Sheet.Title, Sheet.Description, Sheet.Footer, Sheet.Close
|
|
138
|
+
- **drawer** - Drawer.Root, Drawer.Trigger, Drawer.Content, Drawer.Header, Drawer.Title, Drawer.Description, Drawer.Footer, Drawer.Close
|
|
139
|
+
- **popover** - Popover.Root, Popover.Trigger, Popover.Content
|
|
140
|
+
- **hover-card** - HoverCard.Root, HoverCard.Trigger, HoverCard.Content
|
|
141
|
+
- **tooltip** - Tooltip.Root, Tooltip.Trigger, Tooltip.Content, Tooltip.Provider
|
|
142
|
+
- **command** - Command.Root, Command.Input, Command.List, Command.Item, Command.Group
|
|
143
|
+
- **sonner** - Toaster
|
|
144
|
+
|
|
145
|
+
### Navigation & Menus
|
|
146
|
+
|
|
147
|
+
- **tabs** - Tabs.Root, Tabs.List, Tabs.Trigger, Tabs.Content
|
|
148
|
+
- **accordion** - Accordion.Root, Accordion.Item, Accordion.Trigger, Accordion.Content
|
|
149
|
+
- **dropdown-menu** - DropdownMenu.Root, DropdownMenu.Trigger, DropdownMenu.Content, DropdownMenu.Item, DropdownMenu.Separator
|
|
150
|
+
- **context-menu** - ContextMenu.Root, ContextMenu.Trigger, ContextMenu.Content, ContextMenu.Item
|
|
151
|
+
- **menubar** - Menubar
|
|
152
|
+
- **navigation-menu** - NavigationMenu
|
|
153
|
+
- **breadcrumb** - Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbSeparator, BreadcrumbPage
|
|
154
|
+
- **pagination** - Pagination
|
|
155
|
+
- **sidebar** - Sidebar, SidebarProvider, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuItem, SidebarMenuButton, SidebarTrigger
|
|
156
|
+
- **button-group** - ButtonGroup, ButtonGroupText, ButtonGroupSeparator
|
|
157
|
+
|
|
158
|
+
### Date Picking
|
|
159
|
+
|
|
160
|
+
- **calendar** - Calendar
|
|
161
|
+
- **range-calendar** - RangeCalendar
|
|
162
|
+
|
|
163
|
+
### Feedback
|
|
164
|
+
|
|
165
|
+
- **alert** - Alert, AlertTitle, AlertDescription
|
|
166
|
+
|
|
167
|
+
## Example: Sensor Card Pattern
|
|
168
|
+
|
|
169
|
+
```svelte
|
|
170
|
+
<script>
|
|
171
|
+
import { cn } from '$lib/utils.js';
|
|
172
|
+
import { Card, CardHeader, CardTitle, CardContent } from '$lib/components/ui/card/index.js';
|
|
173
|
+
import * as Chart from '$lib/components/ui/chart/index.js';
|
|
174
|
+
|
|
175
|
+
let { title = 'SENSOR', icon: Icon, data = [], class: className, ...restProps } = $props();
|
|
176
|
+
</script>
|
|
177
|
+
|
|
178
|
+
<Card class={cn('p-4', className)} {...restProps}>
|
|
179
|
+
<CardHeader class="flex flex-row items-center justify-between p-0">
|
|
180
|
+
<CardTitle class="text-foreground font-mono text-base uppercase">
|
|
181
|
+
{title}
|
|
182
|
+
</CardTitle>
|
|
183
|
+
{#if Icon}
|
|
184
|
+
<Icon class="text-muted-foreground size-6" aria-hidden="true" />
|
|
185
|
+
{/if}
|
|
186
|
+
</CardHeader>
|
|
187
|
+
<CardContent class="p-0">
|
|
188
|
+
<Chart.Container config={{}} class="h-[220px] w-full">
|
|
189
|
+
<!-- chart content -->
|
|
190
|
+
</Chart.Container>
|
|
191
|
+
</CardContent>
|
|
192
|
+
</Card>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Detailed Conventions
|
|
196
|
+
|
|
197
|
+
See `@rules/components.md` for:
|
|
198
|
+
|
|
199
|
+
- bits-ui wrapper patterns
|
|
200
|
+
- tailwind-variants (tv) usage
|
|
201
|
+
- Conditional rendering patterns
|
|
202
|
+
- Icon handling
|