Next.js (App)

Next.jsのappディレクトリにYamada UIをインストールして使用するためのガイド。

インストール

  • 1

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

    Next.jsのアプリケーションを作成します。

    pnpm create next-app my-app --typescript
    
  • 2

    セットアップする

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

    pnpm dlx @yamada-ui/cli init
    
  • 3

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

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

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

    プロバイダーを追加する

    インストール後、アプリケーションのルートにUIProviderを追加します。 ハイドレーションエラーを抑制するために、htmlbodysuppressHydrationWarningtrueに設定します。

    layout.tsx

    import { UIProvider } from "@workspaces/ui"
    
    export default function RootLayout({
      children,
    }: {
      children: React.ReactNode
    }) {
      return (
        <html lang="en" suppressHydrationWarning>
          <body suppressHydrationWarning>
            <UIProvider>{children}</UIProvider>
          </body>
        </html>
      )
    }
    
  • 5

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

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

    page.tsx

    import { Button } from "@workspaces/ui"
    
    export default function Home() {
      return <Button>Click me!</Button>
    }
    

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

スクリプト

ColorModeScript

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

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

layout.tsx

import { UIProvider, ColorModeScript } from "@workspaces/ui"

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body suppressHydrationWarning>
        <ColorModeScript />

        <UIProvider>{children}</UIProvider>
      </body>
    </html>
  )
}

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

layout.tsx

import { UIProvider, ColorModeScript } from "@workspaces/ui"
import { config } from "@workspace/theme"

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body suppressHydrationWarning>
        <ColorModeScript defaultValue={config.defaultColorMode} />

        <UIProvider config={config}>{children}</UIProvider>
      </body>
    </html>
  )
}

ThemeSchemeScript

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

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

layout.tsx

import { UIProvider, ThemeSchemeScript } from "@workspaces/ui"

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body suppressHydrationWarning>
        <ThemeSchemeScript />

        <UIProvider>{children}</UIProvider>
      </body>
    </html>
  )
}

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

layout.tsx

import { UIProvider, ThemeSchemeScript } from "@workspaces/ui"
import { config } from "@workspace/theme"

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body suppressHydrationWarning>
        <ThemeSchemeScript defaultValue={config.defaultThemeScheme} />

        <UIProvider config={config}>{children}</UIProvider>
      </body>
    </html>
  )
}

クッキーを使用する

クッキーを使用することで、サーバーサイドレンダリングでも正常に動作させることができます。

layout.tsx

import { UIProvider, ColorModeScript, ThemeSchemeScript } from "@workspaces/ui"
import { cookies } from "next/headers"

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const cookieStore = await cookies()

  return (
    <html lang="en" suppressHydrationWarning>
      <body suppressHydrationWarning>
        <ColorModeScript type="cookie" />
        <ThemeSchemeScript type="cookie" />

        <UIProvider cookie={cookieStore.toString()}>{children}</UIProvider>
      </body>
    </html>
  )
}

コンポーネントの統合

Next.jsのLinkImageなどのコンポーネントとYamada UIのコンポーネントを統合することができます。

"use client"

import type {
  ButtonProps,
  HTMLRefAttributes,
  IconButtonProps,
  LinkProps,
  Merge,
} from "@yamada-ui/react"
import type { LinkProps as OriginalLinkProps } from "next/link"
import type { FC } from "react"
import { Button, IconButton, Link } from "@yamada-ui/react"
import OriginalLink from "next/link"

export interface NextLinkProps extends Omit<
  Merge<OriginalLinkProps, LinkProps>,
  "as" | "ref"
> {}

export const NextLink: FC<NextLinkProps> = (props) => {
  return <Link as={OriginalLink} {...props} />
}

export interface NextLinkButtonProps
  extends
    Omit<Merge<OriginalLinkProps, ButtonProps>, "as" | "ref">,
    HTMLRefAttributes<"a"> {}

export const NextLinkButton: FC<NextLinkButtonProps> = (props) => {
  return <Button as={OriginalLink} {...props} />
}

export interface NextLinkIconButtonProps
  extends
    Omit<Merge<OriginalLinkProps, IconButtonProps>, "as" | "ref">,
    HTMLRefAttributes<"a"> {}

export const NextLinkIconButton: FC<NextLinkIconButtonProps> = (props) => {
  return <IconButton as={OriginalLink} {...props} />
}

Image

"use client"

import { styled } from "@yamada-ui/react"
import Image from "next/image"

export const AppImage = styled(Image, {
  forwardProps: ["fill", "height", "width"],
})