-
Notifications
You must be signed in to change notification settings - Fork 65
docs(ai-docs): add docs for meetings widget #642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Changes from all commits
1e7cf7b
b7796b0
ede3349
6630b60
3b4fdaf
e59ce02
a2f82c4
5baf0e3
f4187cb
fc7f57a
08bca0d
28df4c6
aa12c9a
994d249
f51a8ae
2cf590b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,352 @@ | ||||||||
| # Meetings Widget | ||||||||
|
|
||||||||
| ## AI Agent Routing Instructions | ||||||||
|
|
||||||||
| **If you are an AI assistant or automated tool:** | ||||||||
|
|
||||||||
| Do **not** use this file as your main entry point for reasoning or code generation. | ||||||||
|
|
||||||||
| - **How to proceed:** | ||||||||
| - Carefully load and follow the guidance, templates, and routing logic given in this `AGENTS.md`. | ||||||||
|
|
||||||||
| Only after following the routing process laid out in the parent `AGENTS.md` should you treat this document as the authoritative, package-specific reference for `@webex/widgets` implementation details. | ||||||||
|
|
||||||||
| ## Overview | ||||||||
|
|
||||||||
| The Meetings Widget provides a full-featured Webex meeting experience as an embeddable component. It orchestrates three external repositories — `webex-js-sdk` for backend communication, `sdk-component-adapter` for reactive data binding, and `components` for the React UI. | ||||||||
|
|
||||||||
| **Widget:** Meetings | ||||||||
|
|
||||||||
| **Package:** `@webex/widgets` | ||||||||
|
|
||||||||
| **Version:** See [package.json](../package.json) | ||||||||
|
|
||||||||
| **Location:** `packages/@webex/widgets` | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## Why and What is This Used For? | ||||||||
|
|
||||||||
| ### Purpose | ||||||||
|
|
||||||||
| The Meetings Widget lets consuming applications embed a complete meeting experience without building any meeting logic themselves. It handles the entire lifecycle — from SDK initialization through meeting creation, joining, in-meeting controls, and leaving — by composing existing components and adapters together. | ||||||||
|
|
||||||||
| ### Key Capabilities | ||||||||
|
|
||||||||
| - **Join Meetings** — Connect to a meeting via URL, SIP address, or Personal Meeting Room | ||||||||
| - **Audio Controls** — Mute and unmute microphone with transitional states | ||||||||
| - **Video Controls** — Start and stop camera with device switching | ||||||||
| - **Screen Sharing** — Share screen, window, or tab with other participants | ||||||||
| - **Member Roster** — View list of meeting participants | ||||||||
| - **Device Settings** — Switch between cameras, microphones, and speakers | ||||||||
| - **Guest/Host Authentication** — Password-protected meetings with host key support | ||||||||
| - **Waiting for Host** — Automatic transition when host starts the meeting | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## Examples and Use Cases | ||||||||
|
|
||||||||
| ### Getting Started | ||||||||
|
|
||||||||
| #### Basic Usage (React) | ||||||||
|
|
||||||||
| The widget handles SDK initialization, adapter creation, meeting creation, and all internal wiring via the `withAdapter` and `withMeeting` HOCs. Consumers just import and render with props: | ||||||||
|
|
||||||||
| ```jsx | ||||||||
| import {WebexMeetingsWidget} from '@webex/widgets'; | ||||||||
|
Comment on lines
+53
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In the basic integration path, this example only imports Useful? React with 👍 / 👎.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the CSS is self-contained within the widget's source imports. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The "Basic Usage" snippet only imports Useful? React with 👍 / 👎.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. repeated |
||||||||
|
|
||||||||
| function App() { | ||||||||
| return ( | ||||||||
| <WebexMeetingsWidget | ||||||||
| accessToken="your-access-token" | ||||||||
| meetingDestination="user@example.com" | ||||||||
| /> | ||||||||
| ); | ||||||||
| } | ||||||||
| ``` | ||||||||
|
|
||||||||
| #### With All Optional Props | ||||||||
|
|
||||||||
| ```jsx | ||||||||
| <WebexMeetingsWidget | ||||||||
| accessToken={token} | ||||||||
| meetingDestination={destination} | ||||||||
| meetingPasswordOrPin={pinOrPassword} | ||||||||
| participantName="Guest User" | ||||||||
| layout="Grid" | ||||||||
| fedramp={false} | ||||||||
| className="my-custom-class" | ||||||||
| style={{height: '100vh'}} | ||||||||
| /> | ||||||||
| ``` | ||||||||
|
|
||||||||
| #### What Happens Internally | ||||||||
|
|
||||||||
| When `WebexMeetingsWidget` mounts, the `withAdapter` HOC: | ||||||||
|
|
||||||||
| 1. Creates a `Webex` instance using the `accessToken` prop | ||||||||
| 2. Wraps it in a `WebexSDKAdapter` | ||||||||
| 3. Calls `adapter.connect()` (registers device, opens WebSocket, syncs meetings) | ||||||||
| 4. Provides the adapter via `AdapterContext` | ||||||||
|
|
||||||||
| The `withMeeting` HOC then creates a meeting from `meetingDestination` and passes the meeting object as a prop. The widget renders the appropriate view based on meeting state. | ||||||||
|
|
||||||||
| ### Common Use Cases | ||||||||
|
|
||||||||
| #### 1. Password-Protected Meeting | ||||||||
|
|
||||||||
| When a meeting requires a password, the `WebexMeeting` component detects `passwordRequired` from the adapter observable and renders the `WebexMeetingGuestAuthentication` modal. The user enters the password, and `JoinControl.action()` passes it to the SDK. | ||||||||
|
|
||||||||
| **Key Points:** | ||||||||
|
|
||||||||
| - `passwordRequired` is a boolean on the adapter meeting observable | ||||||||
| - The component handles guest vs host authentication flows | ||||||||
| - Wrong password triggers `invalidPassword` flag on the observable | ||||||||
|
|
||||||||
| #### 2. Pre-Join Media Preview | ||||||||
|
|
||||||||
| Before joining, the interstitial screen shows local media preview. The user can mute audio, stop video, or open settings before entering the meeting. | ||||||||
|
|
||||||||
| **Key Points:** | ||||||||
|
|
||||||||
| - `WebexInterstitialMeeting` renders when `state === 'NOT_JOINED'` | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still not fixed from original review. These two lines still use destructured object notation: Should be:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. misconception of the codex reiview bot |
||||||||
| - Controls available pre-join: `mute-audio`, `mute-video`, `settings`, `join-meeting` | ||||||||
| - `JoinControl.display()` shows a hint like "Unmuted, video on" based on current state | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can u point me to code block where this is ? i dont see this in code base
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||
|
|
||||||||
| #### 3. Device Switching Mid-Meeting | ||||||||
|
|
||||||||
| During an active meeting, users can switch cameras, microphones, or speakers through the settings panel. | ||||||||
|
|
||||||||
| **Key Points:** | ||||||||
|
|
||||||||
| - `SettingsControl.action({ meetingID })` opens the `WebexSettings` modal | ||||||||
| - `SwitchCameraControl.action({ meetingID, cameraId })` calls `switchCamera(meetingID, cameraId)` on the adapter | ||||||||
| - The adapter acquires a new media stream with the selected device and emits an updated `localVideo.stream` | ||||||||
|
|
||||||||
| #### 4. Screen Sharing | ||||||||
|
|
||||||||
| The share button triggers the browser's native screen picker. The SDK handles `getDisplayMedia()` and negotiates the share stream with the backend. | ||||||||
|
|
||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect:
|
||||||||
| **Key Points:** | ||||||||
|
|
||||||||
| - `ShareControl` checks `navigator.mediaDevices.getDisplayMedia` availability | ||||||||
| - If unsupported, the control renders as DISABLED | ||||||||
| - The adapter emits `localShare.stream` with the display stream when sharing starts | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## Three-Repository Architecture | ||||||||
|
|
||||||||
| ```mermaid | ||||||||
| graph LR | ||||||||
| subgraph "Widget" | ||||||||
| W[Meetings Widget] | ||||||||
| end | ||||||||
|
|
||||||||
| subgraph "components" | ||||||||
| C[WebexMeeting & UI] | ||||||||
| end | ||||||||
|
|
||||||||
| subgraph "sdk-component-adapter" | ||||||||
| A[MeetingsSDKAdapter] | ||||||||
| end | ||||||||
|
|
||||||||
| subgraph "webex-js-sdk" | ||||||||
| S[Webex Instance] | ||||||||
| end | ||||||||
|
|
||||||||
| W -->|renders| C | ||||||||
| W -->|creates| A | ||||||||
| W -->|initializes| S | ||||||||
| C -->|uses via AdapterContext| A | ||||||||
| A -->|wraps| S | ||||||||
|
|
||||||||
| style W fill:#e1f5ff,color:#000 | ||||||||
| style C fill:#d4edda,color:#000 | ||||||||
| style A fill:#fff4e1,color:#000 | ||||||||
| style S fill:#ffe1e1,color:#000 | ||||||||
| ``` | ||||||||
|
|
||||||||
|
|
||||||||
|
|
||||||||
|
|
||||||||
| | Repository | Role | Key Exports Used | | ||||||||
| | ----------------------- | ----------------------------------------- | ------------------------------------------------------------------- | | ||||||||
| | `webex-js-sdk` | Core SDK for Webex backend communication | `new Webex()`, `webex.meetings`, meeting methods | | ||||||||
| | `sdk-component-adapter` | Reactive adapter layer (RxJS observables) | `WebexSDKAdapter`, `MeetingsSDKAdapter`, all Control classes | | ||||||||
| | `components` | React UI components + hooks | `WebexMeeting`, `AdapterContext`, `useMeeting`, `useMeetingControl` | | ||||||||
|
|
||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## Dependencies | ||||||||
|
|
||||||||
| **Note:** For exact versions, see [package.json](../package.json) | ||||||||
|
|
||||||||
| ### Runtime Dependencies | ||||||||
|
|
||||||||
|
|
||||||||
| | Package | Purpose | | ||||||||
| | ------------------------------------- | ----------------------------------------------------- | | ||||||||
| | `webex` | Core Webex JavaScript SDK for backend communication | | ||||||||
| | `@webex/sdk-component-adapter` | Reactive adapter that wraps SDK into RxJS observables | | ||||||||
| | `@webex/components` | React UI components for meeting views and controls | | ||||||||
| | `@webex/component-adapter-interfaces` | Interface definitions for component adapters | | ||||||||
|
|
||||||||
|
|
||||||||
| ### Peer Dependencies | ||||||||
|
|
||||||||
|
|
||||||||
| | Package | Purpose | | ||||||||
| | ------------ | ------------------------ | | ||||||||
| | `react` | React framework | | ||||||||
| | `react-dom` | React DOM rendering | | ||||||||
| | `prop-types` | React prop type checking | | ||||||||
| | `webex` | Core Webex SDK (peer) | | ||||||||
|
|
||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing Peer DependenciesThe
Also missing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ADDRESSED |
||||||||
| ## API Reference | ||||||||
|
|
||||||||
| ### WebexMeetingsWidget Props (Public API) | ||||||||
|
|
||||||||
| These are the props consumers pass when using the widget. The widget handles SDK/adapter setup internally. | ||||||||
|
|
||||||||
|
|
||||||||
| | Prop | Type | Required | Default | Description | | ||||||||
| | ---------------------------- | ---------- | -------- | ----------- | ---------------------------------------------------------------------- | | ||||||||
| | `accessToken` | `string` | **Yes** | — | Webex access token for authentication | | ||||||||
| | `meetingDestination` | `string` | **Yes** | — | Meeting URL, SIP address, email, or Personal Meeting Room link | | ||||||||
| | `meetingPasswordOrPin` | `string` | No | `''` | Password or host pin for protected meetings | | ||||||||
| | `participantName` | `string` | No | `''` | Display name for guest participants | | ||||||||
| | `fedramp` | `bool` | No | `false` | Enable FedRAMP-compliant environment | | ||||||||
| | `layout` | `string` | No | `'Grid'` | Remote video layout (`Grid`, `Stack`, `Overlay`, `Prominent`, `Focus`) | | ||||||||
| | `controls` | `Function` | No | `undefined` | Function returning control IDs to render | | ||||||||
| | `controlsCollapseRangeStart` | `number` | No | `undefined` | Zero-based index of the first collapsible control | | ||||||||
| | `controlsCollapseRangeEnd` | `number` | No | `undefined` | Zero-based index before the last collapsible control | | ||||||||
| | `className` | `string` | No | `''` | Custom CSS class for the root element | | ||||||||
| | `style` | `object` | No | `{}` | Inline styles for the root element | | ||||||||
|
|
||||||||
|
|
||||||||
| **Source:** `src/widgets/WebexMeetings/WebexMeetings.jsx` (see `WebexMeetingsWidget.propTypes` and `WebexMeetingsWidget.defaultProps`) | ||||||||
|
|
||||||||
| ### Internal Component Props (WebexMeeting from @webex/components) | ||||||||
|
|
||||||||
| These are passed internally by `WebexMeetingsWidget` to the `WebexMeeting` component from `@webex/components`. Consumers do not interact with these directly. | ||||||||
|
|
||||||||
|
|
||||||||
| | Prop | Type | Description | | ||||||||
| | ---------------------- | ------------- | ------------------------------------------------------- | | ||||||||
| | `meetingID` | `string` | Injected by `withMeeting` HOC from `meetingDestination` | | ||||||||
| | `meetingPasswordOrPin` | `string` | Forwarded from widget prop | | ||||||||
| | `participantName` | `string` | Forwarded from widget prop | | ||||||||
| | `controls` | `Function` | Forwarded from widget prop | | ||||||||
| | `layout` | `string` | Forwarded from widget prop | | ||||||||
| | `logo` | `JSX.Element` | Hard-coded `<WebexLogo />` SVG | | ||||||||
| | `className` | `string` | Always `'webex-meetings-widget__content'` | | ||||||||
|
|
||||||||
|
|
||||||||
| The `WebexMeeting` component receives its adapter via `AdapterContext.Provider`, which is set up by the `withAdapter` HOC wrapping the widget. | ||||||||
|
|
||||||||
| ### Hooks | ||||||||
|
|
||||||||
| **Source:** [`@webex/components`](https://github.com/webex/components) → [`src/components/hooks/`](https://github.com/webex/components/tree/master/src/components/hooks) | ||||||||
|
|
||||||||
|
|
||||||||
| | Hook | Parameters | Returns | Description | | ||||||||
| | ------------------------------------------- | --------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------- | | ||||||||
| | `useMeeting(meetingID)` | `meetingID: string` | Meeting object (see ARCHITECTURE.md for shape) | Subscribes to the adapter's meeting observable | | ||||||||
| | `useMeetingControl(type, meetingID)` | `type: string, meetingID: string` | `[action, display]` (array) | Returns action function and display state for a control | | ||||||||
| | `useMeetingDestination(meetingDestination)` | `meetingDestination: string` | Meeting object | Creates a meeting from destination and subscribes to its observable | | ||||||||
|
|
||||||||
|
|
||||||||
| ### WebexSDKAdapter Methods (top-level adapter) | ||||||||
|
|
||||||||
| **Source:** [`@webex/sdk-component-adapter`](https://github.com/webex/sdk-component-adapter) → [`src/WebexSDKAdapter.js`](https://github.com/webex/sdk-component-adapter/blob/master/src/WebexSDKAdapter.js) | ||||||||
|
|
||||||||
|
|
||||||||
| | Method | Returns | Description | | ||||||||
| | -------------- | --------------- | --------------------------------------------------------------------------------------------------------------- | | ||||||||
| | `connect()` | `Promise<void>` | Calls `sdk.internal.device.register()` → `sdk.internal.mercury.connect()` → `meetingsAdapter.connect()` | | ||||||||
| | `disconnect()` | `Promise<void>` | Calls `meetingsAdapter.disconnect()` → `sdk.internal.mercury.disconnect()` → `sdk.internal.device.unregister()` | | ||||||||
|
|
||||||||
|
|
||||||||
| ### MeetingsSDKAdapter Methods | ||||||||
|
|
||||||||
| **Source:** [`@webex/sdk-component-adapter`](https://github.com/webex/sdk-component-adapter) → [`src/MeetingsSDKAdapter.js`](https://github.com/webex/sdk-component-adapter/blob/master/src/MeetingsSDKAdapter.js) | ||||||||
|
|
||||||||
|
|
||||||||
| | Method | Parameters | Returns | Description | | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still incorrect. This says:
The return control ? [function (value) {
return control.action(meetingID, value);
}, display] : [function () {}, {}];Suggested fix:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. misconception of the codex bot |
||||||||
| | ------------------------------------ | ------------------------------------------------------ | --------------------- | ------------------------------------------------------- | | ||||||||
| | `connect()` | — | `Promise<void>` | Calls `meetings.register()` + `meetings.syncMeetings()` | | ||||||||
| | `disconnect()` | — | `Promise<void>` | Calls `meetings.unregister()` | | ||||||||
| | `createMeeting(destination)` | `destination: string` | `Observable<Meeting>` | Creates a meeting from URL, SIP, or PMR | | ||||||||
| | `joinMeeting(ID, options)` | `ID: string, { password?, name?, hostKey?, captcha? }` | `Promise<void>` | Joins the meeting | | ||||||||
| | `leaveMeeting(ID)` | `ID: string` | `Promise<void>` | Leaves and cleans up the meeting | | ||||||||
| | `handleLocalAudio(ID)` | `ID: string` | `Promise<void>` | Toggles audio mute/unmute | | ||||||||
| | `handleLocalVideo(ID)` | `ID: string` | `Promise<void>` | Toggles video on/off | | ||||||||
| | `handleLocalShare(ID)` | `ID: string` | `Promise<void>` | Toggles screen share on/off | | ||||||||
| | `toggleRoster(ID)` | `ID: string` | `Promise<void>` | Toggles member roster panel (client-side only) | | ||||||||
| | `toggleSettings(ID)` | `ID: string` | `Promise<void>` | Toggles settings modal; applies device changes on close | | ||||||||
| | `switchCamera(ID, cameraID)` | `ID, cameraID: string` | `Promise<void>` | Switches to a different camera device | | ||||||||
| | `switchMicrophone(ID, microphoneID)` | `ID, microphoneID: string` | `Promise<void>` | Switches to a different microphone | | ||||||||
| | `switchSpeaker(ID, speakerID)` | `ID, speakerID: string` | `Promise<void>` | Switches to a different speaker (client-side only) | | ||||||||
|
|
||||||||
|
|
||||||||
| ### Control Action Parameters | ||||||||
|
|
||||||||
| **Source:** [`@webex/sdk-component-adapter`](https://github.com/webex/sdk-component-adapter) → [`src/MeetingsSDKAdapter/controls/`](https://github.com/webex/sdk-component-adapter/tree/master/src/MeetingsSDKAdapter/controls) | ||||||||
|
|
||||||||
| Each control's `action()` receives a destructured object from the [`useMeetingControl`](https://github.com/webex/components/blob/master/src/components/hooks/useMeetingControl.js) hook and calls the corresponding adapter method internally. | ||||||||
|
|
||||||||
| | Control | File | Adapter Method Called | | ||||||||
| | ------------------------- | ---------------------------- | -------------------------------------------- | | ||||||||
| | `AudioControl` | `AudioControl.js` | `handleLocalAudio(meetingID)` | | ||||||||
| | `VideoControl` | `VideoControl.js` | `handleLocalVideo(meetingID)` | | ||||||||
| | `ShareControl` | `ShareControl.js` | `handleLocalShare(meetingID)` | | ||||||||
| | `JoinControl` | `JoinControl.js` | `joinMeeting(meetingID, { password, name })` | | ||||||||
| | `ExitControl` | `ExitControl.js` | `leaveMeeting(meetingID)` | | ||||||||
| | `RosterControl` | `RosterControl.js` | `toggleRoster(meetingID)` | | ||||||||
| | `SettingsControl` | `SettingsControl.js` | `toggleSettings(meetingID)` | | ||||||||
| | `SwitchCameraControl` | `SwitchCameraControl.js` | `switchCamera(meetingID, cameraId)` | | ||||||||
| | `SwitchMicrophoneControl` | `SwitchMicrophoneControl.js` | `switchMicrophone(meetingID, microphoneId)` | | ||||||||
| | `SwitchSpeakerControl` | `SwitchSpeakerControl.js` | `switchSpeaker(meetingID, speakerId)` | | ||||||||
|
|
||||||||
|
|
||||||||
| ### Control IDs for WebexMeetingControlBar | ||||||||
|
|
||||||||
| **Source:** Control IDs are registered in [`@webex/sdk-component-adapter`](https://github.com/webex/sdk-component-adapter) → [`src/MeetingsSDKAdapter.js`](https://github.com/webex/sdk-component-adapter/blob/master/src/MeetingsSDKAdapter.js) and rendered by [`WebexMeetingControlBar`](https://github.com/webex/components/tree/master/src/components/WebexMeetingControlBar) from `@webex/components`. The widget passes them via the `controls` prop. | ||||||||
|
|
||||||||
| | Control ID | Class | Type | Available | | ||||||||
| | ------------------- | ------------------------- | ----------- | --------------------- | | ||||||||
| | `mute-audio` | `AudioControl` | BUTTON | Pre-join + In-meeting | | ||||||||
| | `mute-video` | `VideoControl` | BUTTON | Pre-join + In-meeting | | ||||||||
| | `share-screen` | `ShareControl` | TOGGLE | In-meeting only | | ||||||||
| | `join-meeting` | `JoinControl` | JOIN | Pre-join only | | ||||||||
| | `leave-meeting` | `ExitControl` | CANCEL | In-meeting only | | ||||||||
| | `member-roster` | `RosterControl` | TOGGLE | In-meeting only | | ||||||||
| | `settings` | `SettingsControl` | BUTTON | Pre-join + In-meeting | | ||||||||
| | `switch-camera` | `SwitchCameraControl` | MULTISELECT | Settings panel | | ||||||||
| | `switch-microphone` | `SwitchMicrophoneControl` | MULTISELECT | Settings panel | | ||||||||
| | `switch-speaker` | `SwitchSpeakerControl` | MULTISELECT | Settings panel | | ||||||||
|
|
||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## Installation | ||||||||
| The widget declares `react`, `react-dom`, `prop-types`, and `webex` as **peer dependencies**. Consumers must install them alongside the widget at the versions specified in [package.json](../package.json) under `peerDependencies`. | ||||||||
| ```bash | ||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The installation snippet opens a fenced block with ```````bash Useful? React with 👍 / 👎. |
||||||||
| # yarn | ||||||||
| yarn add @webex/widgets react@<version> react-dom@<version> prop-types@<version> webex@<version> | ||||||||
| # npm | ||||||||
| npm install @webex/widgets react@<version> react-dom@<version> prop-types@<version> webex@<version> | ||||||||
| --- | ||||||||
|
|
||||||||
| ## Additional Resources | ||||||||
|
|
||||||||
| For detailed architecture, event flows, data structures, and troubleshooting, see [ARCHITECTURE.md](./ARCHITECTURE.md). | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| *Last Updated: 2026-03-09* | ||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Path is wrong. This references
ai-docs/AGENTS.mdat the repository root, but that file does not exist. The actual root-level agent file is./AGENTS.md(at the repo root, not inside anai-docs/subfolder).The Codex bot also flagged this same issue.
Suggested fix:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
every tiny mistake, will change