chakra-ui

📁 mgd34msu/goodvibes-gemini 📅 1 day ago
3
总安装量
2
周安装量
#58390
全站排名
安装命令
npx skills add https://github.com/mgd34msu/goodvibes-gemini --skill chakra-ui

Agent 安装分布

cline 2
gemini-cli 2
github-copilot 2
codex 2
kimi-cli 2
cursor 2

Skill 文档

Chakra UI v3

Accessible React component library with built-in styling, theming, and design tokens.

Quick Start

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>
  )
}

Core Concepts

Compound Components (v3)

Chakra v3 uses compound components with dot notation:

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>
  )
}

Style Props

Apply styles directly via props:

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>

Common Style Props

Prop CSS Property Example
bg background bg="blue.500"
color color color="gray.700"
p, px, py padding p="4" px="6"
m, mx, my margin m="auto" my="8"
w, h width, height w="full" h="100vh"
rounded border-radius rounded="lg"
shadow box-shadow shadow="md"
display display display="flex"
gap gap gap="4"

Components

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 and Forms

import { Field, Input, Textarea, NativeSelect } from '@chakra-ui/react'

<Field.Root>
  <Field.Label>Email</Field.Label>
  <Input placeholder="you@example.com" />
  <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 (Modal)

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>

Theming

Custom Theme

// 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>
}

Semantic Tokens

Chakra v3 provides 7 semantic tokens per color palette:

Token Purpose
solid Background for solid buttons
contrast Text on solid backgrounds
fg Foreground/text color
muted Muted backgrounds
subtle Subtle backgrounds
emphasized Hover states
focusRing Focus ring color
<Box bg="brand.subtle" color="brand.fg" p="4">
  Semantic tokens adjust for light/dark mode
</Box>

Dark Mode

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 />

Recipes (Component Variants)

Defining Recipes

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',
  },
})

Slot Recipes (Multi-part Components)

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',
        },
      },
    },
  },
})

Responsive Styles

// 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>

Breakpoints: base (0px), sm (480px), md (768px), lg (992px), xl (1280px), 2xl (1536px)

Layout Components

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>

Best Practices

  1. Use compound components – Prefer Dialog.Root, Dialog.Content over flat imports
  2. Leverage semantic tokens – Use brand.solid instead of brand.500 for theme flexibility
  3. Use snippets – Run npx @chakra-ui/cli snippet add for pre-built patterns
  4. Responsive object syntax – Clearer than array syntax for complex responsive styles
  5. Recipes for variants – Define component variants in theme, not inline

Reference Files