From d3f7011ad1bfacef8489208bd54f0f6ea744614b Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 6 Sep 2026 07:15:55 +0300 Subject: [PATCH] Stay as sub toggle on the tournament lfg card --- .../elements/Switch.browser.test.tsx | 65 +++++++++++++++ app/components/elements/Switch.module.css | 6 ++ app/components/elements/Switch.tsx | 8 +- .../components-showcase/routes/components.tsx | 6 ++ .../actions/to.$id.looking.server.ts | 8 +- .../components/LFGGroupCard.tsx | 80 ++++++++++--------- .../tournament-lfg/tournament-lfg-schemas.ts | 5 +- .../2026-09-05-lfg-stay-as-sub-toggle.md | 5 ++ .../tournament/tournament-looking-page.ts | 31 +++++++ e2e/tournament-lfg.spec.ts | 31 ++++++- 10 files changed, 203 insertions(+), 42 deletions(-) create mode 100644 app/components/elements/Switch.browser.test.tsx create mode 100644 changelog/2026-09-05-lfg-stay-as-sub-toggle.md create mode 100644 e2e/pages/tournament/tournament-looking-page.ts 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 ( -