Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions projects/js-packages/base-styles/admin-page-layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
// body.jetpack_page_my-jetpack { @include jetpack-admin-page-layout; }
// }

// To style the scrollable middle from a consumer, include
// `jetpack-admin-page-scrollable-middle` inside the same scope instead of
// copying its selectors:

// @include jetpack-admin-page-scrollable-middle { scrollbar-gutter: stable; }

// Selector hooks this mixin relies on (all stable, not CSS-Modules hashed):

// wp-admin shell: #wpcontent, #wpbody-content, #wpfooter
Expand All @@ -25,6 +31,9 @@
// admin-ui's header: <header> element rendered by admin-ui's <Page>
// inside `.jp-admin-page__page` (no class hooks —
// we anchor structurally to the HTML5 element)
// <AdminPage> content: .jp-admin-page__content (content wrapper of an
// <AdminPage> without a
// title or breadcrumbs)
// <JetpackFooter>: .jetpack-footer
// Tabs wrapper convention: .jp-admin-page-tabs (consumer-applied div that
// wraps `@wordpress/ui`
Expand Down Expand Up @@ -66,6 +75,18 @@ $jp-admin-bar-height-mobile: 46px;
$jp-breakpoint-auto-fold: 960px;
$jp-breakpoint-mobile: 782px;

// The scrollable middle of an <AdminPage>: everything between the header and
// the footer. With a title, admin-ui's <Page> renders children as its own
// direct children (<AdminPage> passes no `hasPadding`, so no content wrapper).
// Without a title, <AdminPage> wraps them in `.jp-admin-page__content`.
@mixin jetpack-admin-page-scrollable-middle {

.jp-admin-page__page > :not(:first-child):not(.jetpack-footer),
.jp-admin-page > .jp-admin-page__content {
@content;
}
}

@mixin jetpack-admin-page-layout {
// ── wp-admin chrome resets ────────────────────────────────────────
#wpcontent {
Expand Down Expand Up @@ -247,17 +268,13 @@ $jp-breakpoint-mobile: 782px;
padding-bottom: 0;
}

// The scrollable middle. <AdminPage> does not pass `hasPadding` to
// admin-ui's <Page>, so admin-ui's content wrapper is not rendered —
// children drop in as direct descendants of the page node. Target
// anything that isn't the header or the footer.

// ── The scrollable middle ─────────────────────────────────────────
// `overflow: auto` (both axes) lets any child wider than the column
// (dashboard grids with fixed column widths, wide tables, `100vw`
// descendants) scroll horizontally inside the middle instead of
// dragging the whole window into a horizontal scrollbar.

// `<AdminPage>` (title-branch) wraps children in
// `<AdminPage>` wraps children in
// `<Container fluid horizontalSpacing={0}><Col>{children}</Col></Container>`
// — that outer Container is `display: grid` and the single Col is a
// grid cell. Without intervention, the chain breaks here: any inner
Expand All @@ -270,7 +287,7 @@ $jp-breakpoint-mobile: 782px;
// fill their bounded slot. Form-style pages keep working: their
// children stay content-sized (default `flex: 0 1 auto`) and any
// overflow still falls back to Container's `overflow: auto`.
.jp-admin-page__page > :not(:first-child):not(.jetpack-footer) {
@include jetpack-admin-page-scrollable-middle {
flex: 1 1 auto;
min-height: 0;
min-width: 0;
Expand Down Expand Up @@ -301,7 +318,7 @@ $jp-breakpoint-mobile: 782px;
// width of the panel area, so the hairline spans the column.

// `position: sticky` pins the strip to the top of the scrollable middle
// (`.jp-admin-page__page > :not(header):not(.jetpack-footer)`),
// (see `jetpack-admin-page-scrollable-middle`),
// which is the local opt-in equivalent of admin-ui's native sticky
// header — disabled globally by `<AdminPage>` per JETPACK-1386. Pinning
// the tabs strip here keeps cross-section navigation accessible while
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Admin page layout: add a `jetpack-admin-page-scrollable-middle` mixin so consumers can style the scroll surface without copying its selectors.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

Admin page layout: make the content of AdminPage screens without a title or breadcrumbs scroll instead of being clipped by the fixed content column.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

AdminPage: add a stable `jp-admin-page__content` class to the content wrapper of pages without a title or breadcrumbs so the shared admin page layout can make it scrollable.
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ const AdminPage: FC< AdminPageProps > = ( {
</Col>
</Container>
) }
<Container fluid horizontalSpacing={ 0 }>
{ /* `jp-admin-page__content` is a stable hook for `jetpack-admin-page-layout`. Do not rename. */ }
<Container fluid horizontalSpacing={ 0 } className="jp-admin-page__content">
<Col>{ children }</Col>
</Container>
{ showFooter && <JetpackFooter menu={ optionalMenuItems } /> }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* eslint-disable testing-library/no-node-access -- these tests check class hooks
that the `jetpack-admin-page-layout` mixin selects on. */
import { render, screen } from '@testing-library/react';
import AdminPage from '../index.tsx';

describe( 'AdminPage', () => {
it( 'wraps children in the scrollable content hook when there is no header', () => {
render(
<AdminPage showHeader={ false }>
<p>Page body</p>
</AdminPage>
);

const content = screen.getByText( 'Page body' ).closest( '.jp-admin-page__content' );
expect( content ).not.toBeNull();
expect( content.parentElement ).toHaveClass( 'jp-admin-page' );
} );

it( 'wraps children in the scrollable content hook with the legacy header', () => {
render(
<AdminPage>
<p>Page body</p>
</AdminPage>
);

const content = screen.getByText( 'Page body' ).closest( '.jp-admin-page__content' );
expect( content ).not.toBeNull();
expect( content.parentElement ).toHaveClass( 'jp-admin-page' );
} );

it( 'renders the admin-ui page hook instead when a title is given', () => {
render(
<AdminPage title="Sample">
<p>Page body</p>
</AdminPage>
);

const body = screen.getByText( 'Page body' );
expect( body.closest( '.jp-admin-page__page' ) ).not.toBeNull();
expect( body.closest( '.jp-admin-page__content' ) ).toBeNull();
} );
} );
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

Secondary admin connection screen: restore scrolling so the connect button is reachable on short viewports.
5 changes: 2 additions & 3 deletions projects/packages/my-jetpack/_inc/style.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@
// between search results and category browse — which changes the content
// height, and thus whether the scrollbar is present — doesn't shift the
// layout sideways. Most noticeable on Firefox / platforms with classic
// (space-consuming) scrollbars; a no-op where unsupported. The selector
// mirrors the "scrollable middle" defined by jetpack-admin-page-layout.
.jp-admin-page__page > :not(:first-child):not(.jetpack-footer) {
// (space-consuming) scrollbars; a no-op where unsupported.
@include jetpack-admin-page-scrollable-middle {
scrollbar-gutter: stable;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

Connection screen: restore scrolling so the connect button is reachable on short viewports.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

Secondary admin connection screen: restore scrolling so the connect button is reachable on short viewports.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

My Jetpack: restore scrolling on the connection screen so the connect button is reachable on short viewports.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: bugfix

My Jetpack: restore scrolling on the connection screen so the connect button is reachable on short viewports.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

My Jetpack: restore scrolling on the connection screen so the connect button is reachable on short viewports.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

My Jetpack: restore scrolling on the connection screen so the connect button is reachable on short viewports.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

My Jetpack: restore scrolling on the connection screen so the connect button is reachable on short viewports.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

My Jetpack: restore scrolling on the connection screen so the connect button is reachable on short viewports.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

My Jetpack: restore scrolling on the connection screen so the connect button is reachable on short viewports.
Loading