Skip to content

Commit f6118c9

Browse files
committed
Wait for fonts before committing the view transition
1 parent fd9cfa4 commit f6118c9

File tree

4 files changed

+49
-2
lines changed

4 files changed

+49
-2
lines changed

fixtures/view-transition/src/components/Chrome.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ export default class Chrome extends Component {
1212
<meta name="viewport" content="width=device-width, initial-scale=1" />
1313
<link rel="shortcut icon" href="favicon.ico" />
1414
<link rel="stylesheet" href={assets['main.css']} />
15+
<link rel="preconnect" href="https://fonts.googleapis.com" />
16+
<link
17+
rel="preconnect"
18+
href="https://fonts.gstatic.com"
19+
crossOrigin=""
20+
/>
21+
<link
22+
href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap"
23+
rel="stylesheet"
24+
/>
1525
<title>{this.props.title}</title>
1626
</head>
1727
<body>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.roboto-font {
2+
font-family: "Roboto", serif;
3+
font-optical-sizing: auto;
4+
font-weight: 100;
5+
font-style: normal;
6+
font-variation-settings:
7+
"wdth" 100;
8+
}

fixtures/view-transition/src/components/Page.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function Component() {
2929
className={
3030
transitions['enter-slide-right'] + ' ' + transitions['exit-slide-left']
3131
}>
32-
<p>Slide In from Left, Slide Out to Right</p>
32+
<p className="roboto-font">Slide In from Left, Slide Out to Right</p>
3333
</ViewTransition>
3434
);
3535
}

packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,13 @@ export function hasInstanceAffectedParent(
11981198
return oldRect.height !== newRect.height || oldRect.width !== newRect.width;
11991199
}
12001200

1201+
// How long to wait for new fonts to load before just committing anyway.
1202+
// This freezes the screen. It needs to be short enough that it doesn't cause too much of
1203+
// an issue when it's a new load and slow, yet long enough that you have a chance to load
1204+
// it. Otherwise we wait for no reason. The assumption here is that you likely have
1205+
// either cached the font or preloaded it earlier.
1206+
const SUSPENSEY_FONT_TIMEOUT = 500;
1207+
12011208
export function startViewTransition(
12021209
rootContainer: Container,
12031210
mutationCallback: () => void,
@@ -1220,8 +1227,30 @@ export function startViewTransition(
12201227
const ownerWindow = ownerDocument.defaultView;
12211228
const pendingNavigation =
12221229
ownerWindow.navigation && ownerWindow.navigation.transition;
1230+
// $FlowFixMe[prop-missing]
1231+
const previousFontLoadingStatus = ownerDocument.fonts.status;
12231232
mutationCallback();
1224-
// TODO: Wait for fonts.
1233+
if (
1234+
previousFontLoadingStatus === 'loaded' && // $FlowFixMe[incompatible-use]
1235+
// Force layout calculation to trigger font loading.
1236+
(ownerDocument.documentElement.clientHeight,
1237+
// $FlowFixMe[prop-missing]
1238+
ownerDocument.fonts.status === 'loading')
1239+
) {
1240+
// The mutation lead to new fonts being loaded. We should wait on them before continuing.
1241+
// This avoids waiting for potentially unrelated fonts that were already loading before.
1242+
// Either in an earlier transition or as part of a sync optimistic state. This doesn't
1243+
// include preloads that happened earlier.
1244+
const fontsReady = Promise.race([
1245+
// $FlowFixMe[prop-missing]
1246+
ownerDocument.fonts.ready,
1247+
new Promise(resolve => setTimeout(resolve, SUSPENSEY_FONT_TIMEOUT)),
1248+
]).then(layoutCallback, layoutCallback);
1249+
const allReady = pendingNavigation
1250+
? Promise.allSettled([pendingNavigation.finished, fontsReady])
1251+
: fontsReady;
1252+
return allReady.then(afterMutationCallback, afterMutationCallback);
1253+
}
12251254
layoutCallback();
12261255
if (pendingNavigation) {
12271256
return pendingNavigation.finished.then(

0 commit comments

Comments
 (0)