Skip to content

Fix: Add minimum horizontal padding to prevent content cutoff at narrow viewport widths - #1073

Merged
JamesPHoughton merged 2 commits into
mainfrom
copilot/set-minimum-x-padding-margin
Oct 30, 2025
Merged

Fix: Add minimum horizontal padding to prevent content cutoff at narrow viewport widths#1073
JamesPHoughton merged 2 commits into
mainfrom
copilot/set-minimum-x-padding-margin

Conversation

Copilot AI commented Oct 23, 2025

Copy link
Copy Markdown
Contributor

Problem

When the browser window width shrinks below a certain point, content runs directly against the viewport edges. This is particularly problematic for:

  • Slider labels that get cut off (e.g., "Strongly Disagree" and "Strongly Agree" labels)
  • General content readability and visual comfort
  • Mobile and narrow viewport experiences

Solution

Added responsive horizontal padding to the main player container in App.jsx. The fix applies progressive padding that scales with viewport size:

// Before
className="h-screen relative overflow-auto"

// After
className="h-screen relative overflow-auto px-4 sm:px-6 md:px-8"

This provides:

  • 16px padding on mobile/narrow viewports (default)
  • 24px padding on small screens (≥640px)
  • 32px padding on medium and larger screens (≥768px)

Why This Approach?

This is the most straightforward solution because:

  1. Single point of change - Only one line modified in one file
  2. Framework-native - Uses existing WindiCSS utility classes
  3. Responsive by design - Automatically scales appropriately for different screen sizes
  4. Non-invasive - Doesn't require changes to absolute positioning logic in child components
  5. Consistent - Ensures uniform spacing across all pages (intro, game, exit)

Alternative approaches (adding margins to individual components, global CSS rules, or wrapper containers) would have required more extensive changes across multiple files.

Visual Demonstration

Narrow Viewport (400px wide)

Narrow viewport comparison

Before (top): Slider labels are cut off at the edges, making "Strongly Disagree" and "Strongly Agree" partially invisible.

After (bottom): All content has proper breathing room with 16px padding on each side, ensuring full visibility of all elements.

Wide Viewport (1024px wide)

Wide viewport comparison

The responsive padding automatically increases to 32px on wider screens, maintaining optimal spacing while efficiently using available screen real estate.

Testing

  • ✅ Verified at multiple viewport widths (320px, 400px, 768px, 1024px, 1440px)
  • ✅ Slider labels remain fully visible at all sizes
  • ✅ No linting errors introduced
  • ✅ No security vulnerabilities (CodeQL analysis passed)
  • ✅ All existing functionality preserved

Fixes #[issue_number]

Original prompt

This section details on the original issue you should resolve

<issue_title>[Bug]: Set minimum x-padding or margin</issue_title>
<issue_description>### What happened?

When the window width shrinks below a certain point, the content runs right up against the sides of the browser window. Sometimes (e.g. with slider labels) this means we can't see some of the content that maybe spills out a bit. I guess we want some minimum amount of white space on the edges. I don't know if this needs to be padding or margin or what, or where it should sit in the component hierarchy.

What browsers do you see the problem on?

  • Firefox
  • Chrome
  • Safari
  • Microsoft Edge

What operating system do you see the problem on?

  • Windows
  • Mac
  • Linux

How did we discover the bug?

  • Reported by participant
  • Observed on Sentry
  • Found in dev

Priority

Inconvenience for participants</issue_description>

<agent_instructions>Diagnose the problem and provide a detailed breakdown of different options for solving it, then recommend the most straightforward.</agent_instructions>

Comments on the Issue (you are @copilot in this section)

Fixes #1072


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: JamesPHoughton <4304478+JamesPHoughton@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix minimum x-padding or margin for content Fix: Add minimum horizontal padding to prevent content cutoff at narrow viewport widths Oct 23, 2025
Copilot AI requested a review from JamesPHoughton October 23, 2025 01:48
@github-actions

Copy link
Copy Markdown
/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/call/Call.jsx
   38:19  error  Do not nest ternary expressions                                                                        no-nested-ternary
  151:5   error  Do not nest ternary expressions                                                                        no-nested-ternary
  202:32  error  Unexpected block statement surrounding arrow body; move the returned value immediately after the '=>'  arrow-body-style
  266:18  error  Do not use Array index in keys                                                                         react/no-array-index-key

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/ConditionalRender.jsx
  39:10  error  'tickTock' is assigned a value but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/IdleProvider.jsx
   56:6   warning  React Hook useEffect has a missing dependency: 'resetTimer'. Either include it or remove the dependency array  react-hooks/exhaustive-deps
  120:57  error    ''' can be escaped with '&apos;', '&lsquo;', '&#39;', '&rsquo;'                                                react/no-unescaped-entities

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/Markdown.jsx
  17:6  error  Unnecessary escape character: !  no-useless-escape

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/SharedNotepad.jsx
  26:6  warning  React Hook useEffect has missing dependencies: 'defaultText', 'game', and 'record'. Either include them or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/TextChat.jsx
   71:6  warning  React Hook useEffect has a missing dependency: 'msgs.length'. Either include it or remove the dependency array  react-hooks/exhaustive-deps
  182:7  warning  Unexpected alert                                                                                                no-alert
  219:7  error    A control must be associated with a text label                                                                  jsx-a11y/control-has-associated-label

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/elements/KitchenTimer.jsx
  9:10  error  'tickTock' is assigned a value but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/elements/Qualtrics.jsx
  54:10  error  'state' is assigned a value but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/elements/TrainingVideo.jsx
  61:6  warning  React Hook useEffect has missing dependencies: 'timer?.elapsed' and 'url'. Either include them or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/Consent.jsx
  129:6  warning  React Hook useEffect has a missing dependency: 'player'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/Countdown.jsx
  8:21  error  Use default import syntax to import 'ReactCountdown'  import/no-named-default

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/setup/CameraCheck.jsx
  96:6  warning  React Hook useEffect has a missing dependency: 'devices'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/setup/LoopbackCheck.jsx
  132:34  error    Return values from promise executor functions cannot be read                                               no-promise-executor-return
  162:6   warning  React Hook useEffect has a missing dependency: 'player'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/setup/MicCheck.jsx
  118:6  warning  React Hook useEffect has a missing dependency: 'devices'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/cypress/e2e/01_Normal_Paths_Omnibus.js
  174:34  error  'actualOrder' is already declared in the upper scope on line 155 column 13  no-shadow
  201:31  error  'newOrder' is already declared in the upper scope on line 190 column 13     no-shadow

/home/runner/work/deliberation-empirica/deliberation-empirica/cypress/support/sharedSteps.js
  8:9  error  'log' is assigned a value but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/getTreatments.js
    8:33  error  Missing file extension for "./preFlight/validateTreatmentFile"  import/extensions
  327:30  error  Unexpected 'await' inside a loop                                no-await-in-loop

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/index.js
  42:43  error  'p' is defined but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/postFlight/exportScienceData.js
  4:17  error  'warn' is defined but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/preFlight/dispatch.js
  477:9  error  Unexpected use of continue statement  no-continue

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/preFlight/preFlightChecks.js
  20:5  error  iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations  no-restricted-syntax

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/preFlight/validateDlConfig.test.js
  2:32  error  Missing file extension for "./validateDlConfig"                                                                            import/extensions
  3:1   error  'vscode' import should occur before import of './validateDlConfig'                                                         import/order
  6:25  error  Unexpected block statement surrounding arrow body; parenthesize the returned value and move it immediately after the '=>'  arrow-body-style

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/preFlight/validatePromptFile.test.js
  7:8  error  Missing file extension for "./validatePromptFile"  import/extensions

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/providers/dailyco.js
   37:23  error  Expected to return a value at the end of async function 'createRoom'     consistent-return
  157:23  error  Expected to return a value at the end of async function 'stopRecording'  consistent-return
  229:7   error  Unexpected if as the only statement in an else block                     no-lonely-if

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/utils/logging.js
  1:17  error  'warn' is defined but never used  no-unused-vars
  1:29  error  'log' is defined but never used   no-unused-vars

✖ 39 problems (30 errors, 9 warnings)
  4 errors and 0 warnings potentially fixable with the '--fix' option.

1 similar comment
@github-actions

Copy link
Copy Markdown
/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/call/Call.jsx
   38:19  error  Do not nest ternary expressions                                                                        no-nested-ternary
  151:5   error  Do not nest ternary expressions                                                                        no-nested-ternary
  202:32  error  Unexpected block statement surrounding arrow body; move the returned value immediately after the '=>'  arrow-body-style
  266:18  error  Do not use Array index in keys                                                                         react/no-array-index-key

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/ConditionalRender.jsx
  39:10  error  'tickTock' is assigned a value but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/IdleProvider.jsx
   56:6   warning  React Hook useEffect has a missing dependency: 'resetTimer'. Either include it or remove the dependency array  react-hooks/exhaustive-deps
  120:57  error    ''' can be escaped with '&apos;', '&lsquo;', '&#39;', '&rsquo;'                                                react/no-unescaped-entities

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/Markdown.jsx
  17:6  error  Unnecessary escape character: !  no-useless-escape

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/SharedNotepad.jsx
  26:6  warning  React Hook useEffect has missing dependencies: 'defaultText', 'game', and 'record'. Either include them or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/components/TextChat.jsx
   71:6  warning  React Hook useEffect has a missing dependency: 'msgs.length'. Either include it or remove the dependency array  react-hooks/exhaustive-deps
  182:7  warning  Unexpected alert                                                                                                no-alert
  219:7  error    A control must be associated with a text label                                                                  jsx-a11y/control-has-associated-label

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/elements/KitchenTimer.jsx
  9:10  error  'tickTock' is assigned a value but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/elements/Qualtrics.jsx
  54:10  error  'state' is assigned a value but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/elements/TrainingVideo.jsx
  61:6  warning  React Hook useEffect has missing dependencies: 'timer?.elapsed' and 'url'. Either include them or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/Consent.jsx
  129:6  warning  React Hook useEffect has a missing dependency: 'player'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/Countdown.jsx
  8:21  error  Use default import syntax to import 'ReactCountdown'  import/no-named-default

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/setup/CameraCheck.jsx
  96:6  warning  React Hook useEffect has a missing dependency: 'devices'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/setup/LoopbackCheck.jsx
  132:34  error    Return values from promise executor functions cannot be read                                               no-promise-executor-return
  162:6   warning  React Hook useEffect has a missing dependency: 'player'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/client/src/intro-exit/setup/MicCheck.jsx
  118:6  warning  React Hook useEffect has a missing dependency: 'devices'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

/home/runner/work/deliberation-empirica/deliberation-empirica/cypress/e2e/01_Normal_Paths_Omnibus.js
  174:34  error  'actualOrder' is already declared in the upper scope on line 155 column 13  no-shadow
  201:31  error  'newOrder' is already declared in the upper scope on line 190 column 13     no-shadow

/home/runner/work/deliberation-empirica/deliberation-empirica/cypress/support/sharedSteps.js
  8:9  error  'log' is assigned a value but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/getTreatments.js
    8:33  error  Missing file extension for "./preFlight/validateTreatmentFile"  import/extensions
  327:30  error  Unexpected 'await' inside a loop                                no-await-in-loop

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/index.js
  42:43  error  'p' is defined but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/postFlight/exportScienceData.js
  4:17  error  'warn' is defined but never used  no-unused-vars

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/preFlight/dispatch.js
  477:9  error  Unexpected use of continue statement  no-continue

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/preFlight/preFlightChecks.js
  20:5  error  iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations  no-restricted-syntax

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/preFlight/validateDlConfig.test.js
  2:32  error  Missing file extension for "./validateDlConfig"                                                                            import/extensions
  3:1   error  'vscode' import should occur before import of './validateDlConfig'                                                         import/order
  6:25  error  Unexpected block statement surrounding arrow body; parenthesize the returned value and move it immediately after the '=>'  arrow-body-style

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/preFlight/validatePromptFile.test.js
  7:8  error  Missing file extension for "./validatePromptFile"  import/extensions

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/providers/dailyco.js
   37:23  error  Expected to return a value at the end of async function 'createRoom'     consistent-return
  157:23  error  Expected to return a value at the end of async function 'stopRecording'  consistent-return
  229:7   error  Unexpected if as the only statement in an else block                     no-lonely-if

/home/runner/work/deliberation-empirica/deliberation-empirica/server/src/utils/logging.js
  1:17  error  'warn' is defined but never used  no-unused-vars
  1:29  error  'log' is defined but never used   no-unused-vars

✖ 39 problems (30 errors, 9 warnings)
  4 errors and 0 warnings potentially fixable with the '--fix' option.

@cypress

cypress Bot commented Oct 23, 2025

Copy link
Copy Markdown

Deliberation    Run #1792

Run Properties:  status check passed Passed #1792  •  git commit 49f92c4dc3: Add horizontal padding to prevent content from touching viewport edges
Project Deliberation
Branch Review copilot/set-minimum-x-padding-margin
Run status status check passed Passed #1792
Run duration 12m 47s
Commit git commit 49f92c4dc3: Add horizontal padding to prevent content from touching viewport edges
Committer copilot-swe-agent[bot]
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 1
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 16
View all changes introduced in this branch ↗︎

@JamesPHoughton
JamesPHoughton marked this pull request as ready for review October 23, 2025 13:17
@JamesPHoughton
JamesPHoughton merged commit c7e13e9 into main Oct 30, 2025
14 of 17 checks passed
@JamesPHoughton
JamesPHoughton deleted the copilot/set-minimum-x-padding-margin branch October 30, 2025 20:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds responsive horizontal padding to the main player container in the application. The change applies Tailwind CSS utility classes to implement a responsive padding pattern that scales with screen size.

  • Adds responsive horizontal padding to the root player container using Tailwind CSS classes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread client/src/App.jsx
const renderPlayer = (playerKey) => (
<div
className="h-screen relative overflow-auto"
className="h-screen relative overflow-auto px-4 sm:px-6 md:px-8"

Copilot AI Oct 30, 2025

Copy link

Choose a reason for hiding this comment

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

Adding horizontal padding to the root player container may conflict with existing absolute positioning patterns used in child components. The Game component at line 38 uses absolute top-12 left-0 right-0 bottom-0 m-2, and GenericIntroExitStep at line 55 uses absolute top-12 bottom-0 left-0 right-0. These absolute positioned children with left-0 and right-0 will extend beyond the parent's padding, potentially causing layout inconsistencies. Consider reviewing how these absolute positioned children interact with the new padding.

Suggested change
className="h-screen relative overflow-auto px-4 sm:px-6 md:px-8"
className="h-screen relative overflow-auto"

Copilot uses AI. Check for mistakes.
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.

[Bug]: Set minimum x-padding or margin

3 participants