Skip to content

Premium Analytics: pin the dashboard section header and condense it on scroll - #51232

Merged
retrofox merged 14 commits into
trunkfrom
update/sticky-section-header
Aug 16, 2026
Merged

retrofox merged 14 commits into
trunkfrom
update/sticky-section-header

Conversation

@retrofox

@retrofox retrofox commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

Proposed changes

On trunk, the dashboard scrolls in the boot stage, above Page, and everything rides along: the section header with its date controls, the tabs, and eventually the page header itself. Page's header is sticky in @wordpress/admin-ui, but .page is height: 100%, one viewport tall, so against that outer scroll the header holds only for the first viewport and then slides off with it.

With this PR, the section panel scrolls in its own container, under the page header:

  • The page header sits above the scroll container and never moves.
  • The section tabs scroll away with the content.
  • The section header (title, subtitle, date controls) pins under the page header and, over the next 40px of scroll, condenses into a compact bar: the subtitle fades out and gives its row back, the padding tightens, and the title drops a step on the type scale. Pinned chrome goes from 190px to 146px.

How it works

The sections root is the section's scroll container, so the page header stays out of the scroll flow entirely and the sticky section header never runs out of containing block, however long the widget grid is.

The condensing is a CSS scroll-driven animation. SectionHeader has a new opt-in condenseOnScroll prop, off by default. The component cannot know where it pins, since what it has to clear (the tab list) belongs to the route, so the route publishes a --section-header-pin view timeline from an invisible 40px marker at the top of the panel: the marker's top edge sits exactly where the header comes to rest, so the timeline's exit phase opens the moment the header pins, and its height is how far the condense runs. timeline-scope on the panel makes the timeline visible to the header.

The whole effect is progressive enhancement, gated behind @supports (animation-timeline: ...). Browsers without scroll-driven animations, surfaces that publish no timeline, and prefers-reduced-motion all keep the resting header. Pinning itself is plain position: sticky and works everywhere.

Notes for reviewers

  • A dragged widget passes under the pinned header: isolation: isolate on the grid caps its layers (edit overlay, resize, the @dnd-kit drag preview) below it.
  • The tab list living inside the scroller is interim: the sections belong in Page's navigation slot (Admin UI: Add Navigation component and Page navigation slot WordPress/gutenberg#79746), which @wordpress/admin-ui does not ship yet. WOOA7S-1931 tracks the move.
  • Other SectionHeader surfaces (post detail, report pages) do not opt in, so they must look exactly as on trunk.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No.

Testing instructions

Go to Jetpack → Stats (Traffic section) with enough widgets to scroll past one viewport.

Screen.Recording.2026-08-14.at.12.13.02.AM.mov

Pinning

  • Scroll to the bottom: the section header stops under the page header, and the page header stays put for the whole scroll (on trunk it holds for about one viewport, then slides off).
  • The header's fill runs edge to edge and lines up with the page header's.

Condensing

  • Scroll down slowly: nothing moves until the tabs scroll away and the header pins; then the subtitle fades out over about 40px. It must not start at scroll zero.
  • Scroll back up: the effect reverses and the header returns to its resting layout, with no leftover gap.

Widgets

  • Widgets pass under the header, never over it. Repeat in Customize mode: toolbars, resize, remove, drag.

Date controls

  • Open the Custom range popover while pinned: it anchors to the trigger and does not clip. Apply a range and confirm the subtitle comes back updated.
  • Narrow the window until the header stacks: the breakpoint should not move, since the condense is height-only.

Fallbacks and other surfaces

  • With reduce motion enabled, the header pins but does not condense.
  • In a browser without scroll-driven animations (Safari 18.x), same thing: the header pins with its resting layout.
  • Check Insights and Subscribers, then a post detail page and a report page with tabs: they share SectionHeader but do not opt in, so nothing should move or change color.

the page header leaves the scroll flow and stays pinned past one viewport
takes that header's fill and hairline, and isolates the grid layers below it
scoped to the dashboard: post detail and the report pages keep the tab bar margin
@retrofox
retrofox requested a review from a team as a code owner August 13, 2026 03:47
@retrofox retrofox added Enhancement Changes to an existing feature — removing, adding, or changing parts of it [Status] Needs Review This PR is ready for review. labels Aug 13, 2026
@retrofox retrofox self-assigned this Aug 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@github-actions

github-actions Bot commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the update/sticky-section-header branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack update/sticky-section-header
bin/jetpack-downloader test jetpack-mu-wpcom-plugin update/sticky-section-header

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@retrofox
retrofox marked this pull request as draft August 13, 2026 03:51
@jp-launch-control

jp-launch-control Bot commented Aug 13, 2026 •

Copy link
Copy Markdown

Code Coverage Summary

This PR did not change code coverage!

That could be good or bad, depending on the situation. Everything covered before, and still is? Great! Nothing was covered before? Not so great. 🤷

Full summary · PHP report · JS report

the sections are links keyed by URL slug and belong in that slot, not in a tablist
subtitle row and title both follow a view timeline the surface publishes
a pin marker opens the range the moment the tabs are cleared, and the band tightens with it
@retrofox retrofox changed the title Premium Analytics: pin the section header under the page header Premium Analytics: pin the section header and settle it into a chrome bar Aug 13, 2026
@retrofox retrofox changed the title Premium Analytics: pin the section header and settle it into a chrome bar Premium Analytics: pin the dashboard section header and condense it on scroll Aug 13, 2026
@retrofox
retrofox marked this pull request as ready for review August 13, 2026 15:14
chihsuan
chihsuan previously approved these changes Aug 14, 2026

@chihsuan chihsuan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice work! @retrofox I ran this locally and looks good.

Related to WOOA7S-1783: in the prototype the page subtitle (Views, visitors, and where they came from.) also hides as you scroll, so the whole top area collapses rather than just the section header. Might worth addressing in a follow-up.

@retrofox

Copy link
Copy Markdown
Contributor Author

Nice work! @retrofox I ran this locally and looks good.

Related to WOOA7S-1783: in the prototype the page subtitle (Views, visitors, and where they came from.) also hides as you scroll, so the whole top area collapses rather than just the section header. Might worth addressing in a follow-up.

This is going to be a tough one. The page subtitle is part of the admin-ui Page component. It doesn't support this feature afaik, and I wonder what the chances are of it being added.

Even more, the PR introducing the Page navigation was merged a few days ago. This means that in the next release, we'll be able to replace the (bad, imo) custom navigation based on tabs with the Page navigation prop.
Again, the scroll-up and pinned behavior won't be supported there.

@retrofox
retrofox merged commit 48b54f2 into trunk Aug 16, 2026
84 of 85 checks passed
@retrofox
retrofox deleted the update/sticky-section-header branch August 16, 2026 21:08
@github-actions github-actions Bot added [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. and removed [Status] In Progress [Status] Needs Review This PR is ready for review. labels Aug 16, 2026
@chihsuan

Copy link
Copy Markdown
Member

This is going to be a tough one. The page subtitle is part of the admin-ui Page component. It doesn't support this feature afaik, and I wonder what the chances are of it being added.

Even more, the PR introducing the Page navigation was merged a few days ago. This means that in the next release, we'll be able to replace the (bad, imo) custom navigation based on tabs with the Page navigation prop. Again, the scroll-up and pinned behavior won't be supported there.

Got it, thanks for the explanation. That makes sense. I think we can discuss later if there are any alternatives with Eder then 🙏

@retrofox

retrofox commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Where the date controls have travelled

With the revised design landing, it is worth writing down how this surface got here. Not to relitigate anything: the design converged through iteration, which is what iteration is for. But the code carries the marks of each step, and whoever reads it next deserves the map.

The picker went full circle

The ported package (#49360) shipped the date picker as a dropdown of presets with "Custom" at the end.

#50365 replaced it with the segmented row of pills trunk has today.

The revised design returns it to a dropdown, modelled on Plausible, with the calendar appearing only on "Custom". #51835 adds that component and #51842 puts it on screen.

Most of what followed served the pills

A pill row has to fit on one line in every locale, and that turned out to be most of the work:

PR What it added
#50523 mobile layout for the row
#50906 measure the presets instead of guessing a breakpoint
#51088 measure an external container with a reserved share
#51133 ellipsize the section title without costing the pills their labels
#51231 shorten the custom-range label
#51340 drop "Last" from the rolling labels

Plus the abbreviated label variants and the CSS that picks between them (WOOA7S-1816, WOOA7S-1900), and the probe that measures the full-length row (WOOA7S-1837).

A dropdown has one trigger and nothing to measure, so #51842 removes the measurement and WOOA7S-2029 takes out what is left behind.

The subtitle, and this PR's condense

#50897 put the applied date configuration in a subtitle under the title, and #51420 added the comparison's dates to it.

This PR pinned the header and condensed it on scroll, and the condense's main move was fading that subtitle out: 190px of pinned chrome down to 146px.

#51707 then removed the subtitle. The condense still runs, but all it has left is the title's font-size step, and the SCSS says so plainly: "Buys no height: the row is floored by the date controls beside it."

The information the subtitle carried did not disappear, it moved onto the controls. #51817 puts the period on the trigger with the exact dates in a tooltip, and #51820 does the same for the comparison.

What survives

Worth stating, because the above reads heavier than it is:

  • Pinning itself, plain position: sticky, is what the design asks for: the whole bar stays on screen.
  • DateRangePopoverContent and its two-click calendar, which the new dropdown reuses whole.
  • The datetime layer: presets, comparison options derived from the range, stepping, drilling.
  • The formatters, natural-language collapse included.
  • The comparison and interval controls.

What goes is the pill row and the measurement around it. And an open question: whether a header with no subtitle still wants a condense at all.

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

Labels

Enhancement Changes to an existing feature — removing, adding, or changing parts of it [Package] Premium Analytics [Status] UI Changes Add this to PRs that change the UI so documentation can be updated.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants