Skip to content

Conversation

TrevorBurnham
Copy link
Contributor

Description

When rendering the AppLayoutToolbar component under the visual refresh theme with SSR, there's a visual glitch where the breadcrumbs are positioned incorrectly before hydration:

breadcrumb-glitch.mp4

This PR addresses the issue by making the SSR render more consistent with the client-side render. This is a relatively small change that should have no effect on applications that use client-side rendering only.

There are several other issues with AppLayoutToolbar in SSR (see #3848); this PR should provide a starting point for fixing them.

How has this been tested?

I have a branch where I've set up a local SSR dev server. You can pull that branch down and run npm run start:watch in one shell and npm run start:ssr in another.

Review checklist

The following items are to be evaluated by the author(s) and the reviewer(s).

Correctness

  • Changes include appropriate documentation updates.
  • Changes are backward-compatible if not indicated, see CONTRIBUTING.md.
  • Changes do not include unsupported browser features, see CONTRIBUTING.md.
  • Changes were manually tested for accessibility, see accessibility guidelines.

Security

Testing

  • Changes are covered with new/existing unit tests?
  • Changes are covered with new/existing integration tests?

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@TrevorBurnham TrevorBurnham requested a review from a team as a code owner September 13, 2025 18:01
@TrevorBurnham TrevorBurnham requested review from cansuaa and removed request for a team September 13, 2025 18:01
@just-boris just-boris requested review from just-boris and removed request for cansuaa September 15, 2025 10:06
@TrevorBurnham TrevorBurnham force-pushed the fix-applayouttoolbar-breadcrumbs-ssr-glitch branch from b0f71d9 to 44fb6a1 Compare September 18, 2025 00:29
@TrevorBurnham
Copy link
Contributor Author

@just-boris I've updated this PR branch to consolidate duplicated code, and rebased against main.

@jperals
Copy link
Member

jperals commented Sep 24, 2025

There are some failing tests. @TrevorBurnham Can you take a look?

  • Unit tests: in src/app-layout/__tests__/main.test.tsx and src/app-layout/__tests__/skeleton.test.tsx
  • Integ tests: src/tabs/__integ__/with-iframe.test.ts

@just-boris just-boris requested review from jperals and removed request for just-boris September 25, 2025 09:14
@TrevorBurnham
Copy link
Contributor Author

@jperals I've updated the branch. Can you re-run the tests and see if they pass now?

contentElAttributes,
} = skeletonSlotsAttributes;

const isWidgetLoaded = !!appLayoutState.widgetizedState;
Copy link
Member

Choose a reason for hiding this comment

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

I think here we could reuse this isWidgetReady function:

export function isWidgetReady(state: AppLayoutPendingState): state is AppLayoutState {
return !!state.widgetizedState;
}


export function BreadcrumbsSlot({ ownBreadcrumbs, discoveredBreadcrumbs }: BreadcrumbsSlotProps) {
const isSSR = typeof window === 'undefined';
const contextValue = React.useMemo(() => ({ isInToolbar: true }), []);
Copy link
Member

Choose a reason for hiding this comment

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

Do we really need to use useMemo here? Unless we really know that the benefit outweighs the overhead, I would be inclined to simplify.

export function ToolbarBreadcrumbsWrapper({ children, includeTestUtils = false }: ToolbarBreadcrumbsWrapperProps) {
return (
<div
className={clsx(toolbarStyles['universal-toolbar-breadcrumbs'], includeTestUtils && testutilStyles.breadcrumbs)}
Copy link
Member

Choose a reason for hiding this comment

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

Why do we only add the testutilStyles.breadcrumbs class conditionally?

includeTestUtils?: boolean;
}

export function ToolbarBreadcrumbsWrapper({ children, includeTestUtils = false }: ToolbarBreadcrumbsWrapperProps) {
Copy link
Member

Choose a reason for hiding this comment

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

This component is only used once further down, so it does not need to be exported, or it could even be removed?

);
}

export function ToolbarDrawersWrapper() {
Copy link
Member

Choose a reason for hiding this comment

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

Also this is used only once below in the same file

discoveredBreadcrumbs={appLayoutInternals.discoveredBreadcrumbs}
/>
</ToolbarSlot>
<ToolbarSkeletonStructure
Copy link
Member

Choose a reason for hiding this comment

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

Codecov points at this line (34) and line 43 below as needing coverage. To be fair, it looks like they were already missing it. Is the change in line 43 necessary though?

ref={ref as React.Ref<any>}
className={clsx(styles['toolbar-container'], className)}
style={{
insetBlockStart: style?.insetBlockStart ?? 0,
Copy link
Member

Choose a reason for hiding this comment

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

Is this line the actual fix? Undefined was not behaving the same way as 0?

@TrevorBurnham
Copy link
Contributor Author

I've pushed another commit to try to address the Codecov CI failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants