aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
103 lines (100 loc) • 3.85 kB
JavaScript
'use client';
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import React, { forwardRef } from 'react';
import { cn } from '../../lib/utilsComprehensive.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 { useA11yId, announceToScreenReader, createModalA11y, keyboardHandlers } from '../../utils/a11y.js';
import { useMotionPreferenceContext } from '../../contexts/MotionPreferenceContext.js';
const GlassBottomSheet = /*#__PURE__*/forwardRef(({
open,
onOpenChange,
children,
height = "70%",
className,
title,
description,
respectMotionPreference = true,
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
"aria-describedby": ariaDescribedBy,
...props
}, ref) => {
// Generate unique IDs for accessibility
const bottomSheetId = useA11yId("glass-bottom-sheet");
const titleId = title ? useA11yId("glass-bottom-sheet-title") : undefined;
const descriptionId = description ? useA11yId("glass-bottom-sheet-desc") : undefined;
const {
prefersReducedMotion
} = useMotionPreferenceContext();
// Create accessibility attributes
const a11yProps = createModalA11y({
id: bottomSheetId,
titleId: ariaLabelledBy || titleId,
descriptionId: ariaDescribedBy || descriptionId,
modal: true
});
// Add aria-label if provided and no title
if (ariaLabel && !ariaLabelledBy && !titleId) {
a11yProps["aria-label"] = ariaLabel;
}
// Handle escape key
const handleEscape = keyboardHandlers.onEscape(() => onOpenChange(false));
// Announce to screen readers when opened
React.useEffect(() => {
if (open) {
announceToScreenReader(`Bottom sheet opened: ${title || ariaLabel || "Bottom sheet"}`, "polite");
}
}, [open, title, ariaLabel]);
const shouldAnimate = respectMotionPreference ? !prefersReducedMotion : true;
return jsxs(Fragment, {
children: [open && jsx(MotionFramer, {
preset: "fadeIn",
duration: shouldAnimate ? 200 : 0,
className: 'fixed inset-0 z-[1100]',
onClick: e => onOpenChange(false),
children: jsx("div", {
className: 'absolute inset-0 glass-surface-dark/50'
})
}), jsx(MotionFramer, {
preset: "slideUp",
duration: shouldAnimate ? 300 : 0,
className: cn("fixed left-0 right-0 bottom-0 z-[1101]", open ? "pointer-events-auto" : "pointer-events-none"),
style: {
height: typeof height === "number" ? `${height}px` : height,
transform: !shouldAnimate && !open ? "translateY(100%)" : undefined
},
onKeyDown: handleEscape,
...a11yProps,
...props,
children: jsxs(OptimizedGlassCore, {
ref: ref,
elevation: "level3",
className: cn("h-full rounded-t-2xl glass-p-4", className),
tabIndex: -1,
children: [jsx("div", {
className: 'glass-mx-auto w-10 h-1.5 glass-radius-full glass-surface-subtle/30 mb-3',
"aria-hidden": "true"
}), (title || description) && jsxs("div", {
className: 'mb-4',
children: [title && jsx("h2", {
id: titleId,
className: 'glass-text-lg font-semibold text-primary',
children: title
}), description && jsx("p", {
id: descriptionId,
className: "glass-text-sm glass-text-secondary glass-mt-1",
children: description
})]
}), children]
})
})]
});
});
GlassBottomSheet.displayName = "GlassBottomSheet";
export { GlassBottomSheet, GlassBottomSheet as default };
//# sourceMappingURL=GlassBottomSheet.js.map