diff --git a/.storybook/main.ts b/.storybook/main.ts index 1a9ac44..65f22b1 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,7 +1,6 @@ import type { StorybookConfig } from "@storybook/react-vite"; const config = { - stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], addons: [ "@storybook/addon-links", "@storybook/addon-essentials", @@ -9,11 +8,12 @@ const config = { "@storybook/addon-themes", "@storybook/addon-a11y", ], + docs: {}, framework: { name: "@storybook/react-vite", options: {}, }, - docs: {}, + stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], } satisfies StorybookConfig; export default config; diff --git a/.storybook/preview.ts b/.storybook/preview.ts index c2d935d..a6be491 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,9 +1,21 @@ import "../src/main.css"; -import { withThemeByDataAttribute } from "@storybook/addon-themes"; import type { Preview } from "@storybook/react"; +import { withThemeByDataAttribute } from "@storybook/addon-themes"; + const preview = { + decorators: [ + withThemeByDataAttribute({ + attributeName: "data-theme", + defaultTheme: "dark", + themes: { + dark: "dark", + light: "light", + }, + }), + ], + parameters: { actions: { argTypesRegex: "^on[A-Z].*" }, controls: { @@ -13,17 +25,6 @@ const preview = { }, }, }, - - decorators: [ - withThemeByDataAttribute({ - themes: { - light: "light", - dark: "dark", - }, - defaultTheme: "dark", - attributeName: "data-theme", - }), - ], } satisfies Preview; export default preview; diff --git a/.vscode/settings.json b/.vscode/settings.json index da3e988..f474eb7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,7 @@ "daisyui", "gitzy", "iconify", + "jiti", "knip", "lefthook", "lockb", diff --git a/bun.lockb b/bun.lockb index f417e02..e50ac59 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/e2e/app.spec.ts b/e2e/app.spec.ts index 93a7f82..5cea1fb 100644 --- a/e2e/app.spec.ts +++ b/e2e/app.spec.ts @@ -12,7 +12,7 @@ test("not found", async ({ page }) => { await expect(page).toHaveTitle(/React Starter/); await expect( - page.getByRole("heading", { name: "Error", level: 1 }), + page.getByRole("heading", { level: 1, name: "Error" }), ).toBeInViewport(); }); @@ -21,7 +21,7 @@ test.describe("external links", () => { await page.goto("/"); }); - test("opened vite docs", async ({ page, context }) => { + test("opened vite docs", async ({ context, page }) => { const pagePromise = context.waitForEvent("page"); await page.getByRole("link", { name: /vite/i }).click(); @@ -33,10 +33,10 @@ test.describe("external links", () => { await expect(newPage).toHaveURL("https://vite.dev/"); }); - test("opened React docs", async ({ page, context }) => { + test("opened React docs", async ({ context, page }) => { const pagePromise = context.waitForEvent("page"); - await page.getByRole("link", { name: "React", exact: true }).click(); + await page.getByRole("link", { exact: true, name: "React" }).click(); const newPage = await pagePromise; @@ -45,7 +45,7 @@ test.describe("external links", () => { await expect(newPage).toHaveURL("https://react.dev/"); }); - test("opened TypeScript docs", async ({ page, context }) => { + test("opened TypeScript docs", async ({ context, page }) => { const pagePromise = context.waitForEvent("page"); await page.getByRole("link", { name: /TypeScript/i }).click(); @@ -57,7 +57,7 @@ test.describe("external links", () => { await expect(newPage).toHaveURL("https://www.typescriptlang.org/"); }); - test("opened tailwindcss docs", async ({ page, context }) => { + test("opened tailwindcss docs", async ({ context, page }) => { const pagePromise = context.waitForEvent("page"); await page.getByRole("link", { name: /tailwindcss/i }).click(); @@ -69,7 +69,7 @@ test.describe("external links", () => { await expect(newPage).toHaveURL("https://tailwindcss.com/"); }); - test("opened repo", async ({ page, context }) => { + test("opened repo", async ({ context, page }) => { const pagePromise = context.waitForEvent("page"); await page.getByRole("link", { name: "GitHub" }).click(); @@ -83,7 +83,7 @@ test.describe("external links", () => { ); }); - test("opened Bun", async ({ page, context }) => { + test("opened Bun", async ({ context, page }) => { const pagePromise = context.waitForEvent("page"); await page.getByRole("link", { name: "Bun" }).click(); @@ -95,7 +95,7 @@ test.describe("external links", () => { await expect(newPage).toHaveURL("https://bun.sh"); }); - test("opened daisyUI docs", async ({ page, context }) => { + test("opened daisyUI docs", async ({ context, page }) => { const pagePromise = context.waitForEvent("page"); await page.getByRole("link", { name: /daisyUI/i }).click(); diff --git a/eslint.config.ts b/eslint.config.ts index 5a9e17d..6507261 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -5,5 +5,5 @@ import eslintPluginStorybook from "eslint-plugin-storybook"; export default jimmyDotCodes({ autoDetect: true, // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - overrides: [...eslintPluginStorybook.configs["flat/recommended"]], + configs: [...eslintPluginStorybook.configs["flat/recommended"]], }); diff --git a/package.json b/package.json index f517362..392c879 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "prettier": "@jimmy.codes/prettier-config", "dependencies": { "@tanstack/react-query": "5.59.16", - "@tanstack/react-router": "1.77.8", + "@tanstack/react-router": "1.77.9", "clsx": "2.1.1", "react": "18.3.1", "react-dom": "18.3.1", @@ -36,22 +36,22 @@ "@iconify-json/logos": "1.2.3", "@iconify-json/lucide": "1.2.11", "@iconify/tailwind": "1.1.3", - "@jimmy.codes/eslint-config": "2.0.0", + "@jimmy.codes/eslint-config": "3.2.1", "@jimmy.codes/prettier-config": "1.1.0", "@playwright/test": "1.48.2", - "@storybook/addon-a11y": "8.3.6", - "@storybook/addon-essentials": "8.3.6", - "@storybook/addon-interactions": "8.3.6", - "@storybook/addon-links": "8.3.6", - "@storybook/addon-themes": "8.3.6", - "@storybook/react": "8.3.6", - "@storybook/react-vite": "8.3.6", + "@storybook/addon-a11y": "8.4.0", + "@storybook/addon-essentials": "8.4.0", + "@storybook/addon-interactions": "8.4.0", + "@storybook/addon-links": "8.4.0", + "@storybook/addon-themes": "8.4.0", + "@storybook/react": "8.4.0", + "@storybook/react-vite": "8.4.0", "@tailwindcss/typography": "0.5.15", "@tanstack/react-query-devtools": "5.59.16", - "@tanstack/router-devtools": "1.77.8", + "@tanstack/router-devtools": "1.77.9", "@tanstack/router-vite-plugin": "1.77.7", "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.2", + "@testing-library/jest-dom": "6.6.3", "@testing-library/react": "16.0.1", "@testing-library/user-event": "14.5.2", "@total-typescript/ts-reset": "0.6.1", @@ -69,12 +69,12 @@ "happy-dom": "15.7.4", "is-ci": "3.0.1", "jiti": "2.3.3", - "knip": "5.34.4", + "knip": "5.36.0", "lefthook": "1.8.2", "msw": "2.6.0", "postcss": "8.4.47", "prettier": "3.3.3", - "storybook": "8.3.6", + "storybook": "8.4.0", "tailwindcss": "3.4.14", "turbo": "2.2.3", "typescript": "5.6.3", diff --git a/playwright.config.ts b/playwright.config.ts index d1800b6..34e4e6a 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -26,6 +26,6 @@ export default defineConfig({ reporter: "html", retries: isCI ? 2 : 0, testDir: "./e2e", - use: { trace: "on-first-retry", baseURL }, + use: { baseURL, trace: "on-first-retry" }, ...(isCI && { workers: 1 }), }); diff --git a/postcss.config.js b/postcss.config.js index 5e07b92..30c1146 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,8 +1,8 @@ /** @type {import("postcss").Postcss} */ const config = { plugins: { - tailwindcss: {}, autoprefixer: {}, + tailwindcss: {}, }, }; diff --git a/src/components/ext-link.stories.ts b/src/components/ext-link.stories.ts index 95c98bb..e730478 100644 --- a/src/components/ext-link.stories.ts +++ b/src/components/ext-link.stories.ts @@ -3,12 +3,12 @@ import type { Meta, StoryObj } from "@storybook/react"; import { ExtLink } from "./ext-link"; const meta = { - title: "Components/ExtLink", component: ExtLink, parameters: { layout: "centered", }, tags: ["autodocs"], + title: "Components/ExtLink", } satisfies Meta; export default meta; @@ -17,39 +17,39 @@ type Story = StoryObj; export const Default: Story = { args: { - to: "daisyUI", children: "daisyUI", + to: "daisyUI", }, }; export const Primary: Story = { args: { - to: "React", - color: "primary", children: "React", + color: "primary", + to: "React", }, }; export const Secondary: Story = { args: { - to: "Vite", - color: "secondary", children: "Vite", + color: "secondary", + to: "Vite", }, }; export const Accent: Story = { args: { - to: "tailwindcss", - color: "accent", children: "tailwindcss", + color: "accent", + to: "tailwindcss", }, }; export const Button: Story = { args: { + children: "TypeScript", to: "TypeScript", variant: "button", - children: "TypeScript", }, }; diff --git a/src/components/ext-link.tsx b/src/components/ext-link.tsx index 034d3bd..df1b484 100644 --- a/src/components/ext-link.tsx +++ b/src/components/ext-link.tsx @@ -4,14 +4,14 @@ import { externalLinks } from "@/config/external-links"; import { cn } from "@/lib/cn"; type Color = "accent" | "primary" | "secondary"; -type Variant = "default" | "button"; +type Variant = "button" | "default"; interface ExtLinkProps { + children: ReactNode; className?: string; - to: keyof typeof externalLinks; color?: Color; + to: keyof typeof externalLinks; variant?: Variant; - children: ReactNode; } /** @@ -21,27 +21,27 @@ interface ExtLinkProps { * tailwindcss // https://tailwindcss.com */ export const ExtLink = ({ - to, + children, className, color, + to, variant = "default", - children, }: ExtLinkProps) => { return ( {children} diff --git a/src/config/external-links.ts b/src/config/external-links.ts index 008f372..d51113e 100644 --- a/src/config/external-links.ts +++ b/src/config/external-links.ts @@ -1,12 +1,12 @@ export const externalLinks = { - "Vite": "https://vite.dev", - "React": "https://react.dev", - "TypeScript": "https://www.typescriptlang.org", - "tailwindcss": "https://tailwindcss.com", - "GitHub": "https://github.com/jimmy-guzman/react-starter", + "Bun": "https://bun.sh", + "daisyUI": "https://daisyui.com", "Deploy": "https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fjimmy-guzman%2Freact-starter&project-name=my-awesome-react-project&repository-name=my-awesome-react-project", - "Bun": "https://bun.sh", + "GitHub": "https://github.com/jimmy-guzman/react-starter", + "React": "https://react.dev", + "tailwindcss": "https://tailwindcss.com", "TanStack Router": "https://tanstack.com/router/latest", - "daisyUI": "https://daisyui.com", + "TypeScript": "https://www.typescriptlang.org", + "Vite": "https://vite.dev", } satisfies Record; diff --git a/src/lib/cn.ts b/src/lib/cn.ts index e576ad8..4e14fa3 100644 --- a/src/lib/cn.ts +++ b/src/lib/cn.ts @@ -1,4 +1,6 @@ -import { type ClassValue, clsx } from "clsx"; +import type { ClassValue } from "clsx"; + +import { clsx } from "clsx"; import { twMerge } from "tailwind-merge"; export const cn = (...classes: ClassValue[]) => { diff --git a/src/pages/error.spec.tsx b/src/pages/error.spec.tsx index 1a99fb0..215b8fc 100644 --- a/src/pages/error.spec.tsx +++ b/src/pages/error.spec.tsx @@ -5,7 +5,7 @@ import { Error as ErrorPage } from "./error"; describe("", () => { it('should render "Something went Wrong!" message', async () => { await render( - , + , ); expect(screen.getByText("Something went Wrong!")).toBeInTheDocument(); diff --git a/src/pages/error.tsx b/src/pages/error.tsx index 0b1458b..ec51de3 100644 --- a/src/pages/error.tsx +++ b/src/pages/error.tsx @@ -1,4 +1,6 @@ -import { type ErrorComponentProps, Link } from "@tanstack/react-router"; +import type { ErrorComponentProps } from "@tanstack/react-router"; + +import { Link } from "@tanstack/react-router"; export const Error = ({ error }: ErrorComponentProps) => { return ( diff --git a/src/pages/home.spec.tsx b/src/pages/home.spec.tsx index aa09f61..2c958db 100644 --- a/src/pages/home.spec.tsx +++ b/src/pages/home.spec.tsx @@ -7,7 +7,7 @@ describe("", () => { await render(); expect( - screen.getByRole("heading", { name: "React Starter", level: 1 }), + screen.getByRole("heading", { level: 1, name: "React Starter" }), ).toBeInTheDocument(); }); }); diff --git a/src/pages/home.stories.tsx b/src/pages/home.stories.tsx index 8f59530..0aab620 100644 --- a/src/pages/home.stories.tsx +++ b/src/pages/home.stories.tsx @@ -3,8 +3,8 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Home as HomeComponent } from "./home"; const meta = { - title: "Pages/Home", component: HomeComponent, + title: "Pages/Home", } satisfies Meta; export default meta; diff --git a/src/pages/home.tsx b/src/pages/home.tsx index a211799..93a66f2 100644 --- a/src/pages/home.tsx +++ b/src/pages/home.tsx @@ -24,10 +24,10 @@ export const Home = () => { daisyUI.

- + Deploy - + GitHub
diff --git a/src/router.tsx b/src/router.tsx index 584a172..1f29b05 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -5,9 +5,9 @@ import { NotFound } from "./pages/not-found"; import { routeTree } from "./route-tree.gen"; export const router = createRouter({ - routeTree, - defaultNotFoundComponent: NotFound, defaultErrorComponent: Error, + defaultNotFoundComponent: NotFound, + routeTree, }); declare module "@tanstack/react-router" { diff --git a/src/testing/utils.tsx b/src/testing/utils.tsx index ab201f6..58c8ecd 100644 --- a/src/testing/utils.tsx +++ b/src/testing/utils.tsx @@ -1,3 +1,6 @@ +import type { RenderOptions } from "@testing-library/react"; +import type { ReactElement, ReactNode } from "react"; + import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { createMemoryHistory, @@ -6,10 +9,9 @@ import { createRouter, RouterProvider, } from "@tanstack/react-router"; -import type { RenderOptions } from "@testing-library/react"; import { act, cleanup, render } from "@testing-library/react"; import { userEvent } from "@testing-library/user-event"; -import { type ReactElement, type ReactNode, useMemo } from "react"; +import { useMemo } from "react"; import { afterEach } from "vitest"; import type { FileRoutesById } from "@/route-tree.gen"; @@ -20,12 +22,12 @@ afterEach(() => { interface WrapperProps { children: ReactNode; - path: keyof FileRoutesById; initialEntries: string[]; + path: keyof FileRoutesById; } // eslint-disable-next-line react-refresh/only-export-components -const Wrapper = ({ children, path, initialEntries }: WrapperProps) => { +const Wrapper = ({ children, initialEntries, path }: WrapperProps) => { const { queryClient, router } = useMemo(() => { const queryClient = new QueryClient({ defaultOptions: { @@ -37,21 +39,21 @@ const Wrapper = ({ children, path, initialEntries }: WrapperProps) => { const rootRoute = createRootRoute(); const testingRoute = createRoute({ + component: () => { + return children; + }, getParentRoute: () => { return rootRoute; }, path, - component: () => { - return children; - }, }); return { queryClient, router: createRouter({ - routeTree: rootRoute.addChildren([testingRoute]), - history: createMemoryHistory({ initialEntries }), context: { queryClient }, + history: createMemoryHistory({ initialEntries }), + routeTree: rootRoute.addChildren([testingRoute]), }), }; }, [children, initialEntries, path]); @@ -77,7 +79,7 @@ const customRender = async ( return render(ui, { wrapper: ({ children }) => { return ( - + {children} ); diff --git a/tailwind.config.ts b/tailwind.config.ts index a5b4251..d49e588 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,20 +1,21 @@ +import type { Config } from "tailwindcss"; + import { addDynamicIconSelectors } from "@iconify/tailwind"; import typography from "@tailwindcss/typography"; import daisyui from "daisyui"; -import type { Config } from "tailwindcss"; const config = { content: ["./index.html", "./src/**/*.{ts,tsx}"], - theme: { - extend: {}, - }, daisyui: { + logs: false, + prefix: "dsy-", // see https://daisyui.com/docs/themes/ for further customization themes: ["dark", "light"], - prefix: "dsy-", - logs: false, }, plugins: [typography, daisyui, addDynamicIconSelectors()], + theme: { + extend: {}, + }, } satisfies Config; export default config; diff --git a/vite.config.ts b/vite.config.ts index 6222682..a3dfe24 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,25 +8,21 @@ export default defineConfig(({ mode }) => { const { PORT = 5173 } = loadEnv(mode, process.cwd(), ""); return { + entries: ["index.html"], plugins: [ react(), tanStackRouterVite({ + autoCodeSplitting: true, generatedRouteTree: "./src/route-tree.gen.ts", - semicolons: true, quoteStyle: "double", - autoCodeSplitting: true, + semicolons: true, }), tsconfigPaths(), ], server: { port: Number(PORT), }, - entries: ["index.html"], test: { - environment: "happy-dom", - globals: true, - exclude: [...configDefaults.exclude, "e2e/*"], - setupFiles: "./src/testing/setup.ts", coverage: { exclude: [ ...(configDefaults.coverage.exclude ?? []), @@ -39,6 +35,10 @@ export default defineConfig(({ mode }) => { "**/*.gen.*", ], }, + environment: "happy-dom", + exclude: [...configDefaults.exclude, "e2e/*"], + globals: true, + setupFiles: "./src/testing/setup.ts", }, }; });