Skip to content

Commit 1e2d70b

Browse files
authored
Update component gallery with grouping and list view (#2351)
## Summary: Hackathon project! I [added the component gallery](#2102) to the overview page last year, and I've been wanting to make some updates to it for a while. - Allow grouping by function rather than package - Also added alphabetical grouping - Added list view - Added compact gallery view to it's easier to see more components at once - Also added a seperate page for it in case people just never scrolled down to it in the overview page. Issue: none ## Test plan: Storybook - http://localhost:6061/?path=/docs/overview--docs - http://localhost:6061/?path=/docs/gallery--docs <img width="1098" alt="image" src="https://github.com/user-attachments/assets/7e1d1aa0-786c-4859-a643-35a613c58735"> Author: nishasy Reviewers: jandrade, nishasy Required Reviewers: Approved By: jandrade Checks: ✅ Chromatic - Get results on regular PRs (ubuntu-latest, 20.x), ✅ Lint / Lint (ubuntu-latest, 20.x), ✅ Test / Test (ubuntu-latest, 20.x, 2/2), ✅ Test / Test (ubuntu-latest, 20.x, 1/2), ✅ Check build sizes (ubuntu-latest, 20.x), ✅ Chromatic - Build on regular PRs / chromatic (ubuntu-latest, 20.x), ✅ Publish npm snapshot (ubuntu-latest, 20.x), ⏭️ Chromatic - Skip on Release PR (changesets), ✅ Prime node_modules cache for primary configuration (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ gerald, ⏭️ dependabot Pull Request URL: #2351
1 parent bb7f7cf commit 1e2d70b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1510
-1081
lines changed

.changeset/slimy-glasses-buy.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

__docs__/_gallery_.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import {Meta} from "@storybook/blocks";
2+
import ComponentGallery from "./components/gallery/component-gallery";
3+
4+
<Meta title="Gallery" />
5+
## Component Gallery
6+
<ComponentGallery />
Lines changed: 134 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,141 @@
11
import * as React from "react";
22

3-
import {View} from "@khanacademy/wonder-blocks-core";
4-
5-
import AccordionGallerySection from "./sections/accordion-section";
6-
import BannerSection from "./sections/banner-section";
7-
import BirthdayPickerSection from "./sections/birthday-picker-section";
8-
import BreadcrumbsSection from "./sections/breadcrumbs-section";
9-
import ButtonSection from "./sections/button-section";
10-
import CellSection from "./sections/cell-section";
11-
import DropdownSection from "./sections/dropdown-section";
12-
import FormSection from "./sections/form-section";
13-
import IconButtonSection from "./sections/icon-button-section";
14-
import IconSection from "./sections/icon-section";
15-
import LinkSection from "./sections/link-section";
16-
import ModalSection from "./sections/modal-section";
17-
import PillSection from "./sections/pill-section";
18-
import PopoverSection from "./sections/popover-section";
19-
import ProgressSpinnerSection from "./sections/progress-spinner-section";
20-
import SearchFieldSection from "./sections/search-field-section";
21-
import SwitchSection from "./sections/switch-section";
22-
import ToolbarSection from "./sections/toolbar-section";
23-
import TooltipSection from "./sections/tooltip-section";
3+
import {StyleSheet} from "aphrodite";
4+
import {RenderStateRoot, View} from "@khanacademy/wonder-blocks-core";
5+
6+
import {spacing} from "@khanacademy/wonder-blocks-tokens";
7+
8+
import {packageGroups, functionGroups, alphabetGroups} from "./groups";
9+
import {HeadingLarge, LabelMedium} from "@khanacademy/wonder-blocks-typography";
10+
import {OptionItem, SingleSelect} from "@khanacademy/wonder-blocks-dropdown";
11+
import {Spring, Strut} from "@khanacademy/wonder-blocks-layout";
12+
13+
import type {GroupMap} from "./groups";
14+
import Banner from "@khanacademy/wonder-blocks-banner";
15+
import Switch from "@khanacademy/wonder-blocks-switch";
2416

2517
export default function ComponentGallery() {
18+
const groupMaps: Record<string, GroupMap[]> = {
19+
package: packageGroups,
20+
function: functionGroups,
21+
alphabet: alphabetGroups,
22+
};
23+
const [currentGroup, setCurrentGroup] = React.useState("function");
24+
const [currentLayout, setCurrentLayout] = React.useState<"grid" | "list">(
25+
"grid",
26+
);
27+
const [compactGridView, setCompactGridView] = React.useState(false);
28+
2629
return (
27-
<View>
28-
<AccordionGallerySection />
29-
<BannerSection />
30-
<BirthdayPickerSection />
31-
<BreadcrumbsSection />
32-
<ButtonSection />
33-
<CellSection />
34-
<DropdownSection />
35-
<FormSection />
36-
<IconButtonSection />
37-
<IconSection />
38-
<LinkSection />
39-
<ModalSection />
40-
<PillSection />
41-
<PopoverSection />
42-
<ProgressSpinnerSection />
43-
<SearchFieldSection />
44-
<SwitchSection />
45-
<ToolbarSection />
46-
<TooltipSection />
47-
</View>
30+
<RenderStateRoot>
31+
<View>
32+
<Banner
33+
kind="info"
34+
layout="floating"
35+
text={`Note: The core, data, translations, layout, testing,
36+
theming, timing, tokens, and typography packages are not
37+
featured in this gallery.`}
38+
/>
39+
<View style={styles.menuBar}>
40+
<LabelMedium tag="label" style={styles.row}>
41+
Group by
42+
<Strut size={spacing.xSmall_8} />
43+
<SingleSelect
44+
selectedValue={currentGroup}
45+
onChange={setCurrentGroup}
46+
// Placehoder is not used here
47+
placeholder=""
48+
>
49+
<OptionItem label="alphabet" value="alphabet" />
50+
<OptionItem label="function" value="function" />
51+
<OptionItem label="package" value="package" />
52+
</SingleSelect>
53+
</LabelMedium>
54+
<Strut size={spacing.large_24} />
55+
56+
<LabelMedium tag="label" style={styles.row}>
57+
Layout
58+
<Strut size={spacing.xSmall_8} />
59+
<SingleSelect
60+
selectedValue={currentLayout}
61+
onChange={(newValue) =>
62+
setCurrentLayout(
63+
newValue === "grid" ? "grid" : "list",
64+
)
65+
}
66+
// Placehoder is not used here
67+
placeholder=""
68+
>
69+
<OptionItem label="grid" value="grid" />
70+
<OptionItem label="list" value="list" />
71+
</SingleSelect>
72+
</LabelMedium>
73+
74+
{currentLayout === "grid" && (
75+
<>
76+
<Spring />
77+
<Switch
78+
// This shouldn't need to be a unique ID, since
79+
// it shoulbe the only compact grid switch on
80+
// the page, and the page should not be
81+
// rendered multiple times in one place.
82+
id="wb-storybook-gallery-compact-grid-switch"
83+
checked={compactGridView}
84+
onChange={setCompactGridView}
85+
/>
86+
<Strut size={spacing.xSmall_8} />
87+
<LabelMedium
88+
tag="label"
89+
htmlFor="wb-storybook-gallery-compact-grid-switch"
90+
style={styles.row}
91+
>
92+
Compact grid
93+
</LabelMedium>
94+
</>
95+
)}
96+
</View>
97+
98+
{groupMaps[currentGroup].map((group) => (
99+
<View key={group.name}>
100+
<HeadingLarge tag="h3" style={styles.sectionLabel}>
101+
{group.name}
102+
</HeadingLarge>
103+
104+
<View style={styles.section}>
105+
{group.components.map((Tile) => {
106+
return (
107+
<Tile
108+
layout={currentLayout}
109+
compactGrid={compactGridView}
110+
/>
111+
);
112+
})}
113+
</View>
114+
</View>
115+
))}
116+
</View>
117+
</RenderStateRoot>
48118
);
49119
}
120+
121+
export const styles = StyleSheet.create({
122+
menuBar: {
123+
marginTop: spacing.medium_16,
124+
flexDirection: "row",
125+
alignItems: "center",
126+
},
127+
section: {
128+
display: "flex",
129+
flexDirection: "row",
130+
flexWrap: "wrap",
131+
},
132+
sectionLabel: {
133+
marginTop: spacing.xLarge_32,
134+
marginBottom: spacing.large_24,
135+
},
136+
row: {
137+
display: "flex",
138+
flexDirection: "row",
139+
alignItems: "center",
140+
},
141+
});

__docs__/components/gallery/component-tile.tsx

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,51 @@ import Clickable from "@khanacademy/wonder-blocks-clickable";
66
import {View} from "@khanacademy/wonder-blocks-core";
77
import {PhosphorIcon} from "@khanacademy/wonder-blocks-icon";
88
import * as tokens from "@khanacademy/wonder-blocks-tokens";
9-
import {Body, HeadingMedium} from "@khanacademy/wonder-blocks-typography";
9+
import {Body, HeadingSmall} from "@khanacademy/wonder-blocks-typography";
10+
import {DetailCell} from "@khanacademy/wonder-blocks-cell";
11+
import {CommonTileProps} from "./types";
12+
import {Spring} from "@khanacademy/wonder-blocks-layout";
1013

11-
type Props = {
14+
type Props = CommonTileProps & {
1215
children: React.ReactNode;
1316
name: string;
1417
description?: string;
1518
href: string;
19+
rightAccessory?: React.ReactNode;
1620
};
1721

1822
export default function ComponentTile(props: Props) {
19-
const {children, description, name, href} = props;
23+
const {
24+
children,
25+
description,
26+
name,
27+
href,
28+
rightAccessory,
29+
layout,
30+
compactGrid,
31+
} = props;
32+
33+
if (layout === "list") {
34+
return (
35+
<DetailCell
36+
title={name}
37+
subtitle2={description}
38+
leftAccessory={<PhosphorIcon icon={externalLinkIcon} />}
39+
rightAccessory={rightAccessory}
40+
href={href}
41+
target="_blank"
42+
/>
43+
);
44+
}
45+
2046
return (
21-
<View style={styles.tile}>
47+
<View
48+
style={[
49+
styles.tile,
50+
compactGrid && styles.tileWithoutDetails,
51+
!compactGrid && styles.tileWithDetails,
52+
]}
53+
>
2254
<Clickable
2355
href={href}
2456
target="_blank"
@@ -27,18 +59,26 @@ export default function ComponentTile(props: Props) {
2759
>
2860
{() => (
2961
<>
30-
<View style={styles.description}>
62+
<View
63+
style={[
64+
compactGrid && styles.descriptionWithoutDetails,
65+
!compactGrid && styles.descriptionWithDetails,
66+
]}
67+
>
3168
<View style={styles.headingContainer}>
32-
<HeadingMedium tag="h4">{name}</HeadingMedium>
69+
<HeadingSmall tag="h4">{name}</HeadingSmall>
3370
<View style={styles.externalLinkIcon}>
3471
<PhosphorIcon
3572
icon={externalLinkIcon}
3673
size="small"
3774
aria-hidden="true"
3875
/>
3976
</View>
77+
<Spring />
78+
{rightAccessory}
4079
</View>
41-
{description && (
80+
81+
{!compactGrid && (
4282
<Body style={styles.descriptionText}>
4383
{description}
4484
</Body>
@@ -59,14 +99,20 @@ const styles = StyleSheet.create({
5999
display: "flex",
60100
flexDirection: "column",
61101
margin: tokens.spacing.xSmall_8,
62-
// Set the width to half the max width of the stories page content.
63-
width: 484,
64-
minHeight: 300,
65102

66103
[mobile]: {
67104
width: "95%",
68105
},
69106
},
107+
tileWithDetails: {
108+
// Set the width to half the max width of the stories page content.
109+
width: 484,
110+
minHeight: 300,
111+
},
112+
tileWithoutDetails: {
113+
width: "auto",
114+
height: "auto",
115+
},
70116
clickable: {
71117
backgroundColor: tokens.color.offWhite,
72118
border: `1px solid ${tokens.color.offBlack16}`,
@@ -83,11 +129,13 @@ const styles = StyleSheet.create({
83129
outline: `1px solid ${tokens.color.blue}`,
84130
},
85131
},
86-
description: {
132+
descriptionWithDetails: {
87133
padding: tokens.spacing.large_24,
88134
},
135+
descriptionWithoutDetails: {
136+
padding: tokens.spacing.small_12,
137+
},
89138
headingContainer: {
90-
width: "fit-content",
91139
flexDirection: "row",
92140
alignItems: "center",
93141
},
@@ -103,12 +151,9 @@ const styles = StyleSheet.create({
103151
borderEndStartRadius: tokens.spacing.small_12,
104152
borderEndEndRadius: tokens.spacing.small_12,
105153
flexGrow: 1,
106-
107-
[mobile]: {
108-
overflowX: "scroll",
109-
},
110154
},
111155
externalLinkIcon: {
112156
marginLeft: tokens.spacing.xSmall_8,
157+
marginRight: tokens.spacing.xSmall_8,
113158
},
114159
});

0 commit comments

Comments
 (0)