aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
236 lines (226 loc) • 6.73 kB
JavaScript
'use client';
import { jsxs, jsx } from 'react/jsx-runtime';
import { forwardRef } from 'react';
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
import { GlassContainer } from './GlassContainer.js';
import { createGlassStyle } from '../../utils/createGlassStyle.js';
/**
* Z-Space App Layout Component
*/
const ZSpaceAppLayout = /*#__PURE__*/forwardRef(({
// TODO: Integrate ContrastGuard for any section titles, labels, and helper text for WCAG AA compliance
children,
className = "",
style = {},
header,
sidebar,
footer,
overlay,
perspective = 1500,
headerDepth = 30,
sidebarDepth = 20,
contentDepth = 0,
footerDepth = 10,
overlayDepth = 100,
sidebarWidth = 280,
headerHeight = 64,
footerHeight = 60,
sidebarPosition = "left",
collapsedSidebar = false,
onSidebarToggle
}, ref) => {
const prefersReducedMotion = useReducedMotion();
// Convert numeric values to pixels
const sidebarWidthPx = typeof sidebarWidth === "number" ? `${sidebarWidth}px` : sidebarWidth;
const headerHeightPx = typeof headerHeight === "number" ? `${headerHeight}px` : headerHeight;
const footerHeightPx = typeof footerHeight === "number" ? `${footerHeight}px` : footerHeight;
/**
* Container styles
*/
const containerStyles = {
...style,
position: "relative",
width: "100%",
height: "100vh",
perspective: `${perspective}px`,
transformStyle: "preserve-3d",
overflow: "hidden"
};
/**
* Get layer transform
*/
const getLayerTransform = depth => {
if (prefersReducedMotion) return "none";
return `translateZ(${depth}px)`;
};
/**
* Header styles
*/
const headerStyles = {
position: "fixed",
top: 0,
left: 0,
right: 0,
height: headerHeightPx,
transform: getLayerTransform(headerDepth),
transformStyle: "preserve-3d",
zIndex: 40
};
/**
* Sidebar styles
*/
const sidebarStyles = {
position: "fixed",
top: header ? headerHeightPx : 0,
[sidebarPosition]: 0,
bottom: footer ? footerHeightPx : 0,
width: collapsedSidebar ? "64px" : sidebarWidthPx,
transform: getLayerTransform(sidebarDepth),
transformStyle: "preserve-3d",
transition: prefersReducedMotion ? "none" : "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
zIndex: 30
};
/**
* Main content styles
*/
const mainStyles = {
position: "fixed",
top: header ? headerHeightPx : 0,
bottom: footer ? footerHeightPx : 0,
left: sidebar && sidebarPosition === "left" ? collapsedSidebar ? "64px" : sidebarWidthPx : 0,
right: sidebar && sidebarPosition === "right" ? collapsedSidebar ? "64px" : sidebarWidthPx : 0,
transform: getLayerTransform(contentDepth),
transformStyle: "preserve-3d",
overflow: "auto",
transition: prefersReducedMotion ? "none" : "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
zIndex: 10
};
/**
* Footer styles
*/
const footerStyles = {
position: "fixed",
bottom: 0,
left: 0,
right: 0,
height: footerHeightPx,
transform: getLayerTransform(footerDepth),
transformStyle: "preserve-3d",
zIndex: 20
};
/**
* Overlay styles
*/
const overlayStyles = {
position: "fixed",
inset: 0,
transform: getLayerTransform(overlayDepth),
transformStyle: "preserve-3d",
zIndex: 50,
pointerEvents: overlay ? "auto" : "none"
};
return jsxs("div", {
ref: ref,
className: `zspace-app-layout ${className}`,
style: containerStyles,
children: [header && jsx("div", {
className: 'zspace-app-layout-header',
style: headerStyles,
children: jsx(GlassContainer, {
style: {
width: "100%",
height: "100%"
},
children: header
})
}), sidebar && jsx("div", {
className: 'zspace-app-layout-sidebar',
style: sidebarStyles,
children: jsxs(GlassContainer, {
style: {
width: "100%",
height: "100%"
},
children: [sidebar, onSidebarToggle && jsx("button", {
onClick: onSidebarToggle,
className: 'zspace-sidebar-toggle glass-focus glass-touch-target glass-contrast-guard glass-focus glass-touch-target glass-contrast-guard',
style: createGlassStyle({
variant: "default",
elev: 2
}),
"aria-label": collapsedSidebar ? "Expand sidebar" : "Collapse sidebar",
children: collapsedSidebar ? "→" : "←"
})]
})
}), jsx("main", {
className: 'zspace-app-layout-main',
style: mainStyles,
children: jsx(GlassContainer, {
style: {
minHeight: "100%",
padding: "20px"
},
children: children
})
}), footer && jsx("div", {
className: 'zspace-app-layout-footer',
style: footerStyles,
children: jsx(GlassContainer, {
style: {
width: "100%",
height: "100%"
},
children: footer
})
}), overlay && jsx("div", {
className: 'zspace-app-layout-overlay',
style: overlayStyles,
children: jsx(GlassContainer, {
style: {
width: "100%",
height: "100%"
},
children: overlay
})
}), jsx("style", {
children: `
.zspace-app-layout {
font-family: var(--aura-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
}
.zspace-sidebar-toggle:hover {
background: var(--aura-glass-bg-hover, rgba(255, 255, 255, 0.15)) !important;
transform: translateY(-50%) scale(1.05);
}
.zspace-sidebar-toggle:active {
transform: translateY(-50%) scale(0.95);
}
.zspace-sidebar-toggle:focus-visible {
outline: 2px solid var(--aura-accent-color, #00d4ff);
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.zspace-app-layout *,
.zspace-sidebar-toggle {
transform: none !important;
transition: none !important;
}
}
@media (max-width: 768px) {
.zspace-app-layout-sidebar {
transform: translateX(${sidebarPosition === "left" ? "-100%" : "100%"}) !important;
}
.zspace-app-layout-sidebar.mobile-open {
transform: none !important;
}
.zspace-app-layout-main {
left: 0 !important;
right: 0 !important;
}
}
`
})]
});
});
ZSpaceAppLayout.displayName = "ZSpaceAppLayout";
export { ZSpaceAppLayout };
//# sourceMappingURL=ZSpaceAppLayout.js.map