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

如何自定义Chakra UI的Alert与Badge组件并关联状态配色?

实现Chakra UI Alert与自定义Badge的颜色联动

核心思路

通过自定义Alert组件,将自身的status映射为Badge的colorScheme,并通过React.cloneElement自动传递给子级的AlertBadge,实现两者颜色联动。


1. 实现自定义AlertBadge组件

先封装带图标和标签的Badge,预留colorScheme接收父组件传递的颜色值:

import { Badge, Box } from '@chakra-ui/react';

export const AlertBadge = ({ icon, label, colorScheme = 'gray' }) => {
  return (
    <Badge colorScheme={colorScheme} variant="solid" px={2}>
      {icon && <Box as="span" mr={1}>{icon}</Box>}
      {label}
    </Badge>
  );
};

2. 自定义Alert组件(核心联动逻辑)

包装Chakra原生Alert,处理子组件并自动传递颜色映射:

import React from 'react';
import { Alert as ChakraAlert, Box } from '@chakra-ui/react';
import { AlertBadge } from './AlertBadge';

export const Alert = ({ status = 'info', children, ...props }) => {
  // 映射Alert status到Badge的colorScheme(可根据需求自定义扩展)
  const statusToColorScheme = {
    success: 'success',
    error: 'error',
    warning: 'warning',
    info: 'info',
    loading: 'blue'
  };
  const badgeColor = statusToColorScheme[status] || 'gray';

  // 遍历子元素,给AlertBadge注入对应的colorScheme
  const processedChildren = React.Children.map(children, child => {
    if (React.isValidElement(child) && child.type === AlertBadge) {
      return React.cloneElement(child, { colorScheme: badgeColor });
    }
    return child;
  });

  // 自定义Alert内部排版(可根据需求调整)
  return (
    <ChakraAlert status={status} {...props}>
      <Box display="flex" flexDirection="column" gap={2}>
        {processedChildren}
      </Box>
    </ChakraAlert>
  );
};

3. 优化Alert内部排版(可选)

如果希望Badge和标题在同一行对齐,修改Alert组件的内部结构:

export const Alert = ({ status = 'info', children, ...props }) => {
  const statusToColorScheme = {
    success: 'success',
    error: 'error',
    warning: 'warning',
    info: 'info',
    loading: 'blue'
  };
  const badgeColor = statusToColorScheme[status] || 'gray';

  const processedChildren = React.Children.map(children, child => {
    if (React.isValidElement(child) && child.type === AlertBadge) {
      return React.cloneElement(child, { colorScheme: badgeColor });
    }
    return child;
  });

  // 拆分Badge、标题、描述,实现灵活排版
  const childArray = React.Children.toArray(processedChildren);
  const badge = childArray.find(child => child.type === AlertBadge);
  const title = childArray.find(child => child.type.name === 'AlertTitle');
  const description = childArray.find(child => child.type.name === 'AlertDescription');

  return (
    <ChakraAlert status={status} {...props}>
      <Box display="flex" flexDirection="column" gap={1}>
        {badge && title ? (
          <Box display="flex" alignItems="center" gap={2}>
            {badge}
            {title}
          </Box>
        ) : (
          <>
            {badge}
            {title}
          </>
        )}
        {description}
      </Box>
    </ChakraAlert>
  );
};

4. 使用示例

import { CheckIcon, WarningIcon } from '@chakra-ui/icons';
import { Alert, AlertBadge, AlertTitle, AlertDescription } from './components';

// 成功状态Alert
<Alert status="success">
  <AlertBadge icon={<CheckIcon />} label="已完成" />
  <AlertTitle>操作成功</AlertTitle>
  <AlertDescription>您的请求已成功处理,请稍后查看结果。</AlertDescription>
</Alert>

// 错误状态Alert
<Alert status="error">
  <AlertBadge icon={<WarningIcon />} label="错误" />
  <AlertTitle>操作失败</AlertTitle>
  <AlertDescription>请求处理出现问题,请检查后重试。</AlertDescription>
</Alert>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:05:37