Skip to content

fix(egress-composite): adjust PaginatedGrid sizing#1966

Open
arnautov-anton wants to merge 10 commits intomainfrom
fix/egress-composite/paginated-grid-sizing-and-refactors
Open

fix(egress-composite): adjust PaginatedGrid sizing#1966
arnautov-anton wants to merge 10 commits intomainfrom
fix/egress-composite/paginated-grid-sizing-and-refactors

Conversation

@arnautov-anton
Copy link
Copy Markdown
Contributor

@arnautov-anton arnautov-anton commented Oct 18, 2025

💡 Overview

Ref: https://getstream.slack.com/archives/C090P1YS3U6/p1760375157855869

📝 Implementation notes

As a side-quest this PR refactors styling overrides and adds layers for easier CSS adjustments, removes clsx (in favour of cx from @emotion/css) and replaces decode from js-base64 with atob.

🎫 Ticket: https://linear.app/stream/issue/XYZ-123

📑 Docs: https://github.com/GetStream/docs-content/pull/1204

Summary by CodeRabbit

  • New Features

    • Grid layout size constraints: improved responsive participant sizing in paginated grid layouts (including optimized two-up behavior).
  • Chores

    • Removed unused dependencies and migrated internal styling to a consolidated approach.
    • Reorganized CSS with layered rules and added local stylesheet inclusion.
    • Added global TypeScript declarations to aid local setup and debugging.

@arnautov-anton arnautov-anton force-pushed the fix/egress-composite/paginated-grid-sizing-and-refactors branch 2 times, most recently from 08e2701 to a3f8662 Compare October 18, 2025 08:21
@arnautov-anton arnautov-anton marked this pull request as ready for review October 22, 2025 08:39
@arnautov-anton arnautov-anton force-pushed the fix/egress-composite/paginated-grid-sizing-and-refactors branch from a4d02bd to 1d46205 Compare November 3, 2025 09:07
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 15, 2026

⚠️ No Changeset found

Latest commit: a8bf925

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 37189d90-a94c-4fcb-a142-d69cd2bda74b

📥 Commits

Reviewing files that changed from the base of the PR and between 6a03494 and 53c1cd7.

📒 Files selected for processing (1)
  • sample-apps/react/egress-composite/src/global.d.ts
✅ Files skipped from review due to trivial changes (1)
  • sample-apps/react/egress-composite/src/global.d.ts

📝 Walkthrough

Walkthrough

Replaced clsx with Emotion’s cx, introduced CSS layering via @layer rules, added grid size-constraints config and a data-group-size attribute in the PaginatedGrid layout, removed js-base64 in favor of atob, added global TypeScript window declarations, updated entry imports, and adjusted tests accordingly.

Changes

Cohort / File(s) Summary
Core SDK
packages/react-sdk/src/core/components/CallLayout/PaginatedGridLayout.tsx
Added data-group-size attribute to the rendered group container div.
Dependencies
sample-apps/react/egress-composite/package.json
Removed clsx and js-base64 from dependencies.
SCSS Layering
sample-apps/react/egress-composite/src/main.scss, .../CompositeApp.scss, .../components/LogoAndTitle.scss, .../layouts/DominantSpeaker/*.scss, .../layouts/DominantSpeakerScreenShare.scss, .../layouts/PaginatedGrid/PaginatedGrid.scss, .../layouts/Spotlight/Spotlight.scss
Wrapped existing styles in @layer blocks (video-sdk-layer, base-layer, overrides-layer) and imported SDK styles into a named layer; added responsive/size-constrained rules in PaginatedGrid SCSS.
Class Utility Migration
sample-apps/react/egress-composite/src/CompositeApp.tsx, .../hooks/options/useGenericLayoutStyles.ts, .../useLogoAndTitleStyles.ts, .../useParticipantLabelStyles.ts, .../useParticipantStyles.ts, .../useVideoStyles.ts, sample-apps/react/egress-composite/tests/layouts.spec.ts
Replaced clsx with cx from @emotion/css; consolidated multiple conditional css fragments into single layered blocks and updated composed class usage.
Grid Layout Config
sample-apps/react/egress-composite/src/components/layouts/PaginatedGrid/PaginatedGrid.tsx, sample-apps/react/egress-composite/src/ConfigurationContext.tsx
Added layout.grid.size_constraints option, conditionally apply paginated-grid--size-constrained class; switched JWT payload decode from decode to atob.
Type Augmentation
sample-apps/react/egress-composite/src/global.d.ts
Added global Window augmentations: setupLayout(configuration: ConfigurationValue): void, call: Call, and client: StreamVideoClient.
Entry / Runtime
sample-apps/react/egress-composite/src/main.tsx
Imported local main.scss, removed SDK CSS import, and removed // @ts-expect-error`` comment on window.setupLayout assignment.
Tests
sample-apps/react/egress-composite/tests/layouts.spec.ts
Switched tests to use cx; extended TestCase with optional options and added a grid case enabling layout.grid.size_constraints.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through layers, base to override,
cx stitched classes where clsx once spied,
atob whispers payloads once decoded,
grids learn their sizes, groups now confided,
A rabbit cheers the styles neatly tied! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(egress-composite): adjust PaginatedGrid sizing' accurately summarizes the main change, directly addressing the primary objective of adjusting PaginatedGrid sizing in the egress-composite sample app.
Description check ✅ Passed The description includes Overview, Implementation notes, Ticket, and Docs sections matching the template structure. It provides context via Slack reference and clearly explains the main changes including CSS refactoring, dependency updates, and the size constraints feature flag.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/egress-composite/paginated-grid-sizing-and-refactors

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
packages/react-sdk/src/core/components/CallLayout/PaginatedGridLayout.tsx (1)

35-66: Consider memoizing PaginatedGridLayoutGroup for large participant lists.

This component renders within PaginatedGridLayout and iterates over participants. Wrapping it with React.memo could prevent unnecessary re-renders when parent state changes but props remain the same.

♻️ Optional: Add React.memo
-const PaginatedGridLayoutGroup = ({
+const PaginatedGridLayoutGroup = React.memo(function PaginatedGridLayoutGroup({
   group,
   mirror,
   VideoPlaceholder,
   PictureInPicturePlaceholder,
   ParticipantViewUI,
-}: PaginatedGridLayoutGroupProps) => {
+}: PaginatedGridLayoutGroupProps) {
   return (
     // ... component body unchanged
   );
-};
+});

As per coding guidelines: "Use React.memo for components rendered in large participant lists to optimize re-render performance"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-sdk/src/core/components/CallLayout/PaginatedGridLayout.tsx`
around lines 35 - 66, Wrap the PaginatedGridLayoutGroup component with
React.memo to avoid unnecessary re-renders when its props (group, mirror,
VideoPlaceholder, PictureInPicturePlaceholder, ParticipantViewUI) haven't
changed; locate the PaginatedGridLayoutGroup function and export (or assign) a
memoized version using React.memo(PaginatedGridLayoutGroup) so the component
only re-renders on prop changes while continuing to render ParticipantView for
each participant.sessionId as before.
sample-apps/react/egress-composite/src/hooks/options/useVideoStyles.ts (1)

17-37: Avoid emitting optional overrides with empty values.

This block is always generated, so unset options still serialize background-color / object-fit declarations with no value. Browsers will ignore them, but it makes the generated CSS harder to inspect and diverges from the conditional cx([...]) pattern already used in the sibling option hooks.

♻️ Possible cleanup
   const styles = [
-    css`
-      `@layer` overrides-layer {
-        & .str-video__video {
-          background-color: ${videoBackgroundColor};
-        }
-
-        & .str-video__video {
-          object-fit: ${typeof videoScaleMode === 'undefined'
-            ? undefined
-            : objectFitMap[videoScaleMode]};
-        }
-
-        & .str-video__video.str-video__video--screen-share {
-          object-fit: ${objectFitMap[videoScreenshareScaleMode]};
-        }
-      }
-    `,
+    videoBackgroundColor &&
+      css`
+        `@layer` overrides-layer {
+          & .str-video__video {
+            background-color: ${videoBackgroundColor};
+          }
+        }
+      `,
+    typeof videoScaleMode !== 'undefined' &&
+      css`
+        `@layer` overrides-layer {
+          & .str-video__video {
+            object-fit: ${objectFitMap[videoScaleMode]};
+          }
+        }
+      `,
+    css`
+      `@layer` overrides-layer {
+        & .str-video__video.str-video__video--screen-share {
+          object-fit: ${objectFitMap[videoScreenshareScaleMode]};
+        }
+      }
+    `,
   ];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sample-apps/react/egress-composite/src/hooks/options/useVideoStyles.ts`
around lines 17 - 37, The generated CSS always emits empty
background-color/object-fit declarations; update useVideoStyles to only add the
corresponding css fragments when values are present: check videoBackgroundColor
before adding the block that sets background-color, check typeof videoScaleMode
!== 'undefined' (or presence) before adding the object-fit block that uses
objectFitMap[videoScaleMode], and check videoScreenshareScaleMode before adding
the screenshare object-fit block. Modify the styles array construction (where
css and cx are used) to push these conditional css snippets (or build separate
css calls) so undefined values are never serialized; keep using css, cx,
objectFitMap, videoScaleMode, videoScreenshareScaleMode, and
videoBackgroundColor to locate and change the code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@sample-apps/react/egress-composite/src/components/layouts/Spotlight/Spotlight.scss`:
- Line 12: Insert a blank line immediately above the single-line SCSS comment
"// max-width: unset;" in Spotlight.scss so there is an empty line before that
comment, which will satisfy the stylelint comment-spacing rule; locate the
comment text "// max-width: unset;" and add one empty line above it.

In `@sample-apps/react/egress-composite/src/components/LogoAndTitle.scss`:
- Around line 7-10: Remove the unexpected empty lines before the declarations in
LogoAndTitle.scss: open the selector/block that contains the width and height
properties (the lines with "width" and "height") and delete the blank lines
immediately preceding those declarations so the properties appear directly under
the selector with no empty lines between the selector and "width" and between
"width" and "height".

In `@sample-apps/react/egress-composite/src/CompositeApp.scss`:
- Around line 8-9: The typography block currently violates stylelint rules: add
a blank line before the declarations to satisfy declaration-empty-line-before
and normalize keyword casing for values to satisfy value-keyword-case;
specifically, in CompositeApp.scss update the block containing the
font-synthesis and text-rendering properties so there is an empty line before
those declarations and change the text-rendering value to the linter-expected
case (use lowercase keyword form) while keeping font-synthesis: none as-is.

In `@sample-apps/react/egress-composite/src/global.d.ts`:
- Line 5: The declaration for setupLayout references the type ConfigurationValue
but it isn't imported; update global.d.ts to import ConfigurationValue from
./ConfigurationContext.tsx and then use that imported type in the setupLayout
signature (the symbol names to edit are ConfigurationValue and setupLayout in
global.d.ts, and the source is ConfigurationContext.tsx).

---

Nitpick comments:
In `@packages/react-sdk/src/core/components/CallLayout/PaginatedGridLayout.tsx`:
- Around line 35-66: Wrap the PaginatedGridLayoutGroup component with React.memo
to avoid unnecessary re-renders when its props (group, mirror, VideoPlaceholder,
PictureInPicturePlaceholder, ParticipantViewUI) haven't changed; locate the
PaginatedGridLayoutGroup function and export (or assign) a memoized version
using React.memo(PaginatedGridLayoutGroup) so the component only re-renders on
prop changes while continuing to render ParticipantView for each
participant.sessionId as before.

In `@sample-apps/react/egress-composite/src/hooks/options/useVideoStyles.ts`:
- Around line 17-37: The generated CSS always emits empty
background-color/object-fit declarations; update useVideoStyles to only add the
corresponding css fragments when values are present: check videoBackgroundColor
before adding the block that sets background-color, check typeof videoScaleMode
!== 'undefined' (or presence) before adding the object-fit block that uses
objectFitMap[videoScaleMode], and check videoScreenshareScaleMode before adding
the screenshare object-fit block. Modify the styles array construction (where
css and cx are used) to push these conditional css snippets (or build separate
css calls) so undefined values are never serialized; keep using css, cx,
objectFitMap, videoScaleMode, videoScreenshareScaleMode, and
videoBackgroundColor to locate and change the code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8a1170ea-ab79-41b1-a266-c51228159a95

📥 Commits

Reviewing files that changed from the base of the PR and between 7d8a50d and 6a03494.

⛔ Files ignored due to path filters (8)
  • packages/audio-filters-web/src/krispai/dist/krispsdk.es5.js is excluded by !**/dist/**
  • packages/audio-filters-web/src/krispai/dist/krispsdk.js is excluded by !**/dist/**
  • packages/audio-filters-web/src/krispai/dist/krispsdk.mjs is excluded by !**/dist/**
  • packages/audio-filters-web/src/krispai/dist/usermedia.js is excluded by !**/dist/**
  • packages/audio-filters-web/src/krispai/dist/usermedia.mjs is excluded by !**/dist/**
  • sample-apps/react/egress-composite/tests/__screenshots__/layouts.spec.ts/Layouts-Should-render-layout---grid-1.png is excluded by !**/*.png
  • sample-apps/react/egress-composite/tests/__screenshots__/layouts.spec.ts/Layouts-Should-render-layout---grid-with-size-constraints-1.png is excluded by !**/*.png
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (20)
  • packages/react-sdk/src/core/components/CallLayout/PaginatedGridLayout.tsx
  • sample-apps/react/egress-composite/package.json
  • sample-apps/react/egress-composite/src/CompositeApp.scss
  • sample-apps/react/egress-composite/src/CompositeApp.tsx
  • sample-apps/react/egress-composite/src/ConfigurationContext.tsx
  • sample-apps/react/egress-composite/src/components/LogoAndTitle.scss
  • sample-apps/react/egress-composite/src/components/layouts/DominantSpeaker/DominantSpeaker.scss
  • sample-apps/react/egress-composite/src/components/layouts/DominantSpeaker/DominantSpeakerScreenShare.scss
  • sample-apps/react/egress-composite/src/components/layouts/PaginatedGrid/PaginatedGrid.scss
  • sample-apps/react/egress-composite/src/components/layouts/PaginatedGrid/PaginatedGrid.tsx
  • sample-apps/react/egress-composite/src/components/layouts/Spotlight/Spotlight.scss
  • sample-apps/react/egress-composite/src/global.d.ts
  • sample-apps/react/egress-composite/src/hooks/options/useGenericLayoutStyles.ts
  • sample-apps/react/egress-composite/src/hooks/options/useLogoAndTitleStyles.ts
  • sample-apps/react/egress-composite/src/hooks/options/useParticipantLabelStyles.ts
  • sample-apps/react/egress-composite/src/hooks/options/useParticipantStyles.ts
  • sample-apps/react/egress-composite/src/hooks/options/useVideoStyles.ts
  • sample-apps/react/egress-composite/src/main.scss
  • sample-apps/react/egress-composite/src/main.tsx
  • sample-apps/react/egress-composite/tests/layouts.spec.ts
💤 Files with no reviewable changes (1)
  • sample-apps/react/egress-composite/package.json

Comment thread sample-apps/react/egress-composite/src/components/LogoAndTitle.scss
Comment thread sample-apps/react/egress-composite/src/CompositeApp.scss
Comment thread sample-apps/react/egress-composite/src/global.d.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants