diff --git a/app/browser-test-setup.ts b/app/browser-test-setup.ts
index 0d4e3aa13..ad31b411c 100644
--- a/app/browser-test-setup.ts
+++ b/app/browser-test-setup.ts
@@ -9,6 +9,8 @@ import "~/styles/common.css";
import "~/styles/utils.css";
import "~/styles/flags.css";
+document.documentElement.classList.add("dark");
+
i18next.use(initReactI18next).init({
...config,
lng: "en",
diff --git a/app/features/components-showcase/ComponentsShowcase.browser.test.tsx b/app/features/components-showcase/ComponentsShowcase.browser.test.tsx
new file mode 100644
index 000000000..f2ce2d52d
--- /dev/null
+++ b/app/features/components-showcase/ComponentsShowcase.browser.test.tsx
@@ -0,0 +1,34 @@
+import { createMemoryRouter, RouterProvider } from "react-router";
+import { describe, expect, it } from "vitest";
+import { page } from "vitest/browser";
+import { render } from "vitest-browser-react";
+import { SECTIONS } from "./routes/components";
+
+const longViewport: (typeof SECTIONS)[number]["id"][] = [
+ "buttons",
+ "miscellaneous",
+];
+
+function renderComponentsShowcase(component: React.ReactNode) {
+ const router = createMemoryRouter(
+ [
+ {
+ path: "/",
+ element: component,
+ },
+ ],
+ { initialEntries: ["/"] },
+ );
+
+ return render();
+}
+
+describe("Components Showcase visual regression", async () => {
+ for (const { title, id, component: Component } of SECTIONS) {
+ it(`${title} section`, async () => {
+ await page.viewport(1000, longViewport.includes(id) ? 2500 : 800);
+ const screen = await renderComponentsShowcase();
+ await expect.element(screen.baseElement).toMatchScreenshot(title);
+ });
+ }
+});
diff --git a/app/features/components-showcase/routes/components.tsx b/app/features/components-showcase/routes/components.tsx
index 0d549bca3..a4063d6fe 100644
--- a/app/features/components-showcase/routes/components.tsx
+++ b/app/features/components-showcase/routes/components.tsx
@@ -46,7 +46,6 @@ import { TrashIcon } from "~/components/icons/Trash";
import { Label } from "~/components/Label";
import { Main } from "~/components/Main";
import { Pagination } from "~/components/Pagination";
-import { Placeholder } from "~/components/Placeholder";
import { Placement } from "~/components/Placement";
import { RelativeTime } from "~/components/RelativeTime";
import { Section } from "~/components/Section";
@@ -58,7 +57,7 @@ import { WeaponSelect } from "~/components/WeaponSelect";
import type { MainWeaponId, StageId } from "~/modules/in-game-lists/types";
import styles from "../components-showcase.module.css";
-const SECTIONS = [
+export const SECTIONS = [
{ title: "Buttons", id: "buttons", component: ButtonsSection },
{ title: "Alerts", id: "alerts", component: AlertsSection },
{ title: "Inputs", id: "inputs", component: InputsSection },
@@ -104,7 +103,7 @@ const SECTIONS = [
{ title: "Badges", id: "badges", component: BadgeSection },
{ title: "Game Selects", id: "game-selects", component: GameSelectSection },
{ title: "Miscellaneous", id: "miscellaneous", component: MiscSection },
-];
+] as const;
export default function ComponentsShowcasePage() {
return (
@@ -1964,15 +1963,6 @@ function BadgeSection({ id }: { id: string }) {
isAnimated={false}
size={64}
/>
-
@@ -2083,17 +2073,10 @@ function MiscSection({ id }: { id: string }) {
-
-
-
-