From a52fefc0c13dcf8326f3a45a9506ea443a6cd1f0 Mon Sep 17 00:00:00 2001 From: Rankush Kumar Date: Thu, 11 Dec 2025 17:02:07 +0530 Subject: [PATCH 1/3] docs(samples-cc-react-app): add AI documentation - AGENTS.md --- .../cc/samples-cc-react-app/ai-docs/AGENTS.md | 365 ++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md diff --git a/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md b/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md new file mode 100644 index 000000000..346249c16 --- /dev/null +++ b/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md @@ -0,0 +1,365 @@ +# React Sample App - Widget Integration Guide + +## Purpose + +Demonstrates how to integrate Contact Center widgets into a React application. Use this as a reference when adding new widgets. + +## Design System + +- **Framework:** React 18.3.1 + TypeScript +- **UI Library:** Momentum Design System (`@momentum-design/components`) +- **State:** MobX store (`@webex/cc-store`) +- **Theme:** Dark/Light mode toggle (persisted in localStorage) +- **Layout:** CSS Grid with `.box`, `.section-box`, `.fieldset` structure + +## Critical Integration Pattern + +**Follow this exact pattern for ALL new widgets:** + +### Step 1: Import the Widget + +```tsx +import { NewWidget } from '@webex/cc-widgets'; +``` + +**Add to imports section (lines 1-28)** with other widgets. + +### Step 2: Add to defaultWidgets + +```tsx +const defaultWidgets = { + stationLogin: true, + userState: true, + // ... existing widgets + newWidget: false, // ← Add here (false by default for user opt-in) +}; +``` + +**Location:** Line 33-42 in `App.tsx` + +### Step 3: Add Checkbox for Widget Selection + +```tsx + + New Widget + +``` + +**Location:** Widget selector section in render (around line 300-400) + +### Step 4: Conditional Rendering with Standard Layout + +```tsx +{selectedWidgets.newWidget && ( +
+
+
+ New Widget + handleNewWidgetEvent(data)} + onError={(error) => onError('NewWidget', error)} + /> +
+
+
+)} +``` + +**Location:** Main render section, grouped by widget category + +### Step 5: Add Event Handlers (if needed) + +```tsx +const handleNewWidgetEvent = (data) => { + console.log('New widget event:', data); + // Handle event logic +}; +``` + +**Location:** With other event handlers in component + +## Layout Structure Rules + +### Container Hierarchy (ALWAYS use this) + +```tsx +
{/* Outer container with background */} +
{/* Inner section with padding */} +
{/* Fieldset for grouping */} + Title {/* Title/legend */} + {/* Actual widget */} +
+
+
+``` + +### Why this structure? + +- `box` - Consistent spacing and background +- `section-box` - Momentum Design padding +- `fieldset` - Semantic grouping +- `legend-box` - Styled title +- **Result:** Visual consistency across all widgets + +## Styling Rules + +### CSS Variables (MUST USE) + +```scss +// Colors +var(--mds-color-theme-text-primary-normal) +var(--mds-color-theme-background-solid-primary-normal) +var(--mds-color-theme-background-primary-normal) + +// Spacing +var(--mds-spacing-1) // 0.25rem (4px) +var(--mds-spacing-2) // 0.5rem (8px) +var(--mds-spacing-3) // 1rem (16px) +var(--mds-spacing-4) // 1.5rem (24px) + +// Typography +var(--mds-font-size-body-small) +var(--mds-font-size-body-medium) +``` + +### ❌ NEVER Do This + +```tsx +
// Hardcoded color +
// Hardcoded spacing +``` + +### ✅ ALWAYS Do This + +```tsx +
+``` + +## Event Handling Pattern + +### Standard onError Handler + +```tsx +const onError = (source: string, error: Error) => { + console.error(`${source} error:`, error); + // Optional: Show toast notification + setToast({ type: 'error' }); +}; +``` + +**EVERY widget MUST have onError callback.** + +### Widget-Specific Events + +```tsx +// IncomingTask +const onIncomingTaskCB = ({ task }) => { + console.log('Incoming task:', task); + setIncomingTasks(prev => [...prev, task]); + playNotificationSound(); // Custom logic +}; + +// UserState +const onAgentStateChangedCB = (newState: AgentState, oldState: AgentState) => { + console.log('State changed from', oldState, 'to', newState); + setSelectedState(newState); +}; + +// CallControl +const onRecordingToggleCB = ({ isRecording, task }) => { + console.log('Recording:', isRecording, 'for task:', task.data.interactionId); +}; +``` + +## Theme Integration + +Widgets automatically use MobX store theme: + +```tsx +// Theme is managed by store.currentTheme +// Widget CSS uses CSS variables that respond to theme changes +// No manual theme passing needed +``` + +**User can toggle theme via UI dropdown** - widgets update automatically. + +## State Management + +### When to Use store Directly + +```tsx +// Access store for global state +import { store } from '@webex/cc-widgets'; + +// Examples: +store.currentTask // Current active task +store.taskList // All tasks +store.incomingTask // Incoming task +store.agentState // Current agent state +``` + +### When to Use Local State + +```tsx +// UI-only state (no widget dependency) +const [showPopup, setShowPopup] = useState(false); +const [selectedOption, setSelectedOption] = useState(''); +``` + +## Complete Example: Adding a New Widget + +```tsx +// 1. Import +import { NewAwesomeWidget } from '@webex/cc-widgets'; + +// 2. Add to defaultWidgets +const defaultWidgets = { + // ... existing + newAwesomeWidget: false, +}; + +// 3. Checkbox in widget selector + + New Awesome Widget + + +// 4. Event handler (if needed) +const handleAwesomeEvent = (data) => { + console.log('Awesome event:', data); +}; + +// 5. Render with standard layout +{selectedWidgets.newAwesomeWidget && ( +
+
+
+ New Awesome Widget + onError('NewAwesomeWidget', error)} + customProp={someValue} + /> +
+
+
+)} +``` + +## Common Mistakes to AVOID + +### ❌ Breaking CSS class structure + +```tsx +// WRONG +
+ +
+``` + +### ✅ Correct + +```tsx +
+
+
+ Widget Name + +
+
+
+``` + +### ❌ Forgetting defaultWidgets entry + +```tsx +// WRONG - Widget renders immediately, user can't disable +{selectedWidgets.newWidget && } +// But newWidget not in defaultWidgets! +``` + +### ✅ Correct + +```tsx +// In defaultWidgets +const defaultWidgets = { + newWidget: false, // ← MUST ADD HERE +}; + +// Then render +{selectedWidgets.newWidget && } +``` + +### ❌ Missing error handler + +```tsx +// WRONG + +``` + +### ✅ Correct + +```tsx + onError('NewWidget', error)} +/> +``` + +### ❌ Hardcoding colors + +```tsx +// WRONG +
+``` + +### ✅ Correct + +```tsx +
+``` + +## Testing Checklist + +After adding a new widget: + +- [ ] Widget imports without errors +- [ ] Appears in widget selector checkbox list +- [ ] Can be enabled/disabled via checkbox +- [ ] Selection persists in localStorage +- [ ] Renders with correct layout (box > section-box > fieldset) +- [ ] Has legend/title +- [ ] Uses Momentum CSS variables (no hardcoded colors) +- [ ] Event handlers fire correctly +- [ ] onError handler present and logs errors +- [ ] Works in both light and dark themes +- [ ] No console errors when enabled/disabled +- [ ] No visual/layout breaking when rendered alongside other widgets + +## File Locations + +- **Main App:** `src/App.tsx` +- **Styles:** `src/App.scss` +- **Widget Imports:** Line 1-28 in `App.tsx` +- **defaultWidgets:** Line 33-42 in `App.tsx` +- **Widget Selector:** Around line 300-400 in render method +- **Widget Render:** Main render section grouped by category + +## Additional Resources + +- [Momentum Design System Docs](https://momentum.design/) +- [MobX Store Package](../../packages/contact-center/store/ai-docs/agent.md) +- [cc-widgets Package](../../packages/contact-center/cc-widgets/ai-docs/agent.md) + From 7e12e58a46e002abb5b18b3b1cf51ce97c6064f2 Mon Sep 17 00:00:00 2001 From: Shreyas Sharma Date: Tue, 3 Feb 2026 10:10:23 +0530 Subject: [PATCH 2/3] docs(ai-docs): review --- widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md b/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md index 346249c16..7b4cf9173 100644 --- a/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md +++ b/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md @@ -45,6 +45,7 @@ const defaultWidgets = { name="newWidget" checked={selectedWidgets.newWidget} htmlId="newWidget-checkbox" + aria-label="new widget checkbox" > New Widget From ef2c049302ba855693d0841ae81968e76e3e4df7 Mon Sep 17 00:00:00 2001 From: Shreyas Sharma Date: Tue, 3 Feb 2026 15:20:19 +0530 Subject: [PATCH 3/3] docs(samples): review comments --- .../cc/samples-cc-react-app/ai-docs/AGENTS.md | 169 +++++++++--------- 1 file changed, 85 insertions(+), 84 deletions(-) diff --git a/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md b/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md index 7b4cf9173..6816fc7b0 100644 --- a/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md +++ b/widgets-samples/cc/samples-cc-react-app/ai-docs/AGENTS.md @@ -19,11 +19,9 @@ Demonstrates how to integrate Contact Center widgets into a React application. U ### Step 1: Import the Widget ```tsx -import { NewWidget } from '@webex/cc-widgets'; +import {NewWidget} from '@webex/cc-widgets'; ``` -**Add to imports section (lines 1-28)** with other widgets. - ### Step 2: Add to defaultWidgets ```tsx @@ -31,12 +29,10 @@ const defaultWidgets = { stationLogin: true, userState: true, // ... existing widgets - newWidget: false, // ← Add here (false by default for user opt-in) + newWidget: false, // ← Add here (false by default for user opt-in) }; ``` -**Location:** Line 33-42 in `App.tsx` - ### Step 3: Add Checkbox for Widget Selection ```tsx @@ -51,49 +47,48 @@ const defaultWidgets = { ``` -**Location:** Widget selector section in render (around line 300-400) - ### Step 4: Conditional Rendering with Standard Layout ```tsx -{selectedWidgets.newWidget && ( -
-
-
- New Widget - handleNewWidgetEvent(data)} - onError={(error) => onError('NewWidget', error)} - /> -
-
-
-)} +{ + selectedWidgets.newWidget && ( +
+
+
+ New Widget + handleNewWidgetEvent(data)} onError={(error) => onError('NewWidget', error)} /> +
+
+
+ ); +} ``` -**Location:** Main render section, grouped by widget category - -### Step 5: Add Event Handlers (if needed) +### Step 5: Add callbacks (if needed) ```tsx -const handleNewWidgetEvent = (data) => { - console.log('New widget event:', data); - // Handle event logic +const handleNewWidgetCallback = (data) => { + console.log('New widget callback:', data); + // Handle callback logic }; ``` -**Location:** With other event handlers in component - ## Layout Structure Rules ### Container Hierarchy (ALWAYS use this) ```tsx -
{/* Outer container with background */} -
{/* Inner section with padding */} -
{/* Fieldset for grouping */} - Title {/* Title/legend */} - {/* Actual widget */} +
+ {' '} + {/* Outer container with background */} +
+ {' '} + {/* Inner section with padding */} +
+ {' '} + {/* Fieldset for grouping */} + Title {/* Title/legend */} + {/* Actual widget */}
@@ -149,10 +144,10 @@ var(--mds-font-size-body-medium) ### Standard onError Handler ```tsx -const onError = (source: string, error: Error) => { - console.error(`${source} error:`, error); +const onError = (widgetName: string, error: Error) => { + console.error(`${widgetName} error:`, error); // Optional: Show toast notification - setToast({ type: 'error' }); + setToast({type: 'error'}); }; ``` @@ -162,10 +157,10 @@ const onError = (source: string, error: Error) => { ```tsx // IncomingTask -const onIncomingTaskCB = ({ task }) => { +const onIncomingTaskCB = ({task}) => { console.log('Incoming task:', task); - setIncomingTasks(prev => [...prev, task]); - playNotificationSound(); // Custom logic + setIncomingTasks((prev) => [...prev, task]); + playNotificationSound(); // Custom logic }; // UserState @@ -175,22 +170,31 @@ const onAgentStateChangedCB = (newState: AgentState, oldState: AgentState) => { }; // CallControl -const onRecordingToggleCB = ({ isRecording, task }) => { +const onRecordingToggleCB = ({isRecording, task}) => { console.log('Recording:', isRecording, 'for task:', task.data.interactionId); }; ``` ## Theme Integration -Widgets automatically use MobX store theme: +Theme is controlled by `@momentum-ui`'s `ThemeProvider`: ```tsx -// Theme is managed by store.currentTheme -// Widget CSS uses CSS variables that respond to theme changes -// No manual theme passing needed +import {ThemeProvider} from '@momentum-design/components/dist/react'; + + + {/* Your widgets */} +; ``` -**User can toggle theme via UI dropdown** - widgets update automatically. +- **Theme provider**: `@momentum-ui` library manages the theme through `ThemeProvider` +- **Theme storage**: `store.currentTheme` stores the theme as a string ('LIGHT' or 'DARK') +- **Theme classes**: Theme class names (`mds-theme-stable-lightWebex` / `mds-theme-stable-darkWebex`) are passed to ThemeProvider +- **Automatic updates**: All widgets automatically respond to theme changes through the ThemeProvider context + +**User can toggle theme via UI checkbox** - widgets update automatically through the provider. ## State Management @@ -198,13 +202,13 @@ Widgets automatically use MobX store theme: ```tsx // Access store for global state -import { store } from '@webex/cc-widgets'; +import {store} from '@webex/cc-widgets'; // Examples: -store.currentTask // Current active task -store.taskList // All tasks -store.incomingTask // Incoming task -store.agentState // Current agent state +store.currentTask; // Current active task +store.taskList; // All tasks +store.incomingTask; // Incoming task +store.agentState; // Current agent state ``` ### When to Use Local State @@ -219,7 +223,7 @@ const [selectedOption, setSelectedOption] = useState(''); ```tsx // 1. Import -import { NewAwesomeWidget } from '@webex/cc-widgets'; +import {NewAwesomeWidget} from '@webex/cc-widgets'; // 2. Add to defaultWidgets const defaultWidgets = { @@ -235,28 +239,30 @@ const defaultWidgets = { htmlId="newAwesomeWidget-checkbox" > New Awesome Widget - +; -// 4. Event handler (if needed) -const handleAwesomeEvent = (data) => { - console.log('Awesome event:', data); +// 4. Setup callback handler (if needed) +const handleCallback = (data) => { + console.log('Callback:', data); }; // 5. Render with standard layout -{selectedWidgets.newAwesomeWidget && ( -
-
-
- New Awesome Widget - onError('NewAwesomeWidget', error)} - customProp={someValue} - /> -
-
-
-)} +{ + selectedWidgets.newAwesomeWidget && ( +
+
+
+ New Awesome Widget + onError('NewAwesomeWidget', error)} + customProp={someValue} + /> +
+
+
+ ); +} ``` ## Common Mistakes to AVOID @@ -287,7 +293,9 @@ const handleAwesomeEvent = (data) => { ```tsx // WRONG - Widget renders immediately, user can't disable -{selectedWidgets.newWidget && } +{ + selectedWidgets.newWidget && ; +} // But newWidget not in defaultWidgets! ``` @@ -296,11 +304,13 @@ const handleAwesomeEvent = (data) => { ```tsx // In defaultWidgets const defaultWidgets = { - newWidget: false, // ← MUST ADD HERE + newWidget: false, // ← MUST ADD HERE }; // Then render -{selectedWidgets.newWidget && } +{ + selectedWidgets.newWidget && ; +} ``` ### ❌ Missing error handler @@ -313,10 +323,7 @@ const defaultWidgets = { ### ✅ Correct ```tsx - onError('NewWidget', error)} -/> + onError('NewWidget', error)} /> ``` ### ❌ Hardcoding colors @@ -343,7 +350,7 @@ After adding a new widget: - [ ] Renders with correct layout (box > section-box > fieldset) - [ ] Has legend/title - [ ] Uses Momentum CSS variables (no hardcoded colors) -- [ ] Event handlers fire correctly +- [ ] Callbacks are handled correctly - [ ] onError handler present and logs errors - [ ] Works in both light and dark themes - [ ] No console errors when enabled/disabled @@ -353,14 +360,8 @@ After adding a new widget: - **Main App:** `src/App.tsx` - **Styles:** `src/App.scss` -- **Widget Imports:** Line 1-28 in `App.tsx` -- **defaultWidgets:** Line 33-42 in `App.tsx` -- **Widget Selector:** Around line 300-400 in render method -- **Widget Render:** Main render section grouped by category ## Additional Resources -- [Momentum Design System Docs](https://momentum.design/) - [MobX Store Package](../../packages/contact-center/store/ai-docs/agent.md) - [cc-widgets Package](../../packages/contact-center/cc-widgets/ai-docs/agent.md) -