diff --git a/src/components/Stepper/Step/Step.scss b/src/components/Stepper/Step/Step.scss
index 518cd2524..bffcdbec9 100644
--- a/src/components/Stepper/Step/Step.scss
+++ b/src/components/Stepper/Step/Step.scss
@@ -29,6 +29,10 @@
text-decoration: underline;
}
+.step-enabled {
+ @include vf-focus-themed;
+}
+
.step-disabled {
color: $colors--theme--text-muted;
pointer-events: none;
diff --git a/src/components/Stepper/Step/Step.test.tsx b/src/components/Stepper/Step/Step.test.tsx
index 750ad4b87..99cd777ea 100644
--- a/src/components/Stepper/Step/Step.test.tsx
+++ b/src/components/Stepper/Step/Step.test.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { render, screen } from "@testing-library/react";
+import { createEvent, fireEvent, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import Step from "./Step";
import type { Props } from "./Step";
@@ -14,6 +14,10 @@ describe("Step component", () => {
handleClick: jest.fn(),
};
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
it("renders the step with the required props", () => {
render();
expect(screen.getByText("Title")).toBeInTheDocument();
@@ -47,6 +51,55 @@ describe("Step component", () => {
expect(props.handleClick).toHaveBeenCalled();
});
+ it("exposes the title as a button role", () => {
+ render();
+ expect(screen.getByRole("button", { name: "Title" })).toBeInTheDocument();
+ });
+
+ it("is keyboard focusable and not aria-disabled when enabled", () => {
+ render();
+ const title = screen.getByText("Title");
+ expect(title).toHaveAttribute("tabindex", "0");
+ expect(title).toHaveAttribute("aria-disabled", "false");
+ });
+
+ it("calls handleClick when Enter is pressed and enabled", async () => {
+ render();
+ screen.getByText("Title").focus();
+ await userEvent.keyboard("{Enter}");
+ expect(props.handleClick).toHaveBeenCalled();
+ });
+
+ it("calls handleClick and prevents default when Space is pressed and enabled", () => {
+ render();
+ const title = screen.getByText("Title");
+ const event = createEvent.keyDown(title, { key: " " });
+ fireEvent(title, event);
+ expect(props.handleClick).toHaveBeenCalled();
+ expect(event.defaultPrevented).toBe(true);
+ });
+
+ it("is not focusable and is aria-disabled when disabled", () => {
+ render();
+ const title = screen.getByText("Title");
+ expect(title).toHaveAttribute("tabindex", "-1");
+ expect(title).toHaveAttribute("aria-disabled", "true");
+ });
+
+ it("does not call handleClick on keyboard activation when disabled", () => {
+ render();
+ const title = screen.getByText("Title");
+ fireEvent.keyDown(title, { key: "Enter" });
+ fireEvent.keyDown(title, { key: " " });
+ expect(props.handleClick).not.toHaveBeenCalled();
+ });
+
+ it("does not call handleClick when clicked while disabled", async () => {
+ render();
+ await userEvent.click(screen.getByText("Title"));
+ expect(props.handleClick).not.toHaveBeenCalled();
+ });
+
it("can display optional label", () => {
render();
diff --git a/src/components/Stepper/Step/Step.tsx b/src/components/Stepper/Step/Step.tsx
index 36d474e62..e34215ef5 100644
--- a/src/components/Stepper/Step/Step.tsx
+++ b/src/components/Stepper/Step/Step.tsx
@@ -63,6 +63,23 @@ const Step = ({
}: Props): React.JSX.Element => {
const stepStatusClass = enabled ? "step-enabled" : "step-disabled";
+ const handleKeyDown = (event: React.KeyboardEvent) => {
+ if (!enabled) {
+ return;
+ }
+ const isEnter = event.key === "Enter";
+ const isSpace = event.key === " " || event.key === "Spacebar";
+ if (isEnter || isSpace) {
+ if (event.repeat) {
+ return;
+ }
+ if (isSpace) {
+ event.preventDefault();
+ }
+ handleClick();
+ }
+ };
+
return (
)}
-
+
{title}
{label && (
diff --git a/src/components/Stepper/__snapshots__/Stepper.test.tsx.snap b/src/components/Stepper/__snapshots__/Stepper.test.tsx.snap
index 81ebea07e..b04bdddeb 100644
--- a/src/components/Stepper/__snapshots__/Stepper.test.tsx.snap
+++ b/src/components/Stepper/__snapshots__/Stepper.test.tsx.snap
@@ -1,4 +1,4 @@
-// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Stepper component renders the stepper 1`] = `
Step 1
@@ -42,7 +45,10 @@ exports[`Stepper component renders the stepper 1`] = `
class="step-content"
>
Step 2
@@ -69,7 +75,10 @@ exports[`Stepper component renders the stepper 1`] = `
class="step-content"
>
Step 3
@@ -102,7 +111,10 @@ exports[`Stepper component renders the stepper 1`] = `
class="step-content"
>
Step 4