@ericrisco/rsc 3.3.1 → 3.4.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 (54) hide show
  1. package/README.md +2 -2
  2. package/manifest.json +43 -22
  3. package/package.json +1 -1
  4. package/scripts/lib/default-skill-floor.js +5 -1
  5. package/scripts/lib/domains.js +2 -2
  6. package/scripts/lib/retired-skills.js +4 -0
  7. package/skills/design/SKILL.md +4 -3
  8. package/skills/design/evals/cases.yaml +2 -2
  9. package/skills/react/SKILL.md +2 -1
  10. package/skills/ux/SKILL.md +149 -0
  11. package/skills/ux/THIRD_PARTY.md +32 -0
  12. package/skills/ux/evals/cases.yaml +40 -0
  13. package/skills/ux/references/flows.md +124 -0
  14. package/skills/ux/upstream/UPSTREAM.json +59 -0
  15. package/skills/ux/upstream/ux-designer/GUIDE.md +180 -0
  16. package/skills/ux/upstream/ux-designer/LICENSE +21 -0
  17. package/skills/ux/upstream/ux-designer/references/01-core-principles.md +251 -0
  18. package/skills/ux/upstream/ux-designer/references/02-laws-of-ux.md +330 -0
  19. package/skills/ux/upstream/ux-designer/references/03-accessibility.md +411 -0
  20. package/skills/ux/upstream/ux-designer/references/04-visual-design.md +433 -0
  21. package/skills/ux/upstream/ux-designer/references/05-information-architecture.md +432 -0
  22. package/skills/ux/upstream/ux-designer/references/06-interaction-design.md +495 -0
  23. package/skills/ux/upstream/ux-designer/references/07-forms-and-inputs.md +491 -0
  24. package/skills/ux/upstream/ux-designer/references/08-mobile-ux.md +539 -0
  25. package/skills/ux/upstream/ux-designer/references/09-ux-writing.md +493 -0
  26. package/skills/ux/upstream/ux-designer/references/10-user-research.md +533 -0
  27. package/skills/ux/upstream/ux-designer/references/11-design-systems.md +618 -0
  28. package/skills/ux/upstream/ux-designer/references/12a-presence-awareness.md +395 -0
  29. package/skills/ux/upstream/ux-designer/references/12b-conflict-resolution-sync.md +420 -0
  30. package/skills/ux/upstream/ux-designer/references/13a-canvas-navigation.md +388 -0
  31. package/skills/ux/upstream/ux-designer/references/13b-canvas-objects-performance.md +559 -0
  32. package/skills/ux/upstream/ux-designer/references/14-ai-ux-patterns.md +511 -0
  33. package/skills/ux/upstream/ux-designer/references/15-ethical-design.md +419 -0
  34. package/skills/ux/upstream/ux-designer/references/16-onboarding.md +430 -0
  35. package/skills/ux/upstream/ux-designer/references/17-notifications.md +461 -0
  36. package/skills/ux/upstream/ux-designer/references/18-data-visualization.md +453 -0
  37. package/skills/ux/upstream/ux-designer/references/19-search-ux.md +479 -0
  38. package/skills/ux/upstream/ux-designer/references/20-emotional-design.md +382 -0
  39. package/skills/ux/upstream/ux-designer/references/21-data-tables.md +629 -0
  40. package/skills/ux/upstream/ux-designer/references/22-performance-ux.md +626 -0
  41. package/skills/ux/upstream/ux-designer/references/23-internationalization.md +347 -0
  42. package/skills/ux/upstream/ux-designer/references/24-voice-and-multimodal.md +308 -0
  43. package/skills/ux/upstream/ux-designer/references/25a-barcode-camera-scanning.md +342 -0
  44. package/skills/ux/upstream/ux-designer/references/25b-barcode-scanner-workflows.md +412 -0
  45. package/skills/ux/upstream/ux-designer/references/25c-barcode-display.md +277 -0
  46. package/skills/ux/upstream/ux-usability-foundations/GUIDE.md +285 -0
  47. package/skills/ux/upstream/ux-usability-foundations/LICENSE +21 -0
  48. package/skills/ux/upstream/ux-usability-foundations/references/anti-patterns.md +267 -0
  49. package/skills/ux/upstream/ux-usability-foundations/references/checklists.md +130 -0
  50. package/skills/ux/upstream/ux-usability-foundations/references/decision-prompts.md +340 -0
  51. package/skills/ux/upstream/ux-usability-foundations/references/principle-cards.md +449 -0
  52. package/targets/clone-bootstrap.mjs +1 -1
  53. package/skills/ui-engineering/SKILL.md +0 -113
  54. package/skills/ui-engineering/evals/cases.yaml +0 -38
@@ -0,0 +1,449 @@
1
+ # Principle Cards — UX Usability Foundations
2
+
3
+ ## Principle: Start with the user goal
4
+
5
+ Rule:
6
+ - Define the user’s goal, task, success condition, and risk before choosing layout, navigation, or controls.
7
+
8
+ Why it matters:
9
+ - Interfaces fail when they express implementation structure or stakeholder feature lists rather than the user’s outcome.
10
+
11
+ Use when:
12
+ - Creating or critiquing any flow, screen, form, or control set.
13
+
14
+ Do not use when:
15
+ - The user only asks for cosmetic styling and the task model is already fixed; still note usability risks.
16
+
17
+ Default recommendation:
18
+ - Optimize the most common successful task first.
19
+
20
+ Ask the user when:
21
+ - The primary task, audience, or consequence of failure is unclear.
22
+
23
+ Question prompt:
24
+ ```js
25
+ question({
26
+ question: "What is the primary task this interface must help users complete?",
27
+ recommended_default: "Optimize for the most common successful task first, then make secondary actions available but visually quieter.",
28
+ options: ["Complete one focused task", "Compare or monitor multiple items", "Explore choices", "Other / custom"]
29
+ })
30
+ ```
31
+
32
+ Agent behavior:
33
+ - Begin recommendations with the task and success condition. Remove or demote UI that does not support that task.
34
+
35
+ ## Principle: Remove question marks
36
+
37
+ Rule:
38
+ - Users should not have to wonder what the page is, where to begin, what is clickable, what words mean, or what happened.
39
+
40
+ Why it matters:
41
+ - Every unnecessary question adds cognitive load and reduces confidence.
42
+
43
+ Use when:
44
+ - Reviewing labels, controls, landing screens, dashboards, forms, navigation, and calls to action.
45
+
46
+ Do not use when:
47
+ - The interface is a game, puzzle, or deliberate learning environment where challenge is the point; even then controls should be understandable.
48
+
49
+ Default recommendation:
50
+ - Make important UI self-evident; make novel or complex UI self-explanatory.
51
+
52
+ Ask the user when:
53
+ - They request clever, branded, or intentionally mysterious wording.
54
+
55
+ Question prompt:
56
+ ```js
57
+ question({
58
+ question: "Should clarity or brand personality win if users may not understand the label immediately?",
59
+ recommended_default: "Use the clearest user-language label first and express brand personality in supporting copy or tone.",
60
+ options: ["Prioritize clarity", "Balance clarity and brand", "Use required brand/domain wording", "Other / custom"]
61
+ })
62
+ ```
63
+
64
+ Agent behavior:
65
+ - Replace vague labels, hidden controls, and ambiguous icons with visible, descriptive cues.
66
+
67
+ ## Principle: Signify every possible action
68
+
69
+ Rule:
70
+ - Controls must communicate what can be done and how to do it.
71
+
72
+ Why it matters:
73
+ - A possible action is useless if users cannot discover it.
74
+
75
+ Use when:
76
+ - Designing buttons, links, drawers, gestures, cards, menus, drag/drop, inputs, or custom components.
77
+
78
+ Do not use when:
79
+ - Hiding an action is a safety mechanism; even then authorized users need discoverable paths.
80
+
81
+ Default recommendation:
82
+ - Use standard labeled controls for important actions.
83
+
84
+ Ask the user when:
85
+ - Space or brand constraints push toward hidden or icon-only actions.
86
+
87
+ Question prompt:
88
+ ```js
89
+ question({
90
+ question: "Can this important action be shown with a visible label, or must it be hidden because of space or platform constraints?",
91
+ recommended_default: "Show a visible label for primary and consequential actions; hide only secondary or infrequent actions.",
92
+ options: ["Visible labeled control", "Icon with tooltip/accessible name", "Overflow/menu", "Other / custom"]
93
+ })
94
+ ```
95
+
96
+ Agent behavior:
97
+ - Identify all actions and ensure each has a visible cue, accessible name, and state.
98
+
99
+ ## Principle: Match mental models, not implementation models
100
+
101
+ Rule:
102
+ - Organize concepts, names, and flows around how users understand the work.
103
+
104
+ Why it matters:
105
+ - Users should not need to learn the database, architecture, file system, or org chart.
106
+
107
+ Use when:
108
+ - Designing navigation, settings, object models, tables, dashboards, admin interfaces, and enterprise workflows.
109
+
110
+ Do not use when:
111
+ - The users are technical operators whose task is to manipulate the implementation model itself.
112
+
113
+ Default recommendation:
114
+ - Use user-visible nouns and verbs; hide implementation artifacts unless meaningful to the task.
115
+
116
+ Ask the user when:
117
+ - The audience may be domain experts who expect specialized terms.
118
+
119
+ Question prompt:
120
+ ```js
121
+ question({
122
+ question: "Are the users domain experts who expect technical terms, or should the interface translate them into plain user language?",
123
+ recommended_default: "Use plain task language, with domain terms only where users already expect them.",
124
+ options: ["Plain language", "Domain-expert terminology", "Dual labels/help text", "Other / custom"]
125
+ })
126
+ ```
127
+
128
+ Agent behavior:
129
+ - Rename and regroup features around user intent. Flag implementation leakage.
130
+
131
+ ## Principle: Design for scanning and satisficing
132
+
133
+ Rule:
134
+ - Assume users scan for a plausible next step rather than reading everything and optimizing.
135
+
136
+ Why it matters:
137
+ - Important content must be findable at a glance, or users will choose the first plausible path.
138
+
139
+ Use when:
140
+ - Designing page structure, content hierarchy, tables, cards, menus, and help text.
141
+
142
+ Do not use when:
143
+ - The product is a long-form reading environment; still provide navigation and summaries.
144
+
145
+ Default recommendation:
146
+ - Use strong headings, meaningful grouping, visible primary actions, concise copy, and scannable lists.
147
+
148
+ Ask the user when:
149
+ - The screen must support dense monitoring or complex comparison.
150
+
151
+ Question prompt:
152
+ ```js
153
+ question({
154
+ question: "Does this screen need to support quick task completion or dense comparison/monitoring?",
155
+ recommended_default: "Optimize for quick scanning and one clear next action unless comparison density is essential.",
156
+ options: ["Quick task completion", "Dense comparison", "Real-time monitoring", "Other / custom"]
157
+ })
158
+ ```
159
+
160
+ Agent behavior:
161
+ - Reorder, group, and cut content so the likely next step appears quickly.
162
+
163
+ ## Principle: Prefer recognition over recall
164
+
165
+ Rule:
166
+ - Put needed context, choices, examples, and state in the interface instead of requiring memory.
167
+
168
+ Why it matters:
169
+ - Memory is fragile under distraction, stress, infrequent use, and complex tasks.
170
+
171
+ Use when:
172
+ - Designing settings, forms, commands, filters, multi-step flows, dashboards, and shortcuts.
173
+
174
+ Do not use when:
175
+ - Expert shortcuts are optional accelerators; still provide visible alternatives.
176
+
177
+ Default recommendation:
178
+ - Provide visible options and context first; add shortcuts as accelerators.
179
+
180
+ Ask the user when:
181
+ - The workflow is for trained experts and speed may justify denser memorized interaction.
182
+
183
+ Question prompt:
184
+ ```js
185
+ question({
186
+ question: "Are users expected to use this frequently enough to learn shortcuts, or must the interface stay discoverable each time?",
187
+ recommended_default: "Keep visible, recognizable paths and add shortcuts only as optional accelerators.",
188
+ options: ["Infrequent/discoverable", "Frequent intermediates", "Trained experts", "Other / custom"]
189
+ })
190
+ ```
191
+
192
+ Agent behavior:
193
+ - Surface recent choices, examples, labels, current filters, and object context.
194
+
195
+ ## Principle: Minimize unnecessary choices
196
+
197
+ Rule:
198
+ - Reduce the number and complexity of choices presented at one time.
199
+
200
+ Why it matters:
201
+ - More choices increase decision time, perceived effort, and error probability.
202
+
203
+ Use when:
204
+ - Designing menus, plans, settings, filters, onboarding, forms, and calls to action.
205
+
206
+ Do not use when:
207
+ - Users need broad comparison or expert control; still group and prioritize.
208
+
209
+ Default recommendation:
210
+ - Present common options first, group the rest, and hide rare advanced choices behind clear controls.
211
+
212
+ Ask the user when:
213
+ - Business requirements demand many visible options.
214
+
215
+ Question prompt:
216
+ ```js
217
+ question({
218
+ question: "Which choices are truly needed for the first decision, and which can be revealed after users choose a path?",
219
+ recommended_default: "Show the common first-step choices and progressively disclose advanced or rare options.",
220
+ options: ["Common choices only", "Grouped full list", "Search/filter first", "Other / custom"]
221
+ })
222
+ ```
223
+
224
+ Agent behavior:
225
+ - Consolidate options, add defaults, group by task, and remove redundant decisions.
226
+
227
+ ## Principle: Provide feedback that teaches system state
228
+
229
+ Rule:
230
+ - Every consequential action should produce timely, informative, proportionate feedback.
231
+
232
+ Why it matters:
233
+ - Without feedback, users retry, abandon, duplicate work, or lose trust.
234
+
235
+ Use when:
236
+ - Designing submits, saves, uploads, deletes, async tasks, sync, loading, filters, and state changes.
237
+
238
+ Do not use when:
239
+ - The action’s visible result is already immediate and obvious.
240
+
241
+ Default recommendation:
242
+ - Use inline status for local actions, progress for delays, persistent status for long-running tasks, and interruption only for blocking issues.
243
+
244
+ Ask the user when:
245
+ - The operation may take time, fail, or have delayed consequences.
246
+
247
+ Question prompt:
248
+ ```js
249
+ question({
250
+ question: "How long can this operation take, and what should users be able to do while it runs?",
251
+ recommended_default: "Show immediate receipt, progress for delays, and allow safe continuation when possible.",
252
+ options: ["Instant", "A few seconds", "Long-running/background", "Other / custom"]
253
+ })
254
+ ```
255
+
256
+ Agent behavior:
257
+ - Specify state transitions and feedback copy/placement.
258
+
259
+ ## Principle: Constrain before correcting
260
+
261
+ Rule:
262
+ - Prevent invalid or dangerous actions through constraints, defaults, input design, and sequencing before relying on error messages.
263
+
264
+ Why it matters:
265
+ - Prevention is faster and less stressful than recovery.
266
+
267
+ Use when:
268
+ - Designing forms, destructive actions, permissions, file uploads, scheduling, payments, medical/legal/financial data, and configuration.
269
+
270
+ Do not use when:
271
+ - Over-constraining blocks valid user intent; provide escape hatches where needed.
272
+
273
+ Default recommendation:
274
+ - Use safe defaults and clear constraints, with flexible input where possible.
275
+
276
+ Ask the user when:
277
+ - Constraints may block legitimate expert or edge-case behavior.
278
+
279
+ Question prompt:
280
+ ```js
281
+ question({
282
+ question: "Should this input be tightly constrained for safety, or flexible enough to handle edge cases?",
283
+ recommended_default: "Constrain dangerous or invalid actions, but keep ordinary input flexible and correctable.",
284
+ options: ["Tightly constrained", "Flexible with validation", "Expert override", "Other / custom"]
285
+ })
286
+ ```
287
+
288
+ Agent behavior:
289
+ - Add constraints, validation, previews, and disabled/hidden behavior with explanations.
290
+
291
+ ## Principle: Recover without blame
292
+
293
+ Rule:
294
+ - Error handling should guide recovery, preserve work, and avoid blaming the user.
295
+
296
+ Why it matters:
297
+ - Users blame themselves when interfaces fail. Good UI keeps them moving.
298
+
299
+ Use when:
300
+ - Writing validation, failure, offline, permission, destructive, and empty-state messages.
301
+
302
+ Do not use when:
303
+ - Security requires withholding details; still provide safe, non-blaming next steps.
304
+
305
+ Default recommendation:
306
+ - Explain the issue, show the affected item, preserve input, and provide a direct fix.
307
+
308
+ Ask the user when:
309
+ - Error details are sensitive, regulated, or security-relevant.
310
+
311
+ Question prompt:
312
+ ```js
313
+ question({
314
+ question: "Can the error message safely explain the exact problem, or must details be limited for security/compliance?",
315
+ recommended_default: "Give specific recovery guidance unless revealing details creates risk.",
316
+ options: ["Specific recovery guidance", "Limited details", "Contact/support handoff", "Other / custom"]
317
+ })
318
+ ```
319
+
320
+ Agent behavior:
321
+ - Rewrite errors as recovery instructions and specify where fixes happen.
322
+
323
+ ## Principle: Prefer undo over confirmation for reversible actions
324
+
325
+ Rule:
326
+ - If an action is reversible, let users do it and offer undo rather than interrupting with confirmation.
327
+
328
+ Why it matters:
329
+ - Repeated confirmations become noise and train users to click through.
330
+
331
+ Use when:
332
+ - Archiving, moving, hiding, dismissing, sorting, lightweight deletion, and changes that can be restored.
333
+
334
+ Do not use when:
335
+ - The action is irreversible, legally binding, costly, dangerous, or affects others irreversibly.
336
+
337
+ Default recommendation:
338
+ - Use undo for reversible actions and confirmation/review for irreversible or high-risk actions.
339
+
340
+ Ask the user when:
341
+ - Reversibility is unclear.
342
+
343
+ Question prompt:
344
+ ```js
345
+ question({
346
+ question: "Is this action fully reversible, and for how long?",
347
+ recommended_default: "Use undo for reversible actions; reserve confirmation for irreversible or high-risk actions.",
348
+ options: ["Fully reversible", "Reversible for limited time", "Not reversible", "Other / custom"]
349
+ })
350
+ ```
351
+
352
+ Agent behavior:
353
+ - Specify undo duration, placement, copy, and state restoration.
354
+
355
+ ## Principle: Keep users oriented
356
+
357
+ Rule:
358
+ - Users should know where they are, how they got there, where they can go, and what will happen next.
359
+
360
+ Why it matters:
361
+ - Disorientation causes backtracking, abandonment, and errors.
362
+
363
+ Use when:
364
+ - Designing navigation, breadcrumbs, app shells, multi-step flows, dashboards, and deep content.
365
+
366
+ Do not use when:
367
+ - A narrow wizard intentionally limits movement; still show progress and exit rules.
368
+
369
+ Default recommendation:
370
+ - Show current section, object, step, and major routes.
371
+
372
+ Ask the user when:
373
+ - Free navigation conflicts with completion requirements.
374
+
375
+ Question prompt:
376
+ ```js
377
+ question({
378
+ question: "Should users be able to move freely, or must this flow keep them in a guided sequence?",
379
+ recommended_default: "Allow free orientation and safe backtracking unless the task requires a controlled sequence.",
380
+ options: ["Free navigation", "Guided sequence", "Hybrid", "Other / custom"]
381
+ })
382
+ ```
383
+
384
+ Agent behavior:
385
+ - Add current states, progress indicators, breadcrumbs, back paths, and stable navigation.
386
+
387
+ ## Principle: Use conventions unless there is a task reason not to
388
+
389
+ Rule:
390
+ - Prefer familiar patterns when they support the task.
391
+
392
+ Why it matters:
393
+ - Familiar patterns let users transfer learning from other products.
394
+
395
+ Use when:
396
+ - Choosing navigation, dialogs, forms, menus, gestures, filtering, search, and selection patterns.
397
+
398
+ Do not use when:
399
+ - Existing conventions are harmful, inaccessible, or mismatched to the task.
400
+
401
+ Default recommendation:
402
+ - Use standard components and patterns; customize content and behavior where the task demands.
403
+
404
+ Ask the user when:
405
+ - A nonstandard interaction is requested.
406
+
407
+ Question prompt:
408
+ ```js
409
+ question({
410
+ question: "What user problem does the nonstandard pattern solve better than the familiar convention?",
411
+ recommended_default: "Use the familiar convention unless the alternative is measurably clearer or faster for this task.",
412
+ options: ["Use standard pattern", "Use nonstandard pattern with explanation", "Prototype/test both", "Other / custom"]
413
+ })
414
+ ```
415
+
416
+ Agent behavior:
417
+ - Challenge novelty that increases learning cost without task benefit.
418
+
419
+ ## Principle: Make accessibility structural
420
+
421
+ Rule:
422
+ - Accessibility is built through perceivable structure, operable controls, understandable language, forgiving flows, and robust implementation.
423
+
424
+ Why it matters:
425
+ - Accessibility failures are usability failures.
426
+
427
+ Use when:
428
+ - Designing or implementing any UI.
429
+
430
+ Do not use when:
431
+ - Never. Accessibility basics are non-optional.
432
+
433
+ Default recommendation:
434
+ - Use semantic controls and labels, keyboard support, focus visibility, non-color cues, and accessible feedback.
435
+
436
+ Ask the user when:
437
+ - Compliance level or procurement requirements are unknown in regulated/public products.
438
+
439
+ Question prompt:
440
+ ```js
441
+ question({
442
+ question: "Does this product have a required accessibility standard or procurement target?",
443
+ recommended_default: "Meet core WCAG-oriented basics by default; confirm stricter targets for regulated, public-sector, education, healthcare, or enterprise contexts.",
444
+ options: ["WCAG AA target", "Internal baseline only", "Regulated/procurement requirement", "Other / custom"]
445
+ })
446
+ ```
447
+
448
+ Agent behavior:
449
+ - Include accessibility behavior in the spec, not as an afterthought.
@@ -95,7 +95,7 @@ export function readManifest(root) {
95
95
  const ids = (v) => (Array.isArray(v) ? v.filter((x) => typeof x === 'string' && ID.test(x)) : []);
96
96
  // Retired skills read as their successors. Canonical map: scripts/lib/retired-skills.js — inlined
97
97
  // because this file cannot import anything, and tests/retired-skills.test.js holds the two equal.
98
- const RETIRED = { eli5: 'orient', 'show-me': 'orient', bro: 'unslop', 'design-loop': 'design', 'design-dna': 'design', 'motion-craft': 'design' };
98
+ const RETIRED = { eli5: 'orient', 'show-me': 'orient', bro: 'unslop', 'design-loop': 'design', 'design-dna': 'design', 'motion-craft': 'design', 'ui-engineering': 'ux' };
99
99
  const skills = [...new Set(ids(parsed.skills).map((id) => (Object.hasOwn(RETIRED, id) ? RETIRED[id] : id)))];
100
100
  const own = ids(parsed.ownSkills);
101
101
  // A manifest with nothing declared is not a clone waiting to be equipped; there is nothing to offer.
@@ -1,113 +0,0 @@
1
- ---
2
- name: ui-engineering
3
- description: "Use when the question is how interface should be BUILT — component boundaries, state that belongs in the URL vs the component, loading/empty/error states, forms, optimistic updates, build vs adopt. NOT the visual system (`design`), NOT framework mechanics (`react`/`nextjs`)."
4
- tags: [interface, frontend, architecture, components, state, craft]
5
- recommends: [design]
6
- profiles: [core, full]
7
- origin: risco
8
- ---
9
-
10
- # UI engineering — the decisions between the design and the framework
11
-
12
- There is a layer that neither the design skill nor the framework skill owns. The design says what
13
- the screen should be. The framework says how its API works. **In between sits every decision that
14
- makes an interface either durable or a maintenance tax** — and it is where most interface work
15
- actually goes wrong.
16
-
17
- Nothing here is framework-specific. These decisions are the same in React, Vue, Svelte, SwiftUI and
18
- plain HTML; only the syntax moves.
19
-
20
- ## The one rule
21
-
22
- **State goes to the outermost place that still needs it, and no further.** Almost every interface
23
- tangle is that rule broken in one of two directions: state hoarded in a component that others need,
24
- or state hoisted into a global store that only one component ever reads.
25
-
26
- | Where the state lives | When that is right |
27
- | --- | --- |
28
- | **The URL** | Anything a user would bookmark, share, or expect the back button to restore: filters, tabs, pagination, the open item |
29
- | **The server** | Anything that outlives the session or belongs to more than one user |
30
- | **A shared parent** | Two siblings genuinely need it, and it dies with the screen |
31
- | **The component** | Nobody else reads it: hover, focus, an open menu, an in-flight draft |
32
-
33
- The most common and most expensive mistake is the first row: state that belongs in the URL kept in a
34
- component. It looks fine until someone reloads, shares a link, or presses back — and then the
35
- interface silently loses what the user did.
36
-
37
- ## Every state, not just the happy one
38
-
39
- An interface is not finished when it renders data. It is finished when it renders **all five**:
40
-
41
- | State | The question it answers | The usual failure |
42
- | --- | --- | --- |
43
- | **Loading** | "Is it working?" | A spinner where the shape is already known — use the shape |
44
- | **Empty** | "Is it broken, or is there nothing?" | Blank. It must say which, and what to do next |
45
- | **Error** | "What now?" | A message with no action. Every denial carries its own way out |
46
- | **Partial** | "Some of it failed" | Ignored entirely; the screen shows a half-truth |
47
- | **Success** | "It worked" | Silence, so the user does it twice |
48
-
49
- The empty state is the one that gets skipped, and it is the first state a new user ever sees.
50
-
51
- ## Component boundaries
52
-
53
- A component earns its existence by **hiding a decision**, not by being reused. Splitting for reuse
54
- alone produces the worst interfaces: a wrapper around a wrapper, each passing props through, none
55
- owning anything.
56
-
57
- Draw the boundary where:
58
-
59
- - it owns a piece of state nothing outside needs;
60
- - it can be described in one sentence without "and";
61
- - swapping its internals changes nothing outside it.
62
-
63
- Do **not** draw a boundary because a file is long. Long is not a defect; a file that does two
64
- unrelated things is, and it is usually short.
65
-
66
- ## Forms
67
-
68
- Forms are where interfaces most often insult people, and the rules are unglamorous:
69
-
70
- - **Validate on blur, not on keystroke.** Telling someone their email is invalid while they are on
71
- the third character is scolding them for not having finished.
72
- - **Never clear what they typed.** Not on error, not on refresh, not on navigation. Their input is
73
- theirs.
74
- - **Disable the submit only while submitting**, never as a way of enforcing validity — a disabled
75
- button with no reason is a dead end.
76
- - **The error goes next to the field**, and says what to do, not what is wrong.
77
-
78
- ## Optimistic updates
79
-
80
- Show the result before the server confirms **only** when you can honestly undo it. That means: the
81
- operation is idempotent, the failure is rare, and reverting it is visible and comprehensible.
82
-
83
- Optimism on a destructive or an expensive action is a lie you will have to retract in front of the
84
- user. Deleting, paying, sending — those wait.
85
-
86
- ## Build or adopt
87
-
88
- Adopting a component costs bundle size, an API you did not design, and an upgrade you will owe
89
- later. Building costs the accessibility work you will get wrong.
90
-
91
- The split is not about difficulty, it is about **who is the authority on the behaviour**:
92
-
93
- - **Adopt** for behaviour with a specification you would otherwise be reimplementing badly: focus
94
- trapping, combobox semantics, date handling, virtualisation.
95
- - **Build** for anything that is your product's own logic wearing a UI, or where the library gives
96
- you 60% and you fight the remaining 40% forever.
97
-
98
- ## Anti-patterns → STOP
99
-
100
- | If you're about to… | Reality / Fix |
101
- | --- | --- |
102
- | Put a filter or tab selection in component state | It belongs in the URL. Reload, share and back are part of the interface. |
103
- | Add a global store because passing props feels tedious | Tedious is not broken. Global state that one component reads is a leak with ceremony. |
104
- | Ship a screen with only the loaded state | Loading, empty, error and partial are not extras. The empty one is what a new user sees first. |
105
- | Split a component because the file got long | Length is not the defect. Two unrelated responsibilities are, and they are usually short. |
106
- | Show a delete as done before the server confirms | Optimism on a destructive action is a lie you will retract in public. |
107
- | Reach here for how the framework's hooks work | That is `../react/SKILL.md` or `../nextjs/SKILL.md`. This skill decides what to build; those decide how to express it. |
108
-
109
- ## See Also
110
-
111
- - `../design/SKILL.md` — the visual system these decisions serve, its motion layer, and the
112
- browser-measured critique that judges the result.
113
- - `../accessibility/SKILL.md` — the ground under focus, semantics and forms.
@@ -1,38 +0,0 @@
1
- skill: ui-engineering
2
-
3
- should_trigger:
4
- - prompt: "Where should the filter state live — component, context or the URL?"
5
- why: "The canonical case: the one rule this skill exists to apply."
6
- - prompt: "How should I split these components? The file is getting big."
7
- why: "Component boundaries, and the file-length premise is one this skill corrects."
8
- - prompt: "We only render the loaded state. What else does this screen need?"
9
- why: "The five states are the checklist this skill owns."
10
- - prompt: "¿Valido el formulario mientras escribe o al salir del campo?"
11
- why: "Form behaviour, in Spanish; the trigger is the decision, not the language."
12
- - prompt: "Should I use a component library for the date picker or build it?"
13
- why: "Build vs adopt, decided by who owns the behaviour's specification."
14
- - prompt: "Can we show the delete as done immediately and roll back if it fails?"
15
- why: "Optimistic updates, and this is the case where the answer is no."
16
-
17
- should_not_trigger:
18
- - prompt: "Design the pricing page — layout, type scale, the colour system."
19
- route_to: "design"
20
- why: "The visual system is decided before this layer has anything to build."
21
- - prompt: "My useEffect runs twice in development and I don't understand why."
22
- route_to: "react"
23
- why: "Framework mechanics. This skill decides what to build, not how the framework behaves."
24
- - prompt: "The dropdown animation feels cheap, what duration should it use?"
25
- route_to: "design"
26
- why: "Once the component exists, how it moves is motion craft."
27
- - prompt: "Grade this dashboard and tell me if it is actually good."
28
- route_to: "design"
29
- why: "Judging a finished screen is the critique loop, not the build decisions."
30
- - prompt: "Set up the Next.js App Router with server actions for this project."
31
- route_to: "nextjs"
32
- why: "Stack setup is the stack skill's; this one is framework-agnostic by construction."
33
-
34
- capability:
35
- - prompt: "Our search page keeps its query and filters in component state. Users complain the back button loses everything. What is wrong and what is the fix?"
36
- why: "The single most expensive instance of the one rule, stated as a real symptom rather than as theory."
37
- - prompt: "This list screen shows a spinner, then rows. What states are we missing and why does each matter?"
38
- why: "Forces the five-state checklist, including the empty state that a new user sees first."