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) +