shadimage
glass-ui
componentavatarsource: ok · hit

Avatar

An image element with a fallback for representing the user.

npx shadcn add "https://glass-ui.crenspire.com/r/avatar.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light
ui-primitives@radix-ui/react-avatar

Registry dependencies

avatar

Files5 · source cached 10/8/2026, 7:42:08 PM

lib/utils.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}
lib/glass-utils.ts
/**
 * Glassmorphism customization utilities
 * Allows users to customize color, transparency, blur, and outline for glass effects
 */

export interface GlassCustomization {
  /**
   * Background color for the glass effect (e.g., "rgba(255, 255, 255, 0.1)" or "#ffffff")
   * Default: uses CSS variable --glass-bg
   */
  color?: string
  
  /**
   * Transparency/opacity for the background (0-1)
   * If provided, will override the alpha channel in color
   */
  transparency?: number
  
  /**
   * Blur amount in pixels
   * Default: uses CSS variable --blur (20px)
   */
  blur?: number | string
  
  /**
   * Border/outline color (e.g., "rgba(255, 255, 255, 0.25)" or "#ffffff")
   * Default: uses CSS variable --glass-border
   */
  outline?: string
  
  /**
   * Border/outline width in pixels
   * Default: 1px
   */
  outlineWidth?: number | string
  
  /**
   * Shadow for the glass effect
   * Default: uses CSS variable --glass-shadow
   */
  shadow?: string
  
  /**
   * Inner glow color and intensity (e.g., "rgba(255, 255, 255, 0.2)")
   * Creates an inset shadow for a glowing effect inside the element
   */
  innerGlow?: string
  
  /**
   * Inner glow blur/spread radius in pixels
   * Default: 20px
   */
  innerGlowBlur?: number | string
}

/**
 * Converts glass customization props to CSS style object
 */
export function getGlassStyles(customization?: GlassCustomization): React.CSSProperties {
  if (!customization) return {}
  
  const styles: React.CSSProperties = {}
  
  // Handle background color and transparency
  if (customization.color || customization.transparency !== undefined) {
    let bgColor = customization.color || 'rgba(255, 255, 255, 0.1)'
    
    // If transparency is provided, adjust the alpha channel
    if (customization.transparency !== undefined) {
      // Extract RGB from color string if it's rgba/rgb
      const rgbaMatch = bgColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/)
      if (rgbaMatch) {
        const [, r, g, b] = rgbaMatch
        bgColor = `rgba(${r}, ${g}, ${b}, ${customization.transparency})`
      } else if (bgColor.startsWith('#')) {
        // Convert hex to rgba
        const hex = bgColor.replace('#', '')
        const r = parseInt(hex.substring(0, 2), 16)
        const g = parseInt(hex.substring(2, 4), 16)
        const b = parseInt(hex.substring(4, 6), 16)
        bgColor = `rgba(${r}, ${g}, ${b}, ${customization.transparency})`
      } else {
        // Fallback: append transparency
        bgColor = `${bgColor}${customization.transparency}`
      }
    }
    
    styles.backgroundColor = bgColor
  }
  
  // Handle blur
  if (customization.blur !== undefined) {
    const blurValue = typeof customization.blur === 'number' 
      ? `${customization.blur}px` 
      : customization.blur
    styles.backdropFilter = `blur(${blurValue})`
    styles.WebkitBackdropFilter = `blur(${blurValue})` // Safari support
  }
  
  // Handle outline/border - always apply border for glassmorphism effect
  if (customization.outline !== undefined) {
    const width = customization.outlineWidth || '1px'
    styles.borderColor = customization.outline
    styles.borderWidth = typeof width === 'number' ? `${width}px` : width
    styles.borderStyle = 'solid'
  } else if (!customization.outline && (customization.color || customization.transparency !== undefined || customization.blur !== undefined)) {
    // Apply default border if glass customization is provided but outline is not
    styles.borderColor = 'rgba(255, 255, 255, 0.3)'
    styles.borderWidth = '1px'
    styles.borderStyle = 'solid'
  }
  
  // Handle shadow and inner glow - combine both if provided
  const shadows: string[] = []
  
  // Add outer shadow
  if (customization.shadow !== undefined) {
    shadows.push(customization.shadow)
  } else if (customization.color || customization.transparency !== undefined || customization.blur !== undefined) {
    // Apply default glass shadow for depth
    shadows.push('0 8px 32px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(0, 0, 0, 0.05)')
  }
  
  // Add inner glow as inset shadow
  if (customization.innerGlow !== undefined) {
    const glowBlur = customization.innerGlowBlur !== undefined 
      ? (typeof customization.innerGlowBlur === 'number' ? `${customization.innerGlowBlur}px` : customization.innerGlowBlur)
      : '20px'
    shadows.push(`inset 0 0 ${glowBlur} ${customization.innerGlow}`)
  }
  
  if (shadows.length > 0) {
    styles.boxShadow = shadows.join(', ')
  }
  
  return styles
}

/**
 * Generates CSS custom properties for glass customization
 * Useful for components that need to pass styles to child elements
 */
export function getGlassCSSVars(customization?: GlassCustomization): Record<string, string> {
  if (!customization) return {}
  
  const vars: Record<string, string> = {}
  
  if (customization.color || customization.transparency !== undefined) {
    let bgColor = customization.color || 'rgba(255, 255, 255, 0.1)'
    
    if (customization.transparency !== undefined) {
      const rgbaMatch = bgColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/)
      if (rgbaMatch) {
        const [, r, g, b] = rgbaMatch
        bgColor = `rgba(${r}, ${g}, ${b}, ${customization.transparency})`
      } else if (bgColor.startsWith('#')) {
        const hex = bgColor.replace('#', '')
        const r = parseInt(hex.substring(0, 2), 16)
        const g = parseInt(hex.substring(2, 4), 16)
        const b = parseInt(hex.substring(4, 6), 16)
        bgColor = `rgba(${r}, ${g}, ${b}, ${customization.transparency})`
      }
    }
    
    vars['--glass-bg-custom'] = bgColor
  }
  
  if (customization.blur !== undefined) {
    const blurValue = typeof customization.blur === 'number' 
      ? `${customization.blur}px` 
      : customization.blur
    vars['--blur-custom'] = blurValue
  }
  
  if (customization.outline !== undefined) {
    vars['--glass-border-custom'] = customization.outline
  }
  
  if (customization.outlineWidth !== undefined) {
    const width = typeof customization.outlineWidth === 'number' 
      ? `${customization.outlineWidth}px` 
      : customization.outlineWidth
    vars['--glass-border-width-custom'] = width
  }
  
  if (customization.shadow !== undefined) {
    vars['--glass-shadow-custom'] = customization.shadow
  }
  
  if (customization.innerGlow !== undefined) {
    vars['--glass-inner-glow-custom'] = customization.innerGlow
  }
  
  if (customization.innerGlowBlur !== undefined) {
    const blurValue = typeof customization.innerGlowBlur === 'number' 
      ? `${customization.innerGlowBlur}px` 
      : customization.innerGlowBlur
    vars['--glass-inner-glow-blur-custom'] = blurValue
  }
  
  return vars
}

lib/hover-effects.ts
import { cva } from "class-variance-authority"

/**
 * Shared hover effect variants for all Glass UI components
 * 
 * Effects:
 * - none: No hover effect
 * - glow: Purple glow shadow that intensifies on hover
 * - shimmer: Moving shimmer effect across the component
 * - ripple: Ripple effect that scales outward on hover
 * - lift: Subtle lift effect with shadow increase
 * - scale: Scale up slightly on hover
 */
export const hoverEffects = cva(
  "transition-all duration-300",
  {
    variants: {
      hover: {
        none: "",
        glow: "shadow-lg shadow-purple-500/50 hover:shadow-xl hover:shadow-purple-500/70",
        shimmer: "relative overflow-hidden before:absolute before:inset-0 before:-translate-x-full before:bg-gradient-to-r before:from-transparent before:via-white/20 before:to-transparent hover:before:translate-x-full before:transition-transform before:duration-1000",
        ripple: "relative overflow-hidden after:absolute after:inset-0 after:scale-0 after:rounded-full after:bg-white/30 after:transition-transform after:duration-500 hover:after:scale-150",
        lift: "hover:-translate-y-1 hover:shadow-lg",
        scale: "hover:scale-105",
      },
    },
    defaultVariants: {
      hover: "none",
    },
  }
)

export type HoverEffect = "none" | "glow" | "shimmer" | "ripple" | "lift" | "scale"

app/globals.css
@import "tailwindcss";
@import "tw-animate-css";

@custom-variant dark (&:is(.dark *));

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --font-sans: var(--font-geist-sans);
  --font-mono: var(--font-geist-mono);
  --color-sidebar-ring: var(--sidebar-ring);
  --color-sidebar-border: var(--sidebar-border);
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
  --color-sidebar-accent: var(--sidebar-accent);
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
  --color-sidebar-primary: var(--sidebar-primary);
  --color-sidebar-foreground: var(--sidebar-foreground);
  --color-sidebar: var(--sidebar);
  --color-chart-5: var(--chart-5);
  --color-chart-4: var(--chart-4);
  --color-chart-3: var(--chart-3);
  --color-chart-2: var(--chart-2);
  --color-chart-1: var(--chart-1);
  --color-ring: var(--ring);
  --color-input: var(--input);
  --color-border: var(--border);
  --color-destructive: var(--destructive);
  --color-accent-foreground: var(--accent-foreground);
  --color-accent: var(--accent);
  --color-muted-foreground: var(--muted-foreground);
  --color-muted: var(--muted);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-secondary: var(--secondary);
  --color-primary-foreground: var(--primary-foreground);
  --color-primary: var(--primary);
  --color-popover-foreground: var(--popover-foreground);
  --color-popover: var(--popover);
  --color-card-foreground: var(--card-foreground);
  --color-card: var(--card);
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --shadow-glass: var(--glass-shadow);
}

:root {
  --radius: 0.625rem;
  /* Base colors - Light mode with dark text */
  --background: transparent;
  --foreground: oklch(0.15 0 0); /* Near black - dark text for light mode */
  --card: transparent;
  --card-foreground: oklch(0.15 0 0); /* Near black - dark text */
  --popover: transparent;
  --popover-foreground: oklch(0.15 0 0); /* Near black - dark text */
  
  /* Primary colors - Light mode */
  --primary: oklch(0.5 0.2 250); /* Blue */
  --primary-foreground: oklch(0.98 0 0); /* White text on primary */
  
  /* Secondary colors - Light mode */
  --secondary: oklch(0.96 0 0); /* Very light gray */
  --secondary-foreground: oklch(0.15 0 0); /* Dark text */
  
  /* Muted colors - Light mode */
  --muted: oklch(0.85 0 0); /* Dark gray - darker shade to avoid glass effect override */
  --muted-foreground: oklch(0.1 0 0); /* Medium gray text */
  
  /* Accent colors - Light mode */
  --accent: oklch(0.96 0 0); /* Very light gray */
  --accent-foreground: oklch(0.15 0 0); /* Dark text */
  
  /* Destructive colors - WCAG AA compliant (4.5:1 contrast) */
  --destructive: oklch(0.55 0.22 25); /* Red - 4.5:1 with white */
  --destructive-foreground: oklch(0.98 0 0); /* White text on red */
  
  /* Border and input - WCAG AA compliant (3:1 for UI components) */
  --border: oklch(0.88 0 0); /* Light gray - 3:1 contrast */
  --input: oklch(0.88 0 0); /* Light gray - 3:1 contrast */
  --ring: oklch(0.5 0.2 250); /* Blue ring - 3:1 contrast */
  
  /* Chart colors - WCAG AA compliant */
  --chart-1: oklch(0.6 0.2 250); /* Blue */
  --chart-2: oklch(0.55 0.15 150); /* Green */
  --chart-3: oklch(0.5 0.2 50); /* Yellow */
  --chart-4: oklch(0.65 0.2 300); /* Purple */
  --chart-5: oklch(0.6 0.2 20); /* Orange */
  
  /* Sidebar colors - Light mode */
  --sidebar: oklch(0.98 0 0); /* Near white */
  --sidebar-foreground: oklch(0.15 0 0); /* Dark text */
  --sidebar-primary: oklch(0.5 0.2 250); /* Blue */
  --sidebar-primary-foreground: oklch(0.98 0 0); /* White text on primary */
  --sidebar-accent: oklch(0.96 0 0); /* Very light gray */
  --sidebar-accent-foreground: oklch(0.15 0 0); /* Dark text */
  --sidebar-border: oklch(0.88 0 0); /* Light gray - 3:1 contrast */
  --sidebar-ring: oklch(0.5 0.2 250); /* Blue ring - 3:1 contrast */

  /* Apple-standard glassmorphism - Very subtle and refined */
  /* Low opacity for Apple's standard glass effect */
  --glass-bg: linear-gradient(135deg, 
    rgba(255, 255, 255, 0.15) 0%, 
    rgba(255, 255, 255, 0.12) 25%,
    rgba(240, 248, 255, 0.13) 50%,
    rgba(255, 255, 255, 0.11) 75%,
    rgba(230, 240, 255, 0.12) 100%
  );
  /* Very subtle white border - Apple standard */
  --glass-border: rgba(255, 255, 255, 0.12);
  /* Minimal shadows with subtle inner glow - Apple standard */
  --glass-shadow: 
    0 4px 16px rgba(0, 0, 0, 0.08),
    0 1px 4px rgba(0, 0, 0, 0.04),
    0 0 0 0.5px rgba(255, 255, 255, 0.08) inset,
    0 0 12px rgba(255, 255, 255, 0.1) inset;
  --glass-shadow-lg: 
    0 8px 32px rgba(0, 0, 0, 0.1),
    0 2px 8px rgba(0, 0, 0, 0.06),
    0 0 0 0.5px rgba(255, 255, 255, 0.1) inset,
    0 0 20px rgba(255, 255, 255, 0.12) inset;
  --glass-shadow-sm: 
    0 2px 8px rgba(0, 0, 0, 0.06),
    0 1px 2px rgba(0, 0, 0, 0.03),
    0 0 0 0.5px rgba(255, 255, 255, 0.06) inset,
    0 0 8px rgba(255, 255, 255, 0.08) inset;
  --gradient: linear-gradient(135deg, #a855f7 0%, #3b82f6 100%);
  /* Apple-standard blur values - moderate blur */
  --blur: 10px;
  --blur-sm: 10px;
  --blur-lg: 10px;
  
  /* Frosted glass variant - Enhanced opacity and stronger blur */
  --glass-frosted-bg: linear-gradient(135deg, 
    rgba(255, 255, 255, 0.25) 0%, 
    rgba(255, 255, 255, 0.22) 25%,
    rgba(240, 248, 255, 0.23) 50%,
    rgba(255, 255, 255, 0.21) 75%,
    rgba(230, 240, 255, 0.22) 100%
  );
  --glass-frosted-border: rgba(255, 255, 255, 0.3);
  --glass-frosted-shadow: 
    0 8px 32px rgba(0, 0, 0, 0.12),
    0 2px 8px rgba(0, 0, 0, 0.08),
    0 0 0 0.5px rgba(255, 255, 255, 0.15) inset,
    0 0 20px rgba(255, 255, 255, 0.18) inset;
  --blur-frosted: 25px;
  
  /* Fluted glass variant - Vertical ridges pattern */
  --glass-fluted-pattern: repeating-linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.08) 0px,
    rgba(255, 255, 255, 0.15) 4px,
    rgba(255, 255, 255, 0.08) 8px,
    rgba(255, 255, 255, 0.02) 10px,
    rgba(255, 255, 255, 0.08) 12px
  );
  
  /* Crystal glass variant - Clear glass with highlights and glow */
  --glass-crystal-bg: rgba(255, 255, 255, 0.3);
  --glass-crystal-border: rgba(255, 255, 255, 0.3);
  --glass-crystal-shadow: 
    0 0 20px rgba(0, 0, 0, 0.2),
    0 0 30px rgba(255, 255, 255, 0.1);
  --glass-crystal-shadow-hover: 
    0 0 25px rgba(0, 0, 0, 0.3),
    0 0 35px rgba(255, 255, 255, 0.15);
  --blur-crystal: 2px;
}

.dark {
  /* Apple-standard glassmorphism for dark mode - Very subtle and refined */
  /* Very low opacity for Apple's standard glass effect in dark mode */
  --glass-bg: linear-gradient(135deg, 
    rgba(255, 255, 255, 0.08) 0%, 
    rgba(255, 255, 255, 0.06) 25%,
    rgba(240, 248, 255, 0.07) 50%,
    rgba(255, 255, 255, 0.05) 75%,
    rgba(230, 240, 255, 0.06) 100%
  );
  /* Very subtle white border - Apple standard */
  --glass-border: rgba(255, 255, 255, 0.15);
  /* Minimal shadows with subtle inner glow - Apple standard for dark mode */
  --glass-shadow: 
    0 4px 16px rgba(0, 0, 0, 0.3),
    0 1px 4px rgba(0, 0, 0, 0.15),
    0 0 0 0.5px rgba(255, 255, 255, 0.12) inset,
    0 0 12px rgba(255, 255, 255, 0.15) inset;
  --glass-shadow-lg: 
    0 8px 32px rgba(0, 0, 0, 0.4),
    0 2px 8px rgba(0, 0, 0, 0.2),
    0 0 0 0.5px rgba(255, 255, 255, 0.15) inset,
    0 0 20px rgba(255, 255, 255, 0.18) inset;
  --glass-shadow-sm: 
    0 2px 8px rgba(0, 0, 0, 0.25),
    0 1px 2px rgba(0, 0, 0, 0.12),
    0 0 0 0.5px rgba(255, 255, 255, 0.1) inset,
    0 0 8px rgba(255, 255, 255, 0.12) inset;
  
  /* Frosted glass variant - Enhanced opacity and stronger blur for dark mode */
  --glass-frosted-bg: linear-gradient(135deg, 
    rgba(255, 255, 255, 0.15) 0%, 
    rgba(255, 255, 255, 0.12) 25%,
    rgba(240, 248, 255, 0.13) 50%,
    rgba(255, 255, 255, 0.11) 75%,
    rgba(230, 240, 255, 0.12) 100%
  );
  --glass-frosted-border: rgba(255, 255, 255, 0.25);
  --glass-frosted-shadow: 
    0 8px 32px rgba(0, 0, 0, 0.5),
    0 2px 8px rgba(0, 0, 0, 0.3),
    0 0 0 0.5px rgba(255, 255, 255, 0.2) inset,
    0 0 20px rgba(255, 255, 255, 0.22) inset;
  
  /* Fluted glass variant - Vertical ridges pattern for dark mode */
  --glass-fluted-pattern: repeating-linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.05) 0px,
    rgba(255, 255, 255, 0.12) 4px,
    rgba(255, 255, 255, 0.05) 8px,
    rgba(255, 255, 255, 0.01) 10px,
    rgba(255, 255, 255, 0.05) 12px
  );
  
  /* Crystal glass variant - Clear glass with highlights and glow for dark mode */
  --glass-crystal-bg: rgba(255, 255, 255, 0.1);
  --glass-crystal-border: rgba(255, 255, 255, 0.3);
  --glass-crystal-shadow: 
    0 0 20px rgba(0, 0, 0, 0.4),
    0 0 30px rgba(255, 255, 255, 0.15);
  --glass-crystal-shadow-hover: 
    0 0 25px rgba(0, 0, 0, 0.5),
    0 0 35px rgba(255, 255, 255, 0.2);
  
  /* Base colors - Apple-style white text */
  --background: transparent;
  --foreground: oklch(1 0 0); /* White - Apple-style */
  --card: transparent;
  --card-foreground: oklch(1 0 0); /* White - Apple-style */
  --popover: transparent;
  --popover-foreground: oklch(1 0 0); /* White - Apple-style */
  
  /* Primary colors - Apple-style white text */
  --primary: oklch(0.7 0.15 250); /* Light blue */
  --primary-foreground: oklch(1 0 0); /* White - Apple-style */
  
  /* Secondary colors - Apple-style white text */
  --secondary: oklch(0.25 0 0); /* Dark gray */
  --secondary-foreground: oklch(1 0 0); /* White - Apple-style */
  
  /* Muted colors - Apple-style white text */
  --muted: oklch(0.18 0 0); /* Darker gray - darker shade to avoid glass effect override */
  --muted-foreground: oklch(1 0 0); /* White - Apple-style */
  
  /* Accent colors - Apple-style white text */
  --accent: oklch(0.25 0 0); /* Dark gray */
  --accent-foreground: oklch(1 0 0); /* White - Apple-style */
  
  /* Destructive colors - WCAG AA compliant (4.5:1 contrast) */
  --destructive: oklch(0.65 0.22 25); /* Light red - 4.5:1 with dark background */
  --destructive-foreground: oklch(0.12 0 0); /* Near black text on red */
  
  /* Border and input - WCAG AA compliant (3:1 for UI components) */
  --border: oklch(0.3 0 0); /* Medium gray - 3:1 contrast */
  --input: oklch(0.25 0 0); /* Dark gray - 3:1 contrast */
  --ring: oklch(0.6 0.2 250); /* Light blue ring - 3:1 contrast */
  
  /* Chart colors - WCAG AA compliant */
  --chart-1: oklch(0.65 0.2 250); /* Light blue */
  --chart-2: oklch(0.7 0.15 150); /* Light green */
  --chart-3: oklch(0.75 0.2 50); /* Light yellow */
  --chart-4: oklch(0.7 0.2 300); /* Light purple */
  --chart-5: oklch(0.68 0.2 20); /* Light orange */
  
  /* Sidebar colors - Apple-style white text */
  --sidebar: oklch(0.18 0 0); /* Dark gray */
  --sidebar-foreground: oklch(1 0 0); /* White - Apple-style */
  --sidebar-primary: oklch(0.7 0.15 250); /* Light blue */
  --sidebar-primary-foreground: oklch(1 0 0); /* White - Apple-style */
  --sidebar-accent: oklch(0.25 0 0); /* Dark gray */
  --sidebar-accent-foreground: oklch(1 0 0); /* White - Apple-style */
  --sidebar-border: oklch(0.3 0 0); /* Medium gray - 3:1 contrast */
  --sidebar-ring: oklch(0.6 0.2 250); /* Light blue ring - 3:1 contrast */
}

@layer base {
  * {
    @apply border-border outline-ring/50;
  }
body {
  @apply text-foreground;
  background-color: transparent;
  }
}

@layer utilities {
  /* Apple-standard glass utility - Very subtle and refined */
  /* This creates Apple's standard glassmorphism with moderate blur */
  .glass-bg {
    /* Low opacity gradient background - Apple standard */
    background-image: var(--glass-bg);
    background-color: transparent;
    /* Moderate backdrop blur - Apple standard (20px) */
    backdrop-filter: blur(var(--blur)) saturate(180%);
    -webkit-backdrop-filter: blur(var(--blur)) saturate(180%);
    /* Very subtle white border - Apple standard */
    border: 0.5px solid var(--glass-border);
    /* Minimal shadow with subtle inner glow - Apple standard */
    box-shadow: var(--glass-shadow);
  }
  
  /* Frosted glass utility - Enhanced blur and higher opacity */
  .glass-frosted {
    background-image: var(--glass-frosted-bg) !important;
    background-color: transparent !important;
    /* Stronger backdrop blur for frosted effect */
    backdrop-filter: blur(var(--blur-frosted)) saturate(200%) !important;
    -webkit-backdrop-filter: blur(var(--blur-frosted)) saturate(200%) !important;
    /* More pronounced border */
    border: 0.5px solid var(--glass-frosted-border) !important;
    /* Enhanced shadow for depth */
    box-shadow: var(--glass-frosted-shadow) !important;
  }
  
  /* Fluted glass utility - Vertical ridges with glass effect */
  .glass-fluted {
    /* Base glass background combined with fluted pattern */
    background-image: var(--glass-fluted-pattern), var(--glass-bg) !important;
    background-color: transparent !important;
    /* Moderate backdrop blur like standard glass */
    backdrop-filter: blur(var(--blur)) saturate(180%) !important;
    -webkit-backdrop-filter: blur(var(--blur)) saturate(180%) !important;
    /* Standard glass border */
    border: 0.5px solid var(--glass-border) !important;
    /* Standard glass shadow */
    box-shadow: var(--glass-shadow) !important;
  }
  
  /* Crystal glass utility - Clear glass with highlights and glow */
  .glass-crystal {
    position: relative;
    background-color: var(--glass-crystal-bg) !important;
    /* Minimal backdrop blur for clarity */
    backdrop-filter: blur(var(--blur-crystal)) !important;
    -webkit-backdrop-filter: blur(var(--blur-crystal)) !important;
    border: 1px solid var(--glass-crystal-border) !important;
    box-shadow: var(--glass-crystal-shadow) !important;
    transition: all 0.3s ease !important;
    /* Top highlight gradient */
    background-image: linear-gradient(to bottom right, rgba(255, 255, 255, 0.15), transparent 50%) !important;
    background-size: 200% 200% !important;
  }
  
  .glass-crystal::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0.4), transparent);
    opacity: 0.7;
    pointer-events: none;
    height: 30%;
  }
  
  .glass-crystal::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(circle at 50% 120%, rgba(255, 255, 255, 0.2), transparent 70%);
    opacity: 0.8;
    pointer-events: none;
  }
  
  .glass-crystal:hover {
    box-shadow: var(--glass-crystal-shadow-hover) !important;
    background-position: 100% 100% !important;
  }

  /* Ensure react-day-picker doesn't override glass effect */
  .glass-bg[class*="rdp"] {
    background-color: transparent !important;
  }
  
  .glass-bg .rdp {
    background-color: transparent !important;
  }
  
  .glass-bg .rdp-month {
    background-color: transparent !important;
  }
}

@keyframes shimmer {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}

/* Sonner Toast Notifications - Glass Effect Overrides */
[data-sonner-toast] {
  background: var(--glass-bg) !important;
  backdrop-filter: blur(var(--blur)) !important;
  -webkit-backdrop-filter: blur(var(--blur)) !important;
  border: 1px solid var(--glass-border) !important;
  box-shadow: var(--glass-shadow-lg) !important;
  color: var(--foreground) !important;
}

[data-sonner-toast][data-type="success"] {
  border-color: rgba(34, 197, 94, 0.3) !important;
}

[data-sonner-toast][data-type="error"] {
  border-color: rgba(239, 68, 68, 0.3) !important;
}

[data-sonner-toast][data-type="warning"] {
  border-color: rgba(234, 179, 8, 0.3) !important;
}

[data-sonner-toast][data-type="info"] {
  border-color: rgba(59, 130, 246, 0.3) !important;
}

/* Toast description text */
[data-sonner-toast] [data-description] {
  color: var(--muted-foreground) !important;
}

/* Toast action buttons - Glass styled */
[data-sonner-toast] [data-button] {
  background: var(--glass-bg) !important;
  backdrop-filter: blur(var(--blur-sm)) !important;
  -webkit-backdrop-filter: blur(var(--blur-sm)) !important;
  border: 1px solid var(--glass-border) !important;
  color: var(--foreground) !important;
  transition: opacity 0.2s ease !important;
}

[data-sonner-toast] [data-button]:hover {
  opacity: 0.9 !important;
}

/* Toast cancel button */
[data-sonner-toast] [data-cancel] {
  background: var(--glass-bg) !important;
  backdrop-filter: blur(var(--blur-sm)) !important;
  -webkit-backdrop-filter: blur(var(--blur-sm)) !important;
  border: 1px solid var(--glass-border) !important;
  color: var(--muted-foreground) !important;
}

[data-sonner-toast] [data-cancel]:hover {
  opacity: 0.9 !important;
}

/* Toast close button */
[data-sonner-toast] [data-close-button] {
  background: var(--glass-bg) !important;
  backdrop-filter: blur(var(--blur-sm)) !important;
  -webkit-backdrop-filter: blur(var(--blur-sm)) !important;
  border: 1px solid var(--glass-border) !important;
  color: var(--foreground) !important;
}

[data-sonner-toast] [data-close-button]:hover {
  opacity: 0.9 !important;
}
components/ui/glass/avatar.tsx
"use client"

import * as React from "react"
import { Avatar as BaseAvatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"
import { cn } from "@/lib/utils"

export interface AvatarProps extends React.ComponentProps<typeof BaseAvatar> {
  glow?: boolean
  size?: "sm" | "md" | "lg"
}

/**
 * Glass UI Avatar - Enhanced avatar with glassy effects
 */
export const Avatar = React.forwardRef<
  React.ElementRef<typeof BaseAvatar>,
  AvatarProps
>(({ className, glow = false, size = "md", ...props }, ref) => {
  const sizeClasses = {
    sm: "h-8 w-8",
    md: "h-10 w-10",
    lg: "h-16 w-16",
  }
  
  return (
    <BaseAvatar
      ref={ref}
      className={cn(
        sizeClasses[size],
        glow && "ring-2 ring-purple-500/30 shadow-lg shadow-purple-500/20",
        "transition-all duration-200",
        className
      )}
      {...props}
    />
  )
})
Avatar.displayName = "Avatar"

export { AvatarImage, AvatarFallback }

More from glass-ui

Browse all components in this library →