New Componet Panel Added
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
---
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
|
||||
interface Props extends HTMLAttributes<"div"> {
|
||||
id: string;
|
||||
wrapperId: string;
|
||||
isOpen?: boolean;
|
||||
width?: number;
|
||||
position?: "left" | "right";
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
id,
|
||||
wrapperId,
|
||||
isOpen = false,
|
||||
width = 360,
|
||||
position = "right",
|
||||
class: className,
|
||||
}: Props = Astro.props;
|
||||
---
|
||||
|
||||
<div
|
||||
id={`panel-${id}`}
|
||||
data-panel
|
||||
data-open="false"
|
||||
class={`panel ${position} ${className ?? ""}`}
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
[data-panel] {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
display: none;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
transition:
|
||||
width 300ms ease,
|
||||
transform 300ms ease,
|
||||
opacity 300ms ease;
|
||||
opacity: 0;
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
[data-panel].left {
|
||||
left: 0;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
[data-panel].right {
|
||||
right: 0;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
[data-panel][data-open="true"] {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script
|
||||
type="module"
|
||||
is:inline
|
||||
define:vars={{ id, isOpen, wrapperId, width, position }}
|
||||
>
|
||||
const panel = document.getElementById(`panel-${id}`);
|
||||
const closePanelBtn = document.getElementById(`close-panel-${id}`);
|
||||
const panelWrapper = document.getElementById(wrapperId);
|
||||
|
||||
function openPanel() {
|
||||
if (!panel || panel.dataset.open === "true") return;
|
||||
|
||||
panel.dataset.open = "true";
|
||||
panel.style.display = "block";
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
panel.style.width = `${width}px`;
|
||||
|
||||
if (position === "left") {
|
||||
panelWrapper.style.transition = "padding-left 300ms ease";
|
||||
panelWrapper.style.paddingLeft = `${width}px`;
|
||||
} else {
|
||||
panelWrapper.style.transition = "padding-right 300ms ease";
|
||||
panelWrapper.style.paddingRight = `${width}px`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closePanel() {
|
||||
if (!panel || panel.dataset.open === "false") return;
|
||||
|
||||
panel.dataset.open = "false";
|
||||
panel.style.width = "0";
|
||||
panel.style.display = "none";
|
||||
|
||||
if (position === "left") {
|
||||
panelWrapper.style.paddingLeft = "0px";
|
||||
} else {
|
||||
panelWrapper.style.paddingRight = "0px";
|
||||
}
|
||||
|
||||
panel.addEventListener(
|
||||
"transitionend",
|
||||
(e) => {
|
||||
if (
|
||||
e.propertyName === "width" &&
|
||||
panel.dataset.open === "false"
|
||||
) {
|
||||
panel.style.display = "none";
|
||||
}
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
}
|
||||
|
||||
// Auto-open if isOpen is passed
|
||||
if (isOpen) {
|
||||
openPanel();
|
||||
}
|
||||
|
||||
// Global triggers
|
||||
window.addEventListener(`open-panel-${id}`, openPanel);
|
||||
window.addEventListener(`close-panel-${id}`, closePanel);
|
||||
|
||||
closePanelBtn?.addEventListener("click", closePanel);
|
||||
</script>
|
||||
Reference in New Issue
Block a user