[P3] At a 320 px viewport, Planner stop-table values break mid-number and the Planner dialog scrolls sideways because of the Import plan JSON file input #121

Open
opened 2026-10-31 19:47:41 +00:00 by pedro · 0 comments
Owner

Priority: P3
Type: bug
Source: full codebase review requested 2026-10-31 (independently reproduced against 2cac7cf)

Location: src/style.css:1734-1737, src/style.css:1082-1093, src/planner/DecompressionPlanning.tsx:203-223, src/planner/PlanLibrary.tsx:148-152, src/style.css:1674-1676

Problem and evidence

.schedule-card { min-width: 0; overflow-wrap: anywhere } (style.css:1734-1737) is inherited by the "Required stops" table cells. At 320 px the table gets about 138 px after the nested dialog, panel and card padding, so the browser breaks inside tokens. Stop durations render as "15:0"/"0", "26:0"/"0" and "49:0"/"0", depths render as "70."/"0 ft" or "10.0"/"ft", and headers render as "Sto/p/dep/th". A wrapped duration like "49:0" over "0" can be misread. Separately, the Planner's input[aria-label='Import plan JSON'] (PlanLibrary.tsx:148-152) has no max-width, because the max-width:100% file-input rule only targets .imported-dive-dialog. Its right edge reaches x=346 in a dialog whose right edge is 301, so the planner dialog gets horizontal scroll (scrollWidth 326 > clientWidth 280). The "Remove planned cylinder 1" button reaches x=301, the dialog's border edge. The project's brand guide (docs/BRAND-STYLE-GUIDE.md:138) asks layouts to stay usable at 320 px, so this falls short of a documented target and is not an accepted limitation.

I ran Playwright Chromium against the HEAD production build (/tmp/divesim-review-dist-SqbiNx, served on a temporary port; I stopped the server afterwards). Steps: open Planner Mode, set Segment 1 depth to 150 (ft), set the hold to 40:00, click "Save comparison snapshot", and open every details element. Results at 320x568: both schedule-card tables are 138 px wide. A Range.getClientRects line count per cell showed "70.0 ft" through "10.0 ft" each on 2 lines, "15:00", "26:00" and "49:00" each on 2 lines, and headers on 4-5 lines. The screenshot shows "15:0 / 0", "26:0 / 0", "49:0 / 0", "70. / 0 ft" and "10.0 / ft". Dialog .planner-dialog: scrollWidth 326, clientWidth 280, right edge 301. Import plan JSON input: left 74, right 346. Remove planned cylinder 1: right edge 301. At 390 px the tables are 208 px wide: values stay on one line, but headers still wrap (2-3 lines), and the dialog has no overflow (scrollWidth 350 = clientWidth 350). The document itself does not overflow (documentElement.scrollWidth 320); only the dialog scrolls.

Suggested correction

  1. Stop numeric table cells from breaking inside values. Add .schedule-card td, .schedule-card th { overflow-wrap: normal; } and white-space: nowrap for the depth and duration cells. Optionally let headers use hyphens:auto/normal wrapping.
  2. Wrap the stops table in an overflow-x: auto container, or reduce the nested padding below about 400 px, so the narrow table scrolls instead of splitting values.
  3. Generalize the file-input rule to .advanced-dialog input[type="file"] { max-width: 100%; }, or at least cover .planner-dialog.
  4. Let the planner cylinder fieldset/row shrink (min-width: 0) so the remove button stays inside the content box.

Acceptance criteria

Playwright at 320x568: Planner Mode with a 150 ft / 40:00 air segment, snapshot saved and details opened. Each stop depth and stop duration cell renders on a single line (Range client rects all share one top), or the table sits in a horizontally scrollable container with unbroken values. .planner-dialog has scrollWidth <= clientWidth. The Import plan JSON input's right edge is <= the dialog content's right edge. Add this as a regression check in the narrow-viewport browser suite, alongside the existing 390 px and 1280 px checks. pnpm verify passes.

Scope: maintenance of the educational simulator. Preserve historical R1 acceptance and operational-validation limits.

Priority: P3 Type: bug Source: full codebase review requested 2026-10-31 (independently reproduced against `2cac7cf`) Location: `src/style.css:1734-1737`, `src/style.css:1082-1093`, `src/planner/DecompressionPlanning.tsx:203-223`, `src/planner/PlanLibrary.tsx:148-152`, `src/style.css:1674-1676` Problem and evidence `.schedule-card { min-width: 0; overflow-wrap: anywhere }` (style.css:1734-1737) is inherited by the "Required stops" table cells. At 320 px the table gets about 138 px after the nested dialog, panel and card padding, so the browser breaks inside tokens. Stop durations render as "15:0"/"0", "26:0"/"0" and "49:0"/"0", depths render as "70."/"0 ft" or "10.0"/"ft", and headers render as "Sto/p/dep/th". A wrapped duration like "49:0" over "0" can be misread. Separately, the Planner's `input[aria-label='Import plan JSON']` (PlanLibrary.tsx:148-152) has no max-width, because the `max-width:100%` file-input rule only targets `.imported-dive-dialog`. Its right edge reaches x=346 in a dialog whose right edge is 301, so the planner dialog gets horizontal scroll (scrollWidth 326 > clientWidth 280). The "Remove planned cylinder 1" button reaches x=301, the dialog's border edge. The project's brand guide (docs/BRAND-STYLE-GUIDE.md:138) asks layouts to stay usable at 320 px, so this falls short of a documented target and is not an accepted limitation. I ran Playwright Chromium against the HEAD production build (/tmp/divesim-review-dist-SqbiNx, served on a temporary port; I stopped the server afterwards). Steps: open Planner Mode, set Segment 1 depth to 150 (ft), set the hold to 40:00, click "Save comparison snapshot", and open every details element. Results at 320x568: both schedule-card tables are 138 px wide. A Range.getClientRects line count per cell showed "70.0 ft" through "10.0 ft" each on 2 lines, "15:00", "26:00" and "49:00" each on 2 lines, and headers on 4-5 lines. The screenshot shows "15:0 / 0", "26:0 / 0", "49:0 / 0", "70. / 0 ft" and "10.0 / ft". Dialog .planner-dialog: scrollWidth 326, clientWidth 280, right edge 301. Import plan JSON input: left 74, right 346. Remove planned cylinder 1: right edge 301. At 390 px the tables are 208 px wide: values stay on one line, but headers still wrap (2-3 lines), and the dialog has no overflow (scrollWidth 350 = clientWidth 350). The document itself does not overflow (documentElement.scrollWidth 320); only the dialog scrolls. Suggested correction 1. Stop numeric table cells from breaking inside values. Add `.schedule-card td, .schedule-card th { overflow-wrap: normal; }` and `white-space: nowrap` for the depth and duration cells. Optionally let headers use `hyphens:auto`/normal wrapping. 2. Wrap the stops table in an `overflow-x: auto` container, or reduce the nested padding below about 400 px, so the narrow table scrolls instead of splitting values. 3. Generalize the file-input rule to `.advanced-dialog input[type="file"] { max-width: 100%; }`, or at least cover `.planner-dialog`. 4. Let the planner cylinder fieldset/row shrink (`min-width: 0`) so the remove button stays inside the content box. Acceptance criteria Playwright at 320x568: Planner Mode with a 150 ft / 40:00 air segment, snapshot saved and details opened. Each stop depth and stop duration cell renders on a single line (Range client rects all share one top), or the table sits in a horizontally scrollable container with unbroken values. `.planner-dialog` has scrollWidth <= clientWidth. The Import plan JSON input's right edge is <= the dialog content's right edge. Add this as a regression check in the narrow-viewport browser suite, alongside the existing 390 px and 1280 px checks. pnpm verify passes. Scope: maintenance of the educational simulator. Preserve historical R1 acceptance and operational-validation limits.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: pedro/DiveSim#121
No description provided.