Skip to content

Commit cfce482

Browse files
fix: restore docs width before first paint (#1383)
1 parent b416acb commit cfce482

4 files changed

Lines changed: 71 additions & 3 deletions

File tree

‎src/components/LibraryLayout.tsx‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,18 @@ export function LibraryLayout({
14421442
)
14431443

14441444
return (
1445-
<WidthToggleContext.Provider value={{ isFullWidth, setIsFullWidth }}>
1445+
<WidthToggleContext.Provider
1446+
value={{
1447+
isFullWidth,
1448+
setIsFullWidth: (fullWidth) => {
1449+
document.documentElement.style.setProperty(
1450+
'--docs-content-width',
1451+
fullWidth ? '100%' : '900px',
1452+
)
1453+
setIsFullWidth(fullWidth)
1454+
},
1455+
}}
1456+
>
14461457
<DocNavigationContext.Provider
14471458
value={{
14481459
libraryId,
@@ -1480,8 +1491,7 @@ export function LibraryLayout({
14801491
!isLandingPage &&
14811492
!isExample &&
14821493
!isNpmStats &&
1483-
!isFullWidth &&
1484-
'mx-auto w-[900px]',
1494+
'mx-auto w-[var(--docs-content-width,900px)]',
14851495
)}
14861496
>
14871497
{children}

‎src/routes/__root.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import {
5555
} from '~/utils/analytics/scarf'
5656
import { createPartnerPlacementSessionSeed } from '~/utils/partner-placement'
5757
import { twMerge } from 'tailwind-merge'
58+
import { DOCS_WIDTH_BOOTSTRAP } from '~/utils/docs-width'
5859

5960
const GOOGLE_ANALYTICS_ID = 'G-JMT1Z50SPS'
6061
const GOOGLE_ANALYTICS_PROXY_PREFIX = '/_a'
@@ -356,6 +357,7 @@ function ShellComponent({ children }: { children: React.ReactNode }) {
356357
dangerouslySetInnerHTML={{ __html: THEME_BOOTSTRAP }}
357358
suppressHydrationWarning
358359
/>
360+
<script dangerouslySetInnerHTML={{ __html: DOCS_WIDTH_BOOTSTRAP }} />
359361
<HeadContent />
360362
{import.meta.env.PROD ? (
361363
<script

‎src/utils/docs-width.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Apply the saved width before the document can paint. Keep the storage shape
2+
// and expiry behavior in sync with useLocalStorage.
3+
export const DOCS_WIDTH_BOOTSTRAP = `(function(){try{var p=JSON.parse(localStorage.getItem('docsFullWidth'));if(p&&p.value===true&&(!p.ttl||Date.now()<=p.ttl)){document.documentElement.style.setProperty('--docs-content-width','100%')}}catch(e){}})()`

‎tests/docs-width.test.ts‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import assert from 'node:assert/strict'
2+
import { test } from 'node:test'
3+
import { runInNewContext } from 'node:vm'
4+
import { DOCS_WIDTH_BOOTSTRAP } from '../src/utils/docs-width'
5+
6+
function applyPreference(value: string | null, blocked = false) {
7+
const properties = new Map<string, string>()
8+
runInNewContext(DOCS_WIDTH_BOOTSTRAP, {
9+
localStorage: {
10+
getItem(key: string) {
11+
assert.equal(key, 'docsFullWidth')
12+
if (blocked) throw new Error('Storage is unavailable')
13+
return value
14+
},
15+
},
16+
document: {
17+
documentElement: {
18+
style: {
19+
setProperty(key: string, value: string) {
20+
properties.set(key, value)
21+
},
22+
},
23+
},
24+
},
25+
Date: { now: () => 1000 },
26+
})
27+
return properties.get('--docs-content-width')
28+
}
29+
30+
test('saved expanded width applies before React mounts', () => {
31+
assert.equal(applyPreference('{"value":true,"ttl":null}'), '100%')
32+
assert.equal(applyPreference('{"value":true}'), '100%')
33+
assert.equal(applyPreference('{"value":true,"ttl":1000}'), '100%')
34+
assert.equal(applyPreference('{"value":true,"ttl":2000}'), '100%')
35+
})
36+
37+
test('constrained, missing, expired and invalid preferences retain the default width', () => {
38+
for (const value of [
39+
null,
40+
'null',
41+
'{}',
42+
'invalid json',
43+
'{"value":false}',
44+
'{"value":"true"}',
45+
'{"value":true,"ttl":999}',
46+
]) {
47+
assert.equal(applyPreference(value), undefined)
48+
}
49+
})
50+
51+
test('blocked storage does not interrupt document initialization', () => {
52+
assert.equal(applyPreference(null, true), undefined)
53+
})

0 commit comments

Comments
 (0)