Skip to content

Commit

Permalink
Updates per PR feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviawongnyc committed Dec 6, 2024
1 parent 7a4da94 commit dc3c8cf
Show file tree
Hide file tree
Showing 10 changed files with 434 additions and 292 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Currently, this repo is in Prerelease. When it is released, this project will ad

### Updates

- Updates `Template` component(s) and styles per [TAD](https://docs.google.com/document/d/1vZJX7Y-DnEM44-iWw5qoXGdxqavHEN6prhr-YDTNr0o/edit?pli=1&tab=t.0).
- [Updates `Template` component(s)](<(https://newyorkpubliclibrary.atlassian.net/browse/DSD-1884)>) and styles per TAD.

## 3.5.0 (December 5, 2024)

Expand Down
27 changes: 17 additions & 10 deletions src/components/Template/Template.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import Link from "../Link/Link";

## Template Overview

TBD
### Using the `Template` with the `Header` and `Footer`

<Source
code={`
Expand All @@ -46,14 +46,18 @@ import {
TemplateMain,
TemplateBottom
} from "@nypl/design-system-react-components";
<Template sidebar="...">
<TemplateBreakout>// ...</TemplateBreakout>
<TemplateTop>// ...</TemplateTop>
<TemplateSidebar>// ...</TemplateSidebar>
<TemplateMain>// ...</TemplateMain>
<TemplateBottom>// ...</TemplateBottom>
</Template>
//...
<>
<SkipNavigation />
<Template sidebar="...">
<TemplateBreakout>...</TemplateBreakout>
<TemplateTop>...</TemplateTop>
<TemplateSidebar>...</TemplateSidebar>
<TemplateMain>...</TemplateMain>
<TemplateBottom>...</TemplateBottom>
</Template>
</>
`} language="jsx" />

## Template Props
Expand Down Expand Up @@ -81,6 +85,9 @@ breaking a reader's rhythm. The `TemplateMain` component has a max width of 1280
which is too wide for text. If your content includes long chunks of text, you
should use the `TemplateMainNarrow` component instead.

This means you may use `TemplateMain` or `TemplateMainNarrow` depending on your needs,
but the two should not be used in conjunction.

The `TemplateMain` and `TemplateMainNarrow` components render the content as a
`<main>` element with a default "id" of `"mainContent"`. This should be used as
the anchor element that the skip navigation link points to. If your application
Expand All @@ -100,7 +107,7 @@ Pass the location of the sidebar to the `sidebar` prop as either "left" or "righ
<Source
code={`
<Template sidebar="left">
// ...
//...
</Template>
`}
language="jsx"
Expand Down
106 changes: 45 additions & 61 deletions src/components/Template/Template.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Meta } from "@storybook/react";
import type { Meta, StoryObj } from "@storybook/react";
import { getPlaceholderImage } from "../../utils/utils";
import Accordion, { AccordionDataProps } from "../Accordion/Accordion";
import Banner from "../Banner/Banner";
Expand All @@ -9,7 +9,7 @@ import FeaturedContent from "../FeaturedContent/FeaturedContent";
import Form, { FormField, FormRow } from "../Form/Form";
import Heading from "../Heading/Heading";
import Hero from "../Hero/Hero";
import { HorizontalRule } from "../HorizontalRule/HorizontalRule";
import HorizontalRule from "../HorizontalRule/HorizontalRule";
import Placeholder from "../Placeholder/Placeholder";
import Table from "../Table/Table";
import TextInput from "../TextInput/TextInput";
Expand All @@ -21,14 +21,25 @@ import {
TemplateMainNarrow,
TemplateSidebar,
TemplateBottom,
sidebarPlacementArray,
SidebarPlacement,
} from "./Template";

const meta: Meta = {
const meta: Meta<typeof Template> = {
title: "Components/Page Layout/Template",
component: Template,
argTypes: {
id: { control: false },
sidebar: {
control: { type: "radio" },
options: sidebarPlacementArray,
table: { defaultValue: { summary: "none" } },
},
},
};

export default meta;
type Story = StoryObj<typeof Template>;

const accordionData: AccordionDataProps[] = [
{
Expand Down Expand Up @@ -169,7 +180,11 @@ const otherSubHeaderText =
* Main Story for the Template component. This must contains the `args`
* and `parameters` properties in this object.
*/
export const WithControls = {

export const sidebarLabel = (sidebar: SidebarPlacement) => {
return `${sidebar[0].toUpperCase()}${sidebar.slice(1)} Sidebar`;
};
export const WithControls: Story = {
args: {
id: "template",
sidebar: "left",
Expand All @@ -180,25 +195,31 @@ export const WithControls = {
table: { defaultValue: { summary: "none" } },
},
},
render: (args) => (
<Template {...args}>
<TemplateBreakout>
<Placeholder variant="short">Breakout</Placeholder>
</TemplateBreakout>
<TemplateTop>
<Placeholder variant="short">Content Top</Placeholder>
</TemplateTop>
<TemplateSidebar>
<Placeholder>Left Sidebar</Placeholder>
</TemplateSidebar>
<TemplateMain>
<Placeholder>Main Content</Placeholder>
</TemplateMain>
<TemplateBottom>
<Placeholder variant="short">Content Bottom</Placeholder>
</TemplateBottom>
</Template>
),
render: (args) => {
const { sidebar } = args;

return (
<Template {...args}>
<TemplateBreakout>
<Placeholder variant="short">Breakout</Placeholder>
</TemplateBreakout>
<TemplateTop>
<Placeholder variant="short">Content Top</Placeholder>
</TemplateTop>
{sidebar !== "none" && (
<TemplateSidebar>
<Placeholder>{sidebarLabel(sidebar)}</Placeholder>
</TemplateSidebar>
)}
<TemplateMain>
<Placeholder>Main Content</Placeholder>
</TemplateMain>
<TemplateBottom>
<Placeholder variant="short">Content Bottom</Placeholder>
</TemplateBottom>
</Template>
);
},
parameters: {
design: {
type: "figma",
Expand All @@ -207,7 +228,7 @@ export const WithControls = {
},
};

export const TemplateFullExample = {
export const TemplateFullExample: Story = {
args: {
sidebar: "left",
},
Expand Down Expand Up @@ -333,36 +354,6 @@ export const TemplateFullExampleNarrow = {
render: () => (
<>
<Template>
<TemplateBreakout>
<Breadcrumbs
breadcrumbsData={[
{ url: "#", text: "Home" },
{ url: "#", text: "Research" },
{
url: "#",
text: "Catalog",
},
]}
/>
<Hero
backgroundImageSrc={getPlaceholderImage()}
heroType="campaign"
heading={<Heading level="h1" id="1" text="Hero Campaign" />}
imageProps={{
alt: "Image example",
src: getPlaceholderImage("smaller"),
}}
isDarkBackgroundImage
subHeaderText={otherSubHeaderText}
/>
</TemplateBreakout>
<TemplateTop>
<Banner
content="This is the top content area!"
heading="Content Top"
type="informative"
/>
</TemplateTop>
<TemplateMainNarrow>
<p>This is the main content!</p>
<p>
Expand All @@ -381,13 +372,6 @@ export const TemplateFullExampleNarrow = {
</p>
<Accordion accordionData={faqContentData} />
</TemplateMainNarrow>
<TemplateBottom>
<Banner
content="This is the bottom content area!"
heading="Content Bottom"
type="informative"
/>
</TemplateBottom>
</Template>
</>
),
Expand Down
105 changes: 84 additions & 21 deletions src/components/Template/Template.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import { axe } from "jest-axe";
import renderer from "react-test-renderer";
Expand All @@ -9,13 +10,14 @@ import {
TemplateMain,
TemplateSidebar,
TemplateBottom,
SidebarPlacement,
TemplateMainNarrow,
} from "./Template";
import Placeholder from "../Placeholder/Placeholder";
import { sidebarLabel } from "./Template.stories";

const breakout = <Placeholder variant="short">Breakout</Placeholder>;
const sidebar = "left";
const contentTop = <Placeholder>Content Top</Placeholder>;
const contentSidebar = <Placeholder>Left Sidebar</Placeholder>;
const contentMain = (
<>
<Placeholder>Main Content</Placeholder>
Expand All @@ -24,26 +26,37 @@ const contentMain = (
);
const contentBottom = <Placeholder variant="short">Content Bottom</Placeholder>;

const templateChildren = (
const templateComponents = (
sidebar: SidebarPlacement = "none",
useMainNarrow: boolean = false
) => (
<Template sidebar={sidebar}>
<TemplateBreakout>{breakout}</TemplateBreakout>
<TemplateTop>{contentTop}</TemplateTop>
<TemplateSidebar>{contentSidebar}</TemplateSidebar>
<TemplateMain>{contentMain}</TemplateMain>
{sidebar !== "none" && !useMainNarrow && (
<TemplateSidebar>
<Placeholder>{sidebarLabel(sidebar)}</Placeholder>
</TemplateSidebar>
)}
{useMainNarrow ? (
<TemplateMainNarrow>{contentMain}</TemplateMainNarrow>
) : (
<TemplateMain>{contentMain}</TemplateMain>
)}
<TemplateBottom>{contentBottom}</TemplateBottom>
</Template>
);

describe("Template components accessibility", () => {
it("passes axe accessibility test", async () => {
const { container } = render(<>{templateChildren}</>);
const { container } = render(templateComponents("left"));
expect(await axe(container)).toHaveNoViolations();
});
});

describe("Template components", () => {
it("renders each section", () => {
render(<>{templateChildren}</>);
it("renders each section with left sidebar", () => {
render(templateComponents("left"));

expect(screen.getByText("Breakout")).toBeInTheDocument();
expect(screen.getByText("Content Top")).toBeInTheDocument();
Expand All @@ -53,26 +66,76 @@ describe("Template components", () => {
expect(screen.getByText("Content Bottom")).toBeInTheDocument();
});

it("renders a #mainContent id in the TemplateContent component", () => {
const { container } = render(<>{templateChildren}</>);
it("renders each section with left sidebar", () => {
render(templateComponents("right"));

expect(screen.getByText("Breakout")).toBeInTheDocument();
expect(screen.getByText("Content Top")).toBeInTheDocument();
expect(screen.getByText("Right Sidebar")).toBeInTheDocument();
expect(screen.getByText("Main Content")).toBeInTheDocument();
expect(screen.getByText("More Content")).toBeInTheDocument();
expect(screen.getByText("Content Bottom")).toBeInTheDocument();
});

it("renders a #mainContent id when using TemplateMain", () => {
const { container } = render(templateComponents("left"));

expect(container.querySelector("#mainContent")).toBeInTheDocument();
expect(screen.getByRole("main")).toHaveAttribute("id", "mainContent");
});

it("renders a #mainContent id when using TemplateMainNarrow", () => {
const { container } = render(templateComponents("none", true));

expect(container.querySelector("#mainContent")).toBeInTheDocument();
expect(screen.getByRole("main")).toHaveAttribute("id", "mainContent");
});

it("passes a ref to the div wrapper element", () => {
const ref = React.createRef<HTMLDivElement>();
const { container } = render(
<Template ref={ref}>
<TemplateMain>{contentMain}</TemplateMain>
</Template>
);

expect(container.querySelectorAll("div")[0]).toBe(ref.current);
});

it("renders the UI snapshot correctly", () => {
const templateComponents = renderer
.create(
<Template sidebar={sidebar}>
<TemplateBreakout>{breakout}</TemplateBreakout>
<TemplateTop>{contentTop}</TemplateTop>
<TemplateSidebar>{contentSidebar}</TemplateSidebar>
<TemplateMain>{contentMain}</TemplateMain>
<TemplateBottom>{contentBottom}</TemplateBottom>
</Template>
)
const templateComponentsLeftSidebar = renderer
.create(templateComponents("left"))
.toJSON();

const templateComponentsRightSidebar = renderer
.create(templateComponents("right"))
.toJSON();

expect(templateComponents).toMatchSnapshot();
const templateComponentsNoSidebar = renderer
.create(templateComponents("none"))
.toJSON();

const templateComponentsMainNarrow = renderer
.create(templateComponents("none", true))
.toJSON();

const templateWithChakraProps = renderer.create(
<Template p="20px" color="ui.error.primary">
<TemplateMain>{contentMain}</TemplateMain>
</Template>
);

const templateWithOtherProps = renderer.create(
<Template data-testid="props">
<TemplateMain>{contentMain}</TemplateMain>
</Template>
);

expect(templateComponentsLeftSidebar).toMatchSnapshot();
expect(templateComponentsRightSidebar).toMatchSnapshot();
expect(templateComponentsNoSidebar).toMatchSnapshot();
expect(templateComponentsMainNarrow).toMatchSnapshot();
expect(templateWithChakraProps).toMatchSnapshot();
expect(templateWithOtherProps).toMatchSnapshot();
});
});
Loading

0 comments on commit dc3c8cf

Please sign in to comment.