tutu/src/material/Scaffold.tsx
2024-11-04 18:02:30 +08:00

70 lines
1.6 KiB
TypeScript

import { createElementSize } from "@solid-primitives/resize-observer";
import {
JSX,
Show,
createRenderEffect,
createSignal,
splitProps,
type Component,
type ParentProps,
} from "solid-js";
import "./Scaffold.css";
type ScaffoldProps = ParentProps<
{
topbar?: JSX.Element;
fab?: JSX.Element;
bottom?: JSX.Element;
} & JSX.HTMLElementTags["div"]
>;
/**
* The passthrough props are passed to the content container.
*/
const Scaffold: Component<ScaffoldProps> = (props) => {
const [managed, rest] = splitProps(props, [
"topbar",
"fab",
"bottom",
"children",
"ref",
]);
const [topbarElement, setTopbarElement] = createSignal<HTMLElement>();
const topbarSize = createElementSize(topbarElement);
return (
<>
<Show when={props.topbar}>
<div class="Scaffold__topbar" ref={setTopbarElement} role="presentation">
{props.topbar}
</div>
</Show>
<Show when={props.fab}>
<div class="Scaffold__fab-dock" role="presentation">{props.fab}</div>
</Show>
<div
ref={(e) => {
createRenderEffect(() => {
e.style.setProperty(
"--scaffold-topbar-height",
(topbarSize.height?.toString() ?? 0) + "px",
);
});
if (managed.ref) {
(managed.ref as (val: typeof e) => void)(e);
}
}}
{...rest}
>
{managed.children}
</div>
<Show when={props.bottom}>
<div class="Scaffold__bottom-dock" role="presentation">{props.bottom}</div>
</Show>
</>
);
};
export default Scaffold;