picasso-skill 1.5.1 → 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 (44) hide show
  1. package/agents/picasso.md +14 -2
  2. package/checklists/pre-ship.md +83 -0
  3. package/commands/backlog.md +34 -0
  4. package/commands/variants.md +18 -0
  5. package/package.json +3 -1
  6. package/references/accessibility-wcag.md +245 -0
  7. package/references/anti-patterns.md +184 -0
  8. package/references/color-and-contrast.md +477 -0
  9. package/references/component-patterns.md +113 -0
  10. package/references/conversion-design.md +193 -0
  11. package/references/data-visualization.md +226 -0
  12. package/references/depth-and-elevation.md +211 -0
  13. package/references/design-system.md +176 -0
  14. package/references/generative-art.md +648 -0
  15. package/references/interaction-design.md +162 -0
  16. package/references/modern-css-performance.md +361 -0
  17. package/references/motion-and-animation.md +267 -0
  18. package/references/performance-optimization.md +746 -0
  19. package/references/react-patterns.md +318 -0
  20. package/references/responsive-design.md +452 -0
  21. package/references/sensory-design.md +369 -0
  22. package/references/spatial-design.md +176 -0
  23. package/references/style-presets.md +502 -0
  24. package/references/tools-catalog.md +103 -0
  25. package/references/typography.md +415 -0
  26. package/references/ux-psychology.md +235 -0
  27. package/references/ux-writing.md +513 -0
  28. package/skills/picasso/SKILL.md +58 -2
  29. package/skills/picasso/references/animation-performance.md +244 -0
  30. package/skills/picasso/references/brand-and-identity.md +136 -0
  31. package/skills/picasso/references/code-typography.md +222 -0
  32. package/skills/picasso/references/color-and-contrast.md +56 -2
  33. package/skills/picasso/references/dark-mode.md +199 -0
  34. package/skills/picasso/references/depth-and-elevation.md +211 -0
  35. package/skills/picasso/references/i18n-visual-patterns.md +177 -0
  36. package/skills/picasso/references/images-and-media.md +222 -0
  37. package/skills/picasso/references/loading-and-states.md +258 -0
  38. package/skills/picasso/references/micro-interactions.md +291 -0
  39. package/skills/picasso/references/motion-and-animation.md +9 -2
  40. package/skills/picasso/references/navigation-patterns.md +247 -0
  41. package/skills/picasso/references/style-presets.md +1 -1
  42. package/skills/picasso/references/tables-and-forms.md +227 -0
  43. package/skills/picasso/references/tools-catalog.md +103 -0
  44. package/skills/picasso/references/typography.md +45 -2
@@ -0,0 +1,162 @@
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
@@ -0,0 +1,361 @@
1
+ # Modern CSS & Web Performance Reference
2
+
3
+ ## 1. Modern CSS Features (2024-2025)
4
+
5
+ ### CSS Nesting (Baseline 2024)
6
+ Native nesting eliminates preprocessor dependency.
7
+
8
+ ```css
9
+ .card {
10
+ padding: 1rem;
11
+ > h2:first-child { margin-block-start: 0; }
12
+ &:hover { box-shadow: 0 4px 12px rgb(0 0 0 / 0.1); }
13
+ @media (width >= 768px) { padding: 2rem; }
14
+ }
15
+ ```
16
+
17
+ ### Cascade Layers (@layer)
18
+ Control specificity ordering without selector wars.
19
+
20
+ ```css
21
+ @layer reset, base, components, utilities;
22
+ @layer reset { *, *::before, *::after { box-sizing: border-box; margin: 0; } }
23
+ @layer base { body { font-family: system-ui; line-height: 1.6; } }
24
+ @layer components { .btn { padding: 0.5rem 1rem; border-radius: 0.375rem; } }
25
+ ```
26
+
27
+ ### :has() Selector
28
+ Style parents based on children.
29
+
30
+ ```css
31
+ form:has(:invalid) { border-color: red; }
32
+ .card:has(img) { grid-template-rows: auto 1fr; }
33
+ body:has(dialog[open]) { overflow: hidden; }
34
+ ```
35
+
36
+ ### CSS Anchor Positioning
37
+ Position elements relative to other elements without JS.
38
+
39
+ ```css
40
+ .trigger { anchor-name: --tooltip-anchor; }
41
+ .tooltip {
42
+ position: absolute;
43
+ position-anchor: --tooltip-anchor;
44
+ top: anchor(bottom);
45
+ left: anchor(center);
46
+ translate: -50% 0.5rem;
47
+ }
48
+ ```
49
+
50
+ ### @scope
51
+ Restrict styles to a DOM subtree with optional lower boundary.
52
+
53
+ ```css
54
+ @scope (.card) to (.card-content) {
55
+ h2 { font-size: 1.25rem; font-weight: 600; }
56
+ p { color: var(--muted); }
57
+ }
58
+ ```
59
+
60
+ ### @property (Typed Custom Properties)
61
+ Register custom properties with type, initial value, and inheritance. Enables animating custom properties.
62
+
63
+ ```css
64
+ @property --gradient-angle {
65
+ syntax: "<angle>";
66
+ initial-value: 0deg;
67
+ inherits: false;
68
+ }
69
+ .gradient-border {
70
+ --gradient-angle: 0deg;
71
+ border-image: conic-gradient(from var(--gradient-angle), #f06, #9f6, #06f) 1;
72
+ animation: spin 3s linear infinite;
73
+ }
74
+ @keyframes spin { to { --gradient-angle: 360deg; } }
75
+ ```
76
+
77
+ ### color-mix()
78
+ Blend colors in any color space at runtime.
79
+
80
+ ```css
81
+ .button {
82
+ --brand: oklch(0.65 0.25 260);
83
+ background: var(--brand);
84
+ &:hover { background: color-mix(in oklch, var(--brand) 85%, white); }
85
+ &:active { background: color-mix(in oklch, var(--brand) 80%, black); }
86
+ }
87
+ ```
88
+
89
+ ### Logical Properties
90
+ Write direction-agnostic layouts (LTR/RTL safe).
91
+
92
+ Key mappings: `margin-left` -> `margin-inline-start`, `padding-top` -> `padding-block-start`, `width` -> `inline-size`, `height` -> `block-size`.
93
+
94
+ ```css
95
+ .sidebar { margin-inline-end: 2rem; padding-block: 1rem; border-inline-start: 3px solid var(--accent); }
96
+ ```
97
+
98
+ ### Subgrid
99
+ Child grids align to parent grid tracks.
100
+
101
+ ```css
102
+ .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
103
+ .grid > .card {
104
+ display: grid;
105
+ grid-row: span 3;
106
+ grid-template-rows: subgrid;
107
+ }
108
+ ```
109
+
110
+ ### Popover API
111
+ Native popovers with light-dismiss, no JS required.
112
+
113
+ ```html
114
+ <button popovertarget="info">Info</button>
115
+ <div popover id="info">Content here. Click outside to dismiss.</div>
116
+ ```
117
+
118
+ ```css
119
+ [popover] {
120
+ &::backdrop { background: rgb(0 0 0 / 0.25); }
121
+ opacity: 0; transition: opacity 0.2s, display 0.2s allow-discrete;
122
+ &:popover-open { opacity: 1; }
123
+ }
124
+ ```
125
+
126
+ ---
127
+
128
+ ## 2. Core Web Vitals Optimization
129
+
130
+ **Thresholds:** LCP < 2.5s | CLS < 0.1 | INP < 200ms
131
+
132
+ ### LCP (Largest Contentful Paint)
133
+ - Preload hero images: `<link rel="preload" as="image" href="hero.webp" fetchpriority="high">`
134
+ - Use `fetchpriority="high"` on the LCP `<img>` element.
135
+ - Eliminate render-blocking CSS/JS; inline critical CSS.
136
+ - Use CDN, compress with Brotli.
137
+
138
+ ### CLS (Cumulative Layout Shift)
139
+ - Always set `width`/`height` or `aspect-ratio` on images and video.
140
+ - Reserve space for ads/embeds with `min-height`.
141
+ - Use `font-display: optional` (best CLS) or `swap` (best UX).
142
+ - Avoid inserting content above the fold after load.
143
+
144
+ ### INP (Interaction to Next Paint)
145
+ Replaced FID in March 2024. Measures all interactions across the page lifecycle.
146
+
147
+ ```js
148
+ button.addEventListener('click', () => {
149
+ button.classList.add('pressed'); // instant visual feedback
150
+ requestAnimationFrame(() => {
151
+ setTimeout(() => doHeavyWork(), 0); // yield to browser
152
+ });
153
+ });
154
+ ```
155
+
156
+ - Break long tasks with `scheduler.yield()` (or `setTimeout(0)` fallback).
157
+ - Use `content-visibility: auto` for off-screen DOM.
158
+ - Avoid layout thrashing: batch reads, then batch writes.
159
+
160
+ ---
161
+
162
+ ## 3. Image Optimization
163
+
164
+ | Format | Best For | vs JPEG |
165
+ |--------|----------|---------|
166
+ | **AVIF** | Photos, complex images | ~50% smaller |
167
+ | **WebP** | Photos, transparency | ~30% smaller |
168
+ | **SVG** | Icons, logos, illustrations | Infinitely scalable |
169
+ | **PNG** | Screenshots, pixel-precise | Lossless only |
170
+
171
+ ### Responsive Images Pattern
172
+
173
+ ```html
174
+ <picture>
175
+ <source srcset="hero.avif" type="image/avif">
176
+ <source srcset="hero.webp" type="image/webp">
177
+ <img src="hero.jpg"
178
+ srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
179
+ sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
180
+ alt="Hero" width="1200" height="675"
181
+ loading="lazy" decoding="async">
182
+ </picture>
183
+ ```
184
+
185
+ **Rules:** Never lazy-load above-the-fold images (hurts LCP). Use `fetchpriority="high"` on LCP image. Always include `width`/`height` for CLS prevention.
186
+
187
+ ### Blur-Up Placeholder
188
+
189
+ ```css
190
+ .img-placeholder {
191
+ background: url('data:image/webp;base64,...') center/cover;
192
+ aspect-ratio: 16/9;
193
+ }
194
+ .img-placeholder img {
195
+ opacity: 0; transition: opacity 0.3s;
196
+ &.loaded { opacity: 1; }
197
+ }
198
+ ```
199
+
200
+ ---
201
+
202
+ ## 4. Font Performance
203
+
204
+ ### Optimal Loading Strategy
205
+
206
+ ```html
207
+ <link rel="preload" href="/fonts/display.woff2" as="font" type="font/woff2" crossorigin>
208
+ ```
209
+
210
+ ```css
211
+ @font-face {
212
+ font-family: 'Display';
213
+ src: url('/fonts/display.woff2') format('woff2');
214
+ font-weight: 100 900;
215
+ font-display: swap;
216
+ unicode-range: U+0000-00FF;
217
+ }
218
+ ```
219
+
220
+ ### font-display Decision Guide
221
+ - **`swap`**: shows fallback immediately, swaps when loaded. Best for body text. Causes FOUT.
222
+ - **`optional`**: uses web font only if cached/instant. Best CLS score.
223
+ - **`fallback`**: 100ms blank, then fallback, short swap window. Good compromise.
224
+ - **`block`**: up to 3s invisible text (FOIT). Avoid for body text.
225
+
226
+ ### Variable Fonts
227
+ One file replaces multiple weight/style files. Use when you need 3+ weights. A single variable font (~90KB) replaces 6 static files (360KB+).
228
+
229
+ ### Subsetting
230
+ Strip unused glyphs with `pyftsubset` or `glyphhanger`. Can reduce 200KB+ files to 15-30KB.
231
+
232
+ ---
233
+
234
+ ## 5. Critical CSS & Resource Hints
235
+
236
+ ### Critical CSS Pattern
237
+
238
+ ```html
239
+ <head>
240
+ <style>/* inlined above-the-fold styles, ~14KB max */</style>
241
+ <link rel="preload" href="/styles.css" as="style" onload="this.rel='stylesheet'">
242
+ <noscript><link rel="stylesheet" href="/styles.css"></noscript>
243
+ </head>
244
+ ```
245
+
246
+ ### Resource Hints
247
+
248
+ ```html
249
+ <link rel="preconnect" href="https://fonts.googleapis.com">
250
+ <link rel="dns-prefetch" href="https://analytics.example.com">
251
+ <link rel="preload" href="/critical.woff2" as="font" crossorigin>
252
+ <link rel="prefetch" href="/next-page.js">
253
+ <link rel="modulepreload" href="/app.js">
254
+ ```
255
+
256
+ **Build tools:** Use `critical` (npm) or `critters` (webpack/vite plugin) to auto-extract above-fold CSS at build time.
257
+
258
+ ---
259
+
260
+ ## 6. Tailwind CSS v4
261
+
262
+ Released January 2025. Core rewritten in Rust (Oxide engine). Full builds 3.8x faster, incremental rebuilds up to 182x faster.
263
+
264
+ ### CSS-First Configuration
265
+
266
+ ```css
267
+ @import "tailwindcss";
268
+
269
+ @theme {
270
+ --color-brand: oklch(0.65 0.25 260);
271
+ --font-display: "Satoshi", sans-serif;
272
+ --breakpoint-3xl: 1920px;
273
+ --ease-fluid: cubic-bezier(0.3, 0, 0, 1);
274
+ }
275
+ ```
276
+
277
+ No `tailwind.config.js` needed. All customization lives in CSS via `@theme`.
278
+
279
+ ### Key Changes
280
+ - **Automatic content detection** -- scans files, respects `.gitignore`.
281
+ - **Built on `@layer`, `@property`, `color-mix()`**.
282
+ - **Container queries** built in: `@sm:`, `@md:` variants.
283
+ - **3D transforms**: `rotate-x-45 transform-3d perspective-distant`.
284
+ - **`@starting-style`** support for enter/exit transitions with `transition-discrete`.
285
+ - **`not-*` variant**: `not-hover:opacity-75`, `not-last:border-b`.
286
+
287
+ ---
288
+
289
+ ## 7. Advanced Animation APIs
290
+
291
+ ### View Transitions API
292
+
293
+ ```css
294
+ @view-transition { navigation: auto; }
295
+ .hero-image { view-transition-name: hero; }
296
+ ::view-transition-old(hero) { animation: fade-out 0.3s ease-out; }
297
+ ::view-transition-new(hero) { animation: fade-in 0.3s ease-in; }
298
+ ```
299
+
300
+ ```js
301
+ document.startViewTransition(() => updateDOM());
302
+ ```
303
+
304
+ ### Scroll-Driven Animations (No JS, Off Main Thread)
305
+
306
+ ```css
307
+ .progress-bar {
308
+ animation: grow-width linear;
309
+ animation-timeline: scroll();
310
+ }
311
+ @keyframes grow-width { from { width: 0; } to { width: 100%; } }
312
+
313
+ .reveal {
314
+ animation: fade-slide-up linear both;
315
+ animation-timeline: view();
316
+ animation-range: entry 0% entry 100%;
317
+ }
318
+ @keyframes fade-slide-up {
319
+ from { opacity: 0; translate: 0 2rem; }
320
+ to { opacity: 1; translate: 0; }
321
+ }
322
+ ```
323
+
324
+ ### Web Animations API (WAAPI)
325
+
326
+ ```js
327
+ element.animate(
328
+ [{ transform: 'translateY(0)', opacity: 1 },
329
+ { transform: 'translateY(-20px)', opacity: 0 }],
330
+ { duration: 300, easing: 'ease-out', fill: 'forwards' }
331
+ );
332
+ ```
333
+
334
+ ### GSAP ScrollTrigger
335
+
336
+ ```js
337
+ gsap.to('.hero-title', {
338
+ scrollTrigger: {
339
+ trigger: '.hero', start: 'top top', end: 'bottom top',
340
+ scrub: true, pin: true
341
+ },
342
+ y: -100, opacity: 0, scale: 0.9
343
+ });
344
+ ```
345
+
346
+ ---
347
+
348
+ ## Browser Support (Baseline 2025)
349
+
350
+ | Feature | Chrome | Firefox | Safari |
351
+ |---------|--------|---------|--------|
352
+ | CSS Nesting | 120+ | 117+ | 17.2+ |
353
+ | :has() | 105+ | 121+ | 15.4+ |
354
+ | @layer | 99+ | 97+ | 15.4+ |
355
+ | Subgrid | 117+ | 71+ | 16+ |
356
+ | Anchor Positioning | 125+ | Nightly | No |
357
+ | View Transitions (SPA) | 111+ | 144+ | 18+ |
358
+ | Scroll-driven Animations | 115+ | Nightly | No |
359
+ | Popover API | 114+ | 125+ | 17+ |
360
+ | @property | 85+ | 128+ | 15.4+ |
361
+ | color-mix() | 111+ | 113+ | 16.2+ |