Call layout

The SDK provides built-in call layouts:

  • PaginatedGridLayout - displays participants in a paginated grid
  • SpeakerLayout - dominant speaker/screen share in focus, others in a bar
  • LivestreamLayout - optimized for livestreaming with dominant speaker in large video

Best Practices

  • Use SpeakerLayout for meetings with screen sharing or presentations.
  • Use PaginatedGridLayout for group calls where everyone is equal.
  • Use LivestreamLayout for one-to-many broadcasts.
  • Use filterParticipants to show only relevant participants (e.g., by role).
  • Set muted={true} only when rendering <ParticipantsAudio /> separately.

Preview of the PaginatedGridLayout component.

Preview of the SpeakerLayout component.

Preview of the LivestreamLayout component.

General usage

Layouts gather state via hooks - no state-related props needed:

import "@stream-io/video-react-sdk/dist/css/styles.css";
import {
  CallControls,
  StreamCall,
  StreamTheme,
  StreamVideo,
  SpeakerLayout,
} from "@stream-io/video-react-sdk";

const MyApp = () => {
  return (
    <StreamVideo client={client}>
      <StreamTheme>
        <StreamCall call={call}>
          <SpeakerLayout />
          <CallControls />
        </StreamCall>
      </StreamTheme>
    </StreamVideo>
  );
};
import "@stream-io/video-react-sdk/dist/css/styles.css";
import {
  CallControls,
  StreamCall,
  StreamTheme,
  StreamVideo,
  PaginatedGridLayout,
} from "@stream-io/video-react-sdk";

const MyApp = () => {
  return (
    <StreamVideo client={client}>
      <StreamTheme>
        <StreamCall call={call}>
          <PaginatedGridLayout />
          <CallControls />
        </StreamCall>
      </StreamTheme>
    </StreamVideo>
  );
};

Built-in Layouts

PaginatedGridLayout

Props

NameDescriptionType
groupSizeThe number of participants to display per pagenumber | undefined
excludeLocalParticipantWhether to exclude the local participant from the gridboolean | undefined
filterParticipantsOptional predicate or filter object to determine whether a participant should be displayed in the gridParticipantPredicate | ParticipantFilter | undefined
mirrorLocalParticipantVideoWhether to mirror the user's own video (default true)boolean | undefined
pageArrowsVisibleTurns on/off the pagination arrowsboolean | undefined
mutedMutes all audio. Only use this if you render <Audio /> or <ParticipantsAudio /> manually somewhere else.boolean
ParticipantViewUISee ParticipantView documentationSee ParticipantView documentation
VideoPlaceholderSee ParticipantView documentationSee ParticipantView documentation
PictureInPicturePlaceholderSee ParticipantView documentationSee ParticipantView documentation

Participant filtering

PaginatedGridLayout supports filtering displayed participants either with a predicate function:

// Display only participants with the role "student":
<PaginatedGridLayout
  filterParticipants={(p) => p.roles.includes("student")}
  /* ... */
/>

Or with a special filter object, which is similar in syntax to that of Mongoose:

// Display only participants with either the role "student",
// or that are currently pinned:
<PaginatedGridLayout
  filterParticipants={{
    $or: [{ roles: { $contains: "student" } }, { isPinned: true }],
  }}
/>

SpeakerLayout

Props

NameDescriptionType
participantsBarPositionThe position of the participants who are not in focus, the default is bottom. Providing null will hide the bartop | bottom | left | right | null
excludeLocalParticipantWhether to exclude the local participant from the layoutboolean | undefined
filterParticipantsOptional predicate or filter object to determine whether a participant should be displayed in the layoutParticipantPredicate | ParticipantFilter | undefined
mirrorLocalParticipantVideoWhether to mirror the user's own video (default true)boolean | undefined
pageArrowsVisibleTurns on/off the pagination arrowsboolean | undefined
mutedMutes all audio. Only use this if you render <Audio /> or <ParticipantsAudio /> manually somewhere else.boolean
enableDragToScrollWhether to enable drag to scroll functionality on the participants list.boolean
ParticipantViewUISpotlightThe participant UI for the spotlight view, see ParticipantView documentationSee ParticipantView documentation
ParticipantViewUIBarThe participant UI for the participants in the bar, see ParticipantView documentationSee ParticipantView documentation
VideoPlaceholderSee ParticipantView documentationSee ParticipantView documentation
PictureInPicturePlaceholderSee ParticipantView documentationSee ParticipantView documentation

Participant filtering

SpeakerLayout supports filtering displayed participants either with a predicate function:

// Display only participants with the role "student":
<SpeakerLayout
  filterParticipants={(p) => p.roles.includes("student")}
  /* ... */
/>

Or with a special filter object, which is similar in syntax to that of Mongoose:

// Display only participants with either the role "student",
// or that are currently pinned:
<SpeakerLayout
  filterParticipants={{
    $or: [{ roles: { $contains: "student" } }, { isPinned: true }],
  }}
/>

LivestreamLayout

Props

NameDescriptionType
mutedMutes all audioboolean
enableFullscreenWill render a button to enable fullscreen modeboolean
showParticipantCountWill show the number of participantsboolean
humanizeParticipantCountWill humanize the participant count. E.g.: 1200 -> 1.2kboolean
showDurationWill show the duration of the livestreamboolean
showLiveBadgeWill show a badge whether the livestream is live or notboolean
showSpeakerNameWill show the name of the speakerboolean
showMuteButtonWill show the speaker mute buttonboolean
mirrorLocalParticipantVideoWhether to mirror the user's own video (default true)boolean
floatingParticipantPropsProps to pass to the floating participant viewobject
floatingParticipantProps.positionPosition of the floating participant viewstring

Customization

If the built-in layouts aren't what you're looking for, it's also possible to create your own layout, see our Custom Call Layout guide for more information.