feat (v1.0.0): initial refactor and redesign

This commit is contained in:
Aidan 2025-10-09 04:12:05 -04:00
parent 3058aa1ab4
commit fe9b50b30e
134 changed files with 17792 additions and 3670 deletions

306
lib/theme/colors.ts Normal file
View file

@ -0,0 +1,306 @@
/**
* Grayscale color palette used throughout the application.
*
* @remarks
* Provides a complete grayscale from near-white (50) to near-black (950).
* Each shade has a specific semantic purpose in the dark-themed UI.
*
* Common usage:
* - 50-400: Text colors (lighter is more prominent)
* - 500-600: Interactive states and borders
* - 700-950: Backgrounds and surfaces
*
* @example
* ```ts
* import { gray } from '@/lib/theme/colors'
*
* const textColor = gray[100] // Primary text
* const cardBg = gray[800] // Card background
* ```
*
* @category Theme
* @public
*/
export const gray = {
/** Near-white, lightest shade - #f9fafb */
50: '#f9fafb',
/** Very light gray - Primary text on dark backgrounds - #f3f4f6 */
100: '#f3f4f6',
/** Light gray - Secondary headings - #e5e7eb */
200: '#e5e7eb',
/** Medium-light gray - Body text - #d1d5db */
300: '#d1d5db',
/** Medium gray - Muted text and descriptions - #9ca3af */
400: '#9ca3af',
/** Medium-dark gray - Disabled states - #6b7280 */
500: '#6b7280',
/** Dark gray - Hover states for borders - #4b5563 */
600: '#4b5563',
/** Darker gray - Default borders and cards - #374151 */
700: '#374151',
/** Very dark gray - Background gradient start - #1f2937 */
800: '#1f2937',
/** Near-black - Background gradient end - #111827 */
900: '#111827',
/** Deepest black - #030712 */
950: '#030712',
} as const
/**
* Background color tokens for page and surface backgrounds.
*
* @remarks
* Provides consistent background colors with semantic naming:
* - Page gradients for main background
* - Surface colors for cards and interactive elements
* - Hover states for transitions
*
* @example
* ```tsx
* import { backgrounds } from '@/lib/theme/colors'
*
* <div style={{ background: `linear-gradient(${backgrounds.pageGradientStart}, ${backgrounds.pageGradientEnd})` }}>
* <div style={{ backgroundColor: backgrounds.card }}>
* Card content
* </div>
* </div>
* ```
*
* @category Theme
* @public
*/
export const backgrounds = {
/** Page background gradient start color (gray-800) - rgb(31, 41, 55) */
pageGradientStart: 'rgb(31, 41, 55)',
/** Page background gradient end color (gray-900) - rgb(17, 24, 39) */
pageGradientEnd: 'rgb(17, 24, 39)',
/** Semi-transparent card background (gray-900/50) - rgba(31, 41, 55, 0.5) */
card: 'rgba(31, 41, 55, 0.5)',
/** Solid card background (gray-800) - #1f2937 */
cardSolid: '#1f2937',
/** Hover state background (gray-700 with opacity) - rgba(55, 65, 81, 0.6) */
hover: 'rgba(55, 65, 81, 0.6)',
} as const
/**
* Border color tokens for consistent border styling.
*
* @remarks
* Provides border colors with varying opacity levels:
* - Default: Standard border for cards and sections
* - Hover: Highlighted border on interactive elements
* - Subtle/Muted: Lower-contrast borders for nested elements
*
* @example
* ```tsx
* import { borders } from '@/lib/theme/colors'
*
* <div style={{ borderColor: borders.default }}>
* // On hover
* <div style={{ borderColor: borders.hover }}>
* Interactive element
* </div>
* </div>
* ```
*
* @category Theme
* @public
*/
export const borders = {
/** Default border color (gray-700) - #374151 */
default: '#374151',
/** Hover border color (gray-600) - #4b5563 */
hover: '#4b5563',
/** Subtle border with low opacity - rgba(75, 85, 99, 0.3) */
subtle: 'rgba(75, 85, 99, 0.3)',
/** Muted border with medium opacity - rgba(75, 85, 99, 0.5) */
muted: 'rgba(75, 85, 99, 0.5)',
} as const
/**
* Text color tokens organized by semantic meaning and visual hierarchy.
*
* @remarks
* Provides a consistent text color scale from most to least prominent:
* - Primary: Most important text (headings, key info)
* - Secondary: Subheadings and emphasized text
* - Body: Standard paragraph text
* - Muted: Less important text (descriptions, captions)
* - Disabled: Inactive or unavailable text
* - Inverse: Text on light backgrounds (opposite of normal)
*
* @example
* ```tsx
* import { text } from '@/lib/theme/colors'
*
* <h1 style={{ color: text.primary }}>Main Title</h1>
* <h2 style={{ color: text.secondary }}>Subtitle</h2>
* <p style={{ color: text.body }}>Paragraph text</p>
* <small style={{ color: text.muted }}>Caption</small>
* ```
*
* @category Theme
* @public
*/
export const text = {
/** Primary text color - Highest contrast (gray-100) - #f3f4f6 */
primary: '#f3f4f6',
/** Secondary text color - Headings and emphasis (gray-200) - #e5e7eb */
secondary: '#e5e7eb',
/** Body text color - Standard paragraphs (gray-300) - #d1d5db */
body: '#d1d5db',
/** Muted text color - Descriptions and captions (gray-400) - #9ca3af */
muted: '#9ca3af',
/** Disabled text color - Inactive elements (gray-500) - #6b7280 */
disabled: '#6b7280',
/** Inverse text color - For light backgrounds (gray-900) - #111827 */
inverse: '#111827',
} as const
/**
* Accent color tokens for links, branding, and semantic states.
*
* @remarks
* Organized into semantic categories:
* - Link colors: Blue tones for hyperlinks
* - AI theme: Orange/rust colors for Claude AI branding
* - Type colors: Purple for documentation type references
* - Semantic colors: Success, warning, error, info states
*
* Each accent color includes hover and background variants where applicable.
*
* @example
* ```tsx
* import { accents } from '@/lib/theme/colors'
*
* <a style={{ color: accents.link }}>Link</a>
* <div style={{ backgroundColor: accents.linkBg }}>Badge</div>
* <span style={{ color: accents.success }}>Success!</span>
* ```
*
* @category Theme
* @public
*/
export const accents = {
/** Link text color (blue-400) - #60a5fa */
link: '#60a5fa',
/** Link hover color (blue-500) - #3b82f6 */
linkHover: '#3b82f6',
/** Link badge background (blue-400/10) - rgba(96, 165, 250, 0.1) */
linkBg: 'rgba(96, 165, 250, 0.1)',
/** AI/Claude primary brand color - #c15f3c */
ai: '#c15f3c',
/** AI/Claude muted variant - #d68b6b */
aiMuted: '#d68b6b',
/** AI/Claude high contrast background - #1a100d */
aiContrast: '#1a100d',
/** Type/interface color for docs (purple-500) - #a855f7 */
type: '#a855f7',
/** Type badge background (purple-500/10) - rgba(168, 85, 247, 0.1) */
typeBg: 'rgba(168, 85, 247, 0.1)',
/** Documentation primary accent (blue-400) - #60a5fa */
docs: '#60a5fa',
/** Documentation card background (blue-500/8) - rgba(59, 130, 246, 0.08) */
docsBg: 'rgba(59, 130, 246, 0.08)',
/** Documentation border (blue-500/25) - rgba(59, 130, 246, 0.25) */
docsBorder: 'rgba(59, 130, 246, 0.25)',
/** Documentation glow/shadow (blue-500/12) - rgba(59, 130, 246, 0.12) */
docsGlow: 'rgba(59, 130, 246, 0.12)',
/** Documentation icon background (blue-500/20) - rgba(59, 130, 246, 0.2) */
docsIconBg: 'rgba(59, 130, 246, 0.2)',
/** Documentation blur effect (blue-500 solid) - #3b82f6 */
docsBlur: '#3b82f6',
/** Success state color (green) - #10b981 */
success: '#10b981',
/** Warning state color (amber) - #f59e0b */
warning: '#f59e0b',
/** Warning badge background (warning/10) - rgba(245, 158, 11, 0.1) */
warningBg: 'rgba(245, 158, 11, 0.1)',
/** Error state color (red) - #ef4444 */
error: '#ef4444',
/** Info state color (blue) - #3b82f6 */
info: '#3b82f6',
} as const
/**
* Effect color tokens for glows, shadows, and other visual effects.
*
* @remarks
* Provides colors specifically for CSS effects like text-shadow and box-shadow.
* Used to create depth and emphasis in the UI.
*
* @example
* ```tsx
* import { effectColors } from '@/lib/theme/colors'
*
* <h1 style={{ textShadow: `0 0 10px ${effectColors.textGlow}` }}>
* Glowing Text
* </h1>
* <div style={{ boxShadow: `0 4px 6px ${effectColors.shadowCard}` }}>
* Card with shadow
* </div>
* ```
*
* @category Theme
* @public
*/
export const effectColors = {
/** Standard text glow (80% opacity) - rgba(255, 255, 255, 0.8) */
textGlow: 'rgba(255, 255, 255, 0.8)',
/** Hover text glow (90% opacity) - rgba(255, 255, 255, 0.9) */
textGlowHover: 'rgba(255, 255, 255, 0.9)',
/** Intense text glow (100% opacity) - rgba(255, 255, 255, 1) */
textGlowIntense: 'rgba(255, 255, 255, 1)',
/** Card box shadow color - rgba(0, 0, 0, 0.2) */
shadowCard: 'rgba(0, 0, 0, 0.2)',
} as const
/**
* Complete color system combining all color token categories.
*
* @remarks
* Central export containing all color tokens organized by purpose:
* - {@link gray}: Grayscale palette
* - {@link backgrounds}: Background colors
* - {@link borders}: Border colors
* - {@link text}: Text colors
* - {@link accents}: Accent and semantic colors
* - {@link effectColors}: Shadow and glow colors
*
* @example
* ```ts
* import { colors } from '@/lib/theme/colors'
*
* // Access any color token
* const primaryText = colors.text.primary
* const cardBg = colors.backgrounds.card
* const linkColor = colors.accents.link
* ```
*
* @category Theme
* @public
*/
export const colors = {
gray,
backgrounds,
borders,
text,
accents,
effectColors,
} as const
/**
* TypeScript type representing all available color tokens.
*
* @remarks
* Use this type for type-safe color access in components and utilities.
*
* @category Theme
* @public
*/
export type ColorTokens = typeof colors

310
lib/theme/effects.ts Normal file
View file

@ -0,0 +1,310 @@
/**
* Text shadow effect tokens for glowing and emphasis effects.
*
* Provides white glow effects at varying intensities for creating visual hierarchy
* and emphasis on text elements in the dark theme.
*
* @example
* ```tsx
* import { textShadows } from '@/lib/theme/effects'
*
* // Standard glow effect
* <h1 style={{ textShadow: textShadows.glow }}>
* Glowing Title
* </h1>
*
* // Hover state with increased glow
* <button
* style={{ textShadow: textShadows.glow }}
* onMouseEnter={(e) => e.currentTarget.style.textShadow = textShadows.glowHover}
* >
* Hover Me
* </button>
*
* // Intense glow for hero text
* <h1 style={{ textShadow: textShadows.glowIntense }}>
* Hero Title
* </h1>
* ```
*
* @category Theme
* @public
*/
export const textShadows = {
/** Standard glow effect (80% opacity) - use for headings and emphasized text */
glow: '0 0 10px rgba(255, 255, 255, 0.8)',
/** Enhanced glow for hover states (90% opacity) - use with interactive text elements */
glowHover: '0 0 15px rgba(255, 255, 255, 0.9)',
/** Intense glow effect (100% opacity) - use sparingly for hero sections and primary headings */
glowIntense: '0 0 20px rgba(255, 255, 255, 1)',
/** Subtle glow (50% opacity) - use for secondary text that needs slight emphasis */
subtle: '0 0 10px rgba(255, 255, 255, 0.5)',
} as const
/**
* Box shadow effect tokens for depth and elevation.
*
* Provides subtle elevation effects for cards, panels, and buttons. All shadows
* use dark colors appropriate for the dark theme interface.
*
* @example
* ```tsx
* import { boxShadows } from '@/lib/theme/effects'
*
* // Card with elevation shadow
* <div style={{ boxShadow: boxShadows.card }}>
* <h3>Card Content</h3>
* </div>
*
* // Button with hover elevation
* <button
* style={{ boxShadow: boxShadows.button }}
* className="hover:shadow-[var(--shadow-button-hover)]"
* >
* Click Me
* </button>
*
* // Panel overlay with shadow
* <div style={{ boxShadow: boxShadows.panel }}>
* <nav>Navigation</nav>
* </div>
* ```
*
* @category Theme
* @public
*/
export const boxShadows = {
/** Card shadow for standard elevation - use on card containers */
card: '0 10px 15px -3px rgba(0, 0, 0, 0.1)',
/** Enhanced card shadow for hover states - creates lifted appearance */
cardHover: '0 20px 25px -5px rgba(0, 0, 0, 0.2)',
/** Panel shadow for floating UI elements - use on dropdowns, modals, and sidebars */
panel: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
/** Button shadow for default state - subtle depth for clickable elements */
button: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
/** Button shadow for hover state - increased shadow for interactivity feedback */
buttonHover: '0 6px 8px -1px rgba(0, 0, 0, 0.15)',
} as const
/**
* Gradient effect tokens for backgrounds and visual interest.
*
* Provides pre-configured gradient styles for page backgrounds, widgets, and special
* UI elements. All gradients follow the dark theme color palette.
*
* @example
* ```tsx
* import { gradients } from '@/lib/theme/effects'
*
* // Page background gradient
* <div style={{ background: gradients.pageBackground }}>
* <main>Page content</main>
* </div>
*
* // Music player widget gradient
* <div style={{ background: gradients.musicPlayer }}>
* <div>Now Playing...</div>
* </div>
*
* // Player button gradient (light variant)
* <button style={{ background: gradients.playerButton.light }}>
* Play
* </button>
* ```
*
* @category Theme
* @public
*/
export const gradients = {
/** Page background gradient from gray-800 to gray-900 - use for main page containers */
pageBackground: 'linear-gradient(180deg, rgb(31, 41, 55) 0%, rgb(17, 24, 39) 100%)',
/** Music player widget gradient with 4-stop gradient - use for music player components */
musicPlayer: 'linear-gradient(to bottom, #4b5563 0%, #374151 30%, #1f2937 70%, #111827 100%)',
/** Player button gradients - use for music control buttons */
playerButton: {
/** Light button gradient with subtle 3D effect - use for play/pause buttons */
light: 'linear-gradient(180deg, #f9fafb 0%, #e5e7eb 49%, #6b7280 51%, #d1d5db 100%)',
},
} as const
/**
* Transition effect tokens for smooth animations and state changes.
*
* Provides Tailwind CSS transition utilities with consistent timing and easing.
* Combine property transitions with duration and easing tokens for complete control.
*
* @example
* ```tsx
* import { transitions } from '@/lib/theme/effects'
*
* // Color transition on hover
* <button className={transitions.colors}>
* Hover Me
* </button>
*
* // All properties transition with custom duration
* <div className={cn(transitions.all, transitions.slow)}>
* Animates all properties slowly
* </div>
*
* // Shadow transition with easing
* <div className={cn(transitions.shadow, transitions.easeInOut)}>
* Shadow changes smoothly
* </div>
*
* // Fast transition for snappy interactions
* <button className={cn('bg-gray-800', transitions.fast)}>
* Quick feedback
* </button>
* ```
*
* @remarks
* Transition tokens are designed to be composable. Combine property transitions
* (colors, all, shadow) with duration modifiers (fast, normal, slow) and easing
* functions (easeInOut, ease) to create custom animation behaviors.
*
* @category Theme
* @public
*/
export const transitions = {
/** Color property transitions with 300ms duration - use for text/background color changes */
colors: 'transition-colors duration-300',
/** All property transitions with 300ms duration - use when multiple properties animate */
all: 'transition-all duration-300',
/** Shadow property transitions with 300ms duration - use for elevation changes */
shadow: 'transition-shadow duration-300',
/** Fast duration (200ms) - use for snappy, responsive interactions */
fast: 'duration-200',
/** Normal duration (300ms) - default timing for most animations */
normal: 'duration-300',
/** Slow duration (500ms) - use for deliberate, emphasis animations */
slow: 'duration-500',
/** Ease-in-out timing function - smooth start and end for polished feel */
easeInOut: 'ease-in-out',
/** Standard ease timing function - slight acceleration for natural motion */
ease: 'ease',
} as const
/**
* Backdrop blur effect tokens for glassmorphism and depth.
*
* Provides backdrop-filter blur utilities for creating frosted glass effects
* on overlays, modals, and panels. Commonly used with semi-transparent backgrounds.
*
* @example
* ```tsx
* import { backdrops } from '@/lib/theme/effects'
*
* // Subtle blur for card overlays
* <div className={cn('bg-gray-900/50', backdrops.blur)}>
* <h3>Content with backdrop blur</h3>
* </div>
*
* // Medium blur for modals
* <div className={cn('bg-gray-800/80', backdrops.blurMedium)}>
* <dialog>Modal Content</dialog>
* </div>
*
* // Strong blur for emphasized overlays
* <div className={cn('bg-gray-900/90', backdrops.blurLarge)}>
* <div>Strongly blurred background</div>
* </div>
* ```
*
* @remarks
* Backdrop blur effects work best when combined with semi-transparent backgrounds
* (e.g., `bg-gray-900/50`). The blur creates a frosted glass effect by blurring
* content behind the element.
*
* @category Theme
* @public
*/
export const backdrops = {
/** Small blur (4px) - use for subtle glassmorphism on cards and overlays */
blur: 'backdrop-blur-sm',
/** Medium blur (12px) - use for modals and prominent panels */
blurMedium: 'backdrop-blur-md',
/** Large blur (24px) - use for strong separation and emphasis */
blurLarge: 'backdrop-blur-lg',
} as const
/**
* Visual effect design tokens for the application theme.
*
* Provides a comprehensive set of visual effects including shadows, gradients,
* transitions, and backdrop filters. All effects are optimized for the dark theme
* and support smooth animations.
*
* @remarks
* This is the main effects export. Import individual categories or the full effects
* object depending on your needs. Effects can be combined with surface styles from
* `lib/theme/surfaces` for complete component styling.
*
* @example
* ```tsx
* import { effects } from '@/lib/theme/effects'
* // or
* import { textShadows, transitions, backdrops } from '@/lib/theme/effects'
*
* // Using the full effects object
* <h1 style={{ textShadow: effects.textShadows.glow }}>
* Glowing Title
* </h1>
*
* // Using individual imports
* <div className={cn(backdrops.blur, transitions.all)}>
* <p>Blurred and animated</p>
* </div>
* ```
*
* @category Theme
* @public
*/
export const effects = {
textShadows,
boxShadows,
gradients,
transitions,
backdrops,
} as const
/**
* TypeScript type representing all available effect tokens.
*
* Use this type for type-safe access to effect styles in components.
*
* @example
* ```tsx
* import type { EffectTokens } from '@/lib/theme/effects'
*
* function EffectWrapper(props: { effects: EffectTokens }) {
* return (
* <div style={{ textShadow: props.effects.textShadows.glow }}>
* Content
* </div>
* )
* }
* ```
*
* @category Theme
* @public
*/
export type EffectTokens = typeof effects

253
lib/theme/index.ts Normal file
View file

@ -0,0 +1,253 @@
/**
* Theme system entry point providing centralized access to design tokens.
*
* @remarks
* This module serves as the main entry point for the aidxnCC theme system,
* providing a unified interface for colors, visual effects, and surface styling.
* All theme tokens are designed to work seamlessly with Tailwind CSS v4.
*
* **Available theme categories:**
* - **colors**: Semantic color tokens (text, backgrounds, borders, accents)
* - **effects**: Visual effects (shadows, gradients, transitions, backdrops)
* - **surfaces**: Pre-composed UI element styles (cards, buttons, badges, sections)
*
* **Usage patterns:**
* - Import individual categories for specific needs
* - Use helper functions for dynamic variant selection
* - Combine with cn() utility for class composition
*
* @example
* ```tsx
* // Import entire theme
* import { theme } from '@/lib/theme'
* const textColor = theme.colors.text.primary
*
* // Import specific categories
* import { colors, surfaces } from '@/lib/theme'
* const cardStyle = surfaces.card.default
*
* // Use helper functions for dynamic variants
* import { getCardStyle, cn } from '@/lib/theme'
* const Card = ({ variant = 'default', className }) => (
* <div className={cn(getCardStyle(variant), className)}>
* Content
* </div>
* )
* ```
*
* @module lib/theme
* @category Theme
* @public
*/
export * from './colors'
export * from './effects'
export * from './surfaces'
import { colors } from './colors'
import { effects } from './effects'
import { surfaces } from './surfaces'
/**
* Unified theme object containing all design tokens.
*
* @remarks
* This object provides centralized access to all theme categories.
* The `as const` assertion ensures type safety and enables TypeScript
* to infer exact string literals for all token values.
*
* @example
* ```tsx
* import { theme } from '@/lib/theme'
*
* // Access colors
* const primaryText = theme.colors.text.primary
*
* // Access effects
* const cardShadow = theme.effects.boxShadows.card
*
* // Access surfaces
* const buttonStyle = theme.surfaces.button.primary
* ```
*
* @category Theme
* @public
*/
export const theme = {
colors,
effects,
surfaces,
} as const
/**
* Type representing the whole theme structure.
*
* @remarks
* This type enables autocomplete and type checking when working with
* theme tokens. It's automatically inferred from the theme object.
*
* @category Theme
* @public
*/
export type Theme = typeof theme
/**
* Utility function for conditionally combining CSS class names.
*
* @param classes - Array of class names (can include undefined, null, or false values)
* @returns Combined class string with falsy values filtered out
*
* @remarks
* This is a lightweight alternative to libraries like `clsx` or `classnames`.
* It filters out falsy values (undefined, null, false) and joins remaining
* strings with spaces. Perfect for conditional class application in React.
*
* **Compared to alternatives:**
* - Simpler than the `cn()` utility in lib/utils.ts (which uses tailwind-merge)
* - Use this for basic class combining without merge logic
* - Use lib/utils.ts cn() when you need Tailwind conflict resolution
*
* @example
* ```tsx
* import { cn } from '@/lib/theme'
*
* // Basic usage
* const classes = cn('text-gray-100', 'bg-gray-800')
* // Result: 'text-gray-100 bg-gray-800'
*
* // With conditional classes
* const isActive = true
* const classes = cn(
* 'base-class',
* isActive && 'active-class',
* undefined,
* null
* )
* // Result: 'base-class active-class'
* ```
*
* @category Theme
* @public
*/
export function cn(...classes: (string | undefined | null | false)[]): string {
return classes.filter(Boolean).join(' ')
}
/**
* Get card surface styles by variant name.
*
* @param variant - Card variant name (default, domain, ai, featured, simple)
* @returns Tailwind CSS class string for the specified card variant
*
* @remarks
* This helper function provides runtime variant selection for card components.
* Use this when card variant is determined dynamically (e.g., from props or state).
*
* **Available variants:**
* - `default`: Standard card styling
* - `domain`: Domain-specific card styling
* - `ai`: AI-themed card styling
* - `featured`: Featured/highlighted card
* - `simple`: Minimal card styling
*
* @example
* ```tsx
* import { getCardStyle } from '@/lib/theme'
*
* // Basic usage
* const Card = ({ variant = 'default', children }) => (
* <div className={getCardStyle(variant)}>
* {children}
* </div>
* )
*
* // Dynamic variant selection
* const DomainCard = ({ domain }) => {
* const variant = domain.featured ? 'featured' : 'domain'
* return <div className={getCardStyle(variant)}>...</div>
* }
* ```
*
* @see {@link surfaces} For all available surface styles
* @category Theme
* @public
*/
export function getCardStyle(variant: keyof typeof surfaces.card = 'default'): string {
return surfaces.card[variant]
}
/**
* Get section surface styles by variant name.
*
* @param variant - Section variant name (default, compact, plain)
* @returns Tailwind CSS class string for the specified section variant
*
* @remarks
* This helper function provides runtime variant selection for section containers.
* Use this when section variant is determined dynamically.
*
* **Available variants:**
* - `default`: Standard section with full spacing
* - `compact`: Reduced spacing for denser layouts
* - `plain`: Minimal styling without background
*
* @example
* ```tsx
* import { getSectionStyle } from '@/lib/theme'
*
* const Section = ({ compact = false, children }) => {
* const variant = compact ? 'compact' : 'default'
* return (
* <section className={getSectionStyle(variant)}>
* {children}
* </section>
* )
* }
* ```
*
* @see {@link surfaces} For all available surface styles
* @category Theme
* @public
*/
export function getSectionStyle(variant: keyof typeof surfaces.section = 'default'): string {
return surfaces.section[variant]
}
/**
* Get button surface styles by variant name.
*
* @param variant - Button variant name (nav, dropdownItem, active, icon, primary)
* @returns Tailwind CSS class string for the specified button variant
*
* @remarks
* This helper function provides runtime variant selection for button components.
* Use this when button variant is determined dynamically.
*
* **Available variants:**
* - `nav`: Navigation button styling
* - `dropdownItem`: Dropdown menu item button
* - `active`: Active/selected state button
* - `icon`: Icon-only button (e.g., close buttons)
* - `primary`: Primary call-to-action button
*
* @example
* ```tsx
* import { getButtonStyle } from '@/lib/theme'
*
* const Button = ({ variant = 'nav', active = false, children }) => {
* const style = active ? 'active' : variant
* return (
* <button className={getButtonStyle(style)}>
* {children}
* </button>
* )
* }
* ```
*
* @see {@link surfaces} For all available surface styles
* @category Theme
* @public
*/
export function getButtonStyle(variant: keyof typeof surfaces.button = 'nav'): string {
return surfaces.button[variant]
}

382
lib/theme/surfaces.ts Normal file
View file

@ -0,0 +1,382 @@
/**
* Card surface styling variants for content containers.
*
* Provides consistent styling patterns for card components with various visual treatments.
* All variants include responsive hover states and smooth transitions.
*
* @example
* ```tsx
* import { card } from '@/lib/theme/surfaces'
*
* // Standard card
* <div className={card.default}>
* <h3>Content</h3>
* </div>
*
* // Domain portfolio card with backdrop blur
* <div className={card.domain}>
* <span>example.com</span>
* </div>
*
* // Featured content with accent border
* <div className={card.featured}>
* <h2>Top Pick</h2>
* </div>
* ```
*
* @category Theme
* @public
*/
export const card = {
/** Standard card with bold border and hover effect - use for general content containers */
default: 'border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300',
/** Domain-specific card with glassmorphism effect - used in domain portfolio grid */
domain: 'bg-gray-900/50 backdrop-blur-sm border border-gray-800 rounded-xl hover:border-gray-700 transition-all hover:shadow-xl hover:shadow-black/20',
/** AI analytics card with padding and hover states - used for usage statistics */
ai: 'p-6 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300',
/** Featured/highlighted card with orange accent border and tinted background - used for TopPick component */
featured: 'p-6 sm:p-8 border-2 border-[#c15f3c] rounded-lg bg-orange-500/5',
/** Minimal card with thin border only - use for nested or subtle containers */
simple: 'border border-gray-700 rounded-lg',
} as const
/**
* Section surface styling variants for page layout containers.
*
* Sections are larger content areas that organize page content into logical blocks.
* Use these for page-level organization and content grouping.
*
* @example
* ```tsx
* import { section } from '@/lib/theme/surfaces'
*
* // Standard section with responsive padding
* <section className={section.default}>
* <h2>Section Title</h2>
* <p>Content...</p>
* </section>
*
* // Compact section for tighter layouts
* <section className={section.compact}>
* <div>Dense content</div>
* </section>
*
* // Plain section for nested content (no border)
* <div className={section.plain}>
* <div>Nested content without visual container</div>
* </div>
* ```
*
* @category Theme
* @public
*/
export const section = {
/** Standard section with responsive padding, border, and hover effect - use for main content areas */
default: 'p-4 sm:p-8 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300',
/** Compact section with reduced padding - use for sidebar or constrained layouts */
compact: 'p-4 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300',
/** Plain section with padding only (no border) - use for nested content areas */
plain: 'p-4 sm:p-8',
} as const
/**
* Panel surface styling variants for overlays and UI elements.
*
* Panels are floating or fixed UI elements like dropdowns, modals, and sidebars.
* These styles provide consistent backdrop effects and layering.
*
* @example
* ```tsx
* import { panel } from '@/lib/theme/surfaces'
*
* // Dropdown menu
* <div className={panel.dropdown}>
* <button>Menu Item 1</button>
* <button>Menu Item 2</button>
* </div>
*
* // Modal overlay
* <div className={panel.overlay}>
* <h3>Modal Content</h3>
* </div>
*
* // Sidebar navigation
* <aside className={panel.sidebar}>
* <nav>Links...</nav>
* </aside>
* ```
*
* @category Theme
* @public
*/
export const panel = {
/** Dropdown panel with solid background and shadow - use for menus and popovers */
dropdown: 'bg-gray-800 rounded-lg shadow-xl border border-gray-700',
/** Overlay panel with translucent backdrop blur - use for modals and dialogs */
overlay: 'bg-gray-800/95 backdrop-blur-sm border border-gray-700/50',
/** Sidebar panel with right border - use for navigation sidebars */
sidebar: 'bg-gray-900/50 backdrop-blur-sm border-r border-gray-800',
} as const
/**
* Button surface styling variants for interactive elements.
*
* Button styles provide consistent interaction patterns across navigation,
* CTAs, and other clickable elements.
*
* @example
* ```tsx
* import { button } from '@/lib/theme/surfaces'
*
* // Navigation button
* <button className={button.nav}>
* Home
* </button>
*
* // Primary CTA button
* <button className={button.primary}>
* Get Started
* </button>
*
* // Active state (combine with nav)
* <button className={cn(button.nav, button.active)}>
* Current Page
* </button>
*
* // Icon button
* <button className={button.icon}>
* <IconComponent />
* </button>
* ```
*
* @category Theme
* @public
*/
export const button = {
/** Navigation button with subtle hover - use for header/sidebar navigation links */
nav: 'text-gray-300 hover:text-white hover:bg-gray-700 rounded-md px-3 py-2 transition-all duration-300',
/** Dropdown menu item with translucent hover - use for menu items in dropdowns */
dropdownItem: 'text-gray-300 hover:text-white hover:bg-gray-700/30 rounded-md transition-all duration-300',
/** Active state styling - combine with nav for current page indication */
active: 'text-white bg-gray-700/50',
/** Icon-only button with fixed size - use for toolbar icons and action buttons */
icon: 'inline-flex h-9 w-9 items-center justify-center rounded-xl bg-gray-800 text-gray-300',
/** Primary CTA button with shadow and lift effect - use for main call-to-action elements */
primary: 'bg-gray-800 text-white font-bold py-2 px-4 rounded-sm shadow-md transition-all duration-300 ease-in-out hover:bg-gray-700 hover:shadow-lg hover:-translate-y-0.5',
} as const
/**
* Badge surface styling variants for labels and status indicators.
*
* Badges are small inline labels used for categories, tags, and status indicators.
* All variants use consistent sizing with semantic color coding.
*
* @example
* ```tsx
* import { badge } from '@/lib/theme/surfaces'
*
* // Default badge
* <span className={badge.default}>Tag</span>
*
* // Muted/subtle badge
* <span className={badge.muted}>Draft</span>
*
* // Status badges with semantic colors
* <span className={badge.success}>Active</span>
* <span className={badge.warning}>Pending</span>
* <span className={badge.error}>Error</span>
* <span className={badge.accent}>Featured</span>
* ```
*
* @category Theme
* @public
*/
export const badge = {
/** Default badge with neutral gray background - use for general tags and categories */
default: 'px-2 py-1 bg-gray-700 rounded text-xs text-gray-300',
/** Muted badge with darker background - use for secondary or de-emphasized labels */
muted: 'px-2 py-1 bg-gray-800 rounded text-xs text-gray-400',
/** Accent badge with orange theme colors - use for featured or highlighted items */
accent: 'px-2 py-1 bg-orange-500/20 border border-orange-500/30 rounded text-xs text-orange-300',
/** Success badge with green colors - use for active, completed, or positive status */
success: 'px-2 py-1 bg-green-500/20 border border-green-500/30 rounded text-xs text-green-300',
/** Warning badge with yellow colors - use for pending, caution, or attention states */
warning: 'px-2 py-1 bg-yellow-500/20 border border-yellow-500/30 rounded text-xs text-yellow-300',
/** Error badge with red colors - use for errors, failures, or critical states */
error: 'px-2 py-1 bg-red-500/20 border border-red-500/30 rounded text-xs text-red-300',
} as const
/**
* Spacing utilities for consistent layout and content organization.
*
* Provides responsive spacing patterns for page layouts, sections, grids, and content flow.
* All spacing values use Tailwind's responsive breakpoints for mobile-first design.
*
* @example
* ```tsx
* import { spacing } from '@/lib/theme/surfaces'
*
* // Page-level container with responsive padding
* <main className={spacing.page}>
* <div>Page content</div>
* </main>
*
* // Section container with vertical spacing
* <div className={spacing.section}>
* <section>Section 1</section>
* <section>Section 2</section>
* </div>
*
* // Grid layout with responsive gaps
* <div className={cn('grid grid-cols-2', spacing.grid)}>
* <div>Grid item 1</div>
* <div>Grid item 2</div>
* </div>
*
* // Content flow with consistent vertical rhythm
* <article className={spacing.content}>
* <p>Paragraph 1</p>
* <p>Paragraph 2</p>
* </article>
* ```
*
* @category Theme
* @public
*/
export const spacing = {
/** Page-level responsive padding - use on main containers and page wrappers */
page: 'px-4 py-8 sm:px-6 lg:px-8',
/** Vertical spacing between major sections - creates consistent rhythm on pages */
section: 'space-y-8',
/** Grid gap with responsive sizing - use with CSS Grid or flex layouts */
grid: 'gap-4 sm:gap-6',
/** Content flow vertical spacing - use for text content and article layouts */
content: 'space-y-4',
} as const
/**
* Layout grid utilities for responsive card and content grids.
*
* Provides pre-configured responsive grid layouts with mobile-first column breakpoints.
* All layouts include consistent gap spacing and padding.
*
* @example
* ```tsx
* import { layout } from '@/lib/theme/surfaces'
*
* // 3-column grid (homepage, about page)
* <div className={layout.grid3col}>
* <div>Card 1</div>
* <div>Card 2</div>
* <div>Card 3</div>
* </div>
*
* // 2-column grid
* <div className={layout.grid2col}>
* <div>Card 1</div>
* <div>Card 2</div>
* </div>
*
* // 4-column grid (stats, icons)
* <div className={layout.grid4col}>
* <div>Stat 1</div>
* <div>Stat 2</div>
* <div>Stat 3</div>
* <div>Stat 4</div>
* </div>
* ```
*
* @category Theme
* @public
*/
export const layout = {
/** 2-column responsive grid - 1 col mobile, 2 cols tablet+ */
grid2col: 'grid grid-cols-1 md:grid-cols-2 gap-4 p-4',
/** 3-column responsive grid - 1 col mobile, 2 cols tablet, 3 cols desktop - use for homepage and about page */
grid3col: 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 p-4',
/** 4-column responsive grid - 2 cols mobile, 4 cols tablet+ */
grid4col: 'grid grid-cols-2 md:grid-cols-4 gap-4',
} as const
/**
* Surface design tokens for consistent UI styling across the application.
*
* Provides a comprehensive set of pre-configured surface styles for cards, sections,
* panels, buttons, badges, and spacing. All styles follow the dark theme design system
* with consistent colors, borders, shadows, and transitions.
*
* @remarks
* This is the main theme export. Import individual categories or the full surfaces object
* depending on your needs. All variants support responsive design and include smooth
* hover transitions.
*
* @example
* ```tsx
* import { surfaces } from '@/lib/theme/surfaces'
* // or
* import { card, button, badge } from '@/lib/theme/surfaces'
*
* // Using the full surfaces object
* <div className={surfaces.card.default}>
* <h2>Card Title</h2>
* </div>
*
* // Using individual imports
* <div className={card.domain}>
* <span>example.com</span>
* </div>
* ```
*
* @category Theme
* @public
*/
export const surfaces = {
card,
section,
panel,
button,
badge,
spacing,
layout,
} as const
/**
* TypeScript type representing all available surface tokens.
*
* Use this type for type-safe access to surface styles in components.
*
* @example
* ```tsx
* import type { SurfaceTokens } from '@/lib/theme/surfaces'
*
* function CustomComponent(props: { surfaces: SurfaceTokens }) {
* return <div className={props.surfaces.card.default}>Content</div>
* }
* ```
*
* @category Theme
* @public
*/
export type SurfaceTokens = typeof surfaces