mcpField
C
chakra-ui

chakra-ui

github.com/mgd34msuデザイン・UI473 回インストール41 週間前に更新
リポジトリ

chakra-ui について

Chakra UI v3は、スタイル、テーマ、デザイントークンを備えたReactコンポーネントライブラリです。複合コンポーネントやレスポンシブなレイアウト機能に加え、コンポーネントのバリエーションを定義するレシピを提供します。

主な機能

  1. 01アクセシブルなReactコンポーネント
  2. 02スタイルプロパティとレイアウト要素
  3. 03テーマとセマンティックトークン
  4. 04レスポンシブスタイル対応
  5. 05コンポーネントとスロットのレシピ
  6. 06事前作成済みコンポーネントスニペット

活用シーン

  1. 01Reactでフォームやダイアログを構築
  2. 02レスポンシブなページレイアウトを作成
  3. 03テーマに沿ったコンポーネントのバリエーションを定義

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mgd34msu/goodvibes-gemini --skill chakra-ui

インストール後、Claude Code で/chakra-uiを入力して読み込まれたか確認します。

同梱ファイルreferences/components.mdreferences/theming.md

詳細

Chakra UI v3

スタイル設定、テーマ設定、デザイントークンを標準搭載した、アクセシブルな React コンポーネントライブラリです。

クイックスタート

npm i @chakra-ui/react @emotion/react

# Add pre-built component snippets
npx @chakra-ui/cli snippet add
// components/ui/provider.tsx (generated by CLI)
import { ChakraProvider, defaultSystem } from '@chakra-ui/react'

export function Provider({ children }: { children: React.ReactNode }) {
  return <ChakraProvider value={defaultSystem}>{children}</ChakraProvider>
}
// app layout
import { Provider } from '@/components/ui/provider'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <Provider>{children}</Provider>
      </body>
    </html>
  )
}
// Usage
import { Button, HStack, Text } from '@chakra-ui/react'

function Demo() {
  return (
    <HStack gap="4">
      <Button colorPalette="blue">Primary</Button>
      <Button variant="outline">Secondary</Button>
    </HStack>
  )
}

コアコンセプト

複合コンポーネント(v3)

Chakra v3 では、ドット記法を使った複合コンポーネントを使用します。

import { Accordion } from '@chakra-ui/react'

function FAQ() {
  return (
    <Accordion.Root>
      <Accordion.Item value="item-1">
        <Accordion.ItemTrigger>
          What is Chakra UI?
          <Accordion.ItemIndicator />
        </Accordion.ItemTrigger>
        <Accordion.ItemContent>
          A component library for React.
        </Accordion.ItemContent>
      </Accordion.Item>
    </Accordion.Root>
  )
}
スタイルプロパティ

プロパティを使ってスタイルを直接適用します。

import { Box, Flex, Text } from '@chakra-ui/react'

<Box
  bg="blue.500"
  color="white"
  p="4"
  rounded="lg"
  shadow="md"
  _hover={{ bg: 'blue.600' }}
>
  Styled box
</Box>

<Flex
  direction={{ base: 'column', md: 'row' }}
  gap="4"
  align="center"
  justify="space-between"
>
  <Text fontSize="xl" fontWeight="bold">Title</Text>
  <Text color="gray.500">Subtitle</Text>
</Flex>
よく使うスタイルプロパティ
プロパティCSS プロパティ例
bg背景bg="blue.500"
color色color="gray.700"
p, px, pyパディングp="4" px="6"
m, mx, myマージンm="auto" my="8"
w, h幅、高さw="full" h="100vh"
rounded角丸rounded="lg"
shadowボックスシャドウshadow="md"
display表示display="flex"
gap間隔gap="4"

コンポーネント

Button
import { Button, ButtonGroup } from '@chakra-ui/react'

<Button colorPalette="blue">Solid</Button>
<Button colorPalette="blue" variant="outline">Outline</Button>
<Button colorPalette="blue" variant="ghost">Ghost</Button>
<Button colorPalette="blue" variant="subtle">Subtle</Button>

<Button size="xs">Extra Small</Button>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>

<Button loading loadingText="Saving...">Submit</Button>
<Button disabled>Disabled</Button>

<ButtonGroup>
  <Button>One</Button>
  <Button>Two</Button>
  <Button>Three</Button>
</ButtonGroup>
Input とフォーム
import { Field, Input, Textarea, NativeSelect } from '@chakra-ui/react'

<Field.Root>
  <Field.Label>Email</Field.Label>
  <Input placeholder="[email protected]" />
  <Field.HelperText>We'll never share your email</Field.HelperText>
</Field.Root>

<Field.Root invalid>
  <Field.Label>Password</Field.Label>
  <Input type="password" />
  <Field.ErrorText>Password is required</Field.ErrorText>
</Field.Root>

<Field.Root>
  <Field.Label>Country</Field.Label>
  <NativeSelect.Root>
    <NativeSelect.Field>
      <option value="">Select country</option>
      <option value="us">United States</option>
      <option value="uk">United Kingdom</option>
    </NativeSelect.Field>
  </NativeSelect.Root>
</Field.Root>
Dialog(モーダル)
import { Button, Dialog, Portal } from '@chakra-ui/react'
import { useState } from 'react'

function ModalExample() {
  const [open, setOpen] = useState(false)

  return (
    <Dialog.Root open={open} onOpenChange={(e) => setOpen(e.open)}>
      <Dialog.Trigger asChild>
        <Button>Open Dialog</Button>
      </Dialog.Trigger>

      <Portal>
        <Dialog.Backdrop />
        <Dialog.Positioner>
          <Dialog.Content>
            <Dialog.Header>
              <Dialog.Title>Dialog Title</Dialog.Title>
            </Dialog.Header>
            <Dialog.Body>
              Dialog content goes here.
            </Dialog.Body>
            <Dialog.Footer>
              <Dialog.ActionTrigger asChild>
                <Button variant="outline">Cancel</Button>
              </Dialog.ActionTrigger>
              <Button colorPalette="blue">Confirm</Button>
            </Dialog.Footer>
            <Dialog.CloseTrigger />
          </Dialog.Content>
        </Dialog.Positioner>
      </Portal>
    </Dialog.Root>
  )
}
Menu
import { Button, Menu, Portal } from '@chakra-ui/react'

<Menu.Root>
  <Menu.Trigger asChild>
    <Button variant="outline">Actions</Button>
  </Menu.Trigger>
  <Portal>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.Item value="edit">Edit</Menu.Item>
        <Menu.Item value="duplicate">Duplicate</Menu.Item>
        <Menu.Separator />
        <Menu.Item value="delete" color="red.500">Delete</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Portal>
</Menu.Root>
Tabs
import { Tabs } from '@chakra-ui/react'

<Tabs.Root defaultValue="account">
  <Tabs.List>
    <Tabs.Trigger value="account">Account</Tabs.Trigger>
    <Tabs.Trigger value="settings">Settings</Tabs.Trigger>
    <Tabs.Trigger value="billing">Billing</Tabs.Trigger>
  </Tabs.List>

  <Tabs.Content value="account">Account settings...</Tabs.Content>
  <Tabs.Content value="settings">App settings...</Tabs.Content>
  <Tabs.Content value="billing">Billing info...</Tabs.Content>
</Tabs.Root>
Card
import { Card, Button, Image, Text } from '@chakra-ui/react'

<Card.Root maxW="sm">
  <Image src="/product.jpg" alt="Product" />
  <Card.Body gap="2">
    <Card.Title>Product Name</Card.Title>
    <Card.Description>
      High-quality product description here.
    </Card.Description>
    <Text textStyle="2xl" fontWeight="medium" mt="2">
      $99.00
    </Text>
  </Card.Body>
  <Card.Footer gap="2">
    <Button colorPalette="blue">Buy Now</Button>
    <Button variant="ghost">Add to Cart</Button>
  </Card.Footer>
</Card.Root>

テーマ設定

カスタムテーマ
// theme.ts
import { createSystem, defaultConfig, defineConfig } from '@chakra-ui/react'

const config = defineConfig({
  theme: {
    tokens: {
      colors: {
        brand: {
          50: { value: '#e6f2ff' },
          100: { value: '#b3d9ff' },
          200: { value: '#80bfff' },
          300: { value: '#4da6ff' },
          400: { value: '#1a8cff' },
          500: { value: '#0073e6' },
          600: { value: '#005cb3' },
          700: { value: '#004480' },
          800: { value: '#002d4d' },
          900: { value: '#00161a' },
        },
      },
      fonts: {
        heading: { value: 'Inter, sans-serif' },
        body: { value: 'Inter, sans-serif' },
      },
    },
    semanticTokens: {
      colors: {
        brand: {
          solid: { value: '{colors.brand.500}' },
          contrast: { value: 'white' },
          fg: { value: '{colors.brand.700}' },
          muted: { value: '{colors.brand.100}' },
          subtle: { value: '{colors.brand.50}' },
          emphasized: { value: '{colors.brand.200}' },
          focusRing: { value: '{colors.brand.500}' },
        },
      },
    },
  },
})

export const system = createSystem(defaultConfig, config)
// provider.tsx
import { ChakraProvider } from '@chakra-ui/react'
import { system } from './theme'

export function Provider({ children }) {
  return <ChakraProvider value={system}>{children}</ChakraProvider>
}
セマンティックトークン

Chakra v3 では、各カラーパレットに 7 つのセマンティックトークンが用意されています。

トークン用途
solid塗りつぶしボタンの背景
contrast塗りつぶし背景上のテキスト
fg前景色/テキスト色
muted控えめな背景
subtleさりげない背景
emphasizedホバー状態
focusRingフォーカスリングの色
<Box bg="brand.subtle" color="brand.fg" p="4">
  Semantic tokens adjust for light/dark mode
</Box>
ダークモード
import { useColorMode, ColorModeButton } from '@chakra-ui/react'

function ThemeToggle() {
  const { colorMode, toggleColorMode } = useColorMode()

  return (
    <Button onClick={toggleColorMode}>
      {colorMode === 'light' ? 'Dark' : 'Light'} Mode
    </Button>
  )
}

// Or use built-in button
<ColorModeButton />

レシピ(コンポーネントのバリエーション)

レシピの定義
import { defineRecipe } from '@chakra-ui/react'

const buttonRecipe = defineRecipe({
  base: {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    fontWeight: 'medium',
    rounded: 'lg',
    transition: 'all 0.2s',
  },
  variants: {
    visual: {
      solid: {
        bg: 'brand.500',
        color: 'white',
        _hover: { bg: 'brand.600' },
      },
      outline: {
        border: '2px solid',
        borderColor: 'brand.500',
        color: 'brand.500',
      },
    },
    size: {
      sm: { h: '8', px: '3', fontSize: 'sm' },
      md: { h: '10', px: '4', fontSize: 'md' },
      lg: { h: '12', px: '6', fontSize: 'lg' },
    },
  },
  defaultVariants: {
    visual: 'solid',
    size: 'md',
  },
})
スロットレシピ(複数パーツのコンポーネント)
import { defineSlotRecipe } from '@chakra-ui/react'

const cardRecipe = defineSlotRecipe({
  slots: ['root', 'header', 'body', 'footer'],
  base: {
    root: {
      bg: 'white',
      rounded: 'xl',
      shadow: 'md',
      overflow: 'hidden',
    },
    header: {
      p: '4',
      borderBottom: '1px solid',
      borderColor: 'gray.200',
    },
    body: {
      p: '4',
    },
    footer: {
      p: '4',
      borderTop: '1px solid',
      borderColor: 'gray.200',
    },
  },
  variants: {
    variant: {
      elevated: {
        root: { shadow: 'xl' },
      },
      outline: {
        root: {
          shadow: 'none',
          border: '1px solid',
          borderColor: 'gray.200',
        },
      },
    },
  },
})

レスポンシブスタイル

// Object syntax
<Box
  fontSize={{ base: 'sm', md: 'md', lg: 'lg' }}
  p={{ base: '2', md: '4', lg: '6' }}
  display={{ base: 'block', md: 'flex' }}
>
  Responsive content
</Box>

// Array syntax (mobile-first)
<Box fontSize={['sm', 'md', 'lg', 'xl']}>
  Responsive text
</Box>

ブレークポイント:base(0px)、sm(480px)、md(768px)、lg(992px)、xl(1280px)、2xl(1536px)

レイアウトコンポーネント

import { Box, Flex, Grid, Stack, Container, Center } from '@chakra-ui/react'

// Flex layout
<Flex gap="4" wrap="wrap" justify="space-between">
  <Box>Item 1</Box>
  <Box>Item 2</Box>
</Flex>

// Grid layout
<Grid templateColumns="repeat(3, 1fr)" gap="4">
  <Box>Cell 1</Box>
  <Box>Cell 2</Box>
  <Box>Cell 3</Box>
</Grid>

// Stack (vertical by default)
<Stack gap="4">
  <Box>Item 1</Box>
  <Box>Item 2</Box>
</Stack>

// HStack / VStack
<HStack gap="4">...</HStack>
<VStack gap="4">...</VStack>

// Container with max-width
<Container maxW="6xl" px="4">
  Centered content
</Container>

// Center content
<Center h="100vh">
  Centered both ways
</Center>

ベストプラクティス

  1. 複合コンポーネントを使う - フラットなインポートよりも Dialog.Root、Dialog.Content を優先します
  2. セマンティックトークンを活用する - テーマの柔軟性を高めるため、brand.500 の代わりに brand.solid を使います
  3. スニペットを使う - 事前構築済みのパターンを追加するには、npx @chakra-ui/cli snippet add を実行します
  4. レスポンシブオブジェクト構文を使う - 複雑なレスポンシブスタイルでは、配列構文よりも明確です
  5. バリエーションにはレシピを使う - コンポーネントのバリエーションはインラインではなく、テーマで定義します

参考ファイル

コメント