Skip to content

Commit 2efe13e

Browse files
committed
fix(nextjs): update board privacy toggle
1 parent 0feb85b commit 2efe13e

2 files changed

Lines changed: 39 additions & 30 deletions

File tree

apps/nextjs/src/app/todos/[boardId]/_components/board-visibility-toggle.tsx

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
"use client";
22

3+
import { Eye, EyeOff } from "lucide-react";
34
import {
45
type AttributesVisibilityEnum2Key,
56
attributesVisibilityEnum2,
67
} from "@rvct/shared";
78
import { useRouter } from "next/navigation";
8-
import { useId, useState, useTransition } from "react";
9+
import { useState, useTransition } from "react";
910
import { updateBoardVisibility } from "~/features/boards/mutations";
10-
import { Label } from "~/shared/ui/label";
11+
import { Button } from "~/shared/ui/button";
1112

1213
type Props = {
1314
id: string;
@@ -19,10 +20,11 @@ export function BoardVisibilityToggle({
1920
visibility = attributesVisibilityEnum2.private,
2021
}: Props) {
2122
const router = useRouter();
22-
const visibilityId = useId();
2323
const [currentVisibility, setCurrentVisibility] = useState(visibility);
2424
const [isPending, startTransition] = useTransition();
2525
const isPublic = currentVisibility === attributesVisibilityEnum2.public;
26+
const Icon = isPublic ? Eye : EyeOff;
27+
const label = isPublic ? "Public board" : "Private board";
2628

2729
const handleVisibilityChange = (checked: boolean) => {
2830
const previousVisibility = currentVisibility;
@@ -47,22 +49,21 @@ export function BoardVisibilityToggle({
4749

4850
return (
4951
<div className="w-full shrink-0 space-y-1 sm:w-auto">
50-
<Label
51-
htmlFor={visibilityId}
52-
className="inline-flex h-9 w-full items-center gap-2 rounded-md border border-input bg-background px-3 whitespace-nowrap sm:w-auto"
52+
<Button
53+
type="button"
54+
variant="outline"
55+
size="sm"
56+
className="w-full justify-start gap-2 sm:w-auto"
57+
aria-label={label}
58+
aria-pressed={isPublic}
59+
disabled={isPending}
60+
onClick={() => handleVisibilityChange(!isPublic)}
5361
>
54-
<input
55-
id={visibilityId}
56-
type="checkbox"
57-
className="size-4 rounded border-input accent-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
58-
checked={isPublic}
59-
disabled={isPending}
60-
onChange={(event) =>
61-
handleVisibilityChange(event.currentTarget.checked)
62-
}
63-
/>
64-
Public
65-
</Label>
62+
<span className="inline-flex size-5 items-center justify-center rounded-full border border-current/15 bg-current/5">
63+
<Icon aria-hidden="true" className="size-3.5" />
64+
</span>
65+
<span>{label}</span>
66+
</Button>
6667
</div>
6768
);
6869
}

apps/nextjs/tests/app/todos/[boardId]/_components/board-visibility-toggle.spec.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,24 @@ describe("BoardVisibilityToggle", () => {
2929

3030
render(<BoardVisibilityToggle id="board-1" visibility="private" />);
3131

32-
const checkbox = screen.getByRole("checkbox", {
33-
name: "Public",
34-
}) as HTMLInputElement;
32+
const button = screen.getByRole("button", {
33+
name: "Private board",
34+
});
3535

36-
expect(checkbox.checked).toBe(false);
36+
expect(button.getAttribute("aria-pressed")).toBe("false");
3737

3838
await act(async () => {
39-
fireEvent.click(checkbox);
39+
fireEvent.click(button);
4040
await Promise.resolve();
4141
});
4242

4343
expect(updateBoardVisibilityMock).toHaveBeenCalledWith("board-1", "public");
4444
expect(refreshMock).toHaveBeenCalledTimes(1);
45-
expect(checkbox.checked).toBe(true);
45+
expect(
46+
screen.getByRole("button", {
47+
name: "Public board",
48+
}),
49+
).toHaveProperty("ariaPressed", "true");
4650
});
4751

4852
test("restores the previous visibility when the update fails", async () => {
@@ -57,14 +61,14 @@ describe("BoardVisibilityToggle", () => {
5761

5862
render(<BoardVisibilityToggle id="board-1" visibility="public" />);
5963

60-
const checkbox = screen.getByRole("checkbox", {
61-
name: "Public",
62-
}) as HTMLInputElement;
64+
const button = screen.getByRole("button", {
65+
name: "Public board",
66+
});
6367

64-
expect(checkbox.checked).toBe(true);
68+
expect(button.getAttribute("aria-pressed")).toBe("true");
6569

6670
await act(async () => {
67-
fireEvent.click(checkbox);
71+
fireEvent.click(button);
6872
await Promise.resolve();
6973
});
7074

@@ -73,6 +77,10 @@ describe("BoardVisibilityToggle", () => {
7377
"private",
7478
);
7579
expect(refreshMock).not.toHaveBeenCalled();
76-
expect(checkbox.checked).toBe(true);
80+
expect(
81+
screen.getByRole("button", {
82+
name: "Public board",
83+
}),
84+
).toHaveProperty("ariaPressed", "true");
7785
});
7886
});

0 commit comments

Comments
 (0)