Skip to content

Commit

Permalink
Update component gallery with grouping and list view (#2351)
Browse files Browse the repository at this point in the history
## 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
  • Loading branch information
nishasy authored Oct 24, 2024
1 parent bb7f7cf commit 1e2d70b
Show file tree
Hide file tree
Showing 55 changed files with 1,510 additions and 1,081 deletions.
2 changes: 2 additions & 0 deletions .changeset/slimy-glasses-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
6 changes: 6 additions & 0 deletions __docs__/_gallery_.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {Meta} from "@storybook/blocks";
import ComponentGallery from "./components/gallery/component-gallery";

<Meta title="Gallery" />
## Component Gallery
<ComponentGallery />
176 changes: 134 additions & 42 deletions __docs__/components/gallery/component-gallery.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,141 @@
import * as React from "react";

import {View} from "@khanacademy/wonder-blocks-core";

import AccordionGallerySection from "./sections/accordion-section";
import BannerSection from "./sections/banner-section";
import BirthdayPickerSection from "./sections/birthday-picker-section";
import BreadcrumbsSection from "./sections/breadcrumbs-section";
import ButtonSection from "./sections/button-section";
import CellSection from "./sections/cell-section";
import DropdownSection from "./sections/dropdown-section";
import FormSection from "./sections/form-section";
import IconButtonSection from "./sections/icon-button-section";
import IconSection from "./sections/icon-section";
import LinkSection from "./sections/link-section";
import ModalSection from "./sections/modal-section";
import PillSection from "./sections/pill-section";
import PopoverSection from "./sections/popover-section";
import ProgressSpinnerSection from "./sections/progress-spinner-section";
import SearchFieldSection from "./sections/search-field-section";
import SwitchSection from "./sections/switch-section";
import ToolbarSection from "./sections/toolbar-section";
import TooltipSection from "./sections/tooltip-section";
import {StyleSheet} from "aphrodite";
import {RenderStateRoot, View} from "@khanacademy/wonder-blocks-core";

import {spacing} from "@khanacademy/wonder-blocks-tokens";

import {packageGroups, functionGroups, alphabetGroups} from "./groups";
import {HeadingLarge, LabelMedium} from "@khanacademy/wonder-blocks-typography";
import {OptionItem, SingleSelect} from "@khanacademy/wonder-blocks-dropdown";
import {Spring, Strut} from "@khanacademy/wonder-blocks-layout";

import type {GroupMap} from "./groups";
import Banner from "@khanacademy/wonder-blocks-banner";
import Switch from "@khanacademy/wonder-blocks-switch";

export default function ComponentGallery() {
const groupMaps: Record<string, GroupMap[]> = {
package: packageGroups,
function: functionGroups,
alphabet: alphabetGroups,
};
const [currentGroup, setCurrentGroup] = React.useState("function");
const [currentLayout, setCurrentLayout] = React.useState<"grid" | "list">(
"grid",
);
const [compactGridView, setCompactGridView] = React.useState(false);

return (
<View>
<AccordionGallerySection />
<BannerSection />
<BirthdayPickerSection />
<BreadcrumbsSection />
<ButtonSection />
<CellSection />
<DropdownSection />
<FormSection />
<IconButtonSection />
<IconSection />
<LinkSection />
<ModalSection />
<PillSection />
<PopoverSection />
<ProgressSpinnerSection />
<SearchFieldSection />
<SwitchSection />
<ToolbarSection />
<TooltipSection />
</View>
<RenderStateRoot>
<View>
<Banner
kind="info"
layout="floating"
text={`Note: The core, data, translations, layout, testing,
theming, timing, tokens, and typography packages are not
featured in this gallery.`}
/>
<View style={styles.menuBar}>
<LabelMedium tag="label" style={styles.row}>
Group by
<Strut size={spacing.xSmall_8} />
<SingleSelect
selectedValue={currentGroup}
onChange={setCurrentGroup}
// Placehoder is not used here
placeholder=""
>
<OptionItem label="alphabet" value="alphabet" />
<OptionItem label="function" value="function" />
<OptionItem label="package" value="package" />
</SingleSelect>
</LabelMedium>
<Strut size={spacing.large_24} />

<LabelMedium tag="label" style={styles.row}>
Layout
<Strut size={spacing.xSmall_8} />
<SingleSelect
selectedValue={currentLayout}
onChange={(newValue) =>
setCurrentLayout(
newValue === "grid" ? "grid" : "list",
)
}
// Placehoder is not used here
placeholder=""
>
<OptionItem label="grid" value="grid" />
<OptionItem label="list" value="list" />
</SingleSelect>
</LabelMedium>

{currentLayout === "grid" && (
<>
<Spring />
<Switch
// This shouldn't need to be a unique ID, since
// it shoulbe the only compact grid switch on
// the page, and the page should not be
// rendered multiple times in one place.
id="wb-storybook-gallery-compact-grid-switch"
checked={compactGridView}
onChange={setCompactGridView}
/>
<Strut size={spacing.xSmall_8} />
<LabelMedium
tag="label"
htmlFor="wb-storybook-gallery-compact-grid-switch"
style={styles.row}
>
Compact grid
</LabelMedium>
</>
)}
</View>

{groupMaps[currentGroup].map((group) => (
<View key={group.name}>
<HeadingLarge tag="h3" style={styles.sectionLabel}>
{group.name}
</HeadingLarge>

<View style={styles.section}>
{group.components.map((Tile) => {
return (
<Tile
layout={currentLayout}
compactGrid={compactGridView}
/>
);
})}
</View>
</View>
))}
</View>
</RenderStateRoot>
);
}

export const styles = StyleSheet.create({
menuBar: {
marginTop: spacing.medium_16,
flexDirection: "row",
alignItems: "center",
},
section: {
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
},
sectionLabel: {
marginTop: spacing.xLarge_32,
marginBottom: spacing.large_24,
},
row: {
display: "flex",
flexDirection: "row",
alignItems: "center",
},
});
77 changes: 61 additions & 16 deletions __docs__/components/gallery/component-tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,51 @@ import Clickable from "@khanacademy/wonder-blocks-clickable";
import {View} from "@khanacademy/wonder-blocks-core";
import {PhosphorIcon} from "@khanacademy/wonder-blocks-icon";
import * as tokens from "@khanacademy/wonder-blocks-tokens";
import {Body, HeadingMedium} from "@khanacademy/wonder-blocks-typography";
import {Body, HeadingSmall} from "@khanacademy/wonder-blocks-typography";
import {DetailCell} from "@khanacademy/wonder-blocks-cell";
import {CommonTileProps} from "./types";
import {Spring} from "@khanacademy/wonder-blocks-layout";

type Props = {
type Props = CommonTileProps & {
children: React.ReactNode;
name: string;
description?: string;
href: string;
rightAccessory?: React.ReactNode;
};

export default function ComponentTile(props: Props) {
const {children, description, name, href} = props;
const {
children,
description,
name,
href,
rightAccessory,
layout,
compactGrid,
} = props;

if (layout === "list") {
return (
<DetailCell
title={name}
subtitle2={description}
leftAccessory={<PhosphorIcon icon={externalLinkIcon} />}
rightAccessory={rightAccessory}
href={href}
target="_blank"
/>
);
}

return (
<View style={styles.tile}>
<View
style={[
styles.tile,
compactGrid && styles.tileWithoutDetails,
!compactGrid && styles.tileWithDetails,
]}
>
<Clickable
href={href}
target="_blank"
Expand All @@ -27,18 +59,26 @@ export default function ComponentTile(props: Props) {
>
{() => (
<>
<View style={styles.description}>
<View
style={[
compactGrid && styles.descriptionWithoutDetails,
!compactGrid && styles.descriptionWithDetails,
]}
>
<View style={styles.headingContainer}>
<HeadingMedium tag="h4">{name}</HeadingMedium>
<HeadingSmall tag="h4">{name}</HeadingSmall>
<View style={styles.externalLinkIcon}>
<PhosphorIcon
icon={externalLinkIcon}
size="small"
aria-hidden="true"
/>
</View>
<Spring />
{rightAccessory}
</View>
{description && (

{!compactGrid && (
<Body style={styles.descriptionText}>
{description}
</Body>
Expand All @@ -59,14 +99,20 @@ const styles = StyleSheet.create({
display: "flex",
flexDirection: "column",
margin: tokens.spacing.xSmall_8,
// Set the width to half the max width of the stories page content.
width: 484,
minHeight: 300,

[mobile]: {
width: "95%",
},
},
tileWithDetails: {
// Set the width to half the max width of the stories page content.
width: 484,
minHeight: 300,
},
tileWithoutDetails: {
width: "auto",
height: "auto",
},
clickable: {
backgroundColor: tokens.color.offWhite,
border: `1px solid ${tokens.color.offBlack16}`,
Expand All @@ -83,11 +129,13 @@ const styles = StyleSheet.create({
outline: `1px solid ${tokens.color.blue}`,
},
},
description: {
descriptionWithDetails: {
padding: tokens.spacing.large_24,
},
descriptionWithoutDetails: {
padding: tokens.spacing.small_12,
},
headingContainer: {
width: "fit-content",
flexDirection: "row",
alignItems: "center",
},
Expand All @@ -103,12 +151,9 @@ const styles = StyleSheet.create({
borderEndStartRadius: tokens.spacing.small_12,
borderEndEndRadius: tokens.spacing.small_12,
flexGrow: 1,

[mobile]: {
overflowX: "scroll",
},
},
externalLinkIcon: {
marginLeft: tokens.spacing.xSmall_8,
marginRight: tokens.spacing.xSmall_8,
},
});
Loading

0 comments on commit 1e2d70b

Please sign in to comment.