Skip to content
Merged
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
248 changes: 235 additions & 13 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

40 changes: 26 additions & 14 deletions projects/js-packages/base-styles/admin-page-layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
// <AdminPage> root: .jp-admin-page (added unconditionally by the
// <AdminPage> component from
// @automattic/jetpack-components)
// @wordpress/admin-ui: .admin-ui-page, .admin-ui-page__header
// admin-ui's <Page>: .jp-admin-page__page (className passed through
// by <AdminPage>; admin-ui
// 2.0.0 forwards it onto
// the page's outer node)
// 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)
// <JetpackFooter>: .jetpack-footer
// Tabs wrapper convention: .jp-admin-page-tabs (consumer-applied div that
// wraps `@wordpress/ui`
Expand Down Expand Up @@ -193,18 +199,24 @@ $jp-breakpoint-mobile: 782px;
}

// ── admin-ui Page internals ───────────────────────────────────────
// admin-ui ships `.admin-ui-page` with `height: 100%`, which fills its
// admin-ui ships its page node with `height: 100%`, which fills its
// parent's computed height. Paired with our flex chain, the element
// becomes a viewport-fitted flex column.
.admin-ui-page {

// admin-ui 2.0.0 moved internals to CSS Modules (no `.admin-ui-page*`
// class hooks anymore). We pass `className="jp-admin-page__page"` from
// <AdminPage>; admin-ui forwards it onto the page's outer node. The
// header is a stable `<header>` element directly inside that node, so
// we anchor to `> header` instead of a class.
.jp-admin-page__page {
flex: 1 1 auto;
min-height: 0;
min-width: 0;
display: flex;
flex-direction: column;
}

.admin-ui-page__header {
.jp-admin-page__page > header {
flex-shrink: 0; // pinned at top of the flex column.
}

Expand All @@ -213,14 +225,14 @@ $jp-breakpoint-mobile: 782px;
// strip's own hairline becomes the only divider between header and tab
// content. Same `:has()` pattern used elsewhere in this mixin to react
// to the page's content shape.
.admin-ui-page:has(.jp-admin-page-tabs) .admin-ui-page__header {
.jp-admin-page__page:has(.jp-admin-page-tabs) > header {
border-bottom: none;
padding-bottom: 0;
}

// The scrollable middle. <AdminPage> does not pass `hasPadding` to
// admin-ui's <Page>, so `.admin-ui-page__content` is not rendered —
// children drop in as direct descendants of `.admin-ui-page`. Target
// 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.

// `overflow: auto` (both axes) lets any child wider than the column
Expand All @@ -241,7 +253,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`.
.admin-ui-page > :not(.admin-ui-page__header):not(.jetpack-footer) {
.jp-admin-page__page > :not(header):not(.jetpack-footer) {
flex: 1 1 auto;
min-height: 0;
min-width: 0;
Expand Down Expand Up @@ -272,16 +284,16 @@ $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
// (`.admin-ui-page > :not(.admin-ui-page__header):not(.jetpack-footer)`),
// (`.jp-admin-page__page > :not(header):not(.jetpack-footer)`),
// 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
// content scrolls underneath.

// Surface + hairline use the same `--wpds-*` design tokens that
// `@wordpress/admin-ui` applies to `.admin-ui-page__header`, so the
// tabs strip reads as a visual continuation of the page header and
// tracks any future token (theme/dark-mode) changes automatically.
// `@wordpress/admin-ui` applies to its page header, so the tabs strip
// reads as a visual continuation of the page header and tracks any
// future token (theme/dark-mode) changes automatically.
.jp-admin-page-tabs {
position: sticky;
top: 0;
Expand All @@ -290,8 +302,8 @@ $jp-breakpoint-mobile: 782px;
border-bottom: var(--wpds-border-width-xs) solid var(--wpds-color-stroke-surface-neutral-weak);

// Align tab buttons' inline padding with the page header's
// horizontal padding (admin-ui ships `.admin-ui-page__header`
// at `padding-inline: var(--wpds-dimension-padding-2xl)`).
// horizontal padding (admin-ui ships its page header at
// `padding-inline: var(--wpds-dimension-padding-2xl)`).
// `@wordpress/ui` Tabs default the buttons to `padding-inline:
// var(--wpds-dimension-padding-lg)`; bump them to 2xl so the
// first tab's start edge lines up under the page title.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

admin-page-layout mixin: anchor selectors to the new `.jp-admin-page__page` className and the rendered `<header>` element, replacing the `.admin-ui-page*` global classes that admin-ui 2.0.0 dropped when it moved to CSS Modules. Restores the viewport-fitted scroll chain on every consumer (Boost, Protect, VideoPress, Search, Newsletter, Publicize, Backup, Jetpack network admin).
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

AdminPage: pass a stable `jp-admin-page__page` className to admin-ui's Page so layout overrides survive admin-ui 2.0.0's switch to CSS Modules; pin the header heading level to `<h2>` and center the new `visual` slot to keep the Jetpack logo aligned with the title.
4 changes: 4 additions & 0 deletions projects/js-packages/components/changelog/update-admin-ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: changed

AdminPage: Update to @wordpress/admin-ui 2.0.0 and use the new `visual` prop to render the Jetpack logo alongside the page title.
20 changes: 4 additions & 16 deletions projects/js-packages/components/components/admin-page/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import restApi from '@automattic/jetpack-api';
import { Page } from '@wordpress/admin-ui';
import '@wordpress/admin-ui/build-style/style.css';
import {
__experimentalHStack as HStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis
} from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import clsx from 'clsx';
import { useEffect, useCallback } from 'react';
Expand Down Expand Up @@ -74,23 +70,15 @@ const AdminPage: FC< AdminPageProps > = ( {
}
}, [] );

// Compose the title with logo for the admin-ui Page header.
// Page's Header wraps this in an <h2> tag, so we just pass the content directly.
const composedTitle = title ? (
<HStack spacing={ 2 } justify="left">
{ logo || <JetpackLogo showText={ false } height={ 20 } /> }
<span>{ title }</span>
</HStack>
) : undefined;

// When title or breadcrumbs are provided, use admin-ui Page for the full page layout.
if ( showHeader && ( composedTitle || breadcrumbs ) ) {
if ( showHeader && ( title || breadcrumbs ) ) {
return (
<div className={ rootClassName }>
<Page
ariaLabel={ title }
className="jp-admin-page__page"
visual={ logo || <JetpackLogo showText={ false } height={ 20 } /> }
breadcrumbs={ breadcrumbs }
title={ composedTitle }
title={ title }
subTitle={ subTitle }
actions={ actions }
showSidebarToggle={ false }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,36 @@
// or when showBottomBorder is false.
// Ideally admin-ui would expose a prop or CSS custom property for this:
// https://github.com/WordPress/gutenberg/issues/75428
&.without-bottom-border :global(.admin-ui-page__header) {

// Anchor: `.jp-admin-page__page` is the className we pass to admin-ui's
// <Page>; admin-ui 2.0.0 renders the header as a stable <header> element
// directly inside that page node — no class hooks anymore.
&.without-bottom-border :global(.jp-admin-page__page > header) {
border-bottom: none;
}

// Disable sticky header until we make it work better across all pages.
// JETPACK-1386
:global(.admin-ui-page__header) {
:global(.jp-admin-page__page > header) {
position: relative;
z-index: 1;
}

// Normalize admin headers: implementation of admin-ui needs to
// comprehend old wp-admin floating containers, such as Hello Dolly.
:global(.admin-ui-page) {
:global(.jp-admin-page__page) {
clear: both;
}

// admin-ui 2.0.0's header `visual` slot is a 24px grid box but does not
// center its contents. Our JetpackLogo is 20px tall, so without this it
// pins to the top-left of the cell and looks misaligned vs. the title.
// admin-ui ships the slot as `<div aria-hidden="true">` in the header.
// TODO: remove once upstream centers contents in `.header-visual`.
:global(.jp-admin-page__page > header [aria-hidden="true"]) {
place-items: center;
}

.admin-page-header {
display: flex;
align-items: center;
Expand Down
2 changes: 1 addition & 1 deletion projects/js-packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"@automattic/number-formatters": "workspace:*",
"@babel/runtime": "^7",
"@gravatar-com/hovercards": "0.16.0",
"@wordpress/admin-ui": "1.12.0",
"@wordpress/admin-ui": "2.0.0",
"@wordpress/browserslist-config": "6.44.0",
"@wordpress/components": "32.6.0",
"@wordpress/compose": "7.44.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: changed

Remove the @wordpress/admin-ui CSS bundle workaround from the default request map.
6 changes: 0 additions & 6 deletions projects/js-packages/webpack-config/src/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,6 @@ const defaultRequestMap = {
external: 'JetpackConnection',
handle: 'jetpack-connection',
},
// Bundle admin-ui CSS with our assets. The JS side is already handled by the
// DependencyExtractionPlugin's BUNDLED_PACKAGES list, but the CSS subpath import
// doesn't match that exact-match check and would be incorrectly externalized.
'@wordpress/admin-ui/build-style/style.css': {
external: false,
},
};

const DependencyExtractionPlugin = ( { requestMap, ...options } = {} ) => {
Expand Down
4 changes: 4 additions & 0 deletions projects/packages/forms/changelog/update-admin-ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: changed

Dashboard: Update to @wordpress/admin-ui 2.0.0 and use the Page component's new `visual` prop for the Jetpack logo.
2 changes: 1 addition & 1 deletion projects/packages/forms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"@automattic/jetpack-shared-extension-utils": "workspace:*",
"@automattic/number-formatters": "workspace:*",
"@automattic/request-external-access": "1.0.1",
"@wordpress/admin-ui": "1.12.0",
"@wordpress/admin-ui": "2.0.0",
"@wordpress/base-styles": "6.20.0",
"@wordpress/block-editor": "15.17.0",
"@wordpress/blocks": "15.17.0",
Expand Down
2 changes: 1 addition & 1 deletion projects/packages/forms/routes/forms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"@automattic/jetpack-components": "workspace:*",
"@automattic/number-formatters": "workspace:*",
"@types/react": "18.3.28",
"@wordpress/admin-ui": "1.12.0",
"@wordpress/admin-ui": "2.0.0",
"@wordpress/api-fetch": "7.44.0",
"@wordpress/components": "32.6.0",
"@wordpress/core-data": "7.44.0",
Expand Down
4 changes: 2 additions & 2 deletions projects/packages/forms/routes/forms/stage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ function StageInner() {

const {
title,
ariaLabel,
visual,
breadcrumbs,
subtitle,
actions: headerActions,
Expand All @@ -595,9 +595,9 @@ function StageInner() {

return (
<Page
visual={ visual }
breadcrumbs={ breadcrumbs }
title={ title }
ariaLabel={ ariaLabel }
subTitle={ subtitle }
actions={ headerActions }
hasPadding={ false }
Expand Down
2 changes: 1 addition & 1 deletion projects/packages/forms/routes/responses/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"@automattic/number-formatters": "workspace:*",
"@tanstack/react-router": ">=1.120.5 <1.121.0",
"@types/react": "18.3.28",
"@wordpress/admin-ui": "1.12.0",
"@wordpress/admin-ui": "2.0.0",
"@wordpress/api-fetch": "7.44.0",
"@wordpress/block-editor": "15.17.0",
"@wordpress/blocks": "15.17.0",
Expand Down
2 changes: 2 additions & 0 deletions projects/packages/forms/routes/responses/stage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ function StageInner() {
badges,
subtitle,
title,
visual,
actions: headerActions,
} = usePageHeaderDetails( {
screen: 'responses',
Expand All @@ -682,6 +683,7 @@ function StageInner() {

return (
<Page
visual={ visual }
breadcrumbs={ breadcrumbs }
badges={ badges }
title={ title }
Expand Down
1 change: 0 additions & 1 deletion projects/packages/forms/routes/shared.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@use "sass:meta";
@include meta.load-css("@wordpress/admin-ui/build-style/style.css");
@include meta.load-css("@wordpress/dataviews/build-style/style.css");

.jp-forms-dataviews__view-actions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import useConfigValue from '../../../hooks/use-config-value.ts';
import { adjustDashboardHeight } from '../../../util/adjust-dashboard-height.ts';
import Integrations from '../../integrations/index.tsx';
import './style.scss';
import '@wordpress/admin-ui/build-style/style.css';

const Layout = () => {
const location = useLocation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { __, sprintf } from '@wordpress/i18n';
import { moreVertical } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
import { useNavigate } from '@wordpress/route';
import { Badge, Stack } from '@wordpress/ui';
import { Badge } from '@wordpress/ui';
/**
* Internal dependencies
*/
Expand Down Expand Up @@ -62,7 +62,8 @@ type UsePageHeaderDetailsProps = {
type UsePageHeaderDetailsReturn = {
ariaLabel: string;
breadcrumbs: ReactNode;
title?: ReactNode;
title?: string;
visual: ReactNode;
badges?: ReactNode;
subtitle: ReactNode;
actions?: ReactNode;
Expand Down Expand Up @@ -458,12 +459,7 @@ export default function usePageHeaderDetails(
trackAction,
] );

const WrapWithJetpackLogo = ( { children }: { children: ReactNode } ) => (
<Stack align="center" gap="xs">
<JetpackLogo showText={ false } width={ 20 } />
{ children }
</Stack>
);
const visual = <JetpackLogo showText={ false } width={ 20 } />;

const ariaLabel = useMemo( () => {
if ( isSingleFormScreen ) {
Expand All @@ -475,10 +471,10 @@ export default function usePageHeaderDetails(

const title = useMemo( () => {
if ( isSingleFormScreen ) {
return null;
return undefined;
}
// "Forms" is a product name, do not translate.
return <WrapWithJetpackLogo>Forms</WrapWithJetpackLogo>;
return 'Forms';
}, [ isSingleFormScreen ] );

const breadcrumbs = useMemo( () => {
Expand All @@ -487,14 +483,12 @@ export default function usePageHeaderDetails(
}

return (
<WrapWithJetpackLogo>
<Breadcrumbs
items={ [
{ label: __( 'Forms', 'jetpack-forms' ), to: '/forms' },
{ label: formTitle || __( 'Form responses', 'jetpack-forms' ) },
] }
/>
</WrapWithJetpackLogo>
<Breadcrumbs
items={ [
{ label: __( 'Forms', 'jetpack-forms' ), to: '/forms' },
{ label: formTitle || __( 'Form responses', 'jetpack-forms' ) },
] }
/>
);
}, [ isSingleFormScreen, formTitle ] );

Expand Down Expand Up @@ -884,5 +878,5 @@ export default function usePageHeaderDetails(
trackExportClickResponsesList,
] );

return { ariaLabel, breadcrumbs, title, badges, subtitle, actions };
return { ariaLabel, breadcrumbs, title, visual, badges, subtitle, actions };
}
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,10 @@ describe( 'usePageHeaderDetails', () => {
} );

describe( 'title and breadcrumbs', () => {
it( 'returns null title and breadcrumbs for single form screen', () => {
it( 'returns undefined title and non-null breadcrumbs for single form screen', () => {
const { result } = renderHook( () => usePageHeaderDetails( defaultProps ) );

expect( result.current.title ).toBeNull();
expect( result.current.title ).toBeUndefined();
expect( result.current.breadcrumbs ).not.toBeNull();
} );

Expand All @@ -317,7 +317,7 @@ describe( 'usePageHeaderDetails', () => {
usePageHeaderDetails( { ...defaultProps, screen: 'forms', sourceId: undefined } )
);

expect( result.current.title ).not.toBeNull();
expect( result.current.title ).toBeDefined();
expect( result.current.breadcrumbs ).toBeNull();
} );
} );
Expand Down
Loading
Loading