Skip to content

feat(mapbox): Add widget support to MapboxOverlay via IControl adapter#9963

Open
chrisgervang wants to merge 7 commits intomasterfrom
chr/mapbox-widget-support
Open

feat(mapbox): Add widget support to MapboxOverlay via IControl adapter#9963
chrisgervang wants to merge 7 commits intomasterfrom
chr/mapbox-widget-support

Conversation

@chrisgervang
Copy link
Collaborator

@chrisgervang chrisgervang commented Jan 25, 2026

Closes #9962

Background

Enable deck widgets to coexist with native Mapbox/MapLibre controls without DOM overlap by rendering widgets with viewId: 'mapbox' into the map's control container system via the new _container prop.

Change List

  • Add DeckWidgetControl class that wraps deck widgets as Mapbox IControls
  • Process widgets with viewId: 'mapbox' in MapboxOverlay, automatically wrapping them as IControls
  • Set widget.props._container to Mapbox-positioned element so WidgetManager appends there
  • Widgets stack correctly with native controls in the same DOM container, preventing overlap

Note

Medium Risk
Adds new widget lifecycle/DOM integration to MapboxOverlay that mutates widget.props._container and manages Mapbox controls; regressions could show up as leaked controls, incorrect positioning, or widget rendering issues across setProps/interleaved modes.

Overview
Adds first-class widget support in MapboxOverlay by adapting deck.gl widgets into Mapbox/MapLibre controls. Widgets with viewId: 'mapbox' are now wrapped in a new DeckWidgetControl and added via map.addControl, so they render inside the map’s native control containers (and avoid overlapping the overlay container).

MapboxOverlay now processes widgets before Deck initialization and before deck.setProps, reusing/removing controls by widget id (and only recreating when placement changes) and cleaning them up on onRemove. Tests and mocks were updated to cover widget/control behavior and to stabilize GL usage in overlaid tests.

Written by Cursor Bugbot for commit 287b467. This will update automatically on new commits. Configure here.

@coveralls
Copy link

coveralls commented Jan 25, 2026

Coverage Status

coverage: 91.05% (+0.02%) from 91.033%
when pulling 287b467 on chr/mapbox-widget-support
into 32c5d8d on master.

@chrisgervang chrisgervang mentioned this pull request Jan 25, 2026
62 tasks
@chrisgervang chrisgervang added this to the v9.3 milestone Feb 2, 2026
@chrisgervang chrisgervang force-pushed the chr/mapbox-widget-support branch from 40d85b9 to 9426c8c Compare February 4, 2026 23:24
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

for (const widget of mapboxWidgets) {
const existingControl = existingControlsById.get(widget.id);

if (existingControl && existingControl.widget.placement === widget.placement) {
Copy link

Choose a reason for hiding this comment

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

Placement change undetected for mutated widget objects

Low Severity

The placement comparison existingControl.widget.placement === widget.placement fails to detect placement changes when the same widget object is passed with a mutated placement property. After setWidget(widget) is called in a previous iteration, existingControl.widget becomes the same reference as the current widget. When both sides of the comparison reference the same object, the comparison is trivially true regardless of whether placement was actually changed. The control remains in its original map position even though the widget's placement changed.

Fix in Cursor Fix in Web

chrisgervang and others added 7 commits February 27, 2026 11:08
Enable deck widgets to coexist with native Mapbox/MapLibre controls without
DOM overlap by rendering widgets with viewId: 'mapbox' into the map's control
container system.

- Add DeckWidgetControl class that wraps deck widgets as IControls
- Process widgets with viewId: 'mapbox' in MapboxOverlay
- Set widget._container to Mapbox-positioned element via IControl
- Widgets stack correctly with native controls in same container

Closes #9962

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add TestWidget class for testing widget integration
- Test regular widgets render in deck container
- Test widgets with viewId: 'mapbox' are wrapped as IControl
- Test mixed widgets (regular + mapbox)
- Test setProps updates widget controls
- Test interleaved mode widget support
- Update mock map to support control positions and hasControl

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Overlaid mode tests create their own Deck instances which can cause GL
context corruption when sharing contexts across tests. Using an isolated
WebGLDevice for these tests prevents hangs in the test suite.

Co-Authored-By: Claude (global.anthropic.claude-opus-4-5-20251101-v1:0) <noreply@anthropic.com>
…d rootElement

When setProps was called with widgets, _processWidgets would destroy and
recreate all DeckWidgetControls. This removed the container from the DOM,
orphaning the widget's rootElement since WidgetManager wouldn't re-attach
it (same widget id means no change detected).

Now matches widgets by id (like WidgetManager) and only recreates controls
when the widget is new or placement changes. For existing widgets with same
id and placement, the container is preserved and copied to the new widget
instance to support React patterns where widgets are recreated on render.

Co-Authored-By: Claude (global.anthropic.claude-opus-4-5-20251101-v1:0) <noreply@anthropic.com>
Co-Authored-By: Claude (global.anthropic.claude-opus-4-5-20251101-v1:0) <noreply@anthropic.com>
Co-Authored-By: Claude (global.anthropic.claude-opus-4-5-20251101-v1:0) <noreply@anthropic.com>
When _processWidgets reuses a DeckWidgetControl for a new widget instance
with the same id and placement, the control's internal _widget reference
must be updated. Otherwise the control references the old widget, causing
incorrect behavior in onRemove() and potential memory leaks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang chrisgervang force-pushed the chr/mapbox-widget-support branch from 79355a6 to 287b467 Compare February 27, 2026 19:08
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.

feat(mapbox): Add widget support to MapboxOverlay via IControl adapter

2 participants