Skip to content

Commit 8cfe2ab

Browse files
Update patterns and components for enhanced agent interaction features
- Added new interaction patterns: Intent Preview, Clarifying Questions, Autonomy Dial, and Escalation Pathway. - Updated existing patterns to include replay functionality. - Refined text and links in the Hero and Footer components for clarity. - Removed unused code and improved styling in various components. - Updated .gitignore to include design documentation.
1 parent a0df976 commit 8cfe2ab

18 files changed

Lines changed: 595 additions & 129 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,6 @@ Thumbs.db
4444
.cursor/*
4545
!.cursor/rules/
4646
.impeccable/
47+
design.md
48+
49+

src/components/Footer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function Footer() {
1616
<p className="font-mono text-xs tracking-[0.08em] text-body-mid">
1717
MIT licensed ·{' '}
1818
<a
19-
href="https://github.com"
19+
href="https://github.com/danielalbinsson/agentic-kit"
2020
target="_blank"
2121
rel="noreferrer"
2222
className="text-body hover:text-ink transition-colors"

src/components/Hero.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ export function Hero() {
99
The interface patterns that make agents feel trustworthy.
1010
</h1>
1111
<p className="mt-6 max-w-2xl text-lg leading-7 text-body">
12-
A playground of copy-paste React components for the moments unique to
13-
agent experiences — streaming, reasoning, confirming, and reporting
12+
Copy-paste React components for the interaction patterns unique to
13+
agent experiences — streaming, reasoning, confirming, reporting
1414
progress. Play with each one, then take the code.
1515
</p>
1616
<div className="mt-8 flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center">

src/components/Nav.tsx

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,3 @@
1-
import { patterns } from '../lib/patterns'
2-
3-
function PatternLink({ title, id }: { title: string; id: string }) {
4-
return (
5-
<a
6-
href={`#${id}`}
7-
className="nav-chip shrink-0 snap-start rounded-pill px-3 py-2 text-sm text-body transition-colors hover:bg-canvas-soft hover:text-ink"
8-
>
9-
{title}
10-
</a>
11-
)
12-
}
13-
141
export function Nav() {
152
return (
163
<nav
@@ -25,35 +12,15 @@ export function Nav() {
2512
agentic-kit.dev
2613
</a>
2714

28-
<div
29-
className="hidden min-w-0 flex-1 gap-1 overflow-x-auto md:flex"
30-
aria-label="Patterns"
31-
>
32-
{patterns.map((p) => (
33-
<PatternLink key={p.id} id={p.id} title={p.title} />
34-
))}
35-
</div>
36-
3715
<a
38-
href="https://github.com"
16+
href="https://github.com/danielalbinsson/agentic-kit"
3917
target="_blank"
4018
rel="noreferrer"
41-
className="btn-outline ml-auto shrink-0 text-sm md:ml-0"
19+
className="btn-outline ml-auto shrink-0 text-sm"
4220
>
4321
GitHub ↗
4422
</a>
4523
</div>
46-
47-
<div
48-
className="border-t border-hairline md:hidden"
49-
aria-label="Jump to pattern"
50-
>
51-
<div className="mx-auto flex max-w-[75rem] gap-2 overflow-x-auto px-6 py-2 scrollbar-none snap-x snap-mandatory">
52-
{patterns.map((p) => (
53-
<PatternLink key={p.id} id={p.id} title={p.title} />
54-
))}
55-
</div>
56-
</div>
5724
</nav>
5825
)
5926
}

src/components/PatternCard.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useState } from 'react'
12
import type { Pattern } from '../lib/types'
23
import { CodeBlock } from './CodeBlock'
34

@@ -12,6 +13,7 @@ const ICON_PATTERNS = new Set([
1213
export function PatternCard({ pattern }: { pattern: Pattern }) {
1314
const { id, title, tagline, description, Demo, code, specName, specUrl } =
1415
pattern
16+
const [runKey, setRunKey] = useState(0)
1517

1618
return (
1719
<section
@@ -24,10 +26,24 @@ export function PatternCard({ pattern }: { pattern: Pattern }) {
2426
<p className="mt-3 text-sm leading-5 text-body">{description}</p>
2527
</header>
2628

27-
<div className="mb-5 flex-1 rounded-sm border border-hairline bg-canvas-mid p-4 sm:p-5">
28-
<Demo />
29+
<div className="flex-1 rounded-sm border border-hairline bg-canvas-mid p-4 sm:p-5">
30+
<Demo key={runKey} />
2931
</div>
3032

33+
{pattern.replayable ? (
34+
<div className="mt-3 mb-5">
35+
<button
36+
type="button"
37+
onClick={() => setRunKey((k) => k + 1)}
38+
className="btn-outline"
39+
>
40+
replay
41+
</button>
42+
</div>
43+
) : (
44+
<div className="mb-5" />
45+
)}
46+
3147
<CodeBlock code={code} />
3248

3349
{ICON_PATTERNS.has(id) && (

src/index.css

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -771,8 +771,6 @@ body {
771771

772772
.demo-ledger-label[data-complete='true'] {
773773
color: var(--color-body-mid);
774-
text-decoration: line-through;
775-
opacity: 0.7;
776774
}
777775

778776
@media (prefers-reduced-motion: reduce) {

src/lib/patterns.ts

Lines changed: 104 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,62 @@
11
import type { Pattern } from './types'
2-
import { StreamingTextDemo, streamingTextCode } from '../patterns/StreamingText'
2+
import { IntentPreviewDemo, intentPreviewCode } from '../patterns/IntentPreview'
3+
import {
4+
ClarifyingQuestionsDemo,
5+
clarifyingQuestionsCode,
6+
} from '../patterns/ClarifyingQuestions'
7+
import { AutonomyDialDemo, autonomyDialCode } from '../patterns/AutonomyDial'
38
import { ThinkingStateDemo, thinkingStateCode } from '../patterns/ThinkingState'
4-
import { ActionConfirmDemo, actionConfirmCode } from '../patterns/ActionConfirm'
5-
import { ContextPanelDemo, contextPanelCode } from '../patterns/ContextPanel'
69
import { ToolCallDemo, toolCallCode } from '../patterns/ToolCall'
710
import { ProgressLedgerDemo, progressLedgerCode } from '../patterns/ProgressLedger'
11+
import { ContextPanelDemo, contextPanelCode } from '../patterns/ContextPanel'
12+
import { ActionConfirmDemo, actionConfirmCode } from '../patterns/ActionConfirm'
13+
import {
14+
EscalationPathwayDemo,
15+
escalationPathwayCode,
16+
} from '../patterns/EscalationPathway'
17+
import { StreamingTextDemo, streamingTextCode } from '../patterns/StreamingText'
18+
19+
const SPEC = 'https://www.agentic-ux.com/patterns'
820

921
export const patterns: Pattern[] = [
22+
// ── Before the agent acts ────────────────────────────────
1023
{
11-
id: 'streaming-text',
12-
title: 'Streaming text reveal',
13-
tagline: 'text appears as it thinks',
24+
id: 'intent-preview',
25+
title: 'Intent preview',
26+
tagline: 'show the plan first',
1427
description:
15-
'Render the response token by token with a blinking caret so the interface feels alive while the model is still generating.',
16-
Demo: StreamingTextDemo,
17-
code: streamingTextCode,
18-
specName: 'Return Moment',
19-
specUrl: 'https://agentic-ux.com',
28+
'Before doing anything, the agent restates the goal and lays out the plan it intends to follow — so the user can approve or adjust before work begins.',
29+
Demo: IntentPreviewDemo,
30+
code: intentPreviewCode,
31+
specName: 'Intent Preview',
32+
specUrl: `${SPEC}/intent-preview`,
33+
replayable: true,
34+
},
35+
{
36+
id: 'clarifying-questions',
37+
title: 'Clarifying questions',
38+
tagline: 'narrow scope before the plan',
39+
description:
40+
'When the request is ambiguous, the agent asks one focused follow-up with inline options instead of guessing — narrowing scope before it commits to a plan.',
41+
Demo: ClarifyingQuestionsDemo,
42+
code: clarifyingQuestionsCode,
43+
specName: 'Clarifying Questions',
44+
specUrl: `${SPEC}/clarifying-questions`,
45+
replayable: true,
2046
},
47+
{
48+
id: 'autonomy-dial',
49+
title: 'Autonomy dial',
50+
tagline: 'choose what the agent can do',
51+
description:
52+
'Let the user set how much the agent acts on its own — from manual to fully automatic — and reflect the chosen level back in plain language.',
53+
Demo: AutonomyDialDemo,
54+
code: autonomyDialCode,
55+
specName: 'Autonomy Dial',
56+
specUrl: `${SPEC}/autonomy-dial`,
57+
},
58+
59+
// ── While the agent works ────────────────────────────────
2160
{
2261
id: 'thinking-state',
2362
title: 'Thinking / reasoning state',
@@ -27,29 +66,8 @@ export const patterns: Pattern[] = [
2766
Demo: ThinkingStateDemo,
2867
code: thinkingStateCode,
2968
specName: 'Progress Ledger',
30-
specUrl: 'https://agentic-ux.com',
31-
},
32-
{
33-
id: 'action-confirm',
34-
title: 'Action preview → confirm',
35-
tagline: 'propose, expand, approve',
36-
description:
37-
'Before the agent acts, state the intent, let the user expand the details, and require an explicit approve or reject for consequential actions.',
38-
Demo: ActionConfirmDemo,
39-
code: actionConfirmCode,
40-
specName: 'Action Audit',
41-
specUrl: 'https://agentic-ux.com',
42-
},
43-
{
44-
id: 'context-panel',
45-
title: 'Context panel',
46-
tagline: 'what the agent knows',
47-
description:
48-
'A slide-out panel that surfaces the context the agent is working from, so the user can inspect and trust what informs each response.',
49-
Demo: ContextPanelDemo,
50-
code: contextPanelCode,
51-
specName: 'Explainable Rationale',
52-
specUrl: 'https://agentic-ux.com',
69+
specUrl: `${SPEC}/progress-ledger`,
70+
replayable: true,
5371
},
5472
{
5573
id: 'tool-call',
@@ -60,7 +78,8 @@ export const patterns: Pattern[] = [
6078
Demo: ToolCallDemo,
6179
code: toolCallCode,
6280
specName: 'Progress Ledger',
63-
specUrl: 'https://agentic-ux.com',
81+
specUrl: `${SPEC}/progress-ledger`,
82+
replayable: true,
6483
},
6584
{
6685
id: 'progress-ledger',
@@ -71,6 +90,55 @@ export const patterns: Pattern[] = [
7190
Demo: ProgressLedgerDemo,
7291
code: progressLedgerCode,
7392
specName: 'Progress Ledger',
74-
specUrl: 'https://agentic-ux.com',
93+
specUrl: `${SPEC}/progress-ledger`,
94+
replayable: true,
95+
},
96+
{
97+
id: 'context-panel',
98+
title: 'Context panel',
99+
tagline: 'what the agent knows',
100+
description:
101+
'A slide-out panel that surfaces the context the agent is working from, so the user can inspect and trust what informs each response.',
102+
Demo: ContextPanelDemo,
103+
code: contextPanelCode,
104+
specName: 'Explainable Rationale',
105+
specUrl: `${SPEC}/explainable-rationale`,
106+
},
107+
108+
// ── After the agent acts ─────────────────────────────────
109+
{
110+
id: 'action-confirm',
111+
title: 'Action audit & undo',
112+
tagline: 'review, approve, undo',
113+
description:
114+
'State the action and its details up front, require approval for consequential changes, and keep an undo within reach after it runs.',
115+
Demo: ActionConfirmDemo,
116+
code: actionConfirmCode,
117+
specName: 'Action Audit & Undo',
118+
specUrl: `${SPEC}/action-audit`,
119+
},
120+
{
121+
id: 'escalation-pathway',
122+
title: 'Escalation pathway',
123+
tagline: 'hand off to a human',
124+
description:
125+
'When the agent hits a limit, it says so plainly and offers a path forward — hand off to a person or try another approach — instead of failing silently.',
126+
Demo: EscalationPathwayDemo,
127+
code: escalationPathwayCode,
128+
specName: 'Escalation Pathway',
129+
specUrl: `${SPEC}/escalation-pathway`,
130+
replayable: true,
131+
},
132+
{
133+
id: 'streaming-text',
134+
title: 'Streaming text reveal',
135+
tagline: 'text appears as it thinks',
136+
description:
137+
'Render the response token by token with a blinking caret so the interface feels alive while the model is still generating.',
138+
Demo: StreamingTextDemo,
139+
code: streamingTextCode,
140+
specName: 'Return Moment',
141+
specUrl: `${SPEC}/return-moment`,
142+
replayable: true,
75143
},
76144
]

src/lib/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ export interface Pattern {
1616
/** matching spec on agentic-ux.com */
1717
specName: string
1818
specUrl: string
19+
/** show a Replay control below the demo (remounts it to re-run) */
20+
replayable?: boolean
1921
}

src/patterns/ActionConfirm.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export function ActionConfirmDemo() {
9898
: 'Cancelled — nothing changed'}
9999
</span>
100100
<button type="button" onClick={reset} className="btn-outline">
101-
reset
101+
{status === 'approved' ? 'Undo' : 'Reset'}
102102
</button>
103103
</div>
104104
</div>
@@ -172,6 +172,10 @@ export function ActionConfirm() {
172172
const [status, setStatus] = useState('pending')
173173
const [expanded, setExpanded] = useState(false)
174174
const phase = status === 'pending' ? 'pending' : 'resolved'
175+
const reset = () => {
176+
setStatus('pending')
177+
setExpanded(false)
178+
}
175179
176180
return (
177181
<div
@@ -218,6 +222,9 @@ export function ActionConfirm() {
218222
<OutcomeIcon approved={status === 'approved'} />
219223
{status === 'approved' ? 'Done — 3 files deleted' : 'Cancelled — nothing changed'}
220224
</span>
225+
<button type="button" className="btn-undo" onClick={reset}>
226+
{status === 'approved' ? 'Undo' : 'Reset'}
227+
</button>
221228
</div>
222229
</div>
223230
)
@@ -279,16 +286,16 @@ export function ActionConfirm() {
279286
display: flex; align-items: center;
280287
animation: fade-in 220ms cubic-bezier(0.22, 1, 0.36, 1);
281288
}
282-
.btn-approve, .btn-reject {
289+
.btn-approve, .btn-reject, .btn-undo {
283290
padding: 4px 12px; font-size: 14px; border-radius: 9999px; cursor: pointer;
284291
}
285292
.btn-approve {
286293
border: 1px solid #fff; background: #fff; color: #0a0a0a;
287294
}
288-
.btn-reject {
295+
.btn-reject, .btn-undo {
289296
border: 1px solid rgba(255,255,255,0.25); background: transparent; color: #fff;
290297
}
291-
.btn-approve:active, .btn-reject:active { transform: scale(0.98); }
298+
.btn-approve:active, .btn-reject:active, .btn-undo:active { transform: scale(0.98); }
292299
.outcome-icon {
293300
display: inline-flex; margin-right: 6px; vertical-align: middle;
294301
animation: icon-in 320ms cubic-bezier(0.22, 1, 0.36, 1);

0 commit comments

Comments
 (0)