Skip to content

Commit 97fb5a4

Browse files
committed
Add documentation page for the lazy utility
1 parent 3b94591 commit 97fb5a4

File tree

5 files changed

+236
-0
lines changed

5 files changed

+236
-0
lines changed

src/pattern-library/components/PlaygroundApp.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export default function PlaygroundApp({
147147
const prototypeRoutes = getRoutes('prototype');
148148

149149
const hookRoutes = getRoutes('hooks');
150+
const utilityRoutes = getRoutes('utilities');
150151

151152
const groupKeys = Object.keys(componentGroups) as Array<
152153
keyof typeof componentGroups
@@ -204,6 +205,13 @@ export default function PlaygroundApp({
204205
))}
205206
</NavList>
206207

208+
<NavHeader>Utilities</NavHeader>
209+
<NavList>
210+
{utilityRoutes.map(route => (
211+
<NavLink key={route.title} route={route} />
212+
))}
213+
</NavList>
214+
207215
{prototypeRoutes.length > 0 && (
208216
<>
209217
<NavHeader>Prototypes</NavHeader>
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import Library from '../../Library';
2+
3+
export default function LazyPage() {
4+
return (
5+
<Library.Page
6+
title="lazy"
7+
intro={
8+
<p>
9+
The <code>lazy</code> utility creates a component which is loaded
10+
asynchronously, displaying fallback content while loading and showing
11+
an error fallback if the component fails to load.
12+
</p>
13+
}
14+
>
15+
<Library.Section title="API">
16+
<Library.Code
17+
content={`function lazy<P>(
18+
displayName: string,
19+
load: () => Promise<FunctionalComponent<P>>,
20+
options: LazyOptions<P>
21+
): FunctionalComponent<P>`}
22+
title="Function signature"
23+
/>
24+
25+
<Library.SectionL2 title="Parameters">
26+
<Library.SectionL3 title="displayName">
27+
<Library.Info>
28+
<Library.InfoItem label="description">
29+
Display name for the lazy wrapper component.
30+
</Library.InfoItem>
31+
<Library.InfoItem label="type">
32+
<code>string</code>
33+
</Library.InfoItem>
34+
</Library.Info>
35+
</Library.SectionL3>
36+
37+
<Library.SectionL3 title="load">
38+
<Library.Info>
39+
<Library.InfoItem label="description">
40+
Callback invoked on first render to load the component. This
41+
returns a promise resolving to the loaded component. A common
42+
use case is to use an <code>import(...)</code> expression to
43+
load the component.
44+
</Library.InfoItem>
45+
<Library.InfoItem label="type">
46+
<code>{'() => Promise<FunctionalComponent<P>>'}</code>
47+
</Library.InfoItem>
48+
</Library.Info>
49+
</Library.SectionL3>
50+
51+
<Library.SectionL3 title="options">
52+
<Library.Info>
53+
<Library.InfoItem label="description">
54+
Configuration for the lazy component
55+
</Library.InfoItem>
56+
<Library.InfoItem label="type">
57+
<code>LazyOptions&lt;P&gt;</code>
58+
</Library.InfoItem>
59+
</Library.Info>
60+
</Library.SectionL3>
61+
</Library.SectionL2>
62+
63+
<Library.SectionL2 title="LazyOptions">
64+
<Library.SectionL3 title="fallback">
65+
<Library.Info>
66+
<Library.InfoItem label="description">
67+
Function that returns content to display while loading
68+
</Library.InfoItem>
69+
<Library.InfoItem label="type">
70+
<code>{'(props: P) => ComponentChildren'}</code>
71+
</Library.InfoItem>
72+
</Library.Info>
73+
</Library.SectionL3>
74+
75+
<Library.SectionL3 title="errorFallback">
76+
<Library.Info>
77+
<Library.InfoItem label="description">
78+
Function that returns content to display if loading fails
79+
</Library.InfoItem>
80+
<Library.InfoItem label="type">
81+
<code>
82+
{
83+
'((props: P, error: Error) => ComponentChildren) | undefined'
84+
}
85+
</code>
86+
</Library.InfoItem>
87+
<Library.InfoItem label="default">
88+
<code>undefined</code>
89+
</Library.InfoItem>
90+
</Library.Info>
91+
</Library.SectionL3>
92+
</Library.SectionL2>
93+
</Library.Section>
94+
95+
<Library.Section title="Examples">
96+
<Library.SectionL2 title="Basic usage">
97+
<p>
98+
Lazy components start loading on first render, and show a fallback
99+
while loading.
100+
</p>
101+
<Library.Demo
102+
title="Basic lazy component"
103+
exampleFile="lazy-basic"
104+
withSource
105+
/>
106+
</Library.SectionL2>
107+
108+
<Library.SectionL2 title="Error handling">
109+
<p>If a component fails to load, the error fallback is displayed:</p>
110+
<Library.Demo
111+
title="Component with error state"
112+
exampleFile="lazy-error-handling"
113+
withSource
114+
/>
115+
</Library.SectionL2>
116+
</Library.Section>
117+
</Library.Page>
118+
);
119+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Button, lazy } from '../../';
2+
3+
type ProfileProps = {
4+
name: string;
5+
description: string;
6+
};
7+
8+
function Profile({ name, description }: ProfileProps) {
9+
return (
10+
<div className="p-4 border border-green-500 rounded">
11+
<h3 className="text-green-700 font-bold">{name}</h3>
12+
<p>{description}</p>
13+
</div>
14+
);
15+
}
16+
17+
let resolve: (x: typeof Profile) => void;
18+
const promise = new Promise<typeof Profile>(resolve_ => (resolve = resolve_));
19+
20+
const LazyProfile = lazy('Profile', () => promise, {
21+
fallback: ({ name }) => (
22+
<div className="p-4 border border-gray-300 rounded">
23+
<p className="text-gray-500 mt-2">
24+
Loading {name}
25+
{"'"}s profile...
26+
</p>
27+
</div>
28+
),
29+
});
30+
31+
export default function App() {
32+
return (
33+
<div>
34+
<Button onClick={() => resolve(Profile)} variant="primary" classes="my-2">
35+
Finish loading
36+
</Button>
37+
<LazyProfile
38+
name="Bob Parr"
39+
description="Robert Parr, also known as Mr. Incredible, is the husband of Helen Parr, and the father of Violet Parr, Dash Parr, and Jack-Jack Parr."
40+
/>
41+
</div>
42+
);
43+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Button, lazy } from '../../';
2+
3+
type ProfileProps = {
4+
name: string;
5+
description: string;
6+
};
7+
8+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
9+
function Profile({ name, description }: ProfileProps) {
10+
return (
11+
<div className="p-4 border border-green-500 rounded">
12+
<h3 className="text-green-700 font-bold">{name}</h3>
13+
<p>{description}</p>
14+
</div>
15+
);
16+
}
17+
18+
let reject: (err: Error) => void;
19+
const promise = new Promise<typeof Profile>(
20+
(_resolve, reject_) => (reject = reject_),
21+
);
22+
23+
const LazyProfile = lazy('Profile', () => promise, {
24+
fallback: ({ name }) => (
25+
<div className="p-4 border border-gray-300 rounded">
26+
<p className="text-gray-500 mt-2">
27+
Loading {name}
28+
{"'"}s profile...
29+
</p>
30+
</div>
31+
),
32+
errorFallback: ({ name }, error) => (
33+
<div className="p-4 border border-red-300 rounded">
34+
<p className="text-gray-500 mt-2">
35+
Unable to load {name}
36+
{"'"}s profile: {error.message}
37+
</p>
38+
</div>
39+
),
40+
});
41+
42+
export default function App() {
43+
return (
44+
<div>
45+
<Button
46+
onClick={() => reject(new Error('Something went wrong'))}
47+
variant="primary"
48+
classes="my-2"
49+
>
50+
Trigger loading error
51+
</Button>
52+
<LazyProfile
53+
name="Bob Parr"
54+
description="Robert Parr, also known as Mr. Incredible, is the husband of Helen Parr, and the father of Violet Parr, Dash Parr, and Jack-Jack Parr."
55+
/>
56+
</div>
57+
);
58+
}

src/pattern-library/routes.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import PaginationPage from './components/patterns/navigation/PaginationPage';
3535
import PointerButtonPage from './components/patterns/navigation/PointerButtonPage';
3636
import TabPage from './components/patterns/navigation/TabPage';
3737
import SliderPage from './components/patterns/transition/SliderPage';
38+
import LazyPage from './components/patterns/utilities/LazyPage';
3839

3940
export const componentGroups = {
4041
data: 'Data Display',
@@ -53,6 +54,7 @@ export type PlaygroundRouteGroup =
5354
| 'foundations'
5455
| 'components'
5556
| 'hooks'
57+
| 'utilities'
5658
| 'prototype'
5759
| 'custom';
5860

@@ -280,6 +282,12 @@ const routes: PlaygroundRoute[] = [
280282
component: UseClickAwayPage,
281283
route: '/hooks-use-click-away',
282284
},
285+
{
286+
title: 'lazy',
287+
group: 'utilities',
288+
component: LazyPage,
289+
route: '/utilities-lazy',
290+
},
283291
];
284292

285293
/**

0 commit comments

Comments
 (0)