goobs-frontend
Version:
A comprehensive React-based libary for building modern web applications
239 lines (217 loc) • 6.43 kB
text/typescript
// --------------------------------------------------------------------------
// TOOLBAR THEME SYSTEM
// --------------------------------------------------------------------------
import React from 'react'
import { TRANSITIONS } from './shared'
export interface ToolbarTheme {
container: {
background: string
border: string
borderRadius: string
boxShadow: string
backdropFilter: string
padding: string
backgroundImage?: string
animation?: string
}
glyph: {
color: string
fontSize: string
animation?: string
}
transition: string
}
export interface ToolbarStyles {
// Theme selection
theme?: 'light' | 'dark' | 'sacred'
// Container styling
backgroundColor?: string
borderColor?: string
borderRadius?: string
borderWidth?: string
boxShadow?: string
backdropFilter?: string
backgroundImage?: string
padding?: string
containerAnimation?: string
// Glyph styling
glyphColor?: string
glyphFontSize?: string
glyphAnimation?: string
// Layout and spacing
gap?: string
margin?: string
marginTop?: string
marginBottom?: string
marginLeft?: string
marginRight?: string
// Transitions
transitionDuration?: string
transitionEasing?: string
// States
disabled?: boolean
outline?: boolean
// Dimensions
width?: string
maxWidth?: string
minWidth?: string
height?: string
maxHeight?: string
minHeight?: string
}
export const toolbarThemes: Record<'light' | 'dark' | 'sacred', ToolbarTheme> =
{
light: {
container: {
background: 'transparent',
border: 'none',
borderRadius: '0',
boxShadow: 'none',
backdropFilter: 'none',
padding: '1rem',
},
glyph: {
color: 'rgba(107, 114, 128, 0.3)',
fontSize: '0.875rem',
},
transition: TRANSITIONS.medium,
},
dark: {
container: {
background: 'transparent',
border: 'none',
borderRadius: '0',
boxShadow: 'none',
backdropFilter: 'none',
padding: '1rem',
},
glyph: {
color: 'rgba(156, 163, 175, 0.3)',
fontSize: '0.875rem',
},
transition: TRANSITIONS.medium,
},
sacred: {
container: {
background: 'transparent',
border: 'none',
borderRadius: '0',
boxShadow: 'none',
backdropFilter: 'none',
padding: '1rem',
backgroundImage: `
radial-gradient(circle at top right, rgba(255, 215, 0, 0.03) 0%, transparent 50%),
radial-gradient(circle at bottom left, rgba(255, 215, 0, 0.02) 0%, transparent 50%)
`,
},
glyph: {
color: 'rgba(255, 215, 0, 0.2)',
fontSize: '0.875rem',
animation: 'glyphRotate 10s linear infinite',
},
transition: TRANSITIONS.slow,
},
}
// Helper function to get computed theme with custom style overrides
export const getToolbarTheme = (styles?: ToolbarStyles): ToolbarTheme => {
const theme = styles?.theme || 'light'
const baseTheme = toolbarThemes[theme]
if (!styles) {
return baseTheme
}
return {
container: {
background: styles.backgroundColor || baseTheme.container.background,
border: styles.borderColor
? `${styles.borderWidth || '1px'} solid ${styles.borderColor}`
: baseTheme.container.border,
borderRadius: styles.borderRadius || baseTheme.container.borderRadius,
boxShadow: styles.boxShadow || baseTheme.container.boxShadow,
backdropFilter:
styles.backdropFilter || baseTheme.container.backdropFilter,
padding: styles.padding || baseTheme.container.padding,
backgroundImage:
styles.backgroundImage || baseTheme.container.backgroundImage,
animation: styles.containerAnimation || baseTheme.container.animation,
},
glyph: {
color: styles.glyphColor || baseTheme.glyph.color,
fontSize: styles.glyphFontSize || baseTheme.glyph.fontSize,
animation: styles.glyphAnimation || baseTheme.glyph.animation,
},
transition: styles.transitionDuration
? `all ${styles.transitionDuration} ${styles.transitionEasing || 'cubic-bezier(0.4, 0, 0.2, 1)'}`
: baseTheme.transition,
}
}
// Main style generator function
export const getToolbarStyles = (
styles?: ToolbarStyles,
isDisabled?: boolean
) => {
const themeConfig = getToolbarTheme(styles)
const containerStyle: React.CSSProperties = {
display: 'flex',
flexDirection: 'column',
width: styles?.width || '100%',
gap: styles?.gap || '1rem',
maxWidth: styles?.maxWidth,
minWidth: styles?.minWidth,
maxHeight: styles?.maxHeight,
minHeight: styles?.minHeight,
margin: styles?.margin,
marginTop: styles?.marginTop,
marginBottom: styles?.marginBottom,
marginLeft: styles?.marginLeft,
marginRight: styles?.marginRight,
background: themeConfig.container.background,
border: themeConfig.container.border,
borderRadius: themeConfig.container.borderRadius,
boxShadow: themeConfig.container.boxShadow,
backdropFilter: themeConfig.container.backdropFilter,
padding: themeConfig.container.padding,
backgroundImage: themeConfig.container.backgroundImage,
animation: themeConfig.container.animation,
position: 'relative',
transition: themeConfig.transition,
opacity: isDisabled ? 0.5 : 1,
pointerEvents: isDisabled ? 'none' : 'auto',
}
const glyphStyle: React.CSSProperties = {
position: 'absolute',
top: '0.25rem',
right: '0.5rem',
color: themeConfig.glyph.color,
fontSize: themeConfig.glyph.fontSize,
animation: themeConfig.glyph.animation,
}
const desktopLeftStyle: React.CSSProperties = {
display: 'none',
}
const desktopRightStyle: React.CSSProperties = {
display: 'none',
}
const tabletContainerStyle: React.CSSProperties = {
display: 'none',
}
const mobileContainerStyle: React.CSSProperties = {
display: 'flex',
flexDirection: 'column',
gap: '1rem',
width: '100%',
}
const mobileRowStyle: React.CSSProperties = {
display: 'flex',
alignItems: 'center',
gap: '1rem',
}
return {
container: containerStyle,
glyph: glyphStyle,
desktopLeft: desktopLeftStyle,
desktopRight: desktopRightStyle,
tabletContainer: tabletContainerStyle,
mobileContainer: mobileContainerStyle,
mobileRow: mobileRowStyle,
}
}