From 99096bdae00a130cefc331c6a677845a37a95ae8 Mon Sep 17 00:00:00 2001 From: FiniteSkills Date: Sat, 4 Jul 2026 06:44:53 +0530 Subject: [PATCH] Add Button loading state --- src/components/Button.tsx | 13 ++++++++-- src/components/__tests__/Button.test.tsx | 30 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/components/__tests__/Button.test.tsx diff --git a/src/components/Button.tsx b/src/components/Button.tsx index ebb85c4..3f7ef4d 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -1,4 +1,5 @@ import { type ButtonHTMLAttributes } from "react"; +import { Spinner } from "./Spinner"; type Variant = "primary" | "secondary" | "danger"; @@ -23,13 +24,21 @@ export function Button({ variant = "primary", loading = false, className = "", + disabled, + children, ...rest }: ButtonProps) { + const isDisabled = disabled || loading; + return ( ); } diff --git a/src/components/__tests__/Button.test.tsx b/src/components/__tests__/Button.test.tsx new file mode 100644 index 0000000..261aa9c --- /dev/null +++ b/src/components/__tests__/Button.test.tsx @@ -0,0 +1,30 @@ +import { render, screen } from "@testing-library/react"; +import { Button } from "../Button"; + +describe("Button", () => { + it("renders children without busy state by default", () => { + render(); + + const button = screen.getByRole("button", { name: "Save" }); + expect(button).toBeEnabled(); + expect(button).not.toHaveAttribute("aria-busy"); + expect(screen.queryByRole("status")).not.toBeInTheDocument(); + }); + + it("disables the button and exposes busy state while loading", () => { + render(); + + const button = screen.getByRole("button", { name: /save/i }); + expect(button).toBeDisabled(); + expect(button).toHaveAttribute("aria-busy", "true"); + expect(screen.getByRole("status")).toHaveTextContent("Loading"); + }); + + it("preserves explicit disabled state when not loading", () => { + render(); + + const button = screen.getByRole("button", { name: "Delete" }); + expect(button).toBeDisabled(); + expect(button).not.toHaveAttribute("aria-busy"); + }); +});