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

Merged
merged 11 commits into from
May 19, 2025
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
34 changes: 18 additions & 16 deletions client/dashboard/agency-overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@ import PageLayout from '../components/page-layout';

export default function AgencyOverview() {
return (
<PageLayout>
<PageHeader
title={ __( 'Agency Overview' ) }
actions={
<>
<Button variant="primary" __next40pxDefaultSize>
{ __( 'Add Sites' ) }
</Button>
<Button variant="secondary" __next40pxDefaultSize>
{ __( 'Add Products' ) }
</Button>
</>
}
description={ __( 'This is a sample overview page.' ) }
/>
</PageLayout>
<PageLayout
header={
<PageHeader
title={ __( 'Agency Overview' ) }
actions={
<>
<Button variant="primary" __next40pxDefaultSize>
{ __( 'Add Sites' ) }
</Button>
<Button variant="secondary" __next40pxDefaultSize>
{ __( 'Add Products' ) }
</Button>
</>
}
description={ __( 'This is a sample overview page.' ) }
/>
}
></PageLayout>
);
}
24 changes: 13 additions & 11 deletions client/dashboard/app/404/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ import RouterLinkButton from '../../components/router-link-button';

function NotFound() {
return (
<PageLayout>
<PageHeader
title={ __( '404 Not Found' ) }
description={ __( 'The page you are looking for does not exist.' ) }
actions={
<RouterLinkButton to="/sites" variant="primary" __next40pxDefaultSize>
{ __( 'Go to Sites' ) }
</RouterLinkButton>
}
/>
</PageLayout>
<PageLayout
header={
<PageHeader
title={ __( '404 Not Found' ) }
description={ __( 'The page you are looking for does not exist.' ) }
actions={
<RouterLinkButton to="/sites" variant="primary" __next40pxDefaultSize>
{ __( 'Go to Sites' ) }
</RouterLinkButton>
}
/>
}
/>
);
}

Expand Down
32 changes: 18 additions & 14 deletions client/dashboard/app/500/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,24 @@ import RouterLinkButton from '../../components/router-link-button';

function UnknownError( { error }: { error: Error } ) {
return (
<PageLayout>
<PageHeader
title={ __( '500 Error' ) }
description={ __( 'Something wrong happened.' ) }
actions={
<RouterLinkButton to="/sites" variant="primary" __next40pxDefaultSize>
{ __( 'Go to Sites' ) }
</RouterLinkButton>
}
/>
<Notice status="error" isDismissible={ false }>
{ error.message }
</Notice>
</PageLayout>
<PageLayout
header={
<PageHeader
title={ __( '500 Error' ) }
description={ __( 'Something wrong happened.' ) }
actions={
<RouterLinkButton to="/sites" variant="primary" __next40pxDefaultSize>
{ __( 'Go to Sites' ) }
</RouterLinkButton>
}
/>
}
notices={
<Notice status="error" isDismissible={ false }>
{ error.message }
</Notice>
}
></PageLayout>
);
}

Expand Down
5 changes: 5 additions & 0 deletions client/dashboard/app/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,11 @@ export const getRouter = ( config: AppConfig ) => {
defaultNotFoundComponent: NotFound,
defaultPreload: 'intent',
defaultPreloadStaleTime: 0,
// 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 .client-dashboard-components-page-header {
view-transition-name: page-layout-header-large;
}
.dashboard-page-layout.is-small .client-dashboard-components-page-header {
view-transition-name: page-layout-header-small;
}

.dashboard-page-layout.is-large .client-dashboard-components-page-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;
}
21 changes: 10 additions & 11 deletions client/dashboard/components/page-header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const PageHeader = ( {
breadcrumbs,
}: PageHeaderProps ) => {
return (
<VStack spacing={ 2 }>
<VStack spacing={ 2 } className="client-dashboard-components-page-header">
{ breadcrumbs }
<HStack spacing={ 4 } justify="flex-start" alignment="flex-start">
{ decoration && (
Expand All @@ -49,16 +49,15 @@ export const PageHeader = ( {
) }
<HStack spacing={ 3 } justify="space-between" alignment="flex-start">
<h1 className="client-dashboard-components-page-header__heading">{ title }</h1>
{ !! actions && (
<HStack
spacing={ 2 }
justify="flex-end"
expanded={ false }
className="client-dashboard-components-page-header__actions"
>
{ actions }
</HStack>
) }
{ /* The wrapper is always needed for view transitions. */ }
<HStack
spacing={ 2 }
justify="flex-end"
expanded={ false }
className="client-dashboard-components-page-header__actions"
>
{ actions }
</HStack>
</HStack>
</HStack>
{ description && (
Expand Down
1 change: 1 addition & 0 deletions client/dashboard/components/page-header/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

.client-dashboard-components-page-header__actions {
flex-shrink: 0;
align-self: stretch;
}

.client-dashboard-components-page-header__description {
Expand Down
16 changes: 14 additions & 2 deletions client/dashboard/components/page-layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,26 @@ const sizes = {

function PageLayout( {
children,
header,
notices,
size = 'large',
}: {
children?: React.ReactNode;
header?: React.ReactNode;
notices?: React.ReactNode;
size?: 'large' | 'small';
} ) {
return (
<VStack spacing={ 8 } className="dashboard-page-layout" style={ sizes[ size ] }>
{ children }
<VStack
spacing={ 8 }
className={ `dashboard-page-layout is-${ size }` }
style={ sizes[ size ] }
>
{ header }
{ notices }
<VStack spacing={ 8 } className="dashboard-page-layout__content">
{ children }
</VStack>
</VStack>
);
}
Expand Down
21 changes: 12 additions & 9 deletions client/dashboard/domains/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,18 @@ function Domains() {
}
const { data: filteredData, paginationInfo } = filterSortAndPaginate( domains, view, fields );
return (
<PageLayout>
<PageHeader
title={ __( 'Domains' ) }
actions={
<Button variant="primary" __next40pxDefaultSize>
{ __( 'Add New Domain' ) }
</Button>
}
/>
<PageLayout
header={
<PageHeader
title={ __( 'Domains' ) }
actions={
<Button variant="primary" __next40pxDefaultSize>
{ __( 'Add New Domain' ) }
</Button>
}
/>
}
>
<DataViewsCard>
<DataViews
data={ filteredData || [] }
Expand Down
39 changes: 22 additions & 17 deletions client/dashboard/emails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,23 +118,28 @@ function Emails() {
};

return (
<PageLayout>
<PageHeader
title={ __( 'Emails' ) }
actions={
<>
<Button variant="secondary" __next40pxDefaultSize>
{ __( 'Add Email Forwarder' ) }
</Button>
<Button variant="primary" __next40pxDefaultSize>
{ __( 'Add Mailbox' ) }
</Button>
</>
}
/>
<Notice status="warning" isDismissible={ false }>
{ __( 'This is using fake data for the moment' ) }
</Notice>
<PageLayout
header={
<PageHeader
title={ __( 'Emails' ) }
actions={
<>
<Button variant="secondary" __next40pxDefaultSize>
{ __( 'Add Email Forwarder' ) }
</Button>
<Button variant="primary" __next40pxDefaultSize>
{ __( 'Add Mailbox' ) }
</Button>
</>
}
/>
}
notices={
<Notice status="warning" isDismissible={ false }>
{ __( 'This is using fake data for the moment' ) }
</Notice>
}
>
<DataViewsCard>
<DataViews
data={ filteredData }
Expand Down
3 changes: 1 addition & 2 deletions client/dashboard/me/active-subscriptions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import PageLayout from '../../components/page-layout';

export default function ActiveSubscriptions() {
return (
<PageLayout size="small">
<PageHeader title={ __( 'Active Subscriptions' ) } />
<PageLayout size="small" header={ <PageHeader title={ __( 'Active Subscriptions' ) } /> }>
<div>Active subscriptions content will go here</div>
</PageLayout>
);
Expand Down
3 changes: 1 addition & 2 deletions client/dashboard/me/billing-history/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import PageLayout from '../../components/page-layout';

function BillingHistory() {
return (
<PageLayout size="small">
<PageHeader title={ __( 'Billing History' ) } />
<PageLayout size="small" header={ <PageHeader title={ __( 'Billing History' ) } /> }>
<div>Billing history content will go here</div>
</PageLayout>
);
Expand Down
3 changes: 1 addition & 2 deletions client/dashboard/me/billing/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import RouterLinkSummaryButton from '../../components/router-link-summary-button

function Billing() {
return (
<PageLayout size="small">
<PageHeader title={ __( 'Billing' ) } />
<PageLayout size="small" header={ <PageHeader title={ __( 'Billing' ) } /> }>
<VStack spacing={ 4 }>
<RouterLinkSummaryButton
title={ __( 'Active subscriptions' ) }
Expand Down
Loading