Skip to content

Commit

Permalink
[Checkbox]: Fix bug with disabled attribute on the button (#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
huntabyte authored Nov 6, 2023
1 parent d358585 commit 7ff5e08
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 32 deletions.
5 changes: 5 additions & 0 deletions .changeset/silver-roses-yell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"bits-ui": patch
---

[Checkbox]: Fix bug with `disabled` attribute on the button
1 change: 1 addition & 0 deletions src/lib/bits/checkbox/components/Checkbox.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
{...attrs}
on:m-click={dispatch}
on:m-keydown={dispatch}
disabled={disabled ? true : undefined}
>
<slot {builder} {attrs} />
</button>
Expand Down
57 changes: 25 additions & 32 deletions src/tests/checkbox/Checkbox.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ import { describe, it } from "vitest";
import CheckboxTest from "./CheckboxTest.svelte";
import { testKbd as kbd } from "../utils.js";
import { tick } from "svelte";
import type { Checkbox } from "$lib";

function setup(props?: Checkbox.Props) {
const user = userEvent.setup();
const returned = render(CheckboxTest, props);
const root = returned.getByTestId("root");
const input = returned.getByTestId("input") as HTMLInputElement;
return {
...returned,
root,
input,
user
};
}

describe("Checkbox", () => {
it("has no accessibility violations", async () => {
Expand All @@ -13,23 +27,19 @@ describe("Checkbox", () => {
});

it("has bits data attrs", async () => {
const { getByTestId } = render(CheckboxTest);
const root = getByTestId("root");
const { getByTestId, root } = setup();
const indicator = getByTestId("indicator");
expect(root).toHaveAttribute("data-bits-checkbox-root");
expect(indicator).toHaveAttribute("data-bits-checkbox-indicator");
});

it('defaults the value to "on", when no value prop is passed', async () => {
const { getByTestId } = render(CheckboxTest);
const input = getByTestId("input");
const { input } = setup();
expect(input).toHaveAttribute("value", "on");
});

it("can be indeterminate", async () => {
const { getByTestId } = render(CheckboxTest, { checked: "indeterminate" });
const root = getByTestId("root");
const input = getByTestId("input") as HTMLInputElement;
const { getByTestId, root, input } = setup({ checked: "indeterminate" });
const indicator = getByTestId("indicator");
expect(root).toHaveAttribute("data-state", "indeterminate");
expect(root).toHaveAttribute("aria-checked", "mixed");
Expand All @@ -40,10 +50,7 @@ describe("Checkbox", () => {
});

it("toggles when clicked", async () => {
const user = userEvent.setup();
const { getByTestId } = render(CheckboxTest);
const root = getByTestId("root");
const input = getByTestId("input") as HTMLInputElement;
const { getByTestId, root, input, user } = setup();
const indicator = getByTestId("indicator");
expect(root).toHaveAttribute("data-state", "unchecked");
expect(root).toHaveAttribute("aria-checked", "false");
Expand All @@ -61,10 +68,7 @@ describe("Checkbox", () => {
});

it("toggles when the `Space` key is pressed", async () => {
const user = userEvent.setup();
const { getByTestId } = render(CheckboxTest);
const root = getByTestId("root");
const input = getByTestId("input") as HTMLInputElement;
const { root, input, user } = setup();
expect(root).toHaveAttribute("data-state", "unchecked");
expect(root).toHaveAttribute("aria-checked", "false");
expect(input.checked).toBe(false);
Expand All @@ -76,10 +80,7 @@ describe("Checkbox", () => {
});

it("does not toggle when the `Enter` key is pressed", async () => {
const user = userEvent.setup();
const { getByTestId } = render(CheckboxTest);
const root = getByTestId("root");
const input = getByTestId("input") as HTMLInputElement;
const { getByTestId, root, input, user } = setup();
const indicator = getByTestId("indicator");
expect(root).toHaveAttribute("data-state", "unchecked");
expect(root).toHaveAttribute("aria-checked", "false");
Expand All @@ -98,24 +99,20 @@ describe("Checkbox", () => {
});

it("should be disabled when the `disabled` prop is passed", async () => {
const user = userEvent.setup();
const { getByTestId } = render(CheckboxTest, { disabled: true });
const root = getByTestId("root");
const input = getByTestId("input") as HTMLInputElement;
const { root, input, user } = setup({ disabled: true });
expect(root).toHaveAttribute("data-state", "unchecked");
expect(root).toHaveAttribute("aria-checked", "false");
expect(input.checked).toBe(false);
expect(input.disabled).toBe(true);
await user.click(root);
expect(root).toHaveAttribute("data-state", "unchecked");
expect(root).toHaveAttribute("aria-checked", "false");
expect(root).toBeDisabled();
expect(input.checked).toBe(false);
});

it("should be required when the `required` prop is passed", async () => {
const { getByTestId } = render(CheckboxTest, { required: true });
const root = getByTestId("root");
const input = getByTestId("input") as HTMLInputElement;
const { root, input } = setup({ required: true });
expect(root).toHaveAttribute("aria-required", "true");
expect(input.required).toBe(true);
});
Expand All @@ -125,17 +122,13 @@ describe("Checkbox", () => {
function onCheckedChange(next: boolean | "indeterminate") {
newValue = next;
}
const user = userEvent.setup();
const { getByTestId } = render(CheckboxTest, { onCheckedChange });
const root = getByTestId("root");
const { root, user } = setup({ onCheckedChange });
await user.click(root);
expect(newValue).toBe(true);
});

it("should respect binding the `checked` prop", async () => {
const user = userEvent.setup();
const { getByTestId } = render(CheckboxTest);
const root = getByTestId("root");
const { root, getByTestId, user } = setup();
const binding = getByTestId("binding");
expect(binding).toHaveTextContent("false");
await user.click(root);
Expand Down

0 comments on commit 7ff5e08

Please sign in to comment.