Skip to content

Commit 9bb464c

Browse files
Shreyas281299Rankush Kumar
andauthored
docs(samples-cc-react-app): add AI documentation - AGENTS.md (#594)
Co-authored-by: Rankush Kumar <rankkuma+cisco@cisco.com>
1 parent 7be06c9 commit 9bb464c

1 file changed

Lines changed: 367 additions & 0 deletions

File tree

  • widgets-samples/cc/samples-cc-react-app/ai-docs
Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
# React Sample App - Widget Integration Guide
2+
3+
## Purpose
4+
5+
Demonstrates how to integrate Contact Center widgets into a React application. Use this as a reference when adding new widgets.
6+
7+
## Design System
8+
9+
- **Framework:** React 18.3.1 + TypeScript
10+
- **UI Library:** Momentum Design System (`@momentum-design/components`)
11+
- **State:** MobX store (`@webex/cc-store`)
12+
- **Theme:** Dark/Light mode toggle (persisted in localStorage)
13+
- **Layout:** CSS Grid with `.box`, `.section-box`, `.fieldset` structure
14+
15+
## Critical Integration Pattern
16+
17+
**Follow this exact pattern for ALL new widgets:**
18+
19+
### Step 1: Import the Widget
20+
21+
```tsx
22+
import {NewWidget} from '@webex/cc-widgets';
23+
```
24+
25+
### Step 2: Add to defaultWidgets
26+
27+
```tsx
28+
const defaultWidgets = {
29+
stationLogin: true,
30+
userState: true,
31+
// ... existing widgets
32+
newWidget: false, // ← Add here (false by default for user opt-in)
33+
};
34+
```
35+
36+
### Step 3: Add Checkbox for Widget Selection
37+
38+
```tsx
39+
<Checkbox
40+
onChange={handleCheckboxChange}
41+
name="newWidget"
42+
checked={selectedWidgets.newWidget}
43+
htmlId="newWidget-checkbox"
44+
aria-label="new widget checkbox"
45+
>
46+
<Text>New Widget</Text>
47+
</Checkbox>
48+
```
49+
50+
### Step 4: Conditional Rendering with Standard Layout
51+
52+
```tsx
53+
{
54+
selectedWidgets.newWidget && (
55+
<div className="box">
56+
<section className="section-box">
57+
<fieldset className="fieldset">
58+
<legend className="legend-box">New Widget</legend>
59+
<NewWidget onEvent={(data) => handleNewWidgetEvent(data)} onError={(error) => onError('NewWidget', error)} />
60+
</fieldset>
61+
</section>
62+
</div>
63+
);
64+
}
65+
```
66+
67+
### Step 5: Add callbacks (if needed)
68+
69+
```tsx
70+
const handleNewWidgetCallback = (data) => {
71+
console.log('New widget callback:', data);
72+
// Handle callback logic
73+
};
74+
```
75+
76+
## Layout Structure Rules
77+
78+
### Container Hierarchy (ALWAYS use this)
79+
80+
```tsx
81+
<div className="box">
82+
{' '}
83+
{/* Outer container with background */}
84+
<section className="section-box">
85+
{' '}
86+
{/* Inner section with padding */}
87+
<fieldset className="fieldset">
88+
{' '}
89+
{/* Fieldset for grouping */}
90+
<legend className="legend-box">Title</legend> {/* Title/legend */}
91+
<WidgetComponent /> {/* Actual widget */}
92+
</fieldset>
93+
</section>
94+
</div>
95+
```
96+
97+
### Why this structure?
98+
99+
- `box` - Consistent spacing and background
100+
- `section-box` - Momentum Design padding
101+
- `fieldset` - Semantic grouping
102+
- `legend-box` - Styled title
103+
- **Result:** Visual consistency across all widgets
104+
105+
## Styling Rules
106+
107+
### CSS Variables (MUST USE)
108+
109+
```scss
110+
// Colors
111+
var(--mds-color-theme-text-primary-normal)
112+
var(--mds-color-theme-background-solid-primary-normal)
113+
var(--mds-color-theme-background-primary-normal)
114+
115+
// Spacing
116+
var(--mds-spacing-1) // 0.25rem (4px)
117+
var(--mds-spacing-2) // 0.5rem (8px)
118+
var(--mds-spacing-3) // 1rem (16px)
119+
var(--mds-spacing-4) // 1.5rem (24px)
120+
121+
// Typography
122+
var(--mds-font-size-body-small)
123+
var(--mds-font-size-body-medium)
124+
```
125+
126+
### ❌ NEVER Do This
127+
128+
```tsx
129+
<div style={{color: '#FF0000'}}> // Hardcoded color
130+
<div style={{padding: '10px'}}> // Hardcoded spacing
131+
```
132+
133+
### ✅ ALWAYS Do This
134+
135+
```tsx
136+
<div style={{
137+
color: 'var(--mds-color-theme-text-primary-normal)',
138+
padding: 'var(--mds-spacing-3)'
139+
}}>
140+
```
141+
142+
## Event Handling Pattern
143+
144+
### Standard onError Handler
145+
146+
```tsx
147+
const onError = (widgetName: string, error: Error) => {
148+
console.error(`${widgetName} error:`, error);
149+
// Optional: Show toast notification
150+
setToast({type: 'error'});
151+
};
152+
```
153+
154+
**EVERY widget MUST have onError callback.**
155+
156+
### Widget-Specific Events
157+
158+
```tsx
159+
// IncomingTask
160+
const onIncomingTaskCB = ({task}) => {
161+
console.log('Incoming task:', task);
162+
setIncomingTasks((prev) => [...prev, task]);
163+
playNotificationSound(); // Custom logic
164+
};
165+
166+
// UserState
167+
const onAgentStateChangedCB = (newState: AgentState, oldState: AgentState) => {
168+
console.log('State changed from', oldState, 'to', newState);
169+
setSelectedState(newState);
170+
};
171+
172+
// CallControl
173+
const onRecordingToggleCB = ({isRecording, task}) => {
174+
console.log('Recording:', isRecording, 'for task:', task.data.interactionId);
175+
};
176+
```
177+
178+
## Theme Integration
179+
180+
Theme is controlled by `@momentum-ui`'s `ThemeProvider`:
181+
182+
```tsx
183+
import {ThemeProvider} from '@momentum-design/components/dist/react';
184+
185+
<ThemeProvider
186+
themeclass={store.currentTheme === 'LIGHT' ? 'mds-theme-stable-lightWebex' : 'mds-theme-stable-darkWebex'}
187+
>
188+
{/* Your widgets */}
189+
</ThemeProvider>;
190+
```
191+
192+
- **Theme provider**: `@momentum-ui` library manages the theme through `ThemeProvider`
193+
- **Theme storage**: `store.currentTheme` stores the theme as a string ('LIGHT' or 'DARK')
194+
- **Theme classes**: Theme class names (`mds-theme-stable-lightWebex` / `mds-theme-stable-darkWebex`) are passed to ThemeProvider
195+
- **Automatic updates**: All widgets automatically respond to theme changes through the ThemeProvider context
196+
197+
**User can toggle theme via UI checkbox** - widgets update automatically through the provider.
198+
199+
## State Management
200+
201+
### When to Use store Directly
202+
203+
```tsx
204+
// Access store for global state
205+
import {store} from '@webex/cc-widgets';
206+
207+
// Examples:
208+
store.currentTask; // Current active task
209+
store.taskList; // All tasks
210+
store.incomingTask; // Incoming task
211+
store.agentState; // Current agent state
212+
```
213+
214+
### When to Use Local State
215+
216+
```tsx
217+
// UI-only state (no widget dependency)
218+
const [showPopup, setShowPopup] = useState(false);
219+
const [selectedOption, setSelectedOption] = useState('');
220+
```
221+
222+
## Complete Example: Adding a New Widget
223+
224+
```tsx
225+
// 1. Import
226+
import {NewAwesomeWidget} from '@webex/cc-widgets';
227+
228+
// 2. Add to defaultWidgets
229+
const defaultWidgets = {
230+
// ... existing
231+
newAwesomeWidget: false,
232+
};
233+
234+
// 3. Checkbox in widget selector
235+
<Checkbox
236+
onChange={handleCheckboxChange}
237+
name="newAwesomeWidget"
238+
checked={selectedWidgets.newAwesomeWidget}
239+
htmlId="newAwesomeWidget-checkbox"
240+
>
241+
<Text>New Awesome Widget</Text>
242+
</Checkbox>;
243+
244+
// 4. Setup callback handler (if needed)
245+
const handleCallback = (data) => {
246+
console.log('Callback:', data);
247+
};
248+
249+
// 5. Render with standard layout
250+
{
251+
selectedWidgets.newAwesomeWidget && (
252+
<div className="box">
253+
<section className="section-box">
254+
<fieldset className="fieldset">
255+
<legend className="legend-box">New Awesome Widget</legend>
256+
<NewAwesomeWidget
257+
handleCallback={handleCallback}
258+
onError={(error) => onError('NewAwesomeWidget', error)}
259+
customProp={someValue}
260+
/>
261+
</fieldset>
262+
</section>
263+
</div>
264+
);
265+
}
266+
```
267+
268+
## Common Mistakes to AVOID
269+
270+
### ❌ Breaking CSS class structure
271+
272+
```tsx
273+
// WRONG
274+
<div>
275+
<NewWidget />
276+
</div>
277+
```
278+
279+
### ✅ Correct
280+
281+
```tsx
282+
<div className="box">
283+
<section className="section-box">
284+
<fieldset className="fieldset">
285+
<legend className="legend-box">Widget Name</legend>
286+
<NewWidget />
287+
</fieldset>
288+
</section>
289+
</div>
290+
```
291+
292+
### ❌ Forgetting defaultWidgets entry
293+
294+
```tsx
295+
// WRONG - Widget renders immediately, user can't disable
296+
{
297+
selectedWidgets.newWidget && <NewWidget />;
298+
}
299+
// But newWidget not in defaultWidgets!
300+
```
301+
302+
### ✅ Correct
303+
304+
```tsx
305+
// In defaultWidgets
306+
const defaultWidgets = {
307+
newWidget: false, // ← MUST ADD HERE
308+
};
309+
310+
// Then render
311+
{
312+
selectedWidgets.newWidget && <NewWidget />;
313+
}
314+
```
315+
316+
### ❌ Missing error handler
317+
318+
```tsx
319+
// WRONG
320+
<NewWidget onEvent={handleEvent} />
321+
```
322+
323+
### ✅ Correct
324+
325+
```tsx
326+
<NewWidget onEvent={handleEvent} onError={(error) => onError('NewWidget', error)} />
327+
```
328+
329+
### ❌ Hardcoding colors
330+
331+
```tsx
332+
// WRONG
333+
<div style={{backgroundColor: '#1a1a1a'}}>
334+
```
335+
336+
### ✅ Correct
337+
338+
```tsx
339+
<div style={{backgroundColor: 'var(--mds-color-theme-background-primary-normal)'}}>
340+
```
341+
342+
## Testing Checklist
343+
344+
After adding a new widget:
345+
346+
- [ ] Widget imports without errors
347+
- [ ] Appears in widget selector checkbox list
348+
- [ ] Can be enabled/disabled via checkbox
349+
- [ ] Selection persists in localStorage
350+
- [ ] Renders with correct layout (box > section-box > fieldset)
351+
- [ ] Has legend/title
352+
- [ ] Uses Momentum CSS variables (no hardcoded colors)
353+
- [ ] Callbacks are handled correctly
354+
- [ ] onError handler present and logs errors
355+
- [ ] Works in both light and dark themes
356+
- [ ] No console errors when enabled/disabled
357+
- [ ] No visual/layout breaking when rendered alongside other widgets
358+
359+
## File Locations
360+
361+
- **Main App:** `src/App.tsx`
362+
- **Styles:** `src/App.scss`
363+
364+
## Additional Resources
365+
366+
- [MobX Store Package](../../packages/contact-center/store/ai-docs/agent.md)
367+
- [cc-widgets Package](../../packages/contact-center/cc-widgets/ai-docs/agent.md)

0 commit comments

Comments
 (0)