diff --git a/src/components/Switch/Switch.stories.tsx b/src/components/Switch/Switch.stories.tsx new file mode 100644 index 00000000..8dcc9285 --- /dev/null +++ b/src/components/Switch/Switch.stories.tsx @@ -0,0 +1,90 @@ +import { Switch, SwitchProps } from "./Switch" +import { Meta, Story } from "@storybook/react/types-6-0" +import { useEffect, useState } from "react" + +export default { + title: "Design System/Switch", + component: Switch, + decorators: [ + (Story) => ( +
+ +
+ ), + ], +} as Meta + +const Template: Story = (props: SwitchProps) => { + const [checked, setChecked] = useState(props.checked) + useEffect(() => setChecked(props.checked), [props.checked]) + + return ( + { + setChecked(event.target.checked) + props.onChange?.(event) + }} + checked={checked} + /> + ) +} + +// Each story then reuses that template +export const Unchecked = Template.bind({}) +Unchecked.args = { + checked: false, + disabled: false, + color: "secondary", +} + +export const Primary = Template.bind({}) +Primary.args = { + checked: true, + disabled: false, + color: "primary", +} + +export const Secondary = Template.bind({}) +Secondary.args = { + checked: true, + disabled: false, + color: "secondary", +} + +export const Success = Template.bind({}) +Success.args = { + checked: true, + disabled: false, + color: "success", +} + +export const Text = Template.bind({}) +Text.args = { + checked: true, + disabled: false, + color: "text", +} + +export const Warning = Template.bind({}) +Warning.args = { + checked: true, + disabled: false, + color: "warning", +} + +export const Disabled = Template.bind({}) +Disabled.args = { + checked: true, + disabled: true, + color: "primary", +} + +export const Labeled = Template.bind({}) +Labeled.args = { + checked: true, + disabled: false, + color: "primary", + label: "Switch Label", + id: "switch", +} diff --git a/src/components/Switch/Switch.test.tsx b/src/components/Switch/Switch.test.tsx new file mode 100644 index 00000000..f4829351 --- /dev/null +++ b/src/components/Switch/Switch.test.tsx @@ -0,0 +1,26 @@ +import { render, screen } from "../../tests/utils" +import { axe } from "jest-axe" +import { Switch } from "./Switch" +import userEvent from "@testing-library/user-event" + +describe("Switch", () => { + test("onChange is called when switch is clicked", async () => { + // Arrange + const onChange = jest.fn() + render() + + // Assert + expect(onChange).not.toHaveBeenCalled() + userEvent.click(screen.getByRole("checkbox")) + expect(onChange).toHaveBeenCalled() + }) + + test("passes a11y check", async () => { + // Arrange + const { container } = render() + const results = await axe(container) + + // Assert + expect(results).toHaveNoViolations() + }) +}) diff --git a/src/components/Switch/Switch.tsx b/src/components/Switch/Switch.tsx new file mode 100644 index 00000000..117e0429 --- /dev/null +++ b/src/components/Switch/Switch.tsx @@ -0,0 +1,87 @@ +/** @jsxImportSource theme-ui */ + +import { forwardRef } from "react" + +export interface SwitchProps { + checked?: boolean + disabled?: boolean + color?: "primary" | "secondary" | "text" | "success" | "warning" + onChange?: (event: React.ChangeEvent) => void + label?: React.ReactNode + name?: string + id?: string +} + +export const Switch = forwardRef(function Switch( + { + checked, + color = "secondary", + disabled = false, + onChange, + label, + name, + id, + }: SwitchProps, + ref +) { + return ( +
+
+ +
+
+ {label && ( + + )} +
+ ) +}) diff --git a/src/components/index.ts b/src/components/index.ts index 493172fd..9c719d68 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -86,6 +86,9 @@ export { useSnackbar } from "./Snackbar/hooks/useSnackbar" export { default as Spinner } from "./Spinner/Spinner" export type { SpinnerProps } from "./Spinner/Spinner" +export { Switch } from "./Switch/Switch" +export type { SwitchProps } from "./Switch/Switch" + export { default as Table } from "./Table/Table" export type { TableProps } from "./Table/Table" diff --git a/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-disabled-1-snap.png b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-disabled-1-snap.png new file mode 100644 index 00000000..3221b0e8 Binary files /dev/null and b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-disabled-1-snap.png differ diff --git a/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-labeled-1-snap.png b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-labeled-1-snap.png new file mode 100644 index 00000000..d2232093 Binary files /dev/null and b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-labeled-1-snap.png differ diff --git a/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-primary-1-snap.png b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-primary-1-snap.png new file mode 100644 index 00000000..7fabd32b Binary files /dev/null and b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-primary-1-snap.png differ diff --git a/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-secondary-1-snap.png b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-secondary-1-snap.png new file mode 100644 index 00000000..37beb216 Binary files /dev/null and b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-secondary-1-snap.png differ diff --git a/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-success-1-snap.png b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-success-1-snap.png new file mode 100644 index 00000000..99e988a1 Binary files /dev/null and b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-success-1-snap.png differ diff --git a/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-text-1-snap.png b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-text-1-snap.png new file mode 100644 index 00000000..52b1dfcf Binary files /dev/null and b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-text-1-snap.png differ diff --git a/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-unchecked-1-snap.png b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-unchecked-1-snap.png new file mode 100644 index 00000000..977caa4d Binary files /dev/null and b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-unchecked-1-snap.png differ diff --git a/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-warning-1-snap.png b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-warning-1-snap.png new file mode 100644 index 00000000..d3015c87 Binary files /dev/null and b/src/tests/__image_snapshots__/storyshots-test-ts-image-storyshots-design-system-switch-warning-1-snap.png differ