diff --git a/app/components/elements/Switch.browser.test.tsx b/app/components/elements/Switch.browser.test.tsx new file mode 100644 index 000000000..1a8bc2241 --- /dev/null +++ b/app/components/elements/Switch.browser.test.tsx @@ -0,0 +1,65 @@ +import { describe, expect, test, vi } from "vitest"; +import { render } from "vitest-browser-react"; +import { SendouSwitch } from "./Switch"; + +function indicatorHeight(container: HTMLElement) { + const indicator = container.querySelector("label > div"); + + return indicator ? Number.parseFloat(getComputedStyle(indicator).height) : 0; +} + +describe("SendouSwitch", () => { + test("toggles when clicked", async () => { + const screen = await render( + , + ); + + await expect.element(screen.getByRole("switch")).not.toBeChecked(); + + await screen.getByTestId("switch").click(); + + await expect.element(screen.getByRole("switch")).toBeChecked(); + }); + + test("reports the new state to onChange", async () => { + const onChange = vi.fn(); + const screen = await render( + , + ); + + await screen.getByTestId("switch").click(); + + expect(onChange).toHaveBeenCalledWith(false); + }); + + test("stays at the state given by isSelected when controlled", async () => { + const screen = await render( + , + ); + + await screen.getByTestId("switch").click(); + + await expect.element(screen.getByRole("switch")).not.toBeChecked(); + }); + + test("renders a smaller indicator with size small", async () => { + const defaultSize = await render(); + const smallSize = await render( + , + ); + + expect(indicatorHeight(smallSize.container)).toBeLessThan( + indicatorHeight(defaultSize.container), + ); + }); +}); diff --git a/app/components/elements/Switch.module.css b/app/components/elements/Switch.module.css index 1d3e956e4..abd257faa 100644 --- a/app/components/elements/Switch.module.css +++ b/app/components/elements/Switch.module.css @@ -70,3 +70,9 @@ overflow: hidden; white-space: nowrap; } + +.small { + --height: var(--selector-size-xs); + + font-size: var(--font-2xs); +} diff --git a/app/components/elements/Switch.tsx b/app/components/elements/Switch.tsx index f3b2109e3..283fab665 100644 --- a/app/components/elements/Switch.tsx +++ b/app/components/elements/Switch.tsx @@ -1,3 +1,4 @@ +import clsx from "clsx"; import type * as React from "react"; import styles from "./Switch.module.css"; @@ -7,6 +8,7 @@ interface SendouSwitchProps { defaultSelected?: boolean; onChange?: (isSelected: boolean) => void; isDisabled?: boolean; + size?: "small"; "aria-label"?: string; "data-testid"?: string; children?: React.ReactNode; @@ -18,12 +20,16 @@ export function SendouSwitch({ defaultSelected, onChange, isDisabled, + size, "aria-label": ariaLabel, "data-testid": testId, children, }: SendouSwitchProps) { return ( -