PluginProbe
Code Snippets / 4.0.0-beta.2
Code Snippets v4.0.0-beta.2
4.0.0-beta.2 3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 All 65 releases
code-snippets / js / components / ManageMenu / AiAgentDemo / AiAgentDemo.tsx

AiAgentDemo.tsx in Code Snippets 4.0.0-beta.2, at js/components/ManageMenu/AiAgentDemo/AiAgentDemo.tsx

179 lines 6.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import React, { useEffect, useRef } from 'react'
2 import { __ } from '@wordpress/i18n'
3 import { WithRestAPIContext } from '../../../hooks/useRestAPI'
4 import { ScreenMetaSlot } from '../../common/ScreenMetaSlot'
5 import { DemoCallout } from '../../common/demo/DemoCallout'
6 import { DemoPageHeader } from '../../common/demo/DemoPageHeader'
7 import { DemoSpotlight } from '../../common/demo/DemoSpotlight'
8 import { useMarkDemoSeen } from '../../common/demo/useDemoSeen'
9 import { getCallout } from './callouts'
10 import { DemoPlanCard } from './DemoPlanCard'
11 import { DemoPromptBox } from './DemoPromptBox'
12 import { DemoResultCard } from './DemoResultCard'
13 import { DemoSidebar } from './DemoSidebar'
14 import { DemoMessage, DemoTransit, DemoTyping } from './DemoThread'
15 import { AiAgentDemoUpsell } from './DemoUpsell'
16 import { DEMO_EXAMPLES, DEMO_PROMPT, DEMO_REFINEMENT_REPLY } from './demoScript'
17 import { useAiAgentDemo } from './useAiAgentDemo'
18 import { hasReached } from './types'
19 import type { DemoStage } from './types'
20
21 /**
22 * Only the steps that point at one particular thing are spotlit. Typing,
23 * planning and building animate in place and need no dimming to be followed.
24 */
25 const STAGE_SPOTLIGHTS: Partial<Record<DemoStage, { target: string, padding?: number }>> = {
26 'plan-ready': { target: '.ai-agent-plan', padding: 6 },
27 'plan-accepted': { target: '.ai-agent-plan', padding: 6 },
28 'result-ready': { target: '.ai-agent-result__rows', padding: 8 },
29 'applying': { target: '.ai-agent-result__edit', padding: 6 }
30 }
31
32 /**
33 * Text announced to assistive technology as each stage begins, so the
34 * walkthrough is followable without watching the animation.
35 */
36 const STAGE_ANNOUNCEMENTS: Partial<Record<DemoStage, string>> = {
37 'typing-prompt': __('Writing a prompt.', 'code-snippets'),
38 'prompt-sent': __('Prompt sent.', 'code-snippets'),
39 'planning': __('Planning your snippets.', 'code-snippets'),
40 'plan-ready': __('The plan is ready.', 'code-snippets'),
41 'plan-accepted': __('Plan accepted.', 'code-snippets'),
42 'building': __('Building the code.', 'code-snippets'),
43 'result-ready': __('Snippets created.', 'code-snippets'),
44 'refine-open': __('Choosing snippets to refine.', 'code-snippets'),
45 'typing-refinement': __('Writing a refinement.', 'code-snippets'),
46 'applying': __('Applying your changes.', 'code-snippets'),
47 'saved': __('Snippets updated and saved to your site.', 'code-snippets'),
48 'finished': __('Demo complete.', 'code-snippets')
49 }
50
51 // eslint-disable-next-line max-lines-per-function -- the timeline reads as one sequence.
52 const AiAgentDemoPage: React.FC = () => {
53 const {
54 stage,
55 typedPrompt,
56 typedRefinement,
57 snippets,
58 hasStarted,
59 isFinished,
60 reducedMotion,
61 play,
62 skip,
63 replay
64 } = useAiAgentDemo()
65
66 const markSeen = useMarkDemoSeen('ai-agent')
67 const upsellRef = useRef<HTMLDivElement>(null)
68
69 useEffect(() => {
70 if (!isFinished) {
71 return
72 }
73
74 markSeen()
75
76 // The closing panel sits below the agent, so bring it into view rather
77 // than leaving the walkthrough to end off screen.
78 upsellRef.current?.scrollIntoView({
79 behavior: reducedMotion ? 'auto' : 'smooth',
80 block: 'end'
81 })
82 }, [isFinished, markSeen, reducedMotion])
83
84 const promptSent = hasReached(stage, 'prompt-sent')
85
86 return (
87 <>
88 <ScreenMetaSlot />
89
90 <DemoPageHeader
91 title={__('AI Agent', 'code-snippets')}
92 description={__('A guided walkthrough of the Pro AI Agent. Press play and watch it plan, build, and refine a snippet on your site.', 'code-snippets')}
93 hasStarted={hasStarted}
94 isFinished={isFinished}
95 onPlay={play}
96 onSkip={skip}
97 onReplay={replay}
98 />
99
100 <section className="ai-agent ai-agent-demo" aria-label={__('AI Agent demo', 'code-snippets')}>
101 <div className="screen-reader-text" aria-live="polite">{STAGE_ANNOUNCEMENTS[stage]}</div>
102
103 <DemoCallout callout={getCallout(stage)} />
104
105 <DemoSpotlight {...STAGE_SPOTLIGHTS[stage]} />
106
107 <div className="ai-agent-layout">
108 <div className="ai-agent-layout__main">
109 {!promptSent && <div className="ai-agent-empty">
110 <p className="ai-agent-empty__eyebrow">{__('Start with these prompts', 'code-snippets')}</p>
111
112 <div className="ai-agent-empty__chips">
113 {DEMO_EXAMPLES.map(example =>
114 <button key={example} type="button" className="ai-agent-empty__chip" disabled>
115 {example}
116 </button>)}
117 </div>
118 </div>}
119
120 <div className="ai-agent-thread">
121 {hasReached(stage, 'prompt-sent') && <DemoMessage speaker="user">{DEMO_PROMPT}</DemoMessage>}
122
123 {'planning' === stage && <>
124 <DemoTransit label={__('Sending your prompt to Code Snippets Cloud.', 'code-snippets')} />
125 <DemoTyping label={__('Planning your snippets…', 'code-snippets')} />
126 </>}
127
128 {hasReached(stage, 'plan-ready') && !hasReached(stage, 'building') &&
129 <DemoPlanCard accepted={'plan-accepted' === stage} />}
130
131 {'building' === stage && <>
132 <DemoTransit label={__('Building the snippets in Code Snippets Cloud.', 'code-snippets')} />
133 <DemoTyping label={__('Building the code…', 'code-snippets')} />
134 </>}
135
136 {hasReached(stage, 'result-ready') && <DemoResultCard
137 stage={stage}
138 snippets={snippets}
139 typedRefinement={typedRefinement}
140 />}
141
142 {'applying' === stage && <DemoTyping label={__('Applying your changes…', 'code-snippets')} />}
143
144 {hasReached(stage, 'saved') && <DemoMessage speaker="assistant">{DEMO_REFINEMENT_REPLY}</DemoMessage>}
145 </div>
146
147 <DemoPromptBox
148 value={hasReached(stage, 'planning') ? '' : typedPrompt}
149 typing={'typing-prompt' === stage}
150 pressed={'prompt-sent' === stage}
151 disabled={promptSent}
152 submitLabel={__('Send', 'code-snippets')}
153 placeholder={__('Describe what you want to build…', 'code-snippets')}
154 />
155 </div>
156
157 <div className="ai-agent-layout__sidebar">
158 <DemoSidebar stage={stage} />
159 </div>
160 </div>
161
162 {isFinished && <div
163 ref={upsellRef}
164 className="ai-agent-demo__closing"
165 role="region"
166 aria-label={__('AI Agent demo complete', 'code-snippets')}
167 >
168 <AiAgentDemoUpsell onReplay={replay} />
169 </div>}
170 </section>
171 </>
172 )
173 }
174
175 export const AiAgentDemo: React.FC = () =>
176 <WithRestAPIContext>
177 <AiAgentDemoPage />
178 </WithRestAPIContext>
179