You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chakra UI v3+Vite+React主题与按钮样式异常求助

问题:Instagram克隆项目样式异常,需调整为深色背景+黑色按钮白字

我正在跟随教程开发Instagram克隆,但当前页面显示白色背景、灰色按钮白字,想要实现深色背景+黑色按钮白字效果,已困扰多周,相关代码如下:

package.json

{
  "name": "insta-clone",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "@chakra-ui/react": "^3.0.0",
    "@emotion/is-prop-valid": "^1.3.1",
    "@emotion/react": "^11.1.0",
    "@emotion/styled": "^11.1.0",
    "framer-motion": "^12.9.1",
    "next-themes": "^0.4.6",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-icons": "^5.5.0"
  },
  "devDependencies": {
    "@eslint/js": "^9.22.0",
    "@types/react": "^19.0.10",
    "@types/react-dom": "^19.0.4",
    "@vitejs/plugin-react": "^4.3.4",
    "eslint": "^9.22.0",
    "eslint-plugin-react-hooks": "^5.2.0",
    "eslint-plugin-react-refresh": "^0.4.19",
    "globals": "^16.0.0",
    "vite": "^6.3.3",
    "vite-tsconfig-paths": "^5.1.4"
  }
}

main.jsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import { ChakraProvider } from '@chakra-ui/react';
import App from './App';
import theme from './themes/index';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <ChakraProvider value={theme}>
      <App />
    </ChakraProvider>
  </React.StrictMode>
);

App.jsx

import React from 'react';
import CustomButton from './themes/components/CustomButton'

function App() {
  return (
    <div>
        <CustomButton variant="primary" onClick={() => console.log('clicked')}>Click Me</CustomButton>
    </div>
  );
}

export default App;

主题文件 themes/index.ts

import { createSystem, defineConfig, defaultConfig } from '@chakra-ui/react'
import buttonRecipe from './foundation/recipes/button'

const tokens = {
  colors: {
    bg: {
      default: '#121212',
    },
    text: {
      default: '#ffffff',
    },
    teal: {
      400: '#38b2ac',
    },
  },
  radii: {
    md: '0.375rem',
  },
  fontWeights: {
    semibold: 600,
  },
  space: {
    4: '1rem',
  },
}

const theme = createSystem({
  config: defineConfig({
    initialColorMode: 'dark',
    useSystemColorMode: false,
  }),
  tokens,
  recipes: {
    button: buttonRecipe,
  },
})

export default theme;

themes/foundation/recipes/button.ts

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

const buttonRecipe = defineRecipe({
  base: {
    fontWeight: 'semibold',
    borderRadius: 'md',
    px: '4',
    py: '2',
    _hover: {
      opacity: 0.9,
    },
  },
  variants: {
    variant: {
      primary: {
        bg: 'teal.400',
        color: 'white',
      },
      defaultVariants: {
        variant: 'primary',
      },
    },
  },
})

export default buttonRecipe;

themes/components/CustomButton.tsx

import React from 'react'
import { Button } from '@chakra-ui/react'
import { css } from '@emotion/react'

interface CustomButtonProps {
  children: React.ReactNode
  variant?: 'primary' | 'secondary'
  [key: string]: any
}

const CustomButton = ({ children, variant = 'primary', ...props }: CustomButtonProps) => {
  console.log('Props:', props)

  const buttonStyles = {
    base: {
      fontWeight: 'semibold',
      borderRadius: 'md',
      px: '4',
      py: '2',
      _hover: {
        opacity: 0.9,
      },
    },
    primary: {
      bg: 'teal.400',
      color: 'white',
    },
    secondary: {
      bg: 'gray.400',
      color: 'black',
    },
  }

  console.log('Variant:', variant)
  console.log('Props:', props)

  const mergedStyles = {
    ...buttonStyles.base,
    ...(variant ? buttonStyles[variant] : {}),
  }

  return (
    <Button
      {...props}
      style={{
        fontWeight: 'semibold',
        borderRadius: 'md',
        paddingLeft: '1rem',
        paddingRight: '1rem',
        paddingTop: '0.5rem',
        paddingBottom: '0.5rem',
        backgroundColor: 'teal.400',
        color: 'white',
      }}
    >
      {children}
    </Button>
  )
}

export default CustomButton

jsconfig.json

{
    "compilerOptions": {
      "module": "ESNext",
      "moduleResolution": "node",
      "target": "ESNext",
      "jsx": "react-jsx",
      "baseUrl": "./",
      "paths": {
        "@ui/*": ["src/components/ui/*"],
        "@/*": ["src/*"]
      }
    },
    "include": ["src/**/*"]
  }

解决方案

1. 修复ChakraProvider主题传递方式

Chakra UI v3中,ChakraProvider接收主题的属性是theme而非value,修改main.jsx:

<ChakraProvider theme={theme}>
  <App />
</ChakraProvider>

2. 设置全局深色背景

改用Chakra的Box组件作为根容器,继承主题中的深色背景:
修改App.jsx:

import React from 'react';
import { Box } from '@chakra-ui/react';
import CustomButton from './themes/components/CustomButton'

function App() {
  return (
    <Box minH="100vh" bg="bg.default" color="text.default">
        <CustomButton variant="primary" onClick={() => console.log('clicked')}>Click Me</CustomButton>
    </Box>
  );
}

export default App;

3. 调整按钮为黑色背景

修改按钮recipe的primary变体背景色为黑色:
修改themes/foundation/recipes/button.ts:

const buttonRecipe = defineRecipe({
  base: {
    fontWeight: 'semibold',
    borderRadius: 'md',
    px: '4',
    py: '2',
    _hover: {
      opacity: 0.9,
    },
  },
  variants: {
    variant: {
      primary: {
        bg: 'black',
        color: 'white',
      },
      defaultVariants: {
        variant: 'primary',
      },
    },
  },
})

4. 简化CustomButton组件

去掉硬编码样式,直接利用Chakra主题的按钮变体:
修改CustomButton.tsx:

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

interface CustomButtonProps {
  children: React.ReactNode
  variant?: 'primary' | 'secondary'
  [key: string]: any
}

const CustomButton = ({ children, variant = 'primary', ...props }: CustomButtonProps) => {
  return (
    <Button variant={variant} {...props}>
      {children}
    </Button>
  )
}

export default CustomButton

内容的提问来源于stack exchange,提问作者Mahesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:55:54