goobs-frontend
Version:
A comprehensive React-based libary for building modern web applications
349 lines (325 loc) • 9.05 kB
text/typescript
/**
* @fileoverview Theme system for Card components
*/
// --------------------------------------------------------------------------
// CARD THEME SYSTEM
// --------------------------------------------------------------------------
import React from 'react'
import { TRANSITIONS, SHADOWS } from './shared'
export interface CardTheme {
container: {
background: string
border: string
borderRadius: string
boxShadow: string
backdropFilter: string
position: React.CSSProperties['position']
overflow: React.CSSProperties['overflow']
transition: string
backgroundImage?: string
color?: string
}
containerHover?: {
transform?: string
boxShadow?: string
borderColor?: string
backgroundColor?: string
}
containerDisabled?: {
opacity: number
backgroundColor: string
color: string
borderColor?: string
cursor: React.CSSProperties['cursor']
}
content: {
padding: string
position?: React.CSSProperties['position']
zIndex?: number
}
actions: {
padding: string
display: React.CSSProperties['display']
alignItems: React.CSSProperties['alignItems']
justifyContent: React.CSSProperties['justifyContent']
gap: string
borderTop: string
position?: React.CSSProperties['position']
zIndex?: number
}
glyph?: {
position: React.CSSProperties['position']
fontSize: string
opacity: number
color: string
transition: string
pointerEvents: React.CSSProperties['pointerEvents']
zIndex: number
}
shimmer?: {
position: React.CSSProperties['position']
top: string
left: string
width: string
height: string
background: string
animation: string
zIndex: number
}
}
export interface CardStyles {
// Theme selection
theme?: 'light' | 'dark' | 'sacred'
// Container styling
backgroundColor?: string
borderColor?: string
borderRadius?: string
borderWidth?: string
boxShadow?: string
backdropFilter?: string
backgroundImage?: string
color?: string
elevation?: number
// Content styling
contentPadding?: string
// Actions styling
actionsPadding?: string
actionsJustify?: string
// Layout and positioning
margin?: string
marginTop?: string
marginBottom?: string
marginLeft?: string
marginRight?: string
width?: string
height?: string
minWidth?: string
minHeight?: string
maxWidth?: string
maxHeight?: string
// Hover states
hoverTransform?: string
hoverBoxShadow?: string
hoverBorderColor?: string
hoverBackgroundColor?: string
// Disabled state
disabled?: boolean
disabledOpacity?: number
disabledBackgroundColor?: string
disabledColor?: string
disabledBorderColor?: string
}
// --------------------------------------------------------------------------
// THEME DEFINITIONS
// --------------------------------------------------------------------------
const lightTheme: CardTheme = {
container: {
background: 'rgba(255, 255, 255, 0.95)',
border: '1px solid rgba(226, 232, 240, 0.6)',
borderRadius: '8px',
boxShadow: SHADOWS.light.small,
backdropFilter: 'blur(8px)',
position: 'relative',
overflow: 'hidden',
transition: TRANSITIONS.medium,
},
containerHover: {
transform: 'translateY(-2px)',
boxShadow: SHADOWS.light.medium,
},
containerDisabled: {
opacity: 0.6,
backgroundColor: 'rgba(248, 250, 252, 0.8)',
color: 'rgba(148, 163, 184, 1)',
cursor: 'not-allowed',
},
content: {
padding: '16px',
},
actions: {
padding: '8px 16px',
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
gap: '8px',
borderTop: '1px solid rgba(226, 232, 240, 0.6)',
},
}
const darkTheme: CardTheme = {
container: {
background: 'rgba(30, 41, 59, 0.95)',
border: '1px solid rgba(71, 85, 105, 0.6)',
borderRadius: '8px',
boxShadow: SHADOWS.dark.small,
backdropFilter: 'blur(12px)',
position: 'relative',
overflow: 'hidden',
transition: TRANSITIONS.medium,
color: 'rgba(248, 250, 252, 1)',
},
containerHover: {
transform: 'translateY(-2px)',
boxShadow: SHADOWS.dark.medium,
},
containerDisabled: {
opacity: 0.6,
backgroundColor: 'rgba(15, 23, 42, 0.8)',
color: 'rgba(100, 116, 139, 1)',
cursor: 'not-allowed',
},
content: {
padding: '16px',
},
actions: {
padding: '8px 16px',
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
gap: '8px',
borderTop: '1px solid rgba(71, 85, 105, 0.6)',
},
}
const sacredTheme: CardTheme = {
container: {
background: `linear-gradient(135deg,
rgba(10, 10, 10, 0.95) 0%,
rgba(26, 26, 26, 0.97) 50%,
rgba(10, 10, 10, 0.95) 100%
)`,
border: '2px solid rgba(255, 215, 0, 0.4)',
borderRadius: '12px',
boxShadow: `${SHADOWS.sacred.small}, 0 8px 32px rgba(0, 0, 0, 0.3)`,
backdropFilter: 'blur(16px)',
position: 'relative',
overflow: 'hidden',
transition: TRANSITIONS.premium,
color: 'rgba(255, 215, 0, 1)',
},
containerHover: {
transform: 'translateY(-4px) scale(1.005)',
boxShadow: `${SHADOWS.sacred.medium}, 0 12px 48px rgba(0, 0, 0, 0.4)`,
borderColor: 'rgba(255, 215, 0, 0.6)',
},
containerDisabled: {
opacity: 0.6,
backgroundColor: 'rgba(0, 0, 0, 0.3)',
color: 'rgba(255, 215, 0, 0.4)',
borderColor: 'rgba(255, 215, 0, 0.2)',
cursor: 'not-allowed',
},
content: {
padding: '20px',
position: 'relative',
zIndex: 2,
},
actions: {
padding: '12px 20px',
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
gap: '12px',
borderTop: '1px solid rgba(255, 215, 0, 0.3)',
position: 'relative',
zIndex: 2,
},
glyph: {
position: 'absolute',
fontSize: '12px',
opacity: 0.05,
color: 'rgba(255, 215, 0, 1)',
transition: TRANSITIONS.medium,
pointerEvents: 'none',
zIndex: 1,
},
shimmer: {
position: 'absolute',
top: '0',
left: '-100%',
width: '100%',
height: '100%',
background:
'linear-gradient(90deg, transparent, rgba(255, 215, 0, 0.1), transparent)',
animation: 'sacredShimmer 2s ease-in-out',
zIndex: 1,
},
}
// --------------------------------------------------------------------------
// THEME MAPPING
// --------------------------------------------------------------------------
export const cardThemes = {
light: lightTheme,
dark: darkTheme,
sacred: sacredTheme,
}
// --------------------------------------------------------------------------
// HELPER FUNCTIONS
// --------------------------------------------------------------------------
export const getCardTheme = (
theme: 'light' | 'dark' | 'sacred' = 'light'
): CardTheme => {
return cardThemes[theme]
}
export const getCardStyles = (
styles?: CardStyles,
isHovered: boolean = false,
isDisabled: boolean = false,
elevation: number = 1
): {
container: React.CSSProperties
content: React.CSSProperties
actions: React.CSSProperties
shimmer: React.CSSProperties
glyph: React.CSSProperties
} => {
const theme = styles?.theme || 'light'
const baseTheme = getCardTheme(theme)
// Apply elevation shadow adjustments
let boxShadow = baseTheme.container.boxShadow
if (elevation > 1) {
const shadowConfig = SHADOWS[theme] || SHADOWS.light
boxShadow =
elevation <= 4
? shadowConfig.small
: elevation <= 8
? shadowConfig.medium
: shadowConfig.large
}
const container: React.CSSProperties = {
...baseTheme.container,
boxShadow,
...(styles?.backgroundColor && { backgroundColor: styles.backgroundColor }),
...(styles?.borderColor && { borderColor: styles.borderColor }),
...(styles?.borderRadius && { borderRadius: styles.borderRadius }),
...(styles?.boxShadow && { boxShadow: styles.boxShadow }),
...(styles?.color && { color: styles.color }),
...(styles?.width && { width: styles.width }),
...(styles?.height && { height: styles.height }),
...(styles?.margin && { margin: styles.margin }),
...(isHovered && !isDisabled && baseTheme.containerHover),
...(isHovered &&
!isDisabled &&
styles?.hoverTransform && { transform: styles.hoverTransform }),
...(isHovered &&
!isDisabled &&
styles?.hoverBoxShadow && { boxShadow: styles.hoverBoxShadow }),
...(isDisabled && baseTheme.containerDisabled),
...(isDisabled &&
styles?.disabledOpacity && { opacity: styles.disabledOpacity }),
}
const content: React.CSSProperties = {
...baseTheme.content,
...(styles?.contentPadding && { padding: styles.contentPadding }),
}
const actions: React.CSSProperties = {
...baseTheme.actions,
...(styles?.actionsPadding && { padding: styles.actionsPadding }),
...(styles?.actionsJustify && { justifyContent: styles.actionsJustify }),
}
return {
container,
content,
actions,
shimmer: baseTheme.shimmer || {},
glyph: baseTheme.glyph || {},
}
}