picasso-skill 1.0.0 → 1.2.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.
@@ -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
@@ -1,260 +0,0 @@
1
- # Motion and Animation Reference
2
-
3
- ## Table of Contents
4
- 1. Principles
5
- 2. Easing Functions
6
- 3. Duration Guidelines
7
- 4. Staggered Reveals
8
- 5. Scroll-Triggered Animation
9
- 6. Text Morphing
10
- 7. Micro-Interactions
11
- 8. Reduced Motion
12
- 9. Common Mistakes
13
-
14
- ---
15
-
16
- ## 1. Principles
17
-
18
- Motion serves three purposes: feedback (confirming an action), orientation (showing where something went), and delight (making the interface feel alive). If an animation does not serve one of these, remove it.
19
-
20
- ### Priority of Animation Investment
21
- 1. Page load choreography (highest impact, seen by everyone)
22
- 2. State transitions (tabs, modals, accordions)
23
- 3. Hover/focus states
24
- 4. Scroll-triggered reveals
25
- 5. Loading states and skeletons
26
- 6. Micro-interactions (button press effects, toggle animations)
27
-
28
- Invest time in this order. A well-choreographed page load does more than fifty micro-interactions.
29
-
30
- ---
31
-
32
- ## 2. Easing Functions
33
-
34
- ### Use These
35
- ```css
36
- /* Standard ease-out: elements arriving */
37
- --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
38
-
39
- /* Standard ease-in: elements departing */
40
- --ease-in: cubic-bezier(0.55, 0.085, 0.68, 0.53);
41
-
42
- /* Standard ease-in-out: elements transforming in place */
43
- --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
44
-
45
- /* Spring-like (subtle): natural deceleration */
46
- --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
47
- ```
48
-
49
- ### Never Use
50
- - `linear` for UI animations (looks mechanical)
51
- - `ease` (the CSS default is mediocre)
52
- - `bounce` / elastic easing (looks dated and gimmicky)
53
- - Spring animations with visible oscillation (too playful for most UIs)
54
-
55
- ---
56
-
57
- ## 3. Duration Guidelines
58
-
59
- | Type | Duration | Why |
60
- |---|---|---|
61
- | Hover state change | 100-150ms | Must feel instant |
62
- | Button press | 80-120ms | Tactile response |
63
- | Tooltip appear | 150-200ms | Quick but not jarring |
64
- | Fade in/out | 150-250ms | Smooth perception |
65
- | Slide/expand | 200-350ms | Visible movement |
66
- | Page transition | 300-500ms | Substantial change |
67
- | Complex choreography | 400-800ms total | Entrance sequence |
68
-
69
- Rule of thumb: if the user is waiting for it, it should be fast (under 200ms). If the user is watching it, it can be slower (200-500ms).
70
-
71
- ---
72
-
73
- ## 4. Staggered Reveals
74
-
75
- The most impactful animation pattern. Elements enter one after another with increasing delay.
76
-
77
- ### CSS-Only Pattern
78
- ```css
79
- .reveal-item {
80
- opacity: 0;
81
- transform: translateY(12px);
82
- animation: reveal 0.5s var(--ease-out) forwards;
83
- }
84
-
85
- @keyframes reveal {
86
- to {
87
- opacity: 1;
88
- transform: translateY(0);
89
- }
90
- }
91
-
92
- .reveal-item:nth-child(1) { animation-delay: 0ms; }
93
- .reveal-item:nth-child(2) { animation-delay: 60ms; }
94
- .reveal-item:nth-child(3) { animation-delay: 120ms; }
95
- .reveal-item:nth-child(4) { animation-delay: 180ms; }
96
- .reveal-item:nth-child(5) { animation-delay: 240ms; }
97
- ```
98
-
99
- ### Key Parameters
100
- - **Stagger interval**: 40-80ms between items (shorter for many items, longer for few)
101
- - **Translate distance**: 8-16px (subtle is better)
102
- - **Do not stagger more than 6-8 items**. After that, group them.
103
-
104
- ### React with Motion Library
105
- ```jsx
106
- import { motion } from "framer-motion";
107
-
108
- const container = {
109
- hidden: {},
110
- show: { transition: { staggerChildren: 0.06 } }
111
- };
112
-
113
- const item = {
114
- hidden: { opacity: 0, y: 12 },
115
- show: { opacity: 1, y: 0, transition: { duration: 0.5, ease: [0.16, 1, 0.3, 1] } }
116
- };
117
- ```
118
-
119
- ---
120
-
121
- ## 5. Scroll-Triggered Animation
122
-
123
- ### CSS-Only with Scroll-Driven Animations
124
- ```css
125
- @keyframes fade-in {
126
- from { opacity: 0; transform: translateY(20px); }
127
- to { opacity: 1; transform: translateY(0); }
128
- }
129
-
130
- .scroll-reveal {
131
- animation: fade-in linear both;
132
- animation-timeline: view();
133
- animation-range: entry 0% entry 30%;
134
- }
135
- ```
136
-
137
- ### Intersection Observer Pattern
138
- ```js
139
- const observer = new IntersectionObserver(
140
- (entries) => {
141
- entries.forEach(entry => {
142
- if (entry.isIntersecting) {
143
- entry.target.classList.add('visible');
144
- observer.unobserve(entry.target);
145
- }
146
- });
147
- },
148
- { threshold: 0.15, rootMargin: '0px 0px -50px 0px' }
149
- );
150
-
151
- document.querySelectorAll('.animate-on-scroll').forEach(el => observer.observe(el));
152
- ```
153
-
154
- ---
155
-
156
- ## 6. Text Morphing
157
-
158
- For animated text transitions (changing labels, counters, status updates), use **Torph** (dependency-free).
159
-
160
- ### Installation
161
- ```
162
- npm i torph
163
- ```
164
-
165
- ### Usage
166
- ```jsx
167
- import { TextMorph } from 'torph/react';
168
-
169
- // Automatically animates between text values
170
- <TextMorph>{status}</TextMorph>
171
-
172
- // Works with any dynamic text
173
- <button>
174
- <TextMorph>{isLoading ? "Processing..." : `Buy for $${price}`}</TextMorph>
175
- </button>
176
- ```
177
-
178
- Torph morphs individual characters with smooth enter/exit animations. It works with React, Vue, Svelte, and vanilla TypeScript.
179
-
180
- ### When to Use
181
- - Tab labels that change on selection
182
- - Button text that updates (Add to Cart -> Added!)
183
- - Counter values that increment
184
- - Status indicators that cycle through states
185
- - Any text that changes in response to user action
186
-
187
- ---
188
-
189
- ## 7. Micro-Interactions
190
-
191
- ### Button Press
192
- ```css
193
- button:active {
194
- transform: scale(0.97);
195
- transition: transform 80ms var(--ease-in);
196
- }
197
- ```
198
-
199
- ### Toggle Switch
200
- Animate the knob position and background color simultaneously. The knob should arrive slightly before the color finishes changing.
201
-
202
- ### Checkbox
203
- Scale the checkmark from 0 to 1 with a slight overshoot:
204
- ```css
205
- .checkbox-mark {
206
- transform: scale(0);
207
- transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
208
- }
209
- .checkbox:checked .checkbox-mark {
210
- transform: scale(1);
211
- }
212
- ```
213
-
214
- ### Skeleton Loading
215
- Shimmer from left to right using a gradient animation:
216
- ```css
217
- .skeleton {
218
- background: linear-gradient(90deg,
219
- var(--surface-2) 25%,
220
- var(--surface-3) 50%,
221
- var(--surface-2) 75%
222
- );
223
- background-size: 200% 100%;
224
- animation: shimmer 1.5s infinite;
225
- }
226
- @keyframes shimmer {
227
- 0% { background-position: 200% 0; }
228
- 100% { background-position: -200% 0; }
229
- }
230
- ```
231
-
232
- ---
233
-
234
- ## 8. Reduced Motion
235
-
236
- Always respect the user's motion preference:
237
- ```css
238
- @media (prefers-reduced-motion: reduce) {
239
- *, *::before, *::after {
240
- animation-duration: 0.01ms !important;
241
- animation-iteration-count: 1 !important;
242
- transition-duration: 0.01ms !important;
243
- scroll-behavior: auto !important;
244
- }
245
- }
246
- ```
247
-
248
- This does not mean removing all visual feedback. Opacity changes (fades) are still acceptable. Remove translation, scaling, and rotation animations.
249
-
250
- ---
251
-
252
- ## 9. Common Mistakes
253
-
254
- - Animating everything on the page (creates visual noise, reduces perceived performance)
255
- - Using `animation-duration: 0` for reduced motion (some browsers behave unexpectedly; use 0.01ms)
256
- - Bounce/elastic easing on UI elements (acceptable only in game-like or toy-like contexts)
257
- - Animating layout properties (width, height, top, left) instead of transforms (causes layout thrashing)
258
- - Forgetting `will-change` on frequently animated elements (or overusing it on everything)
259
- - Staggering 20+ items with visible delays (group them or animate the container)
260
- - Using `transition: all 0.3s` (animates properties you did not intend; be explicit about which properties to transition)
@@ -1,216 +0,0 @@
1
- # React Patterns Reference
2
-
3
- ## Table of Contents
4
- 1. Component Architecture
5
- 2. State Management
6
- 3. Performance
7
- 4. Composition Patterns
8
- 5. Data Fetching
9
- 6. Styling
10
- 7. Common Mistakes
11
-
12
- ---
13
-
14
- ## 1. Component Architecture
15
-
16
- ### Server vs. Client Components
17
- Default to Server Components. Add `'use client'` only when the component needs:
18
- - Event handlers (onClick, onChange, etc.)
19
- - useState, useEffect, useRef, or other hooks
20
- - Browser APIs (window, document, navigator)
21
- - Third-party libraries that use hooks or browser APIs
22
-
23
- ### File Organization
24
- Colocate related files. Keep components, styles, tests, and types in the same directory:
25
- ```
26
- components/
27
- user-card/
28
- user-card.tsx
29
- user-card.test.tsx
30
- user-card.module.css
31
- types.ts
32
- ```
33
-
34
- ### Naming
35
- - Components: PascalCase (`UserCard`, `DashboardHeader`)
36
- - Files: kebab-case (`user-card.tsx`, `dashboard-header.tsx`)
37
- - Hooks: camelCase with `use` prefix (`useAuth`, `useMediaQuery`)
38
- - Event handlers: `handle` + event (`handleClick`, `handleSubmit`)
39
- - Boolean props: `is`/`has`/`should` prefix (`isLoading`, `hasError`)
40
-
41
- ### Export Patterns
42
- - **Default export**: page/route components and layout components
43
- - **Named export**: everything else (utilities, hooks, shared components)
44
-
45
- ---
46
-
47
- ## 2. State Management
48
-
49
- ### Where State Lives
50
- 1. **URL state**: filters, pagination, search queries (use `searchParams`)
51
- 2. **Server state**: data from APIs (use React Query, SWR, or server components)
52
- 3. **Local state**: form inputs, UI toggles, hover/focus state (use `useState`)
53
- 4. **Shared local state**: state needed by siblings (lift to parent, or use context)
54
- 5. **Global state**: rarely needed (auth user, theme preference, feature flags)
55
-
56
- ### Rules
57
- - Do not store derived state. Compute it during render.
58
- - Do not sync state between sources. Pick one source of truth.
59
- - Prefer `useReducer` over `useState` when the next state depends on the previous state or when managing more than 3 related state variables.
60
-
61
- ```tsx
62
- // Bad: storing derived state
63
- const [items, setItems] = useState(data);
64
- const [filteredItems, setFilteredItems] = useState([]);
65
- useEffect(() => {
66
- setFilteredItems(items.filter(i => i.active));
67
- }, [items]);
68
-
69
- // Good: compute during render
70
- const [items, setItems] = useState(data);
71
- const filteredItems = items.filter(i => i.active);
72
- ```
73
-
74
- ---
75
-
76
- ## 3. Performance
77
-
78
- ### Rendering
79
- - Use `React.memo` only for components that re-render often with the same props
80
- - Use `useMemo` for expensive computations, not for every variable
81
- - Use `useCallback` for callbacks passed to memoized children
82
- - Use `key` props correctly (stable, unique identifiers, never array indices for reorderable lists)
83
-
84
- ### Code Splitting
85
- ```tsx
86
- import dynamic from 'next/dynamic';
87
-
88
- const Chart = dynamic(() => import('./chart'), {
89
- loading: () => <ChartSkeleton />,
90
- ssr: false,
91
- });
92
- ```
93
-
94
- ### Virtualization
95
- For lists with 100+ items, use `react-window` or `@tanstack/virtual`:
96
- ```tsx
97
- import { FixedSizeList } from 'react-window';
98
-
99
- <FixedSizeList height={600} itemCount={items.length} itemSize={48} width="100%">
100
- {({ index, style }) => <Row style={style} item={items[index]} />}
101
- </FixedSizeList>
102
- ```
103
-
104
- ### Image Optimization
105
- Use `next/image` in Next.js or `loading="lazy"` with explicit `width`/`height` attributes. Always set `aspect-ratio` to prevent layout shift.
106
-
107
- ---
108
-
109
- ## 4. Composition Patterns
110
-
111
- ### Compound Components
112
- Components that share implicit state through context:
113
- ```tsx
114
- <Select value={value} onChange={setValue}>
115
- <Select.Trigger>Choose a fruit</Select.Trigger>
116
- <Select.Content>
117
- <Select.Item value="apple">Apple</Select.Item>
118
- <Select.Item value="banana">Banana</Select.Item>
119
- </Select.Content>
120
- </Select>
121
- ```
122
-
123
- ### Slot Pattern
124
- Flexible component composition through named children:
125
- ```tsx
126
- function Card({ header, children, footer }) {
127
- return (
128
- <div className="card">
129
- {header && <div className="card-header">{header}</div>}
130
- <div className="card-body">{children}</div>
131
- {footer && <div className="card-footer">{footer}</div>}
132
- </div>
133
- );
134
- }
135
- ```
136
-
137
- ### Render Props (when needed)
138
- For components that need to share behavior, not UI:
139
- ```tsx
140
- <DataFetcher url="/api/users">
141
- {({ data, isLoading }) => isLoading ? <Skeleton /> : <UserList users={data} />}
142
- </DataFetcher>
143
- ```
144
-
145
- ---
146
-
147
- ## 5. Data Fetching
148
-
149
- ### Server Components (preferred)
150
- ```tsx
151
- async function UserList() {
152
- const users = await fetch('/api/users').then(r => r.json());
153
- return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
154
- }
155
- ```
156
-
157
- ### Client-Side with Suspense
158
- ```tsx
159
- function Dashboard() {
160
- return (
161
- <Suspense fallback={<DashboardSkeleton />}>
162
- <DashboardContent />
163
- </Suspense>
164
- );
165
- }
166
- ```
167
-
168
- ### Error Boundaries
169
- Wrap data-fetching components in error boundaries:
170
- ```tsx
171
- <ErrorBoundary fallback={<ErrorMessage />}>
172
- <Suspense fallback={<Skeleton />}>
173
- <DataComponent />
174
- </Suspense>
175
- </ErrorBoundary>
176
- ```
177
-
178
- ---
179
-
180
- ## 6. Styling
181
-
182
- ### Tailwind Best Practices
183
- - Use Tailwind's core utility classes (pre-defined classes only in Claude artifacts)
184
- - Extract repeated patterns into component variants, not `@apply` rules
185
- - Use CSS variables for theme values, Tailwind utilities for everything else
186
- - Never use more than ~10 utility classes on a single element; extract a component instead
187
-
188
- ### CSS Modules
189
- For non-Tailwind projects:
190
- ```tsx
191
- import styles from './button.module.css';
192
- <button className={styles.primary}>Click</button>
193
- ```
194
-
195
- ### Semantic HTML
196
- Use the right element, not just `div` with classes:
197
- - `<nav>` for navigation
198
- - `<main>` for primary content
199
- - `<section>` for thematic grouping
200
- - `<article>` for self-contained content
201
- - `<aside>` for tangentially related content
202
- - `<header>` and `<footer>` for their semantic purpose
203
- - `<button>` for clickable actions, `<a>` for navigation
204
-
205
- ---
206
-
207
- ## 7. Common Mistakes
208
-
209
- - Using `useEffect` for derived state (compute during render instead)
210
- - Putting everything in global state (most state should be local or server-derived)
211
- - Using `index` as `key` for dynamic lists
212
- - Wrapping every component in `React.memo`
213
- - Using `any` in TypeScript (defeats the purpose of type safety)
214
- - Fetching data in `useEffect` when a server component would suffice
215
- - Not using Suspense boundaries (the whole page flashes instead of parts loading independently)
216
- - Prop drilling through 5+ levels (use composition or context)