diff --git a/src/material/BottomSheet.module.css b/src/material/BottomSheet.module.css index 4a35711..f73f562 100644 --- a/src/material/BottomSheet.module.css +++ b/src/material/BottomSheet.module.css @@ -1,5 +1,7 @@ .bottomSheet { - composes: surface from "material.module.css"; + composes: surface from "./material.module.css"; + composes: cardGutSkip from "./cards.module.css"; + composes: cardNoPad from "./cards.module.css"; border: none; position: absolute; left: 50%; @@ -42,9 +44,21 @@ &.animated { position: absolute; transform: none; + overflow: hidden; + will-change: width, height, top, left; &::backdrop { opacity: 0; } + + & * { + overflow: hidden; + } + } + + &.bottom { + top: unset; + transform: translateX(-50%); + bottom: 0; } } diff --git a/src/material/BottomSheet.tsx b/src/material/BottomSheet.tsx index d37a0e2..3191426 100644 --- a/src/material/BottomSheet.tsx +++ b/src/material/BottomSheet.tsx @@ -13,9 +13,12 @@ import { } from "solid-js"; import styles from "./BottomSheet.module.css"; import { useHeroSignal } from "../platform/anim"; +import { makeEventListener } from "@solid-primitives/event-listener"; export type BottomSheetProps = { open?: boolean; + bottomUp?: boolean; + onClose?(reason: "backdrop"): void; }; export const HERO = Symbol("BottomSheet Hero Symbol"); @@ -52,7 +55,7 @@ const BottomSheet: ParentComponent = (props) => { createEffect(() => { if (props.open) { if (!element.open && !pending()) { - animatedOpen(); + requestAnimationFrame(animatedOpen); setCache(ochildren()); } } else { @@ -63,15 +66,16 @@ const BottomSheet: ParentComponent = (props) => { } }); + const onClose = () => { + element.close(); + setHero(); + }; + const animatedClose = () => { const endRect = hero(); if (endRect) { const startRect = element.getBoundingClientRect(); const animation = animateHero(startRect, endRect, element, true); - const onClose = () => { - element.close(); - setHero(); - }; animation.addEventListener("finish", onClose); animation.addEventListener("cancel", onClose); } else { @@ -123,8 +127,29 @@ const BottomSheet: ParentComponent = (props) => { } }); + const onDialogClick = ( + event: MouseEvent & { currentTarget: HTMLDialogElement }, + ) => { + const rect = event.currentTarget.getBoundingClientRect(); + const isInDialog = + rect.top <= event.clientY && + event.clientY <= rect.top + rect.height && + rect.left <= event.clientX && + event.clientX <= rect.left + rect.width; + if (!isInDialog) { + props.onClose?.("backdrop"); + } + }; + return ( - + {ochildren() ?? cache()} ); diff --git a/src/material/Scaffold.tsx b/src/material/Scaffold.tsx index f1f9d34..cebcda7 100644 --- a/src/material/Scaffold.tsx +++ b/src/material/Scaffold.tsx @@ -12,6 +12,7 @@ import { css } from "solid-styled"; interface ScaffoldProps { topbar?: JSX.Element; fab?: JSX.Element; + bottom?: JSX.Element; } const Scaffold: ParentComponent = (props) => { @@ -36,6 +37,16 @@ const Scaffold: ParentComponent = (props) => { right: 40px; z-index: var(--tutu-zidx-nav, auto); } + + .bottom-dock { + position: sticky; + bottom: 0; + left: 0; + right: 0; + z-index: var(--tutu-zidx-nav, auto); + padding-bottom: var(--safe-area-inset-bottom, 0); + + } `; return ( <> @@ -48,6 +59,9 @@ const Scaffold: ParentComponent = (props) => {
{props.fab}
{props.children}
+ +
{props.bottom}
+
); }; diff --git a/src/platform/polyfills.ts b/src/platform/polyfills.ts index 6897af7..0e9d53e 100644 --- a/src/platform/polyfills.ts +++ b/src/platform/polyfills.ts @@ -2,7 +2,21 @@ //! It recommended to include the module by