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