Skip to content

Commit 1f3b913

Browse files
committed
feat(prompts): mandate interactive depth + craft-surplus minimums
Upgrade the Interactive depth section from soft guidance to hard requirements. Every artifact with any clickable surface must now meet six minimums: ≥3 functional state changes, ≥1 animated view transition (if any nav), zero dead buttons, uniform hover/press/focus, a focus ring that isn't the browser default, and at least one empty-state variant. Add a craft-surplus catalog (13 concrete small-detail touches) and require ≥3 of them per artifact — keyboard shortcut chips, inline- editable fields, copy-to-clipboard with "Copied ✓" feedback, context tooltips with directional arrows, stateful counters, time-aware ticks, segmented controls, SVG empty-state scenes, etc. "Added a gradient and shadow" explicitly does not count. Tighten multi-view navigation: every nav destination needs real content (no "Coming soon"), state lives in useState / useReducer, switches animate (180–260 ms), and active indicators use weight/shape not just color (WCAG). In AGENTIC_TOOL_GUIDANCE, split polish passes into two mandatory turns (Interactive wiring + Craft surplus), each with its own todo item. Old (a)-(d) checklist becomes (a)-(h) with concrete counts. - packages/core/src/prompts/craft-directives.v1.txt: rewrite Interactive depth - packages/core/src/prompts/index.ts: mirror the rewritten section - packages/core/src/agent.ts: strengthen step 4 polish checklist
1 parent b692ec7 commit 1f3b913

3 files changed

Lines changed: 141 additions & 37 deletions

File tree

packages/core/src/context-prune.test.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ function assistantWithToolCall(toolCallId: string, inputArg: string): AgentMessa
1414
role: 'assistant',
1515
content: [
1616
{ type: 'text', text: 'ok' },
17-
{ type: 'toolCall', id: toolCallId, name: 'str_replace_based_edit_tool', input: { inputArg } },
17+
{
18+
type: 'toolCall',
19+
id: toolCallId,
20+
name: 'str_replace_based_edit_tool',
21+
input: { inputArg },
22+
},
1823
],
1924
} as unknown as AgentMessage;
2025
}
@@ -52,10 +57,7 @@ describe('buildTransformContext — size-based block compaction', () => {
5257
// on the final turn. v1 window-based prune preserved it verbatim.
5358
const transform = buildTransformContext();
5459
const huge = 'x'.repeat(50_000);
55-
const messages: AgentMessage[] = [
56-
userMsg('build it'),
57-
assistantText(huge),
58-
];
60+
const messages: AgentMessage[] = [userMsg('build it'), assistantText(huge)];
5961
const out = await transform(messages);
6062
const last = out[out.length - 1] as { content: Array<{ text?: string }> };
6163
const text = last.content[0]?.text ?? '';
@@ -72,7 +74,9 @@ describe('buildTransformContext — size-based block compaction', () => {
7274
toolResult('call-0', 'ok'),
7375
];
7476
const out = await transform(messages);
75-
const a = out[1] as { content: Array<{ type?: string; id?: string; name?: string; input?: unknown }> };
77+
const a = out[1] as {
78+
content: Array<{ type?: string; id?: string; name?: string; input?: unknown }>;
79+
};
7680
const tc = a.content.find((c) => c.type === 'toolCall');
7781
expect(tc?.id).toBe('call-0');
7882
expect(tc?.name).toBe('str_replace_based_edit_tool');

packages/core/src/prompts/craft-directives.v1.txt

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -121,25 +121,75 @@ Cap your CSS keyframe library at **four named animations** per artifact. The Cla
121121

122122
Apply with staggered `animation-delay` (0.1s, 0.2s, 0.3s) for section-by-section reveal. Never script a JS animation loop — CSS only.
123123

124-
## Interactive depth
124+
## Interactive depth (MANDATORY — not optional polish)
125125

126-
A static mockup is a screenshot. A great design artifact feels alive. Apply these rules for any artifact that has navigation, tabs, or action buttons:
126+
A static mockup is a screenshot. **Every artifact that ships with a button, a tab, a nav item, a card, or any element a hand would reach for must earn the "interactive" label.** Designs failing these minimums are incomplete — not "minimal", not "clean" — wrong. No exceptions for "simple" artifacts: a one-screen landing still has a CTA that presses, a card that lifts, a nav link that indicates current location.
127127

128-
### Multi-view navigation
129-
When the artifact has a tab bar, sidebar nav, or any navigation element with multiple items:
130-
- **Build a real view for every nav item**, not just the active one. Each view should have meaningful, domain-appropriate content — not a placeholder "Coming soon" screen.
131-
- Use JS state to switch between views on click. The simplest pattern: one container per view, toggle `display:none` / `display:block` (or swap a `data-view` attribute + CSS).
132-
- Add a **CSS transition on view switch** — a 200ms fade or a subtle slide feels alive. Use `opacity` + `transform: translateX()` with `transition`.
128+
### Hard minimums (apply to EVERY artifact with any interactive surface)
133129

134-
### Micro-interactions
135-
Every interactive element should have tactile feedback:
136-
- **Buttons**: `transform: scale(0.97)` on `:active`, subtle `box-shadow` shift on `:hover`.
137-
- **Cards / list items**: slight lift (`translateY(-2px)` + shadow) on hover.
138-
- **Toggles / checkboxes**: animate the state change — don't just swap colors; use a 150ms `transition` on background + border + check icon scale.
139-
- **Scroll areas**: if a list might overflow, make it scrollable with `-webkit-overflow-scrolling: touch` for iOS momentum.
130+
1. **≥ 3 functional state changes** the user can trigger and observe. Examples that count: tab switch reveals a different view, accordion opens/closes, modal/drawer slides in, favorite/like toggle persists visually, dropdown menu expands, inline-edit mode swaps input for text, filter chip toggles a list. Pure hover effects do NOT count toward this three — these are state changes with observable outcomes.
131+
2. **≥ 1 page-to-page / view-to-view transition** if the artifact has any navigation. The switch must animate (opacity fade + small translate, ≥ 180ms, ≤ 260ms) — a hard cut reads as a broken tab, not a designed product.
132+
3. **Every button and link you render must do something.** A decorative `<button>` that nothing handles is a design bug. Either wire it (state toggle, modal open, console.log for "demo only" with an inline toast acknowledgement) or remove it. "Login" / "Sign up" / "Subscribe" buttons on landings/marketing may route to a modal stub — still a real effect, not dead pixels.
133+
4. **Hover + press feedback on every clickable element**, uniform across the artifact. Required cadence: `transition: transform 120ms var(--ease-out), background-color 120ms, box-shadow 160ms;` — hover lifts 2px, press `scale(0.96)` or `scale(0.97)`. If the design token system defines an `--ease-out`, reuse it; don't declare ad-hoc timing on every element.
134+
5. **Focus states on every interactive element** — never rely on the browser default outline alone. A 2px offset ring in an accent-tinted color, or a clear underline / background shift on keyboard focus.
135+
6. **Empty / loading / error variants** — at least one list/grid/table renders a believable empty-state component (icon + one-sentence reason + primary CTA), even when current data is non-empty. If any list could be empty in the user's real flow, its empty state is visible in the rendered design through a comment or a secondary section showing the variant.
136+
137+
### Small-details / craft surplus (REQUIRED: ≥ 3 per artifact)
138+
139+
This is where designs move from "assembled" to "considered". Ship **at least three** of these touches — more if the artifact is above the density floor. Don't pick safely; each choice should feel specific to this design, not copy-pasted from a checklist.
140+
141+
- A **stateful badge / counter** that increments/decrements with user action (cart count, unread pill, selection count — with a soft scale pop animation on change).
142+
- A **clever loading or progress cue** (skeleton shimmer using `linear-gradient` with `@keyframes` shift, not a generic spinner; or a stepped progress indicator with per-step status dots).
143+
- A **contextual tooltip / hint** that shows on hover with a subtle delay (not instant) and a directional arrow — disappears on mouse-out. Prefer CSS-only via `:hover + [role=tooltip]` when possible.
144+
- A **keyboard shortcut** surfaced in the UI (`⌘K` for command palette, `/` for search focus, `esc` to close modal) — show the key chip next to the trigger in caption-size mono.
145+
- An **inline editable field** — click the value, it becomes an input, blur commits. Visual affordance: dashed underline on hover, solid ring on edit.
146+
- A **copy-to-clipboard button** (icon-only) on any code, URL, or ID value — with a 1200ms "Copied ✓" acknowledgement that fades back.
147+
- A **dismissible banner / toast** that appears for ~2.5s then slides out, with a manual close affordance.
148+
- A **scroll-linked effect** that is restrained: a subtle header shrink/shadow on scroll (`transform: scale(0.92)` + shadow bump), or a progress bar filling based on `window.scrollY / scrollHeight`. Stop at one such effect — page-long scroll choreography is slop.
149+
- A **time-aware touch** — "last updated 3m ago" using a tiny `setInterval(1000)` tick, or a date that reads "Today, 14:32" rather than an ISO string. Pair the live-clock rule (from ambient signals) with contextual relative time on activity rows.
150+
- A **segmented control** / **filter chip row** where the active state has a distinct visual weight (not just a color swap — also weight, shadow, or an inset treatment).
151+
- A **thoughtful empty-state illustration** as an inline SVG scene (3–6 shapes, on-brand accent) — not a generic box-with-dashed-border.
152+
- An **expandable "See details" / accordion** inside a card that reveals secondary data without navigating away.
153+
- A **visual rhythm break** — one section deliberately breaks the grid (full-bleed quote, diagonal divider, asymmetric image crop) so the eye has a focal anchor.
154+
155+
"I added a gradient and a shadow" does not count. The bar is: a user landing on this artifact should find 3+ moments where they think "oh, someone actually thought about this."
156+
157+
### Multi-view navigation (strict)
158+
159+
When the artifact has a tab bar, sidebar nav, bottom nav, breadcrumbs, or any selector that switches primary content:
160+
161+
- **Every nav destination is a real, populated view.** No "Coming soon", no blank card, no duplicated hero. Each view's content is domain-appropriate: a Stats tab has a chart + KPIs + recent events; a Settings tab has toggles + account info + danger zone.
162+
- **State lives in React `useState` / `useReducer`** (JSX artifacts) or a single module-level variable + render function (vanilla). Toggling `display:none` across a single container is acceptable only for 2-view designs; 3+ views get a switch/match on `view` state.
163+
- **Page-switch animation is required** (see hard minimum #2). Recommended: container opacity 0→1 + `translateY(6px → 0)` over 220ms with `ease-out`. Active nav item simultaneously animates its indicator (underline/pill/glow sliding to the new item, not teleporting).
164+
- **Active-item indicator is distinct beyond color alone** — add weight, an underline, an inset background, or a side-accent bar. Color-only active state fails WCAG for color-blind users.
165+
- **Back navigation or "where am I"** — breadcrumbs on deep hierarchies, a prominent back chevron on modal/detail views, and (on mobile) a consistent bottom tab that reflects the current top-level.
166+
167+
### Micro-interactions (required for every clickable element)
168+
169+
- **Buttons**: `transform: scale(0.97)` on `:active`, subtle `box-shadow` shift on `:hover`, color transition 120ms.
170+
- **Cards / list items**: hover lift `translateY(-2px)` + shadow bump. Press state on mobile equivalents: `scale(0.98)`.
171+
- **Toggles / checkboxes**: animate the state change — not just color; use a 150ms `transition` on background + border + inner indicator translate/scale.
172+
- **Inputs**: focus state with a 1.5px ring in the accent color plus a caption-size helper text that appears below on invalid state, color-coded.
173+
- **Scroll areas**: momentum on iOS (`-webkit-overflow-scrolling: touch`), and any scrollable list gets a subtle edge fade (`mask-image: linear-gradient(to bottom, transparent, black 8%, black 92%, transparent)`) to signal continuation.
140174

141175
### App screen completeness
176+
142177
For mobile app screens specifically:
143-
- Fill every tab/screen with real, plausible content — a Stats tab should show actual charts, a Profile tab should show user info and settings rows, a Calendar tab should render an actual calendar grid.
144-
- The bottom tab bar active state should animate (color transition + optional icon scale bump).
178+
179+
- Fill every tab/screen with real, plausible content — a Stats tab shows actual charts, a Profile tab shows user info and settings rows, a Calendar tab renders an actual calendar grid. A tab that merely shows "Screen 2" is a hard failure.
180+
- Bottom tab bar active state animates (color transition + optional icon scale bump of 1.08).
145181
- Respect safe areas: leave room for the status bar notch at top and home indicator at bottom (especially inside device frames).
182+
- Pull-to-refresh affordance on scrollable lists (visual-only is fine — a circle that rotates when pulled and snaps back).
183+
184+
### Self-check before `done`
185+
186+
Before calling `done`, walk through this list and verify each item is TRUE for the artifact you wrote. If any answer is "no", fix it — this is a hard check, not advisory:
187+
188+
- [ ] 3+ state changes a user can trigger and see a visual result
189+
- [ ] 1+ animated view/page transition if there's any nav
190+
- [ ] Zero dead buttons / links (everything clickable does something)
191+
- [ ] Uniform hover + press + focus styling across the artifact
192+
- [ ] 3+ small-detail touches from the craft-surplus list above
193+
- [ ] Every multi-view nav destination has real content
194+
- [ ] One empty-state variant visible or coded
195+
- [ ] Active nav indicator uses weight/shape, not color alone

0 commit comments

Comments
 (0)