vercel-labs / vercel-labs/native
Per-view widget layout budget (1024 nodes) drops whole frames on real multi-pane app views
Nobody has claimed this yet.
- Dominant language
- Zig
- Stars
- 7.7k
- Forks
- 314
- Avg merge
- 5h
- Merged PRs (30d)
- 13
Description
Symptom
A production three-pane desktop app built on the SDK hits WidgetLayoutListFull on ordinary interactions. The layout-retention failure drops the whole frame: opening a dialog, or clicking controls in a large view, leaves the UI visually unchanged — buttons appear dead. Once a view is over budget, the error fires on every invalidated frame, wedging the view's interactions entirely.
Evidence
View composition (real app, nothing exotic):
- a session rail enumerating ~50 session rows,
- a detail timeline retaining the full transcript,
- a model-picker dialog listing ~60 model rows with provider-group headers.
Automation snapshot of the dialog frame: 1008 widgets. The retained node count runs ≈1.8 nodes per widget (each row widget carries inner rows/columns/text), so the frame needs ~1800 nodes — well past the 1024 cap in canvas_limits.max_canvas_widget_nodes_per_view. The error path is adoptWidgetLayout → WidgetLayoutListFull → the rebuild never lands and the whole frame is discarded.
The current comment sizes 1024 against "the measured worst realistic three-pane view is ~500 nodes". That estimate predates list-dense surfaces: any app whose rails/dialogs enumerate unbounded collections (sessions, models, files) crosses 1024 with a single dialog open on top of the base chrome. The failure mode is much worse than the budget's "fail loudly" intent — it doesn't reject an operation, it silently kills every subsequent frame for the view.
Proposed fix
Raise the budget 1024 → 4096 (and automation.snapshot.max_widgets_per_view in lockstep; the existing lockstep test in canvas_widget_layout_tests.zig keeps them equal). These are validation bounds over fixed-capacity address space — pages are only touched as views use capacity — so the raise costs address space, not committed memory. PR to follow.
Longer term, apps retaining unbounded collections will outgrow any fixed cap; windowed/virtualized retention for list widgets would remove the cliff entirely. Happy to file a separate issue for that discussion if useful.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with canvas_limits.max_canvas_widget_nodes_per_view and the automation.snapshot.max_widgets_per_view definitions, then read the lockstep test in canvas_widget_layout_tests.zig. Reproduce or inspect the existing capacity validation and update both bounds consistently. Done means the test still verifies equality and a three-pane view needing roughly 1800 retained nodes no longer hits WidgetLayoutListFull.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- zig
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100