feat(design): the public watch page on the app's surfaces (B6) — the scheme backdrop, the title and actions on a glass panel, a glass Download (E28 S3d4)
This commit is contained in:
@@ -84,6 +84,27 @@ describe("WatchPage action row", () => {
|
||||
expect(repeat.className).toContain("h-7");
|
||||
expect(download.className).toContain("h-7");
|
||||
});
|
||||
|
||||
// E28 S3d4 (B6): the page the stranger sees wears the app's surfaces — the scheme's ambient
|
||||
// backdrop (no page fill over the body's), the title and actions on a glass panel, a glass Download.
|
||||
it("sits on the app's surfaces: backdrop, a glass panel, a glass Download", async () => {
|
||||
window.history.replaceState({}, "", "/watch/tok-b6");
|
||||
mockMeta({
|
||||
needs_password: false,
|
||||
audio: false,
|
||||
allow_download: true,
|
||||
file_url: "/f.mp4",
|
||||
title: "A clip",
|
||||
});
|
||||
const view = render(<WatchPage />);
|
||||
const title = await view.findByRole("heading", { name: "A clip" });
|
||||
expect((view.container.firstElementChild as HTMLElement).className).not.toMatch(
|
||||
/(^|\s)bg-bg(\s|$)/,
|
||||
);
|
||||
expect(title.closest(".glass")).toBeTruthy();
|
||||
const download = view.container.querySelector('a[href="/f.mp4"]')!;
|
||||
expect(download.className).toContain("glass-card");
|
||||
});
|
||||
});
|
||||
|
||||
describe("WatchPage media element (S3 · 5a)", () => {
|
||||
|
||||
@@ -230,7 +230,8 @@ export default function WatchPage() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-bg text-fg flex flex-col items-center">
|
||||
// No page fill of its own (B6): the body's ambient scheme backdrop shows through, as in the app.
|
||||
<div className="min-h-dvh text-fg flex flex-col items-center">
|
||||
<div className="w-full max-w-4xl px-4 py-6 flex-1 flex flex-col">
|
||||
<div className="flex items-center gap-2 mb-5 text-sm text-muted">
|
||||
<PlayCircle className="w-5 h-5 text-accent" />
|
||||
@@ -364,13 +365,13 @@ export default function WatchPage() {
|
||||
loop={repeat}
|
||||
src={meta.file_url}
|
||||
poster={meta.poster_url || undefined}
|
||||
className="max-h-[80vh] max-w-full mx-auto block"
|
||||
className="max-h-[80dvh] max-w-full mx-auto block"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{/* The actions wrap under the title when the row is too narrow for both (a phone), rather
|
||||
than squeezing the title into a column a word wide. */}
|
||||
<div className="mt-3 flex flex-wrap items-start gap-x-3 gap-y-2">
|
||||
<div className={`${SURFACE.panel} mt-3 flex flex-wrap items-start gap-x-3 gap-y-2 p-3`}>
|
||||
<div className="min-w-0 flex-1 basis-60">
|
||||
<h1 className="text-lg font-semibold leading-snug break-words">
|
||||
{meta.title || "Video"}
|
||||
@@ -403,7 +404,7 @@ export default function WatchPage() {
|
||||
</Chip>
|
||||
{/* The toolbar rung, level with the Repeat chip beside it (one row, one height). */}
|
||||
{meta.allow_download && (
|
||||
<LinkButton href={meta.file_url} icon={<Download />} size="sm">
|
||||
<LinkButton href={meta.file_url} icon={<Download />} size="sm" variant="glass">
|
||||
{T.download}
|
||||
</LinkButton>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user