feat(GlassCard): 新增通用毛玻璃卡片组件
- 支持多种变体: default, elevated, subtle, transparent - 支持悬停效果、发光效果、角落装饰 - 黑金配色主题,可全局复用 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
179
src/components/GlassCard/index.js
Normal file
179
src/components/GlassCard/index.js
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* GlassCard - 通用毛玻璃卡片组件
|
||||
*
|
||||
* 复用自 Company 页面的 Glassmorphism 风格
|
||||
* 可在全局使用
|
||||
*/
|
||||
|
||||
import React, { memo, forwardRef } from 'react';
|
||||
import { Box } from '@chakra-ui/react';
|
||||
|
||||
// 主题配置
|
||||
const GLASS_THEME = {
|
||||
colors: {
|
||||
gold: {
|
||||
400: '#D4AF37',
|
||||
500: '#B8960C',
|
||||
},
|
||||
bg: {
|
||||
deep: '#0A0A14',
|
||||
primary: '#0F0F1A',
|
||||
elevated: '#1A1A2E',
|
||||
surface: '#252540',
|
||||
},
|
||||
line: {
|
||||
subtle: 'rgba(212, 175, 55, 0.1)',
|
||||
default: 'rgba(212, 175, 55, 0.2)',
|
||||
emphasis: 'rgba(212, 175, 55, 0.4)',
|
||||
},
|
||||
},
|
||||
blur: {
|
||||
sm: 'blur(8px)',
|
||||
md: 'blur(16px)',
|
||||
lg: 'blur(24px)',
|
||||
},
|
||||
glow: {
|
||||
sm: '0 0 8px rgba(212, 175, 55, 0.3)',
|
||||
md: '0 0 16px rgba(212, 175, 55, 0.4)',
|
||||
},
|
||||
};
|
||||
|
||||
// 变体样式
|
||||
const VARIANTS = {
|
||||
default: {
|
||||
bg: `linear-gradient(135deg, ${GLASS_THEME.colors.bg.elevated} 0%, ${GLASS_THEME.colors.bg.primary} 100%)`,
|
||||
border: `1px solid ${GLASS_THEME.colors.line.default}`,
|
||||
backdropFilter: GLASS_THEME.blur.md,
|
||||
},
|
||||
elevated: {
|
||||
bg: `linear-gradient(145deg, ${GLASS_THEME.colors.bg.surface} 0%, ${GLASS_THEME.colors.bg.elevated} 100%)`,
|
||||
border: `1px solid ${GLASS_THEME.colors.line.emphasis}`,
|
||||
backdropFilter: GLASS_THEME.blur.lg,
|
||||
},
|
||||
subtle: {
|
||||
bg: 'rgba(212, 175, 55, 0.05)',
|
||||
border: `1px solid ${GLASS_THEME.colors.line.subtle}`,
|
||||
backdropFilter: GLASS_THEME.blur.sm,
|
||||
},
|
||||
transparent: {
|
||||
bg: 'rgba(15, 15, 26, 0.8)',
|
||||
border: `1px solid ${GLASS_THEME.colors.line.default}`,
|
||||
backdropFilter: GLASS_THEME.blur.lg,
|
||||
},
|
||||
};
|
||||
|
||||
const ROUNDED_MAP = {
|
||||
sm: '8px',
|
||||
md: '12px',
|
||||
lg: '16px',
|
||||
xl: '20px',
|
||||
'2xl': '24px',
|
||||
};
|
||||
|
||||
const PADDING_MAP = {
|
||||
none: 0,
|
||||
sm: 3,
|
||||
md: 4,
|
||||
lg: 6,
|
||||
};
|
||||
|
||||
// 角落装饰
|
||||
const CornerDecor = memo(({ position }) => {
|
||||
const baseStyle = {
|
||||
position: 'absolute',
|
||||
width: '12px',
|
||||
height: '12px',
|
||||
borderColor: GLASS_THEME.colors.gold[400],
|
||||
borderStyle: 'solid',
|
||||
borderWidth: 0,
|
||||
opacity: 0.6,
|
||||
};
|
||||
|
||||
const positions = {
|
||||
tl: { top: '8px', left: '8px', borderTopWidth: '2px', borderLeftWidth: '2px' },
|
||||
tr: { top: '8px', right: '8px', borderTopWidth: '2px', borderRightWidth: '2px' },
|
||||
bl: { bottom: '8px', left: '8px', borderBottomWidth: '2px', borderLeftWidth: '2px' },
|
||||
br: { bottom: '8px', right: '8px', borderBottomWidth: '2px', borderRightWidth: '2px' },
|
||||
};
|
||||
|
||||
return <Box sx={{ ...baseStyle, ...positions[position] }} />;
|
||||
});
|
||||
|
||||
CornerDecor.displayName = 'CornerDecor';
|
||||
|
||||
/**
|
||||
* GlassCard 组件
|
||||
*
|
||||
* @param {string} variant - 变体: 'default' | 'elevated' | 'subtle' | 'transparent'
|
||||
* @param {boolean} hoverable - 是否启用悬停效果
|
||||
* @param {boolean} glowing - 是否启用发光效果
|
||||
* @param {boolean} cornerDecor - 是否显示角落装饰
|
||||
* @param {string} rounded - 圆角: 'sm' | 'md' | 'lg' | 'xl' | '2xl'
|
||||
* @param {string} padding - 内边距: 'none' | 'sm' | 'md' | 'lg'
|
||||
*/
|
||||
const GlassCard = forwardRef(
|
||||
(
|
||||
{
|
||||
children,
|
||||
variant = 'default',
|
||||
hoverable = true,
|
||||
glowing = false,
|
||||
cornerDecor = false,
|
||||
rounded = 'lg',
|
||||
padding = 'md',
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const variantStyle = VARIANTS[variant] || VARIANTS.default;
|
||||
|
||||
return (
|
||||
<Box
|
||||
ref={ref}
|
||||
position="relative"
|
||||
bg={variantStyle.bg}
|
||||
border={variantStyle.border}
|
||||
borderRadius={ROUNDED_MAP[rounded]}
|
||||
backdropFilter={variantStyle.backdropFilter}
|
||||
p={PADDING_MAP[padding]}
|
||||
transition="all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)"
|
||||
overflow="hidden"
|
||||
_hover={
|
||||
hoverable
|
||||
? {
|
||||
borderColor: GLASS_THEME.colors.line.emphasis,
|
||||
boxShadow: glowing ? GLASS_THEME.glow.md : GLASS_THEME.glow.sm,
|
||||
transform: 'translateY(-2px)',
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
sx={{
|
||||
...(glowing && {
|
||||
boxShadow: GLASS_THEME.glow.sm,
|
||||
}),
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{/* 角落装饰 */}
|
||||
{cornerDecor && (
|
||||
<>
|
||||
<CornerDecor position="tl" />
|
||||
<CornerDecor position="tr" />
|
||||
<CornerDecor position="bl" />
|
||||
<CornerDecor position="br" />
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* 内容 */}
|
||||
<Box position="relative" zIndex={1}>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
GlassCard.displayName = 'GlassCard';
|
||||
|
||||
export default memo(GlassCard);
|
||||
export { GLASS_THEME };
|
||||
Reference in New Issue
Block a user