Skip to content

fix(explore): keep the annotation layer modal usable in a small viewport - #42614

Merged
EnxDev merged 7 commits into
masterfrom
enxdev/fix/annotation-layer-modal-overflow-and-slice-config
Jul 30, 2026
Merged

fix(explore): keep the annotation layer modal usable in a small viewport#42614
EnxDev merged 7 commits into
masterfrom
enxdev/fix/annotation-layer-modal-overflow-and-slice-config

Conversation

@EnxDev

@EnxDev EnxDev commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

SUMMARY

Fixes two issues in the Add annotation layer modal that occur after selecting a chart as the annotation source.

Annotation Slice Configuration fields not rendering

fetchSliceData and fetchAppliedChart read the source chart's form data from:

JSON.parse(result.query_context).form_data

However, query_context is a derived cache that is only populated after a chart has been opened in Explore. For charts that have never been opened there, query_context can therefore be null.

Although JSON.parse(null) returns null, accessing .form_data then throws. The promise rejection was not handled, slice was never set, and the Annotation Slice Configuration fields remained hidden, leaving Apply/OK disabled.

Form data is now resolved through a helper that:

  • prefers query_context.form_data when available;
  • falls back to the chart's saved params, which contain the persisted form data;
  • guards parsing failures; and
  • handles request rejections instead of failing silently.

Modal overflowing the viewport

The modal could overflow narrow viewports, particularly when Superset is embedded in an iframe, causing the Display configuration section and Apply/OK actions to become unreachable.

The sections were rendered in an unbounded, non-wrapping flex row. In addition, Ant Design only enables shiftX/shiftY for the four base placements, while ControlPopover uses corner placements that only received { adjustX, adjustY }. These options can flip the popup relative to its trigger, but cannot shift it back inside the viewport when neither side has enough space.

ControlPopover now explicitly enables shifting.

Because rc-trigger's shift calculation discounts popupOffsetX, shifting alone is not sufficient. The section row is therefore also capped to the available space beside the control panel and allowed to wrap when necessary.

The control panel edge is used as the sizing anchor rather than the popover itself, avoiding unstable measurements while the popover width is still responding to its content.

The width constraint only takes effect when space is limited. At normal desktop widths, the natural width remains unchanged and the existing three-column layout is preserved.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Measured in a 1160×859 iframe:

  • Before
before-missing-fields
before-missing-fields.mp4
  • After
after-missing-fields
after-missing-fields.mp4
  • Before
before-overflow
before-overflow.mp4
  • After
after-overflow
after-overflow.mp4

TESTING INSTRUCTIONS

Missing slice configuration fields:

  1. Pick a chart that has never been opened in Explore, so its query_context is still NULL (select id from slices where query_context is null). It must be a viz type that can be an annotation source Table or Table V2 and be owned, created or favourited by you, since the Chart dropdown filters on chart_owned_created_favored_by_me.
  2. Open a Line chart in Explore, expand Annotations and Layers, click Add annotation layer.
  3. Set Annotation layer type to Event and Annotation source to Table, thenselect the chart from step 1.
  4. The Annotation Slice Configuration fields render, with the column list taken from the chart's saved params, and Apply/OK enable once a time column is set. On master the fields never appear and Apply/OK stay disabled.

Viewport overflow:

  1. Embed Superset in an iframe narrower than the browser window (a host page with a sidebar), and repeat steps 2–3 with a source chart that does have a query_context, so the third section appears.
  2. The popover stays inside the iframe on both axes and Apply/OK remain clickable. On master the Display configuration column and Apply/OK are pushed off the right edge.
  3. Repeat at a full desktop width and confirm the three-column layout is unchanged.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

Two defects in the "Add annotation layer" modal, both surfacing when a chart
is picked as the annotation source.

Annotation Slice Configuration fields never rendered
----------------------------------------------------
`fetchSliceData` and `fetchAppliedChart` read the source chart's form data as
`JSON.parse(result.query_context).form_data`. `query_context` is a derived
cache, backfilled the first time a chart is opened in Explore, so a chart that
has never been opened there has `query_context: null`. `JSON.parse(null)`
returns `null`, reading `.form_data` off it throws, the promise rejects
unhandled and `slice` is never set: the fields stay absent and Apply/OK stay
disabled. Nearly every chart is affected, since the column is only ever
populated as a side effect of visiting Explore.

The form data now resolves through a helper that prefers
`query_context.form_data` and falls back to the chart's saved `params`, which
hold the same form data and are always present. Parsing is guarded and both
requests handle rejection instead of failing silently.

Modal overflowed the viewport, hiding Display configuration and Apply/OK
----------------------------------------------------------------------
The sections were laid out in an unbounded, non-wrapping flex row, so the third
one pushed the popover past a narrow viewport - an embedding iframe, typically.
Nothing could recover from it: antd only configures `shiftX`/`shiftY` for the
four base placements, and ControlPopover computes corner placements, which get
`{adjustX, adjustY}` alone. Those can flip a popup across its trigger but never
nudge it back into view, so when neither side fitted the popover simply stayed
off screen with its footer unreachable.

ControlPopover now opts into shifting, so a popup that does not fit is pulled
back rather than left hanging. That alone still leaves `popupOffsetX` behind,
because the shift discounts it, so the section row is additionally capped to the
room left beside the control panel and wraps within it. The panel's edge is the
anchor rather than the popover's own, which trails its content width by several
frames and would feed each cap into the next measurement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dosubot dosubot Bot added change:frontend Requires changing the frontend design:accessibility Related to accessibility standards explore:annotation Related to annotations in Explore labels Jul 30, 2026
@bito-code-review

bito-code-review Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #742a90

Actionable Suggestions - 0
Additional Suggestions - 2
  • superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.test.tsx - 1
    • CWE-1106: Private API dependency in test · Line 27-29
      Direct import from antd internal path `antd/lib/_util/placements` creates a fragile dependency. Internal paths have no semantic versioning guarantee — an antd upgrade could break this test silently or change the function signature. The comment acknowledges this risk but does not mitigate it. Consider using a mock to isolate the test from private API changes.
  • superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.tsx - 1
    • Missing dependency in effect · Line 282-282
      The `useLayoutEffect` at line 1078 uses `hasSliceConfiguration` in its dependency array, but references `slice` from the outer component scope for conditional rendering. Since slice data may change asynchronously after initial render, the effect should re-run to recalculate `sectionsMaxWidth` for the new content.
Review Details
  • Files reviewed - 4 · Commit Range: 8ed97fc..8ed97fc
    • superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
    • superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.tsx
    • superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.test.tsx
    • superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.tsx
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.61905% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.41%. Comparing base (59a5ae0) to head (f0c4097).

Files with missing lines Patch % Lines
...ontrols/AnnotationLayerControl/AnnotationLayer.tsx 97.40% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #42614      +/-   ##
==========================================
+ Coverage   65.40%   65.41%   +0.01%     
==========================================
  Files        2810     2810              
  Lines      159102   159163      +61     
  Branches    36273    36287      +14     
==========================================
+ Hits       104068   104124      +56     
- Misses      52993    52998       +5     
  Partials     2041     2041              
Flag Coverage Δ
javascript 71.49% <97.61%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@amaannawab923 amaannawab923 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.

nice one, this is a solid fix. the params fallback for null query_context makes sense and i like that you added the catch so it stops failing silently. the width stuff is fiddly but reads well and good on you for actually testing it with a mocked ResizeObserver. few thoughts below, none of them blocking.

@amaannawab923 amaannawab923 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.

LGTM !

@apache apache deleted a comment from bito-code-review Bot Jul 30, 2026
@bito-code-review

bito-code-review Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #196b06

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.test.tsx - 1
    • Type mismatch in helper function · Line 257-257
      The `openAt` helper's `placement` parameter is typed as `string`, but the component's `setPlacement` at ControlPopover.tsx:97 expects `TooltipPlacement`. This creates a type gap that could allow invalid placement strings to be passed silently.
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.tsx - 1
Review Details
  • Files reviewed - 6 · Commit Range: 8ed97fc..dc6e048
    • superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
    • superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.tsx
    • superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.test.tsx
    • superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.tsx
    • superset-frontend/src/explore/components/ControlPanelsContainer.tsx
    • superset-frontend/src/explore/constants.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@EnxDev
EnxDev merged commit 473f447 into master Jul 30, 2026
66 checks passed
@EnxDev
EnxDev deleted the enxdev/fix/annotation-layer-modal-overflow-and-slice-config branch July 30, 2026 17:10
@bito-code-review

Copy link
Copy Markdown
Contributor

Bito Automatic Review Skipped – PR Already Merged

Bito scheduled an automatic review for this pull request, but the review was skipped because this PR was merged before the review could be run.
No action is needed if you didn't intend to review it. To get a review, you can type /review in a comment and save it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:frontend Requires changing the frontend design:accessibility Related to accessibility standards explore:annotation Related to annotations in Explore size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants