Skip to content

Commit

Permalink
Wait for fonts before committing the view transition
Browse files Browse the repository at this point in the history
  • Loading branch information
sebmarkbage committed Jan 9, 2025
1 parent fd9cfa4 commit f6118c9
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 2 deletions.
10 changes: 10 additions & 0 deletions fixtures/view-transition/src/components/Chrome.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ export default class Chrome extends Component {
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" href="favicon.ico" />
<link rel="stylesheet" href={assets['main.css']} />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossOrigin=""
/>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap"
rel="stylesheet"
/>
<title>{this.props.title}</title>
</head>
<body>
Expand Down
8 changes: 8 additions & 0 deletions fixtures/view-transition/src/components/Page.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.roboto-font {
font-family: "Roboto", serif;
font-optical-sizing: auto;
font-weight: 100;
font-style: normal;
font-variation-settings:
"wdth" 100;
}
2 changes: 1 addition & 1 deletion fixtures/view-transition/src/components/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function Component() {
className={
transitions['enter-slide-right'] + ' ' + transitions['exit-slide-left']
}>
<p>Slide In from Left, Slide Out to Right</p>
<p className="roboto-font">Slide In from Left, Slide Out to Right</p>
</ViewTransition>
);
}
Expand Down
31 changes: 30 additions & 1 deletion packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,13 @@ export function hasInstanceAffectedParent(
return oldRect.height !== newRect.height || oldRect.width !== newRect.width;
}

// How long to wait for new fonts to load before just committing anyway.
// This freezes the screen. It needs to be short enough that it doesn't cause too much of
// an issue when it's a new load and slow, yet long enough that you have a chance to load
// it. Otherwise we wait for no reason. The assumption here is that you likely have
// either cached the font or preloaded it earlier.
const SUSPENSEY_FONT_TIMEOUT = 500;

export function startViewTransition(
rootContainer: Container,
mutationCallback: () => void,
Expand All @@ -1220,8 +1227,30 @@ export function startViewTransition(
const ownerWindow = ownerDocument.defaultView;
const pendingNavigation =
ownerWindow.navigation && ownerWindow.navigation.transition;
// $FlowFixMe[prop-missing]
const previousFontLoadingStatus = ownerDocument.fonts.status;
mutationCallback();
// TODO: Wait for fonts.
if (
previousFontLoadingStatus === 'loaded' && // $FlowFixMe[incompatible-use]
// Force layout calculation to trigger font loading.
(ownerDocument.documentElement.clientHeight,
// $FlowFixMe[prop-missing]
ownerDocument.fonts.status === 'loading')
) {
// The mutation lead to new fonts being loaded. We should wait on them before continuing.
// This avoids waiting for potentially unrelated fonts that were already loading before.
// Either in an earlier transition or as part of a sync optimistic state. This doesn't
// include preloads that happened earlier.
const fontsReady = Promise.race([
// $FlowFixMe[prop-missing]
ownerDocument.fonts.ready,
new Promise(resolve => setTimeout(resolve, SUSPENSEY_FONT_TIMEOUT)),
]).then(layoutCallback, layoutCallback);
const allReady = pendingNavigation
? Promise.allSettled([pendingNavigation.finished, fontsReady])
: fontsReady;
return allReady.then(afterMutationCallback, afterMutationCallback);
}
layoutCallback();
if (pendingNavigation) {
return pendingNavigation.finished.then(
Expand Down

0 comments on commit f6118c9

Please sign in to comment.