picasso-skill 1.6.0 → 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.
- package/agents/picasso.md +14 -2
- package/commands/backlog.md +34 -0
- package/commands/variants.md +18 -0
- package/package.json +1 -1
- package/skills/picasso/SKILL.md +26 -2
- package/skills/picasso/references/animation-performance.md +244 -0
- package/skills/picasso/references/brand-and-identity.md +136 -0
- package/skills/picasso/references/code-typography.md +222 -0
- package/skills/picasso/references/dark-mode.md +199 -0
- package/skills/picasso/references/i18n-visual-patterns.md +177 -0
- package/skills/picasso/references/images-and-media.md +222 -0
- package/skills/picasso/references/loading-and-states.md +258 -0
- package/skills/picasso/references/micro-interactions.md +291 -0
- package/skills/picasso/references/navigation-patterns.md +247 -0
- package/skills/picasso/references/tables-and-forms.md +227 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# Tables and Forms Reference
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
1. Sortable Tables
|
|
5
|
+
2. Responsive Tables
|
|
6
|
+
3. Inline Editing
|
|
7
|
+
4. Multi-Select Patterns
|
|
8
|
+
5. Form Validation
|
|
9
|
+
6. Multi-Step Forms
|
|
10
|
+
7. Complex Inputs
|
|
11
|
+
8. Common Mistakes
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. Sortable Tables
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<table>
|
|
19
|
+
<thead>
|
|
20
|
+
<tr>
|
|
21
|
+
<th aria-sort="ascending">
|
|
22
|
+
<button>Name <span aria-hidden="true">↑</span></button>
|
|
23
|
+
</th>
|
|
24
|
+
<th aria-sort="none">
|
|
25
|
+
<button>Date <span aria-hidden="true">↕</span></button>
|
|
26
|
+
</th>
|
|
27
|
+
</tr>
|
|
28
|
+
</thead>
|
|
29
|
+
</table>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- Use `aria-sort` on `<th>`: `ascending`, `descending`, or `none`.
|
|
33
|
+
- Sort icon: `↑` ascending, `↓` descending, `↕` unsorted. Use `aria-hidden="true"` on the icon.
|
|
34
|
+
- Sortable headers must be `<button>` inside `<th>`, not clickable `<th>`.
|
|
35
|
+
- Default sort: most recent first for dates, alphabetical for names.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 2. Responsive Tables
|
|
40
|
+
|
|
41
|
+
**Option A: Horizontal scroll** (preferred for data tables)
|
|
42
|
+
|
|
43
|
+
```css
|
|
44
|
+
.table-container {
|
|
45
|
+
overflow-x: auto;
|
|
46
|
+
-webkit-overflow-scrolling: touch;
|
|
47
|
+
border: 1px solid var(--border);
|
|
48
|
+
border-radius: 8px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* Fade edge to hint scrollability */
|
|
52
|
+
.table-container::after {
|
|
53
|
+
content: '';
|
|
54
|
+
position: absolute;
|
|
55
|
+
right: 0;
|
|
56
|
+
top: 0;
|
|
57
|
+
bottom: 0;
|
|
58
|
+
width: 40px;
|
|
59
|
+
background: linear-gradient(to left, var(--surface-1), transparent);
|
|
60
|
+
pointer-events: none;
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Option B: Stacked cards** (for simple tables on mobile)
|
|
65
|
+
|
|
66
|
+
```css
|
|
67
|
+
@media (max-width: 640px) {
|
|
68
|
+
table, thead, tbody, th, td, tr { display: block; }
|
|
69
|
+
thead { display: none; }
|
|
70
|
+
td { padding: 8px 16px; text-align: right; }
|
|
71
|
+
td::before {
|
|
72
|
+
content: attr(data-label);
|
|
73
|
+
float: left;
|
|
74
|
+
font-weight: 600;
|
|
75
|
+
color: var(--text-secondary);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 3. Inline Editing
|
|
83
|
+
|
|
84
|
+
Click to edit pattern: display text, click reveals input, blur/Enter saves.
|
|
85
|
+
|
|
86
|
+
```jsx
|
|
87
|
+
function EditableCell({ value, onSave }) {
|
|
88
|
+
const [editing, setEditing] = useState(false);
|
|
89
|
+
const [draft, setDraft] = useState(value);
|
|
90
|
+
|
|
91
|
+
if (!editing) return (
|
|
92
|
+
<span onClick={() => setEditing(true)} className="cursor-text hover:bg-surface-2 px-2 py-1 rounded">
|
|
93
|
+
{value}
|
|
94
|
+
</span>
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<input
|
|
99
|
+
value={draft}
|
|
100
|
+
onChange={e => setDraft(e.target.value)}
|
|
101
|
+
onBlur={() => { onSave(draft); setEditing(false); }}
|
|
102
|
+
onKeyDown={e => { if (e.key === 'Enter') { onSave(draft); setEditing(false); } if (e.key === 'Escape') setEditing(false); }}
|
|
103
|
+
autoFocus
|
|
104
|
+
className="input-base w-full"
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Show a subtle pencil icon on row hover. Use `opacity-0 group-hover:opacity-100` pattern.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 4. Multi-Select Patterns
|
|
115
|
+
|
|
116
|
+
- **Checkbox column**: leftmost column, always visible.
|
|
117
|
+
- **Shift-click range select**: select from last checked to current.
|
|
118
|
+
- **Select all**: checkbox in header, toggles all visible (filtered) rows.
|
|
119
|
+
- **Bulk action bar**: appears when 1+ rows selected. Shows count + actions.
|
|
120
|
+
|
|
121
|
+
```jsx
|
|
122
|
+
<div className={`fixed bottom-4 left-1/2 -translate-x-1/2 bg-surface-2 rounded-xl px-4 py-2
|
|
123
|
+
flex items-center gap-4 shadow-lg border border-border transition-transform
|
|
124
|
+
${selectedCount > 0 ? 'translate-y-0' : 'translate-y-[200%]'}`}>
|
|
125
|
+
<span className="text-sm font-medium">{selectedCount} selected</span>
|
|
126
|
+
<button className="btn-ghost text-sm">Export</button>
|
|
127
|
+
<button className="btn-ghost text-sm text-red">Delete</button>
|
|
128
|
+
</div>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 5. Form Validation
|
|
134
|
+
|
|
135
|
+
**When to validate:**
|
|
136
|
+
|
|
137
|
+
| Trigger | Use For |
|
|
138
|
+
|---|---|
|
|
139
|
+
| On blur | Email format, required fields, min/max length |
|
|
140
|
+
| On submit | All fields, server-side checks |
|
|
141
|
+
| Real-time (on change) | Password strength, username availability |
|
|
142
|
+
| Never on keystroke | Don't interrupt typing. Wait for blur or 500ms debounce. |
|
|
143
|
+
|
|
144
|
+
```jsx
|
|
145
|
+
<div className="space-y-1.5">
|
|
146
|
+
<label htmlFor="email" className="text-sm font-medium">Email</label>
|
|
147
|
+
<input
|
|
148
|
+
id="email"
|
|
149
|
+
type="email"
|
|
150
|
+
aria-invalid={error ? "true" : undefined}
|
|
151
|
+
aria-describedby={error ? "email-error" : undefined}
|
|
152
|
+
className={`input-base ${error ? 'border-red' : ''}`}
|
|
153
|
+
/>
|
|
154
|
+
{error && (
|
|
155
|
+
<p id="email-error" role="alert" className="text-xs text-red flex items-center gap-1">
|
|
156
|
+
<svg className="w-3.5 h-3.5" aria-hidden="true">...</svg>
|
|
157
|
+
{error}
|
|
158
|
+
</p>
|
|
159
|
+
)}
|
|
160
|
+
</div>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Error messages: specific and helpful. "Enter a valid email" not "Invalid input."
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 6. Multi-Step Forms
|
|
168
|
+
|
|
169
|
+
Show a progress indicator. Allow back navigation. Validate per step, not all at once.
|
|
170
|
+
|
|
171
|
+
```jsx
|
|
172
|
+
<div className="flex items-center gap-2 mb-8">
|
|
173
|
+
{steps.map((step, i) => (
|
|
174
|
+
<Fragment key={i}>
|
|
175
|
+
<div className={`flex items-center justify-center h-8 w-8 rounded-full text-sm font-bold
|
|
176
|
+
${i < currentStep ? 'bg-accent text-white' :
|
|
177
|
+
i === currentStep ? 'border-2 border-accent text-accent' :
|
|
178
|
+
'border border-border text-muted'}`}>
|
|
179
|
+
{i < currentStep ? '✓' : i + 1}
|
|
180
|
+
</div>
|
|
181
|
+
{i < steps.length - 1 && (
|
|
182
|
+
<div className={`flex-1 h-0.5 ${i < currentStep ? 'bg-accent' : 'bg-border'}`} />
|
|
183
|
+
)}
|
|
184
|
+
</Fragment>
|
|
185
|
+
))}
|
|
186
|
+
</div>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Rules:
|
|
190
|
+
- Save progress per step (don't lose data on back).
|
|
191
|
+
- Validate step before advancing (disable Next if invalid).
|
|
192
|
+
- Show step count: "Step 2 of 4".
|
|
193
|
+
- Allow clicking completed steps to go back.
|
|
194
|
+
- Final step: show summary before submit.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 7. Complex Inputs
|
|
199
|
+
|
|
200
|
+
**Date pickers:** Use native `<input type="date">` first. Custom picker only if design requires it. Always allow manual text entry as fallback.
|
|
201
|
+
|
|
202
|
+
**File upload:** Show progress, preview (for images), allow removal.
|
|
203
|
+
|
|
204
|
+
```jsx
|
|
205
|
+
<label className="flex flex-col items-center gap-2 p-8 border-2 border-dashed border-border
|
|
206
|
+
rounded-xl cursor-pointer hover:border-accent hover:bg-accent/5 transition-colors">
|
|
207
|
+
<svg>...</svg>
|
|
208
|
+
<span className="text-sm text-secondary">Drop files or click to upload</span>
|
|
209
|
+
<input type="file" className="hidden" onChange={handleUpload} />
|
|
210
|
+
</label>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Address autocomplete:** Use Google Places API or similar. Show suggestions in a dropdown. Parse into structured fields (street, city, state, zip).
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## 8. Common Mistakes
|
|
218
|
+
|
|
219
|
+
- **Sortable `<th>` without `<button>`.** Clicking a `<th>` isn't keyboard accessible.
|
|
220
|
+
- **No `aria-sort` on sortable columns.** Screen readers can't announce sort state.
|
|
221
|
+
- **Validating on every keystroke.** Annoying. Use blur or 500ms debounce.
|
|
222
|
+
- **Error messages without `role="alert"`.** Screen readers won't announce them.
|
|
223
|
+
- **Multi-step form losing data on back.** Save each step's state.
|
|
224
|
+
- **No horizontal scroll hint on tables.** Users don't know content is hidden. Add fade gradient.
|
|
225
|
+
- **Custom date picker without text input fallback.** Some users prefer typing dates.
|
|
226
|
+
- **Select all selecting ALL rows, not just filtered.** Only select what's visible.
|
|
227
|
+
- **Labels as placeholder text.** Labels must be visible above the input, always.
|