如何自定义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
相关产品推荐
相关产品推荐

