fix(dashboard): hidden widgets render at proper size in edit mode (t-paliad-238) #74

Open
mAi wants to merge 0 commits from mai/tesla/dashboard-resize-clamp into main
Collaborator

Symptom

m 2026-05-22 15:41: "Resizing my dashboard layout lead to an error where now I have some super slim columns which I can move but not resize - and they seem greyed out."

No Gitea issue filed yet — head dispatched this as task t-paliad-238 directly. Filing an issue retro-actively if needed.

Root cause

Hidden widgets in edit mode were rendering as 1×1 slivers because applyLayout left their inline grid-column empty — placeWidgets skipped non-visible entries entirely, so CSS Grid auto-flowed them into the next free cell at 1/12 width.

  • Super slim — 1/12 of the grid (no grid-column inline → auto-flow as 1×1).
  • Can move but not resizerebuildEditChrome correctly omits the resize handle for hidden widgets (line 940-943); this is intentional UX (un-hide before resizing).
  • Greyed outdashboard-widget--hidden class adds opacity: 0.45.

The last two are correct signals that a widget is hidden. The slim rendering was the bug. Resize itself never changed visibility — the user likely hit × at some point (deliberately or accidentally) and saw the result on the next edit-mode entry.

Fix

Frontend (frontend/src/client/dashboard-grid.ts)

  • placeWidgets() gains a {includeHidden} option.
  • When true, a second pass places hidden widgets after the visible pass — collision-aware + cursor-aware so the hidden tray stacks below the active layout. Visible widgets always claim their cells first.
  • applyLayout() passes includeHidden: editMode.
  • materializePositions() keeps the default (hidden widgets retain stored coordinates so un-hiding restores them in place).

Backend (internal/services/dashboard_layout_spec.go)

  • SanitizeForRead now also clamps each widget's W/H/X against the catalog MinW/MaxW/MinH/MaxH + grid bounds on load. Stale rows with W below MinW (or above MaxW, or X+W overflowing the grid) heal on the next GET /api/me/dashboard-layout and the cleaned spec is persisted back.
  • W=0 stays 0 (auto/default sentinel — the placer expands it).
  • The validator stays strict on write; the read-path sanitiser only exists to recover users who got into a bad state under earlier rules.

Recovery for m

If m's saved layout already has out-of-range sizes, the next /api/me/dashboard-layout GET will heal them and persist the cleaned spec back. He should see proper rendering on reload.

Tests

  • bun (frontend): 4 new cases in dashboard-grid.test.ts pin includeHidden behaviour. All 103 frontend tests pass.
  • go (backend): 7 sub-tests in dashboard_layout_spec_test.go cover each SanitizeForRead clamp plus a round-trip Validate guarantee. All ./internal/... tests pass.
  • boot smoke: go test ./cmd/server/... clean.
  • builds: go build ./... + bun run build clean.

Test plan

  • bun test 103/103
  • go test ./internal/... ./cmd/server/... clean
  • go build ./... + bun run build clean
  • Manual: hide a widget, reload in edit mode, confirm hidden widget renders at proper size in the hidden tray below the active layout
## Symptom m 2026-05-22 15:41: *"Resizing my dashboard layout lead to an error where now I have some super slim columns which I can move but not resize - and they seem greyed out."* No Gitea issue filed yet — head dispatched this as task t-paliad-238 directly. Filing an issue retro-actively if needed. ## Root cause Hidden widgets in edit mode were rendering as 1×1 slivers because `applyLayout` left their inline `grid-column` empty — `placeWidgets` skipped non-visible entries entirely, so CSS Grid auto-flowed them into the next free cell at 1/12 width. - **Super slim** — 1/12 of the grid (no grid-column inline → auto-flow as 1×1). - **Can move but not resize** — `rebuildEditChrome` correctly omits the resize handle for hidden widgets (line 940-943); this is intentional UX (un-hide before resizing). - **Greyed out** — `dashboard-widget--hidden` class adds `opacity: 0.45`. The last two are correct signals that a widget is hidden. The slim rendering was the bug. Resize itself never changed visibility — the user likely hit × at some point (deliberately or accidentally) and saw the result on the next edit-mode entry. ## Fix ### Frontend (`frontend/src/client/dashboard-grid.ts`) - `placeWidgets()` gains a `{includeHidden}` option. - When true, a **second pass** places hidden widgets after the visible pass — collision-aware + cursor-aware so the hidden tray stacks below the active layout. Visible widgets always claim their cells first. - `applyLayout()` passes `includeHidden: editMode`. - `materializePositions()` keeps the default (hidden widgets retain stored coordinates so un-hiding restores them in place). ### Backend (`internal/services/dashboard_layout_spec.go`) - `SanitizeForRead` now also clamps each widget's `W`/`H`/`X` against the catalog `MinW`/`MaxW`/`MinH`/`MaxH` + grid bounds on load. Stale rows with `W` below `MinW` (or above `MaxW`, or `X+W` overflowing the grid) heal on the next `GET /api/me/dashboard-layout` and the cleaned spec is persisted back. - `W=0` stays `0` (auto/default sentinel — the placer expands it). - The validator stays strict on write; the read-path sanitiser only exists to recover users who got into a bad state under earlier rules. ### Recovery for m If m's saved layout already has out-of-range sizes, the next `/api/me/dashboard-layout` GET will heal them and persist the cleaned spec back. He should see proper rendering on reload. ## Tests - **bun (frontend)**: 4 new cases in `dashboard-grid.test.ts` pin `includeHidden` behaviour. All 103 frontend tests pass. - **go (backend)**: 7 sub-tests in `dashboard_layout_spec_test.go` cover each `SanitizeForRead` clamp plus a round-trip `Validate` guarantee. All `./internal/...` tests pass. - **boot smoke**: `go test ./cmd/server/...` clean. - **builds**: `go build ./...` + `bun run build` clean. ## Test plan - [x] `bun test` 103/103 - [x] `go test ./internal/... ./cmd/server/...` clean - [x] `go build ./...` + `bun run build` clean - [ ] Manual: hide a widget, reload in edit mode, confirm hidden widget renders at proper size in the hidden tray below the active layout
mAi added 1 commit 2026-05-22 13:52:12 +00:00
Symptom (m, 2026-05-22): "super slim columns which I can move but not
resize - and they seem greyed out." Hidden widgets in edit mode were
rendering as 1×1 slivers because applyLayout left their inline grid-
column empty — placeWidgets skipped non-visible entries entirely, so
CSS Grid auto-flowed them into the next free cell at 1/12th width.
The greyed-out + no-resize-handle parts were correct UX signalling
that the widget is hidden; the slim rendering was the bug.

Fix:
- placeWidgets() gains a {includeHidden} option. When true, a second
  pass places hidden widgets after the visible pass — collision-aware
  + cursor-aware so the hidden tray stacks below the active layout
  without ever displacing a visible widget. applyLayout() passes
  includeHidden:true in edit mode.
- materializePositions() keeps the default (hidden widgets retain
  their stored coordinates so un-hiding restores them in place).

Server-side recovery (m/paliad#73 belt-and-braces):
- SanitizeForRead now also clamps each widget's W/H/X against the
  catalog Min/Max + grid bounds on load. Stale rows with W below MinW
  (or above MaxW, or X+W overflowing the grid) heal on the next
  /api/me/dashboard-layout GET and the cleaned spec is persisted
  back. W=0 stays 0 (auto/default sentinel — the placer expands it).
- The validator stays strict on write; the read-path sanitiser only
  exists to recover users who got into a bad state under the old
  rules.

Tests:
- bun: 4 new cases in dashboard-grid.test.ts pin includeHidden
  behaviour (hidden skipped by default, two-pass ordering, multi-
  hidden, no-overlap invariant).
- go: 7 sub-tests in dashboard_layout_spec_test.go cover each
  SanitizeForRead clamp (MinW, MaxW, grid-width, MaxH, X+W overflow,
  W=0 sentinel, negative X) plus a round-trip Validate guarantee.
mAi changed title from fix(dashboard): t-paliad-238 — hidden widgets render at proper size in edit mode to fix(dashboard): hidden widgets render at proper size in edit mode (t-paliad-238) 2026-05-22 13:52:57 +00:00
m force-pushed mai/tesla/dashboard-resize-clamp from d5b3652963 to 4cd2f05d33 2026-05-22 13:53:22 +00:00 Compare
This branch is already included in the target branch. There is nothing to merge.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin mai/tesla/dashboard-resize-clamp:mai/tesla/dashboard-resize-clamp
git checkout mai/tesla/dashboard-resize-clamp
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#74
No description provided.