Skip to content

Commit b24c97a

Browse files
Defer Charts docs runtime until interaction (#1131)
1 parent 9ab7a51 commit b24c97a

3 files changed

Lines changed: 37 additions & 38 deletions

File tree

src/components/charts/ChartsCatalogDocExample.client.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,25 @@ const LazyExampleWorkbench = React.lazy(() =>
1313

1414
export function ChartsCatalogDocExampleClient({
1515
caseId,
16+
edit,
1617
fallback,
1718
height,
1819
source,
1920
title,
2021
}: {
2122
caseId: string
23+
edit: boolean
2224
fallback: React.ReactNode
2325
height: number
2426
source: 'hidden' | 'collapsed' | 'expanded'
2527
title?: string
2628
}) {
2729
const [definition, setDefinition] = React.useState<ExampleDefinition>()
28-
const [editing, setEditing] = React.useState(source === 'expanded')
30+
const [editing, setEditing] = React.useState(edit)
2931

3032
React.useEffect(() => {
31-
setEditing(source === 'expanded')
32-
}, [caseId, source])
33+
setEditing(edit)
34+
}, [caseId, edit])
3335

3436
React.useEffect(() => {
3537
let cancelled = false

src/components/charts/ChartsCatalogDocExample.tsx

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ClientOnly } from '@tanstack/react-router'
22
import * as React from 'react'
33
import { ChartsCatalogPreview } from './ChartsCatalogPreview'
4+
import { Button } from '~/components/ds/ui'
45

56
const LazyChartsCatalogDocExample = React.lazy(() =>
67
import('./ChartsCatalogDocExample.client').then((module) => ({
@@ -19,45 +20,30 @@ export function ChartsCatalogDocExample({
1920
source?: 'hidden' | 'collapsed' | 'expanded'
2021
title?: string
2122
}) {
22-
const containerRef = React.useRef<HTMLElement>(null)
23-
const [shouldLoad, setShouldLoad] = React.useState(false)
23+
const [activation, setActivation] = React.useState<{
24+
caseId: string
25+
edit: boolean
26+
}>()
27+
const isActive = activation?.caseId === caseId
2428
const fallback = (
2529
<ChartsCatalogDocExampleFallback
2630
caseId={caseId}
2731
height={height}
32+
onEdit={() => setActivation({ caseId, edit: true })}
33+
onRun={() => setActivation({ caseId, edit: false })}
2834
source={source}
2935
title={title}
3036
/>
3137
)
3238

33-
React.useEffect(() => {
34-
const container = containerRef.current
35-
if (shouldLoad || !container) return
36-
37-
if (!('IntersectionObserver' in window)) {
38-
setShouldLoad(true)
39-
return
40-
}
41-
42-
const observer = new IntersectionObserver(
43-
(entries) => {
44-
if (!entries.some((entry) => entry.isIntersecting)) return
45-
setShouldLoad(true)
46-
observer.disconnect()
47-
},
48-
{ rootMargin: '320px 0px' },
49-
)
50-
observer.observe(container)
51-
return () => observer.disconnect()
52-
}, [shouldLoad])
53-
5439
return (
55-
<section ref={containerRef} className="not-prose my-5">
56-
{shouldLoad ? (
40+
<section className="not-prose my-5">
41+
{isActive ? (
5742
<ClientOnly fallback={fallback}>
5843
<React.Suspense fallback={fallback}>
5944
<LazyChartsCatalogDocExample
6045
caseId={caseId}
46+
edit={activation.edit}
6147
fallback={fallback}
6248
height={height}
6349
source={source}
@@ -75,11 +61,15 @@ export function ChartsCatalogDocExample({
7561
function ChartsCatalogDocExampleFallback({
7662
caseId,
7763
height,
64+
onEdit,
65+
onRun,
7866
source,
7967
title,
8068
}: {
8169
caseId: string
8270
height: number
71+
onEdit: () => void
72+
onRun: () => void
8373
source: 'hidden' | 'collapsed' | 'expanded'
8474
title?: string
8575
}) {
@@ -90,19 +80,25 @@ function ChartsCatalogDocExampleFallback({
9080
className="overflow-hidden rounded-lg border border-border-default bg-background-default"
9181
data-chart-example={caseId}
9282
>
93-
{source !== 'hidden' ? (
94-
<div className="flex min-h-10 items-center justify-between gap-3 border-b border-border-default px-3">
83+
<div
84+
className={`flex min-h-10 items-center gap-3 border-b border-border-default px-2 ${source === 'hidden' ? 'justify-end' : 'justify-between pl-3'}`}
85+
>
86+
{source !== 'hidden' ? (
9587
<span className="min-w-0 truncate font-ds-mono text-xs text-text-muted">
9688
{label}
9789
</span>
98-
<a
99-
className="shrink-0 text-xs font-medium text-text-secondary hover:text-text-primary"
100-
href={`/charts/catalog/charts/${caseId}`}
101-
>
102-
Open example
103-
</a>
90+
) : null}
91+
<div className="flex shrink-0 items-center gap-1">
92+
{source !== 'hidden' ? (
93+
<Button type="button" variant="ghost" size="xs" onClick={onEdit}>
94+
Edit
95+
</Button>
96+
) : null}
97+
<Button type="button" variant="primary" size="xs" onClick={onRun}>
98+
Run
99+
</Button>
104100
</div>
105-
) : null}
101+
</div>
106102
<div aria-label={`${label} chart preview`} role="img" style={{ height }}>
107103
<ChartsCatalogPreview caseId={caseId} className="p-8" family="" />
108104
</div>

tests/charts-catalog-frame-embedding.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ test('chart example comments retain a useful static document', () => {
163163
assert.match(html, /data-chart-example="01-line-gaps"/)
164164
assert.match(html, /data-catalog-preview-case="01-line-gaps"/)
165165
assert.match(html, /height:480px/)
166-
assert.match(html, /Open example/)
166+
assert.match(html, />Edit</)
167+
assert.match(html, />Run</)
167168
assert.doesNotMatch(html, /<iframe/)
168169
})
169170

0 commit comments

Comments
 (0)