aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
298 lines (295 loc) • 10.6 kB
JavaScript
'use client';
import { jsx, jsxs } from 'react/jsx-runtime';
import { forwardRef } from 'react';
import { glassTokenUtils } from '../../tokens/glass.js';
import '../../primitives/GlassCore.js';
import '../../primitives/glass/GlassAdvanced.js';
import { OptimizedGlassCore } from '../../primitives/OptimizedGlassCore.js';
import '../../primitives/glass/OptimizedGlassAdvanced.js';
import '../../primitives/MotionNative.js';
import { MotionFramer } from '../../primitives/motion/MotionFramer.js';
import { cn } from '../../lib/utilsComprehensive.js';
import { useA11yId } from '../../utils/a11y.js';
import { useMotionPreferenceContext } from '../../contexts/MotionPreferenceContext.js';
const GlassLoadingSkeleton = /*#__PURE__*/forwardRef(({
// TODO: Integrate ContrastGuard for table cells, list items, badges, card titles, and other text content for WCAG AA compliance
rows = 3,
height = "1rem",
width = "100%",
avatar = false,
avatarSize = "md",
animate = true,
variant = "default",
shimmer = true,
respectMotionPreference = true,
"aria-label": ariaLabel,
className,
children,
...props
}, ref) => {
const skeletonId = useA11yId("skeleton");
const {
prefersReducedMotion
} = useMotionPreferenceContext();
const shouldAnimate = animate && (!respectMotionPreference || !prefersReducedMotion);
const shouldShimmer = shimmer && (!respectMotionPreference || !prefersReducedMotion);
const avatarSizes = {
sm: "w-8 h-8",
md: "w-12 h-12",
lg: "w-16 h-16",
xl: "w-20 h-20"
};
const baseClasses = cn("glass-skeleton", "glass-radius-md", shouldShimmer && shouldAnimate && "animate-pulse", "glass-backdrop-blur-md");
// Consistent glassmorphism styling for all skeleton elements
const getSkeletonStyle = () => ({
background: `
linear-gradient(135deg, rgba(255,255,255,0.015) 0%, rgba(255,255,255,0.005) 50%, rgba(255,255,255,0.015) 100%),
linear-gradient(135deg, ${glassTokenUtils.getSurface("neutral", "level1").border.color} 0%, rgba(147,51,234,0.1) 100%)
`,
border: "1px solid rgba(255,255,255,0.04)",
boxShadow: "0 4px 16px rgba(var(--glass-color-black) / var(--glass-opacity-10)), 0 1px 0 rgba(255,255,255,0.03) inset"
});
const renderBasicSkeleton = () => jsxs("div", {
className: "glass-auto-gap glass-auto-gap-md",
children: [avatar && jsx("div", {
className: cn("glass-radius-full", baseClasses, avatarSizes[avatarSize]),
style: getSkeletonStyle()
}), Array.from({
length: rows
}, (_, index) => {
const isLast = index === rows - 1;
const rowWidth = isLast && rows > 1 ? "80%" : width;
return jsx("div", {
className: baseClasses,
style: {
height: typeof height === "number" ? `${height}px` : height,
width: typeof rowWidth === "number" ? `${rowWidth}px` : rowWidth,
...getSkeletonStyle()
}
}, index);
})]
});
const renderCardSkeleton = () => jsx(OptimizedGlassCore, {
elevation: "level1",
intensity: "medium",
depth: 2,
tint: "neutral",
border: "subtle",
animation: "none",
performanceMode: "medium",
className: "glass-p-6",
children: jsxs("div", {
className: "glass-auto-gap glass-auto-gap-lg",
children: [jsxs("div", {
className: "glass-flex glass-items-center glass-gap-4",
children: [avatar && jsx("div", {
className: cn("glass-radius-full", baseClasses, avatarSizes[avatarSize]),
style: getSkeletonStyle()
}), jsxs("div", {
className: "glass-auto-gap glass-auto-gap-sm glass-flex-1",
children: [jsx("div", {
className: cn(baseClasses, "h-5 w-3/4"),
style: getSkeletonStyle()
}), jsx("div", {
className: cn(baseClasses, "h-4 w-1/2"),
style: getSkeletonStyle()
})]
})]
}), jsx("div", {
className: "glass-auto-gap glass-auto-gap-sm",
children: Array.from({
length: rows
}, (_, index) => jsx("div", {
className: cn(baseClasses, "h-4"),
style: {
width: index === rows - 1 ? "60%" : "100%",
...getSkeletonStyle()
}
}, index))
}), jsxs("div", {
className: 'glass-flex glass-gap-3 pt-2',
children: [jsx("div", {
className: cn(baseClasses, "h-9 w-20 glass-radius-lg"),
style: getSkeletonStyle()
}), jsx("div", {
className: cn(baseClasses, "h-9 w-16 glass-radius-lg"),
style: getSkeletonStyle()
})]
})]
})
});
const renderListSkeleton = () => jsx("div", {
className: "glass-auto-gap glass-auto-gap-md",
children: Array.from({
length: rows
}, (_, index) => jsxs("div", {
className: "glass-flex glass-items-center glass-gap-4 glass-p-3",
children: [jsx("div", {
className: cn("glass-radius-full", baseClasses, "w-10 h-10"),
style: getSkeletonStyle()
}), jsxs("div", {
className: "glass-auto-gap glass-auto-gap-sm glass-flex-1",
children: [jsx("div", {
className: cn(baseClasses, "h-4 w-3/4"),
style: getSkeletonStyle()
}), jsx("div", {
className: cn(baseClasses, "h-3 w-1/2"),
style: getSkeletonStyle()
})]
}), jsx("div", {
className: cn(baseClasses, "h-6 w-16 glass-radius-md"),
style: getSkeletonStyle()
})]
}, index))
});
const renderTableSkeleton = () => jsxs("div", {
className: "glass-auto-gap glass-auto-gap-sm",
children: [jsx("div", {
className: "glass-grid glass-grid-cols-4 glass-gap-4 glass-p-4 glass-border-b glass-border-white/10",
children: Array.from({
length: 4
}, (_, index) => jsx("div", {
className: cn(baseClasses, "h-4 w-16"),
style: getSkeletonStyle()
}, index))
}), Array.from({
length: rows
}, (_, rowIndex) => jsx("div", {
className: "glass-grid glass-grid-cols-4 glass-gap-4 glass-p-4",
children: Array.from({
length: 4
}, (_, colIndex) => jsx("div", {
className: cn(baseClasses, "h-4"),
style: getSkeletonStyle()
}, colIndex))
}, rowIndex))]
});
const renderFormSkeleton = () => jsxs("div", {
className: "glass-auto-gap glass-auto-gap-2xl",
children: [Array.from({
length: rows
}, (_, index) => jsxs("div", {
className: "glass-auto-gap glass-auto-gap-sm",
children: [jsx("div", {
className: cn(baseClasses, "h-4 w-24"),
style: getSkeletonStyle()
}), jsx("div", {
className: cn(baseClasses, "h-10 w-full glass-radius-lg"),
style: getSkeletonStyle()
})]
}, index)), jsxs("div", {
className: 'glass-flex glass-gap-3 pt-4',
children: [jsx("div", {
className: cn(baseClasses, "h-10 w-24 glass-radius-lg"),
style: getSkeletonStyle()
}), jsx("div", {
className: cn(baseClasses, "h-10 w-20 glass-radius-lg"),
style: getSkeletonStyle()
})]
})]
});
const renderDashboardSkeleton = () => jsx("div", {
className: 'glass-grid glass-grid-cols-1 md:grid-cols-2 lg:grid-cols-3 glass-gap-6',
children: Array.from({
length: rows
}, (_, index) => jsx(OptimizedGlassCore, {
elevation: "level1",
intensity: "medium",
depth: 2,
tint: "neutral",
border: "subtle",
animation: "none",
performanceMode: "medium",
className: "glass-p-6",
children: jsxs("div", {
className: "glass-auto-gap glass-auto-gap-lg",
children: [jsxs("div", {
className: "glass-flex glass-items-center glass-justify-between",
children: [jsx("div", {
className: cn(baseClasses, "h-5 w-24"),
style: getSkeletonStyle()
}), jsx("div", {
className: cn(baseClasses, "h-6 w-6 glass-radius-md"),
style: getSkeletonStyle()
})]
}), jsx("div", {
className: cn(baseClasses, "h-8 w-16"),
style: getSkeletonStyle()
}), jsxs("div", {
className: "glass-auto-gap glass-auto-gap-sm",
children: [jsx("div", {
className: cn(baseClasses, "h-3 w-full"),
style: getSkeletonStyle()
}), jsx("div", {
className: cn(baseClasses, "h-3 w-3/4"),
style: getSkeletonStyle()
})]
})]
})
}, index))
});
const renderSkeleton = () => {
if (children) {
return children;
}
switch (variant) {
case "card":
return renderCardSkeleton();
case "list":
return renderListSkeleton();
case "table":
return renderTableSkeleton();
case "form":
return renderFormSkeleton();
case "dashboard":
return renderDashboardSkeleton();
default:
return renderBasicSkeleton();
}
};
return jsx(MotionFramer, {
preset: shouldAnimate ? "fadeIn" : undefined,
className: cn("glass-loading-skeleton", className),
children: jsxs("div", {
ref: ref,
id: skeletonId,
role: "status",
"aria-label": ariaLabel || "Loading content",
"aria-busy": "true",
"aria-live": "polite",
className: 'relative',
...props,
children: [renderSkeleton(), shouldShimmer && jsx("div", {
className: 'absolute inset-0 -skew-x-12 glass-gradient-primary glass-gradient-primary via-blue-300/10 glass-gradient-primary animate-shimmer'
})]
})
});
});
GlassLoadingSkeleton.displayName = "GlassLoadingSkeleton";
// Utility components for common patterns
const GlassSkeletonText = /*#__PURE__*/forwardRef((props, ref) => jsx(GlassLoadingSkeleton, {
ref: ref,
variant: "default",
...props
}));
const GlassSkeletonCard = /*#__PURE__*/forwardRef((props, ref) => jsx(GlassLoadingSkeleton, {
ref: ref,
variant: "card",
...props
}));
const GlassSkeletonList = /*#__PURE__*/forwardRef((props, ref) => jsx(GlassLoadingSkeleton, {
ref: ref,
variant: "list",
...props
}));
const GlassSkeletonTable = /*#__PURE__*/forwardRef((props, ref) => jsx(GlassLoadingSkeleton, {
ref: ref,
variant: "table",
...props
}));
GlassSkeletonText.displayName = "GlassSkeletonText";
GlassSkeletonCard.displayName = "GlassSkeletonCard";
GlassSkeletonList.displayName = "GlassSkeletonList";
GlassSkeletonTable.displayName = "GlassSkeletonTable";
export { GlassLoadingSkeleton, GlassSkeletonCard, GlassSkeletonList, GlassSkeletonTable, GlassSkeletonText, GlassLoadingSkeleton as default };
//# sourceMappingURL=GlassLoadingSkeleton.js.map