picasso-skill 2.5.0 → 2.6.1
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 +4 -6
- package/commands/mood.md +3 -2
- package/commands/preset.md +2 -2
- package/commands/preview.md +3 -3
- package/commands/variants.md +3 -4
- package/package.json +1 -1
- package/references/accessibility-wcag.md +3 -0
- package/references/code-typography.md +36 -166
- package/references/color-and-contrast.md +78 -345
- package/references/generative-art.md +49 -561
- package/references/modern-css-performance.md +46 -258
- package/references/motion-and-animation.md +225 -88
- package/references/navigation-patterns.md +29 -186
- package/references/performance-optimization.md +42 -678
- package/references/react-patterns.md +56 -216
- package/references/responsive-design.md +77 -379
- package/references/sensory-design.md +62 -263
- package/references/ux-writing.md +64 -354
- package/references/visual-preview.md +17 -9
- package/references/animation-performance.md +0 -244
- package/references/interaction-design.md +0 -162
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
# Animation Performance Reference
|
|
2
|
-
|
|
3
|
-
## Table of Contents
|
|
4
|
-
1. Compositor-Only Properties
|
|
5
|
-
2. Will-Change Best Practices
|
|
6
|
-
3. Layout Thrashing
|
|
7
|
-
4. IntersectionObserver vs Scroll Events
|
|
8
|
-
5. Web Animations API
|
|
9
|
-
6. Performance Measurement
|
|
10
|
-
7. Testing on Low-End Devices
|
|
11
|
-
8. Contain Property
|
|
12
|
-
9. Common Mistakes
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## 1. Compositor-Only Properties
|
|
17
|
-
|
|
18
|
-
Only two CSS properties can be animated without triggering layout or paint: **transform** and **opacity**. Everything else causes reflow.
|
|
19
|
-
|
|
20
|
-
| Property | Layout | Paint | Composite | Animate? |
|
|
21
|
-
|---|---|---|---|---|
|
|
22
|
-
| `transform` | No | No | Yes | **Yes** |
|
|
23
|
-
| `opacity` | No | No | Yes | **Yes** |
|
|
24
|
-
| `filter` | No | Yes | Yes | Carefully |
|
|
25
|
-
| `background-color` | No | Yes | No | Avoid |
|
|
26
|
-
| `width`, `height` | Yes | Yes | No | **Never** |
|
|
27
|
-
| `top`, `left` | Yes | Yes | No | **Never** |
|
|
28
|
-
| `margin`, `padding` | Yes | Yes | No | **Never** |
|
|
29
|
-
| `border-radius` | No | Yes | No | Avoid |
|
|
30
|
-
|
|
31
|
-
```css
|
|
32
|
-
/* Good: compositor-only */
|
|
33
|
-
.slide-in {
|
|
34
|
-
transform: translateX(-100%);
|
|
35
|
-
opacity: 0;
|
|
36
|
-
transition: transform 300ms var(--ease-out), opacity 300ms var(--ease-out);
|
|
37
|
-
}
|
|
38
|
-
.slide-in.active {
|
|
39
|
-
transform: translateX(0);
|
|
40
|
-
opacity: 1;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/* Bad: triggers layout on every frame */
|
|
44
|
-
.slide-in-bad {
|
|
45
|
-
left: -100%;
|
|
46
|
-
transition: left 300ms ease;
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## 2. Will-Change Best Practices
|
|
53
|
-
|
|
54
|
-
`will-change` promotes an element to its own compositor layer. This speeds up animation but consumes GPU memory.
|
|
55
|
-
|
|
56
|
-
Rules:
|
|
57
|
-
- Add `will-change` BEFORE the animation starts (e.g., on hover, not in the animation itself).
|
|
58
|
-
- Remove it AFTER the animation completes.
|
|
59
|
-
- Never use `will-change: all` — it promotes everything.
|
|
60
|
-
- Never apply it to more than 10 elements simultaneously.
|
|
61
|
-
- Don't put it in your stylesheet permanently.
|
|
62
|
-
|
|
63
|
-
```js
|
|
64
|
-
// Good: apply before, remove after
|
|
65
|
-
element.addEventListener('mouseenter', () => {
|
|
66
|
-
element.style.willChange = 'transform';
|
|
67
|
-
});
|
|
68
|
-
element.addEventListener('transitionend', () => {
|
|
69
|
-
element.style.willChange = 'auto';
|
|
70
|
-
});
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
```css
|
|
74
|
-
/* Acceptable: for elements that are ALWAYS animated (e.g., loading spinners) */
|
|
75
|
-
.spinner { will-change: transform; }
|
|
76
|
-
|
|
77
|
-
/* Bad: permanent will-change on static elements */
|
|
78
|
-
.card { will-change: transform, opacity; } /* don't do this */
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
## 3. Layout Thrashing
|
|
84
|
-
|
|
85
|
-
Reading layout properties then writing them in a loop forces the browser to recalculate layout on every iteration.
|
|
86
|
-
|
|
87
|
-
```js
|
|
88
|
-
// BAD: layout thrashing (read-write-read-write)
|
|
89
|
-
elements.forEach(el => {
|
|
90
|
-
const height = el.offsetHeight; // READ — forces layout
|
|
91
|
-
el.style.height = height + 10 + 'px'; // WRITE — invalidates layout
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// GOOD: batch reads, then batch writes
|
|
95
|
-
const heights = elements.map(el => el.offsetHeight); // all reads first
|
|
96
|
-
elements.forEach((el, i) => {
|
|
97
|
-
el.style.height = heights[i] + 10 + 'px'; // all writes after
|
|
98
|
-
});
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Properties that trigger forced layout when read: `offsetHeight`, `offsetWidth`, `getBoundingClientRect()`, `scrollTop`, `clientHeight`, `getComputedStyle()`.
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## 4. IntersectionObserver vs Scroll Events
|
|
106
|
-
|
|
107
|
-
| | `scroll` event | IntersectionObserver |
|
|
108
|
-
|---|---|---|
|
|
109
|
-
| Performance | Fires every pixel, blocks main thread | Async, fires on threshold crossing |
|
|
110
|
-
| Throttling | Manual (requestAnimationFrame) | Built-in |
|
|
111
|
-
| Use case | Scroll-linked animation (position) | Visibility detection (enter/exit) |
|
|
112
|
-
| Recommendation | Almost never | Almost always |
|
|
113
|
-
|
|
114
|
-
```js
|
|
115
|
-
// Good: IntersectionObserver for reveal animations
|
|
116
|
-
const observer = new IntersectionObserver(
|
|
117
|
-
(entries) => {
|
|
118
|
-
entries.forEach(entry => {
|
|
119
|
-
entry.target.classList.toggle('visible', entry.isIntersecting);
|
|
120
|
-
});
|
|
121
|
-
},
|
|
122
|
-
{ threshold: 0.1 }
|
|
123
|
-
);
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
For scroll-linked animations where you need exact scroll position, use the Scroll-Driven Animations API:
|
|
127
|
-
|
|
128
|
-
```css
|
|
129
|
-
@keyframes fade-in {
|
|
130
|
-
from { opacity: 0; transform: translateY(20px); }
|
|
131
|
-
to { opacity: 1; transform: translateY(0); }
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.scroll-reveal {
|
|
135
|
-
animation: fade-in linear;
|
|
136
|
-
animation-timeline: view();
|
|
137
|
-
animation-range: entry 0% entry 100%;
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
## 5. Web Animations API
|
|
144
|
-
|
|
145
|
-
For complex JS-driven animations, use WAAPI instead of manual `requestAnimationFrame`:
|
|
146
|
-
|
|
147
|
-
```js
|
|
148
|
-
element.animate(
|
|
149
|
-
[
|
|
150
|
-
{ transform: 'translateY(20px)', opacity: 0 },
|
|
151
|
-
{ transform: 'translateY(0)', opacity: 1 }
|
|
152
|
-
],
|
|
153
|
-
{
|
|
154
|
-
duration: 300,
|
|
155
|
-
easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
|
|
156
|
-
fill: 'forwards'
|
|
157
|
-
}
|
|
158
|
-
);
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
Benefits over CSS: programmable, cancellable, can read progress, can reverse.
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## 6. Performance Measurement
|
|
166
|
-
|
|
167
|
-
```js
|
|
168
|
-
// Measure animation frame rate
|
|
169
|
-
let frames = 0;
|
|
170
|
-
let lastTime = performance.now();
|
|
171
|
-
|
|
172
|
-
function countFrames() {
|
|
173
|
-
frames++;
|
|
174
|
-
const now = performance.now();
|
|
175
|
-
if (now - lastTime >= 1000) {
|
|
176
|
-
console.log(`FPS: ${frames}`);
|
|
177
|
-
frames = 0;
|
|
178
|
-
lastTime = now;
|
|
179
|
-
}
|
|
180
|
-
requestAnimationFrame(countFrames);
|
|
181
|
-
}
|
|
182
|
-
requestAnimationFrame(countFrames);
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
Chrome DevTools:
|
|
186
|
-
1. Performance tab → Record → interact with animations → Stop
|
|
187
|
-
2. Look for long frames (> 16ms) in the flame chart
|
|
188
|
-
3. Rendering tab → Paint flashing (green = repaint, should be minimal)
|
|
189
|
-
4. Rendering tab → Layer borders (orange = composited layers)
|
|
190
|
-
|
|
191
|
-
Target: 60fps = 16.67ms per frame. If ANY frame takes > 33ms, users perceive jank.
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
## 7. Testing on Low-End Devices
|
|
196
|
-
|
|
197
|
-
Your M-series Mac is not representative. Test with:
|
|
198
|
-
- **Chrome DevTools CPU throttling:** Performance tab → CPU → 6x slowdown
|
|
199
|
-
- **Network throttling:** Slow 3G preset to test loading animations
|
|
200
|
-
- **Real device:** Test on a 3-year-old Android phone if possible
|
|
201
|
-
|
|
202
|
-
If an animation stutters at 6x CPU throttle, reduce:
|
|
203
|
-
1. Number of concurrent animations
|
|
204
|
-
2. Element count being animated
|
|
205
|
-
3. Complexity of each animation
|
|
206
|
-
|
|
207
|
-
---
|
|
208
|
-
|
|
209
|
-
## 8. Contain Property
|
|
210
|
-
|
|
211
|
-
`contain` tells the browser what NOT to recalculate when an element changes.
|
|
212
|
-
|
|
213
|
-
```css
|
|
214
|
-
/* Isolate layout/paint to this element */
|
|
215
|
-
.card {
|
|
216
|
-
contain: layout paint;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/* Full isolation — best for off-screen or independent components */
|
|
220
|
-
.widget {
|
|
221
|
-
contain: strict; /* = size + layout + paint + style */
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/* Content containment — layout + paint + style (most common) */
|
|
225
|
-
.list-item {
|
|
226
|
-
contain: content;
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
Use `contain: content` on repeated elements (list items, cards) to prevent layout changes from propagating to siblings.
|
|
231
|
-
|
|
232
|
-
---
|
|
233
|
-
|
|
234
|
-
## 9. Common Mistakes
|
|
235
|
-
|
|
236
|
-
- **Animating `width`/`height`/`top`/`left`.** Use `transform: translate/scale` instead.
|
|
237
|
-
- **`will-change` on everything.** Max 10 elements. Remove after animation completes.
|
|
238
|
-
- **`addEventListener('scroll')` for visibility.** Use IntersectionObserver.
|
|
239
|
-
- **Reading layout properties in animation loops.** Batch reads before writes.
|
|
240
|
-
- **Testing only on fast hardware.** Use Chrome CPU throttling at 6x.
|
|
241
|
-
- **No frame budget awareness.** 16ms per frame. If your JS takes 20ms, you drop frames.
|
|
242
|
-
- **CSS `transition: all`.** Transitions every property including layout triggers.
|
|
243
|
-
- **Forgetting `contain` on repeated elements.** One card's layout change recalculates the entire list.
|
|
244
|
-
- **`requestAnimationFrame` without cancellation.** Always store the ID and `cancelAnimationFrame` on cleanup.
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
# Interaction Design Reference
|
|
2
|
-
|
|
3
|
-
## Table of Contents
|
|
4
|
-
1. Form Design
|
|
5
|
-
2. Focus Management
|
|
6
|
-
3. Loading Patterns
|
|
7
|
-
4. Empty States
|
|
8
|
-
5. Error Handling
|
|
9
|
-
6. UX Writing
|
|
10
|
-
7. Common Mistakes
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 1. Form Design
|
|
15
|
-
|
|
16
|
-
### Input Fields
|
|
17
|
-
- Use visible labels above inputs, not placeholder-only labels (placeholders disappear on focus)
|
|
18
|
-
- Input height: 40-48px for desktop, 48px minimum for touch
|
|
19
|
-
- Group related fields visually (name + email, street + city + zip)
|
|
20
|
-
- Show validation inline, not in an alert after submission
|
|
21
|
-
- Use `inputmode` attribute for mobile keyboards: `inputmode="email"`, `inputmode="numeric"`, `inputmode="tel"`
|
|
22
|
-
- Auto-focus the first field on page load when the form is the primary task
|
|
23
|
-
|
|
24
|
-
### Field States
|
|
25
|
-
Every input needs four visible states:
|
|
26
|
-
1. **Default**: subtle border, neutral background
|
|
27
|
-
2. **Focus**: accent border (2px), subtle glow or shadow
|
|
28
|
-
3. **Error**: error-colored border, inline error message below the field
|
|
29
|
-
4. **Disabled**: reduced opacity (0.5), `cursor: not-allowed`
|
|
30
|
-
|
|
31
|
-
### Buttons
|
|
32
|
-
- Primary action: filled, high contrast (accent color)
|
|
33
|
-
- Secondary action: outlined or ghost (border only)
|
|
34
|
-
- Destructive action: red/error color, requires confirmation for irreversible actions
|
|
35
|
-
- Button text: verb-first ("Save changes", "Create project"), never "Submit" or "Click here"
|
|
36
|
-
- Loading state: replace text with spinner or use `aria-busy="true"`, disable the button to prevent double-submission
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## 2. Focus Management
|
|
41
|
-
|
|
42
|
-
### Focus Indicators
|
|
43
|
-
Never remove focus outlines without replacement. Use a visible, high-contrast focus ring:
|
|
44
|
-
```css
|
|
45
|
-
:focus-visible {
|
|
46
|
-
outline: 2px solid var(--accent);
|
|
47
|
-
outline-offset: 2px;
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Use `:focus-visible` (not `:focus`) to show focus rings only for keyboard navigation, not mouse clicks.
|
|
52
|
-
|
|
53
|
-
### Focus Trapping
|
|
54
|
-
Modal dialogs must trap focus within them. When a modal opens:
|
|
55
|
-
1. Move focus to the first focusable element inside
|
|
56
|
-
2. Tab cycles within the modal
|
|
57
|
-
3. Escape closes the modal
|
|
58
|
-
4. Focus returns to the trigger element on close
|
|
59
|
-
|
|
60
|
-
### Skip Links
|
|
61
|
-
Add a skip-to-content link as the first focusable element:
|
|
62
|
-
```html
|
|
63
|
-
<a href="#main-content" class="skip-link">Skip to content</a>
|
|
64
|
-
```
|
|
65
|
-
```css
|
|
66
|
-
.skip-link {
|
|
67
|
-
position: absolute;
|
|
68
|
-
top: -100%;
|
|
69
|
-
left: 0;
|
|
70
|
-
}
|
|
71
|
-
.skip-link:focus {
|
|
72
|
-
top: 0;
|
|
73
|
-
z-index: 1000;
|
|
74
|
-
}
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
---
|
|
78
|
-
|
|
79
|
-
## 3. Loading Patterns
|
|
80
|
-
|
|
81
|
-
### Skeleton Screens
|
|
82
|
-
Replace content with gray shapes that match the expected layout. This feels faster than a spinner because the user can see the structure forming.
|
|
83
|
-
|
|
84
|
-
### Progressive Loading
|
|
85
|
-
Show content as it arrives. Do not wait for everything to load before showing anything. Use `Suspense` boundaries in React to show parts of the page while others load.
|
|
86
|
-
|
|
87
|
-
### Optimistic Updates
|
|
88
|
-
For user-initiated actions (like, save, delete), update the UI immediately and reconcile with the server response. Show a subtle undo option if the server rejects the action.
|
|
89
|
-
|
|
90
|
-
### Spinner vs. Skeleton
|
|
91
|
-
- **Spinner**: Use for actions that take 1-3 seconds (button submissions, API calls). Place inside the triggering element.
|
|
92
|
-
- **Skeleton**: Use for content areas that take 0.5-5 seconds to load. Match the shape of the expected content.
|
|
93
|
-
- **Progress bar**: Use for operations that take 5+ seconds with measurable progress (file uploads, multi-step processes).
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## 4. Empty States
|
|
98
|
-
|
|
99
|
-
Empty states are an opportunity, not a placeholder. They should:
|
|
100
|
-
1. Explain what this area will contain once populated
|
|
101
|
-
2. Provide a clear action to get started
|
|
102
|
-
3. Optionally include an illustration or icon for warmth
|
|
103
|
-
|
|
104
|
-
```
|
|
105
|
-
No projects yet.
|
|
106
|
-
Create your first project to get started.
|
|
107
|
-
[+ Create Project]
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Never show a blank page, an error message, or raw "null" / "undefined" in place of empty content.
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## 5. Error Handling
|
|
115
|
-
|
|
116
|
-
### Inline Errors
|
|
117
|
-
Show errors next to the element that caused them, not in a modal or toast. Use the error color for the field border and display the message directly below.
|
|
118
|
-
|
|
119
|
-
### Error Messages
|
|
120
|
-
- Be specific: "Email address must include an @ symbol" not "Invalid input"
|
|
121
|
-
- Be helpful: suggest the fix, not just the problem
|
|
122
|
-
- Be human: "We couldn't find that page" not "404 Not Found"
|
|
123
|
-
|
|
124
|
-
### Network Errors
|
|
125
|
-
Show a non-blocking banner or inline message with a retry action. Never show a raw error object or stack trace.
|
|
126
|
-
|
|
127
|
-
### Form Validation
|
|
128
|
-
Validate on blur (when the user leaves a field), not on every keystroke. Show success indicators for valid fields (subtle checkmark or green border).
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
## 6. UX Writing
|
|
133
|
-
|
|
134
|
-
### Buttons
|
|
135
|
-
- Use action verbs: "Save", "Send", "Create", "Delete"
|
|
136
|
-
- Be specific: "Save changes" > "Save", "Send message" > "Send"
|
|
137
|
-
- Match the action to the context: "Place order" not "Submit"
|
|
138
|
-
|
|
139
|
-
### Labels
|
|
140
|
-
- Clear and concise: "Full name" not "Please enter your full name"
|
|
141
|
-
- Avoid jargon: "Phone number" not "Primary contact number"
|
|
142
|
-
|
|
143
|
-
### Confirmations
|
|
144
|
-
- State what happened: "Project created successfully"
|
|
145
|
-
- Provide next step if relevant: "Project created. Add your first task?"
|
|
146
|
-
|
|
147
|
-
### Destructive Actions
|
|
148
|
-
- State what will happen: "This will permanently delete 3 files"
|
|
149
|
-
- Require explicit confirmation: "Type DELETE to confirm"
|
|
150
|
-
- Provide an out: "Cancel" should be more prominent than "Delete"
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## 7. Common Mistakes
|
|
155
|
-
|
|
156
|
-
- Placeholder text as the only label (disappears on focus, inaccessible)
|
|
157
|
-
- Disabling the submit button before all fields are filled (users do not know which field is missing)
|
|
158
|
-
- Using toast notifications for errors (the user may not see them, they disappear)
|
|
159
|
-
- No loading feedback after clicking a button (user clicks again, causing duplicate submissions)
|
|
160
|
-
- Custom scrollbars that break native scroll behavior
|
|
161
|
-
- Hover-only interactions with no keyboard or touch equivalent
|
|
162
|
-
- Alert/confirm dialogs that block the entire page for minor confirmations
|