Compare commits

...

2 commits

Author SHA1 Message Date
thislight
e8a4e382ba
MediaAttachmentGrid: lazily created viewer
All checks were successful
/ depoly (push) Successful in 1m7s
The reworked viewer presentation process delay the
creation of the viewer until the user interaction,
to reduce the DOM created during viewing the list.
2024-09-14 20:21:19 +08:00
thislight
bf7e694e00
MediaAttachmentGrid: optimize preview layout (#11) 2024-09-14 20:09:54 +08:00
2 changed files with 36 additions and 14 deletions

View file

@ -1,8 +1,9 @@
import type { mastodon } from "masto"; import type { mastodon } from "masto";
import { type Component, For, createSignal } from "solid-js"; import { type Component, For, createSignal, onMount } from "solid-js";
import { css } from "solid-styled"; import { css } from "solid-styled";
import tootStyle from "./toot.module.css"; import tootStyle from "./toot.module.css";
import MediaViewer from "./MediaViewer"; import MediaViewer from "./MediaViewer";
import { render } from "solid-js/web";
const MediaAttachmentGrid: Component<{ const MediaAttachmentGrid: Component<{
attachments: mastodon.v1.MediaAttachment[]; attachments: mastodon.v1.MediaAttachment[];
@ -13,16 +14,35 @@ const MediaAttachmentGrid: Component<{
const gridTemplateColumns = () => { const gridTemplateColumns = () => {
const l = props.attachments.length; const l = props.attachments.length;
if (l < 2) { if (l < 2) {
return "1fr"; return "minmax(40px, auto)";
} }
if (l < 4) { if (l < 4) {
return "repeat(2, 1fr)"; return "repeat(2, minmax(40px, auto))";
} }
return "repeat(3, 1fr)"; return "repeat(3, minmax(40px, auto))";
}; };
const openViewerFor = (index: number) => { const openViewerFor = (index: number) => {
setViewerIndex(index); setViewerIndex(index);
const container = document.createElement("div");
container.setAttribute("role", "presentation");
document.body.appendChild(container);
let dispose: () => void
dispose = render(() => {
return (
<MediaViewer
show={viewerOpened()}
index={viewerIndex() || 0}
onIndexUpdated={setViewerIndex}
media={props.attachments}
onClose={() => {
setViewerIndex(undefined);
dispose();
document.body.removeChild(container)
}}
/>
);
}, container);
}; };
css` css`
@ -56,13 +76,6 @@ const MediaAttachmentGrid: Component<{
} }
}} }}
</For> </For>
<MediaViewer
show={viewerOpened()}
index={viewerIndex() || 0}
onIndexUpdated={setViewerIndex}
media={props.attachments}
onClose={() => setViewerIndex(undefined)}
/>
</section> </section>
); );
}; };

View file

@ -140,7 +140,7 @@
max-height: calc(4 * var(--title-line-height) * var(--title-size)); max-height: calc(4 * var(--title-line-height) * var(--title-size));
} }
> p { >p {
max-height: calc(8 * var(--body-line-height) * var(--body-size)); max-height: calc(8 * var(--body-line-height) * var(--body-size));
} }
@ -228,10 +228,19 @@
> :where(img) { > :where(img) {
max-height: 35vh; max-height: 35vh;
min-height: 40px; min-height: 40px;
object-fit: none; object-fit: contain;
width: 100%; max-width: 100%;
background-color: var(--tutu-color-surface-d); background-color: var(--tutu-color-surface-d);
border-radius: 2px; border-radius: 2px;
border: 1px solid transparent;
transition: border-color 220ms var(--tutu-anim-curve-std),
box-shadow 220ms var(--tutu-anim-curve-std);
&:hover,
&:focus-visible {
border: 1px solid var(--tutu-color-surface-dd);
box-shadow: var(--tutu-shadow-e1);
}
} }
} }