Skip to content

Hosting Dashboard v2: view transitions (part 1) #103278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: trunk
Choose a base branch
from
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
5 changes: 5 additions & 0 deletions client/dashboard/app/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ export const getRouter = ( config: AppConfig ) => {
basepath: config.basePath,
defaultErrorComponent: UnknownError,
defaultNotFoundComponent: NotFound,
// Calling document.startViewTransition() ourselves is really tricky,
// Tanstack Router knows how to do it best. Even though it says
// "default", we can still customize it in CSS and add more transition
// areas.
defaultViewTransition: true,
} );
};

Expand Down
4 changes: 3 additions & 1 deletion client/dashboard/app/secondary-menu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ function UserProfile() {
<Text variant="muted">@{ user.username }</Text>
</VStack>
<MenuGroup>
<RouterLinkMenuItem to="/me/profile">{ __( 'Account' ) }</RouterLinkMenuItem>
<RouterLinkMenuItem to="/me/profile" onClick={ onClose }>
{ __( 'Account' ) }
</RouterLinkMenuItem>
</MenuGroup>
<MenuGroup>
<MenuItem
Expand Down
2 changes: 2 additions & 0 deletions client/dashboard/app/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// I'm tempted to even just replace all this with a display:none on the logo
@import './loading-screen';

@import './view-transitions';
Copy link
Contributor

Choose a reason for hiding this comment

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

I like that it feels not intrusive like that. It's its own CSS file that we can remove and iterate on as needed. I don't like that we have to use classnames for things that are rendered in different places to achieve it though.

I'm not sure yet what's the best approach.


// Hacks that shouldn't be necessary.
.environment-badge {
display: none;
Expand Down
66 changes: 66 additions & 0 deletions client/dashboard/app/view-transitions.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 250ms;
}

// The main and sub headers must be separate view transitions, othervise the sub
// header won't slide in!
header.dashboard-header-bar {
view-transition-name: main-header;
}
main div.dashboard-header-bar {
view-transition-name: sub-header;
}

// Headers should show on top of the rest of the page (important for sticky).
::view-transition-group(main-header),
::view-transition-group(sub-header) {
z-index: 1;
}

// Do not let the browser transform (slide in) the main hear. This is important
// for sticy positioning (when the page is scrolled down) and gently switching
// between the main and sub headers.
::view-transition-group(main-header) {
transform: none !important;
}

::view-transition-image-pair(main-header),
::view-transition-image-pair(sub-header) {
height: auto;
}

// Large and small must be separate so they don't cross-animate.
.dashboard-page-layout.is-large > .dashboard-page-layout__header {
view-transition-name: page-layout-header-large;
}
.dashboard-page-layout.is-small > .dashboard-page-layout__header {
view-transition-name: page-layout-header-small;
}

.dashboard-page-layout.is-large > .dashboard-page-layout__header .components-button.is-primary {
view-transition-name: page-layout-header-large--button;
}

::view-transition-old(page-layout-header-large--button),
::view-transition-new(page-layout-header-large--button) {
height: 100%;
}

.dashboard-page-layout__content {
view-transition-name: page-layout-content;
}

::view-transition-old(page-layout-content),
::view-transition-new(page-layout-content) {
// Never expand the main content horizontally, but allow it to shrink.
width: auto;
// Also disable shrinking. Leaving it commented out to test.
// max-width: 100%;
height: auto;
}

::view-transition-image-pair(page-layout-content) {
display: flex;
justify-content: center;
}
17 changes: 14 additions & 3 deletions client/dashboard/components/page-layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,24 @@ function PageLayout( {
title,
description,
actions,
notices,
children,
size = 'large',
}: {
title: string;
description?: React.ReactNode;
actions?: React.ReactNode;
notices?: React.ReactNode;
children?: React.ReactNode;
size?: 'large' | 'small';
} ) {
return (
<VStack spacing={ 8 } className="dashboard-page-layout" style={ sizes[ size ] }>
<VStack spacing={ 4 }>
<VStack
spacing={ 8 }
className={ `dashboard-page-layout is-${ size }` }
style={ sizes[ size ] }
>
<VStack className="dashboard-page-layout__header" spacing={ 4 }>
<HStack justify="space-between" alignment="center">
<Heading level={ 1 } style={ { flexShrink: 0 } }>
{ title }
Expand All @@ -45,7 +51,12 @@ function PageLayout( {
<Text className="dasboard-page-layout__description">{ description } </Text>
) }
</VStack>
{ !! children && <VStack spacing={ 8 }>{ children }</VStack> }
{ notices }
{ !! children && (
<VStack className="dashboard-page-layout__content" spacing={ 8 }>
{ children }
</VStack>
) }
</VStack>
);
}
Expand Down
8 changes: 5 additions & 3 deletions client/dashboard/emails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,12 @@ function Emails() {
</Button>
</div>
}
notices={
<Notice status="warning" isDismissible={ false }>
{ __( 'This is using fake data for the moment' ) }
</Notice>
}
>
<Notice status="warning" isDismissible={ false }>
{ __( 'This is using fake data for the moment' ) }
</Notice>
<DataViewsCard>
<DataViews
data={ filteredData }
Expand Down
12 changes: 7 additions & 5 deletions client/dashboard/me/notifications/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { __experimentalVStack as VStack } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import PageLayout from '../../components/page-layout';
import RouterLinkSummaryButton from '../../components/router-link-summary-button';

function Notifications() {
return (
<PageLayout
title={ __( 'Notifications' ) }
description={ __( 'Manage your notification settings.' ) }
size="small"
/>
<PageLayout title={ __( 'Notifications' ) } size="small">
<VStack spacing={ 4 }>
<RouterLinkSummaryButton title={ __( 'Details' ) } to="/me/notifications" />
</VStack>
</PageLayout>
);
}

Expand Down
12 changes: 7 additions & 5 deletions client/dashboard/me/privacy/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { __experimentalVStack as VStack } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import PageLayout from '../../components/page-layout';
import RouterLinkSummaryButton from '../../components/router-link-summary-button';

function Privacy() {
return (
<PageLayout
title={ __( 'Privacy' ) }
description={ __( 'Manage your privacy settings.' ) }
size="small"
/>
<PageLayout title={ __( 'Privacy' ) } size="small">
<VStack spacing={ 4 }>
Copy link
Member

Choose a reason for hiding this comment

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

Why would we need to add VStack in various pages? Also have you removed the description intentionally?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the description is not present in the designs, so I removed it.

It's necessary for there to be some content because otherwise the content will slide in (from nothing) instead of cross fade.

Copy link
Member

Choose a reason for hiding this comment

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

Should we just add a placeholder paragraph then instead of these? Also PageLayout is a VStack wrapper and its children are wrapped.

Copy link
Contributor Author

@ellatrix ellatrix May 9, 2025

Choose a reason for hiding this comment

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

I don't understand what you mean. I added the VStack because billing has that too for the summary buttons. Why a paragraph? These should because summary buttons, not paragraphs.

<RouterLinkSummaryButton title={ __( 'Details' ) } to="/me/privacy" />
</VStack>
</PageLayout>
);
}

Expand Down
12 changes: 7 additions & 5 deletions client/dashboard/me/security/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { __experimentalVStack as VStack } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import PageLayout from '../../components/page-layout';
import RouterLinkSummaryButton from '../../components/router-link-summary-button';

function Security() {
return (
<PageLayout
title={ __( 'Security' ) }
description={ __( 'Manage your security settings.' ) }
size="small"
/>
<PageLayout title={ __( 'Security' ) } size="small">
<VStack spacing={ 4 }>
<RouterLinkSummaryButton title={ __( 'Details' ) } to="/me/security" />
</VStack>
</PageLayout>
);
}

Expand Down
9 changes: 8 additions & 1 deletion client/dashboard/sites/deployments/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { __ } from '@wordpress/i18n';
import DataViewsCard from '../../components/dataviews-card';
import PageLayout from '../../components/page-layout';

function SiteDeployments() {
return <PageLayout title={ __( 'Deployments' ) } />;
return (
<PageLayout title={ __( 'Deployments' ) }>
<DataViewsCard>
<></>
</DataViewsCard>
</PageLayout>
);
}

export default SiteDeployments;
11 changes: 10 additions & 1 deletion client/dashboard/sites/performance/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { Card, CardBody } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import PageLayout from '../../components/page-layout';

function SitePerformance() {
return <PageLayout title={ __( 'Performance' ) } />;
return (
<PageLayout title={ __( 'Performance' ) }>
<Card>
<CardBody>
<></>
</CardBody>
</Card>
</PageLayout>
);
}

export default SitePerformance;