Profile: add subscribe menu

This commit is contained in:
thislight 2024-11-03 20:50:31 +08:00
parent 8a435be4c8
commit 65fa4c4fa5
No known key found for this signature in database
GPG key ID: FCFE5192241CCD4E
6 changed files with 226 additions and 151 deletions

View file

@ -3,8 +3,9 @@ import { MenuList } from "@suid/material";
import {
createEffect,
createSignal,
type Component,
type JSX,
type ParentComponent,
type ParentProps,
} from "solid-js";
import { ANIM_CURVE_STD } from "./theme";
import "./Menu.css";
@ -13,13 +14,13 @@ import {
animateShrinkToTopRight,
} from "../platform/anim";
type Anchor = Pick<DOMRect, "top" | "left" | "right">
export type Anchor = Pick<DOMRect, "top" | "left" | "right">
type Props = {
export type MenuProps = ParentProps<{
open?: boolean;
onClose?: JSX.EventHandlerUnion<HTMLDialogElement, Event>;
anchor: () => Anchor;
};
}>;
function px(n?: number) {
if (n) {
@ -29,7 +30,22 @@ function px(n?: number) {
}
}
const Menu: ParentComponent<Props> = (props) => {
export function createManagedMenuState() {
const [anchor, setAnchor] = createSignal<Anchor>();
return [
setAnchor,
{
get open() {
return !!anchor();
},
anchor: anchor as () => Anchor,
onClose: () => setAnchor(),
},
] as const;
}
const Menu: Component<MenuProps> = (props) => {
let root: HTMLDialogElement;
const windowSize = useWindowSize();

22
src/material/Scaffold.css Normal file
View file

@ -0,0 +1,22 @@
.Scaffold__topbar {
position: sticky;
top: 0px;
z-index: var(--tutu-zidx-nav, auto);
}
.Scaffold__fab-dock {
position: fixed;
bottom: 40px;
right: 40px;
z-index: var(--tutu-zidx-nav, auto);
}
.Scaffold__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);
}

View file

@ -1,66 +1,67 @@
import { createElementSize } from "@solid-primitives/resize-observer";
import {
JSX,
Show,
createRenderEffect,
createSignal,
onCleanup,
type JSX,
type ParentComponent,
splitProps,
type Component,
type ParentProps,
} from "solid-js";
import { css } from "solid-styled";
import "./Scaffold.css";
interface ScaffoldProps {
topbar?: JSX.Element;
fab?: JSX.Element;
bottom?: JSX.Element;
}
type ScaffoldProps = ParentProps<
{
topbar?: JSX.Element;
fab?: JSX.Element;
bottom?: JSX.Element;
} & JSX.HTMLElementTags["div"]
>;
const Scaffold: ParentComponent<ScaffoldProps> = (props) => {
/**
* 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);
css`
.scaffold-content {
--scaffold-topbar-height: ${(topbarSize.height?.toString() ?? 0) + "px"};
}
.topbar {
position: sticky;
top: 0px;
z-index: var(--tutu-zidx-nav, auto);
}
.fab-dock {
position: fixed;
bottom: 40px;
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 (
<>
<Show when={props.topbar}>
<div class="topbar" ref={setTopbarElement}>
<div class="Scaffold__topbar" ref={setTopbarElement}>
{props.topbar}
</div>
</Show>
<Show when={props.fab}>
<div class="fab-dock">{props.fab}</div>
<div class="Scaffold__fab-dock">{props.fab}</div>
</Show>
<div class="scaffold-content">{props.children}</div>
<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="bottom-dock">{props.bottom}</div>
<div class="Scaffold__bottom-dock">{props.bottom}</div>
</Show>
</>
);

View file

@ -106,6 +106,8 @@
/* Submenu (+1dp for each submenu) */
--tutu-shadow-e9: 0px 9px 18px 0px var(--tutu-color-shadow);
--tutu-shadow-e10: 0px 10px 18px 0px var(--tutu-color-shadow);
--tutu-shadow-e11: 0px 11px 18px 0px var(--tutu-color-shadow-l1);
/* (pressed) FAB */
--tutu-shadow-e12: 0px 12px 24px 0px var(--tutu-color-shadow-l1);