TanStack Router

TanStack RouterのプロジェクトにYamada UIをインストールして使用するためのガイド。

インストール

  • 1

    アプリケーションを作成する

    TanStack Routerのアプリケーションを作成します。

    pnpm dlx create-tsrouter-app my-app
    
  • 2

    セットアップする

    コマンドを実行すると、プロジェクトに必要なファイルやフォルダが作成されます。

    pnpm dlx @yamada-ui/cli init
    
  • 3

    パッケージをインストールする

    アプリケーションに@workspaces/uiをインストールします。

    pnpm add "@workspaces/ui@workspace:*"
    
  • 4

    プロバイダーを追加する

    インストール後、アプリケーションのルートにUIProviderを追加します。

    main.tsx

    import ReactDOM from "react-dom/client"
    import { RouterProvider, createRouter } from "@tanstack/react-router"
    import { routeTree } from "./routeTree.gen"
    import { UIProvider } from "@workspaces/ui"
    
    const router = createRouter({
      routeTree,
      defaultPreload: "intent",
      scrollRestoration: true,
    })
    
    declare module "@tanstack/react-router" {
      interface Register {
        router: typeof router
      }
    }
    
    const rootElement = document.getElementById("app")!
    
    if (!rootElement.innerHTML) {
      const root = ReactDOM.createRoot(rootElement)
      root.render(
        <UIProvider>
          <RouterProvider router={router} />
        </UIProvider>,
      )
    }
    
  • 5

    コンポーネントを使用する

    UIProviderを追加したら、アプリケーション内でコンポーネントを使用します。

    index.tsx

    import { createFileRoute } from "@tanstack/react-router"
    import { Button } from "@workspaces/ui"
    
    export const Route = createFileRoute("/")({ component: App })
    
    function App() {
      return <Button>Click me!</Button>
    }
    

    これで、Yamada UIのセットアップは完了です!

スクリプト

ColorModeScript

カラーモードを使用する場合は、正常に動作させるためにbodyColorModeScriptを追加する必要があります。

理由は、カラーモードがlocalStoragecookiesを用いて実装されており、ページの読み込み時に同期を正しく機能させるためです。

vite.config.ts

import viteReact from "@vitejs/plugin-react"
import type { Plugin } from "vite"
import { defineConfig } from "vite"
import tsconfigPaths from "vite-tsconfig-paths"
import { devtools } from "@tanstack/devtools-vite"
import { tanstackRouter } from "@tanstack/router-plugin/vite"
import { COLOR_MODE_STORAGE_KEY, getStorageScript } from "@workspaces/ui"

function injectColorModeScript(): Plugin {
  return {
    name: "inject-color-mode-script",
    transformIndexHtml(html) {
      const content = getStorageScript(
        "colorMode",
        COLOR_MODE_STORAGE_KEY,
      )({ defaultValue: "light" })

      return html.replace("<body>", `<body><script>${content}</script>`)
    },
  }
}

const config = defineConfig({
  plugins: [
    devtools(),
    tsconfigPaths({ projects: ["./tsconfig.json"] }),
    tanstackRouter({ target: "react", autoCodeSplitting: true }),
    viteReact(),
    injectColorModeScript(),
  ],
})

export default config

もし、コンフィグdefaultColorModeを変更した場合は、ColorModeScriptdefaultValueを設定します。

vite.config.ts

import viteReact from "@vitejs/plugin-react"
import type { Plugin } from "vite"
import { defineConfig } from "vite"
import tsconfigPaths from "vite-tsconfig-paths"
import { devtools } from "@tanstack/devtools-vite"
import { tanstackRouter } from "@tanstack/router-plugin/vite"
import { COLOR_MODE_STORAGE_KEY, getStorageScript } from "@workspaces/ui"
import { config as themeConfig } from "@workspaces/theme"

function injectColorModeScript(): Plugin {
  return {
    name: "inject-color-mode-script",
    transformIndexHtml(html) {
      const content = getStorageScript(
        "colorMode",
        COLOR_MODE_STORAGE_KEY,
      )({ defaultValue: themeConfig.defaultColorMode })

      return html.replace("<body>", `<body><script>${content}</script>`)
    },
  }
}

const config = defineConfig({
  plugins: [
    devtools(),
    tsconfigPaths({ projects: ["./tsconfig.json"] }),
    tanstackRouter({ target: "react", autoCodeSplitting: true }),
    viteReact(),
    injectColorModeScript(),
  ],
})

export default config

ThemeSchemeScript

テーマの切り替えを使用する場合は、正常に動作させるためにbodyThemeSchemeScriptを追加する必要があります。

理由は、テーマの切り替えがlocalStoragecookiesを用いて実装されており、ページの読み込み時に同期を正しく機能させるためです。

vite.config.ts

import viteReact from "@vitejs/plugin-react"
import type { Plugin } from "vite"
import { defineConfig } from "vite"
import tsconfigPaths from "vite-tsconfig-paths"
import { devtools } from "@tanstack/devtools-vite"
import { tanstackRouter } from "@tanstack/router-plugin/vite"
import { THEME_SCHEME_STORAGE_KEY, getStorageScript } from "@workspaces/ui"

function injectThemeSchemeScript(): Plugin {
  return {
    name: "inject-theme-scheme-script",
    transformIndexHtml(html) {
      const content = getStorageScript(
        "themeScheme",
        THEME_SCHEME_STORAGE_KEY,
      )({ defaultValue: "base" })

      return html.replace("<body>", `<body><script>${content}</script>`)
    },
  }
}

const config = defineConfig({
  plugins: [
    devtools(),
    tsconfigPaths({ projects: ["./tsconfig.json"] }),
    tanstackRouter({ target: "react", autoCodeSplitting: true }),
    viteReact(),
    injectThemeSchemeScript(),
  ],
})

export default config

もし、コンフィグdefaultThemeSchemeを変更した場合は、ThemeSchemeScriptdefaultValueを設定します。

vite.config.ts

import viteReact from "@vitejs/plugin-react"
import type { Plugin } from "vite"
import { defineConfig } from "vite"
import tsconfigPaths from "vite-tsconfig-paths"
import { devtools } from "@tanstack/devtools-vite"
import { tanstackRouter } from "@tanstack/router-plugin/vite"
import { THEME_SCHEME_STORAGE_KEY, getStorageScript } from "@workspaces/ui"
import { config as themeConfig } from "@workspaces/theme"

function injectThemeSchemeScript(): Plugin {
  return {
    name: "inject-theme-scheme-script",
    transformIndexHtml(html) {
      const content = getStorageScript(
        "themeScheme",
        THEME_SCHEME_STORAGE_KEY,
      )({ defaultValue: themeConfig.defaultThemeScheme })

      return html.replace("<body>", `<body><script>${content}</script>`)
    },
  }
}

const config = defineConfig({
  plugins: [
    devtools(),
    tsconfigPaths({ projects: ["./tsconfig.json"] }),
    tanstackRouter({ target: "react", autoCodeSplitting: true }),
    viteReact(),
    injectThemeSchemeScript(),
  ],
})

export default config

コンポーネントの統合

TanStack RouterのLinkなどのコンポーネントとYamada UIのコンポーネントを統合することができます。

import type { LinkComponent } from "@tanstack/react-router"
import { createLink } from "@tanstack/react-router"
import { Button, IconButton, Link } from "@workspaces/ui"

const CreatedLink = createLink(Link)

export const RouterLink: LinkComponent<typeof CreatedLink> = (props) => {
  return <CreatedLink {...props} />
}

const CreatedLinkButton = createLink(Button)

export const RouterLinkButton: LinkComponent<typeof CreatedLinkButton> = (
  props,
) => {
  return <CreatedLinkButton {...props} />
}

const CreatedLinkIconButton = createLink(IconButton)

export const RouterLinkIconButton: LinkComponent<
  typeof CreatedLinkIconButton
> = (props) => {
  return <CreatedLinkIconButton {...props} />
}