Skip to content

Commit

Permalink
Consolidate Design System Components (#960)
Browse files Browse the repository at this point in the history
* setup jsconfig to support finding file references in vscode

* consolidate components from design-system

* properly format component paths in design-system component stories

* Add resources for stories and tests

* integrate DSButton styling with SCLabs styling

* remove duplicate CallToAction.js

* various fixes to stories, unit tests and styling

* move default brandLinks story prop to Footer.js default props

* fix vertical alignment of text in DSButton supertask state

* add missing axe check in Footer unit test

* fix SubFooterBand margin-left

* fix Footer unit test
  • Loading branch information
will0684 authored Jan 17, 2024
1 parent 3a82e6b commit bd06d3e
Show file tree
Hide file tree
Showing 47 changed files with 932 additions and 578 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
import PropTypes from "prop-types";
import { Image } from "./Image";

export function Button(props) {
const style = "btn-" + props.styling;
// Button used in HelpIcon.js and CTA.js
// Use ActionButton.js for all other buttons in the app
export function DSButton(props) {
//Styling for buttons and links
const PRIMARY =
"text-multi-neutrals-white bg-multi-blue-blue70 hover:bg-multi-blue-blue60g focus:bg-multi-blue-blue60g";
const SECONDARY =
"text-multi-blue-blue60b bg-multi-neutrals-grey30a hover:bg-multi-neutrals-grey50a focus:bg-multi-neutrals-grey60";
const SUPERTASK =
"text-multi-neutrals-white bg-specific-green-green50 hover:bg-specific-green-green70 focus:bg-sepcific-green-green70";
const DANGER =
"text-multi-neutrals-white bg-specific-red-red50 hover:bg-specific-red-red70 focus:bg-specific-red-red70";
const LINK =
"text-multi-blue-blue60c hover:text-multi-blue-blue50b focus:text-multi-blue-blue60f";

const styling =
props.styling === "primary"
? PRIMARY
: props.styling === "secondary"
? SECONDARY
: props.styling === "supertask"
? SUPERTASK
: props.styling === "danger"
? DANGER
: props.styling === "link"
? LINK
: "";

return props.href === "no ref" ? (
<button
className={`flex flex-row ${style} focus:ring focus:ring-offset-4 ${props.className} `}
className={`flex flex-row px-[16px] py-[8px] ${styling} rounded-sm focus:ring focus:ring-offset-4 ${props.className} `}
onClick={props.onClick}
type={props.type}
id={props.id}
Expand All @@ -18,7 +44,13 @@ export function Button(props) {
<Image className="pr-2" src={props.icon} alt={props.iconAltText} />
</span>
) : undefined}
{props.text}
<span
className={`grid place-items-center ${
props.styling === "supertask" ? "h-8" : ""
}`}
>
{props.text}
</span>
{props.children}
{props.icon && props.iconEnd ? (
<span className="grid place-items-center h-8 w-8">
Expand Down Expand Up @@ -59,14 +91,14 @@ export function Button(props) {
);
}

Button.defaultProps = {
DSButton.defaultProps = {
id: "btn1",
styling: "supertask",
text: "default",
href: "no ref",
};

Button.propTypes = {
DSButton.propTypes = {
/**
* Identify which button being clicked
*/
Expand Down
61 changes: 61 additions & 0 deletions components/atoms/DSButton.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { DSButton } from "./DSButton";

export default {
title: "Components/Atoms/DSButton",
component: DSButton,
};

const Template = (args) => <DSButton {...args} />;

export const Supertask = Template.bind({});
export const SupertaskIcon = Template.bind({});
export const Primary = Template.bind({});
export const Secondary = Template.bind({});
export const Danger = Template.bind({});
export const Link = Template.bind({});

Supertask.args = {
id: "supertask",
styling: "supertask",
text: "Supertask button",
iconAltText: "supertask",
};

SupertaskIcon.args = {
id: "supertask_icon",
styling: "supertask",
text: "Supertask button",
icon: "plus.svg",
iconAltText: "icon",
iconEnd: false,
};

Primary.args = {
id: "primary",
text: "Primary button",
iconAltText: "prime",
styling: "primary",
};

Secondary.args = {
id: "secondary",
text: "Secondary Button",
iconEnd: false,
secondary: true,
styling: "secondary",
};

Danger.args = {
id: "danger",
text: "Danger Button",
iconEnd: false,
styling: "danger",
};

Link.args = {
id: "link",
text: "Link Button",
styling: "link",
href: "/",
iconAltText: "link",
};
69 changes: 69 additions & 0 deletions components/atoms/DSButton.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* @jest-environment jsdom
*/

import React from "react";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { axe, toHaveNoViolations } from "jest-axe";
import {
Primary,
Secondary,
Danger,
Link,
Supertask,
} from "./DSButton.stories";
import { DSButton } from "./DSButton";

expect.extend(toHaveNoViolations);

describe("DSButton", () => {
it("renders supertask", async () => {
const { container } = render(<DSButton {...Supertask.args} />);
expect(screen.getByRole("button")).toHaveTextContent(Supertask.args.text);
expect(screen.getByRole("button")).toHaveClass(
"flex flex-row px-[16px] py-[8px] text-multi-neutrals-white bg-specific-green-green50 hover:bg-specific-green-green70 focus:bg-sepcific-green-green70 rounded-sm focus:ring focus:ring-offset-4 undefined"
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});

it("renders primary", async () => {
const { container } = render(<DSButton {...Primary.args} />);
expect(screen.getByRole("button")).toHaveTextContent(Primary.args.text);
expect(screen.getByRole("button")).toHaveClass(
"flex flex-row px-[16px] py-[8px] text-multi-neutrals-white bg-multi-blue-blue70 hover:bg-multi-blue-blue60g focus:bg-multi-blue-blue60g rounded-sm focus:ring focus:ring-offset-4 undefined"
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});

it("renders secondary", async () => {
const { container } = render(<DSButton {...Secondary.args} />);
expect(screen.getByRole("button")).toHaveTextContent(Secondary.args.text);
expect(screen.getByRole("button")).toHaveClass(
"flex flex-row px-[16px] py-[8px] text-multi-blue-blue60b bg-multi-neutrals-grey30a hover:bg-multi-neutrals-grey50a focus:bg-multi-neutrals-grey60 rounded-sm focus:ring focus:ring-offset-4 undefined"
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});

it("renders danger", async () => {
const { container } = render(<DSButton {...Danger.args} />);
expect(screen.getByRole("button")).toHaveTextContent(Danger.args.text);
expect(screen.getByRole("button")).toHaveClass(
"flex flex-row px-[16px] py-[8px] text-multi-neutrals-white bg-specific-red-red50 hover:bg-specific-red-red70 focus:bg-specific-red-red70 rounded-sm focus:ring focus:ring-offset-4 undefined"
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});

it("renders link styles as button", async () => {
const { container } = render(<DSButton {...Link.args} />);
expect(screen.getByRole("button")).toHaveTextContent(Link.args.text);
expect(screen.getByRole("button")).toHaveAttribute("href");
expect(screen.getByRole("button")).toHaveClass("btn-link");
const results = await axe(container);
expect(results).toHaveNoViolations();
});
});
File renamed without changes.
41 changes: 41 additions & 0 deletions components/atoms/Image.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Image } from "./Image";

export default {
title: "Components/Atoms/Image",
component: Image,
};
import imageFile from "../../public/image1.png";
import imageFile2 from "../../public/image2.png";

const Template = (args) => <Image {...args} />;

export const Default = Template.bind({});
export const Mobile = Template.bind({});
export const DefaultWithRounded = Template.bind({});
export const MobileWithRounded = Template.bind({});

Default.args = {
id: "image",
alt: "Default Image",
src: imageFile,
};

DefaultWithRounded.args = {
id: "image",
alt: "Default Image with rounded",
rounded: "rounded",
src: imageFile,
};

Mobile.args = {
id: "image",
alt: "Mobile Image",
src: imageFile2,
};

MobileWithRounded.args = {
id: "image",
alt: "Mobile Image with rounded",
rounded: "rounded",
src: imageFile2,
};
47 changes: 47 additions & 0 deletions components/atoms/Image.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { axe, toHaveNoViolations } from "jest-axe";
import {
Default,
Mobile,
DefaultWithRounded,
MobileWithRounded,
} from "./Image.stories";
import { Image } from "./Image";

expect.extend(toHaveNoViolations);

describe("Image", () => {
it("renders default image", async () => {
const { container } = render(<Image {...Default.args} />);
expect(screen.getByAltText("Default Image"));
const results = await axe(container);
expect(results).toHaveNoViolations();
});

it("renders mobile image", async () => {
const { container } = render(<Image {...Mobile.args} />);
expect(screen.getByAltText("Mobile Image"));
const results = await axe(container);
expect(results).toHaveNoViolations();
});

it("renders default image with rounded corner", async () => {
const { container } = render(<Image {...DefaultWithRounded.args} />);
expect(screen.getByAltText("Default Image with rounded")).toHaveClass(
"rounded"
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});

it("renders mobile image with rounded", async () => {
const { container } = render(<Image {...MobileWithRounded.args} />);
expect(screen.getByAltText("Mobile Image with rounded")).toHaveClass(
"rounded"
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
import PropTypes from "prop-types";

// Use this component for Footer link and use Next.js <Link>
// for all links within the site
export function Link(props) {
//Styling for links based on Figma Design
let basicStyle = "";
Expand Down
56 changes: 56 additions & 0 deletions components/atoms/Link.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Link } from "./Link";

export default {
title: "Components/Atoms/Link",
component: Link,
};

const Template = (args) => <Link {...args} />;

export const Default = Template.bind({});
export const RegularLinkwithEmphasis = Template.bind({});
export const TitleLink = Template.bind({});
export const FooterBlueLink = Template.bind({});
export const BreadcrumbsLink = Template.bind({});
export const CardActionLink = Template.bind({});

Default.args = {
id: "link",
text: "Regular Link",
href: "/",
};

RegularLinkwithEmphasis.args = {
id: "link",
text: "Regular link with Emphasis",
href: "/",
linkStyle: "basicStyleWithEmphasis",
};

TitleLink.args = {
id: "link",
text: "Title Link",
href: "/",
linkStyle: "titleLink",
};

FooterBlueLink.args = {
id: "link",
text: "Small link - Footer blue",
href: "/",
linkStyle: "smfooterBlue",
};

BreadcrumbsLink.args = {
id: "link",
text: "Small link - Breadcrumbs & French toggle",
href: "/",
linkStyle: "smBreadcrumbs",
};

CardActionLink.args = {
id: "link",
text: "Card Action Link",
href: "/",
linkStyle: "cardActionLink",
};
Loading

0 comments on commit bd06d3e

Please sign in to comment.