MeetingRoom
A whole video call: tiles, layouts, people, chat and controls.
SourcePackage @weft-js/warp
Preview
tsx
import { state } from '@weft-js/core'import { Button, Card, Inset, MeetingRoom, Text } from '@weft-js/warp'import type { Participant } from '@weft-js/warp'import type { Invite } from '@weft-js/warp'export function Incident() { const left = state(false) return ( <div style="block-size:560px"> {left.value ? <Card title="You left the incident review" sweep={false}><Button onClick={() => (left.value = false)}>Rejoin</Button></Card> : <MeetingRoom title="Incident review" timer="12:48" recording participants={CALL} self={CALL_SELF} presenter="Sam" shareTitle="Incident timeline" share={SLIDE} chat={CHAT} invite={INVITE} onLeave={() => (left.value = true)} />} </div> )}const CALL: Participant[] = [ { id: 'sam', name: 'Sam Okafor', role: 'host', isSpeaking: true }, { id: 'jun', name: 'Jun Tanaka', isMuted: true }, { id: 'ines', name: 'Inés Vidal' }, { id: 'mara', name: 'Mara Lindqvist', handRaised: true }, { id: 'lena', name: 'Lena Fischer', isMuted: true, network: 'poor' }, { id: 'tomas', name: 'Tomás Oliveira', isCamOn: false },]const CALL_SELF: Participant = { id: 'priya', name: 'Priya Raman' }const CHAT = () => <Inset pad="group"><Text subtle>Sam: the rollback finished at 15:41.</Text></Inset>const SLIDE = () => <Inset pad="section"><Text role="heading">mobile-bff timeline</Text></Inset>const INVITE = () => <Button emphasis="outline" tone="neutral" size="sm" full>Invite people</Button>Installation
npm install @weft-js/warpUsage
tsx
import { MeetingRoom } from '@weft-js/warp'On a phone
compact shows the speaker, and icons only.
tsx
import { Inset, MeetingRoom, Text } from '@weft-js/warp'import type { Participant } from '@weft-js/warp'export function Phone() { return ( <div style="block-size:620px"> <MeetingRoom compact title="Incident review" timer="12:48" participants={CALL} self={CALL_SELF} chat={CHAT} /> </div> )}const CALL: Participant[] = [ { id: 'sam', name: 'Sam Okafor', role: 'host', isSpeaking: true }, { id: 'jun', name: 'Jun Tanaka', isMuted: true }, { id: 'ines', name: 'Inés Vidal' }, { id: 'mara', name: 'Mara Lindqvist', handRaised: true }, { id: 'lena', name: 'Lena Fischer', isMuted: true, network: 'poor' }, { id: 'tomas', name: 'Tomás Oliveira', isCamOn: false },]const CALL_SELF: Participant = { id: 'priya', name: 'Priya Raman' }const CHAT = () => <Inset pad="group"><Text subtle>Sam: the rollback finished at 15:41.</Text></Inset>Accessibility
- Raised hands are announced. Who is speaking is not, or it would never stop.
- warp never touches the camera or microphone: media is yours.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | The heading. |
participants | Participant[] | { value: Participant[]; } | (() => Participant[]) | — | Everyone but you. |
self | Participant | — | You. |
layout | MeetingLayout | State<MeetingLayout> | — | gallery, speaker, presentation or board. |
timer | unknown | — | Elapsed time, already formatted. |
recording | boolean | false | Shows a Rec badge in the header. |
live | string | (() => string) | 'live' | The room's connection. |
compact | boolean | false | For a phone. Unset, it follows the room's width. |
theme | "dark" | "light" | 'dark' | Dark unless you say otherwise. |
video | Video | — | Return the <video> for a participant. |
share | (() => unknown) | — | The shared screen. |
presenter | string | — | Who is sharing. |
shareTitle | string | 'Shared screen' | What is being shared, in the presentation header. Default "Shared screen". |
board | (() => unknown) | — | The whiteboard. |
chat | (() => unknown) | — | The Chat panel. |
invite | (() => unknown) | — | Below People. |
mic | boolean | State<boolean> | — | Whether your mic is on: a state the room writes, or a value with onMic. |
camera | boolean | State<boolean> | — | Whether your camera is on: a state the room writes, or a value with onCamera. |
hand | boolean | State<boolean> | — | Whether your hand is raised: a state the room writes, or a value with onHand. |
sharing | boolean | State<boolean> | — | Whether you are sharing your screen: a state the room writes, or a value with onShare. |
sidebar | "chat" | "people" | State<"chat" | "people" | null> | null | — | The open side panel, people or chat, or null for none. |
reaction | string | '🎉' | The emoji the React button sends. Default 🎉. |
| Event | Type | Default | Description |
|---|---|---|---|
onLayoutChange | ((l: MeetingLayout) => void) | — | Called with the layout picked in the switcher. |
onMic | ((on: boolean) => void) | — | Called with the mic's new state. Start or stop the track here. |
onCamera | ((on: boolean) => void) | — | Called with the camera's new state. Start or stop the track here. |
onHand | ((on: boolean) => void) | — | Called with true when you raise your hand and false when you lower it. |
onShare | ((on: boolean) => void) | — | Called with true to start sharing your screen and false to stop. |
onReact | ((emoji: string) => void) | — | Called with the emoji when you react. |
onLeave | (() => void) | — | Called when Leave is pressed. |
onMore | (() => void) | — | More: replaces the phone's default, which opens the People and Chat panel. |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="call-controls"] [data-part="control"]
controlrootheaderrecspacerstagetilesstripsharerailsidebarapp-barpeople
RelatedTileControl barPrejoin