This commit is contained in:
parent
3cacf64c8e
commit
4d9c2b3aa8
3 changed files with 167 additions and 95 deletions
97
src/timelines/toot-components/PreviewCard.tsx
Normal file
97
src/timelines/toot-components/PreviewCard.tsx
Normal file
|
@ -0,0 +1,97 @@
|
|||
import Color from "colorjs.io";
|
||||
import type { mastodon } from "masto";
|
||||
import { createEffect, createMemo, Show } from "solid-js";
|
||||
import { Title, Body1 } from "../../material/typography";
|
||||
import { averageColorHex } from "../../platform/blurhash";
|
||||
import "./PreviewCard.css";
|
||||
|
||||
export function PreviewCard(props: {
|
||||
src: mastodon.v1.PreviewCard;
|
||||
alwaysCompact?: boolean;
|
||||
}) {
|
||||
let root: HTMLAnchorElement;
|
||||
|
||||
createEffect(() => {
|
||||
if (props.alwaysCompact) {
|
||||
root.classList.add("compact");
|
||||
return;
|
||||
}
|
||||
if (!props.src.width) return;
|
||||
const width = root.getBoundingClientRect().width;
|
||||
if (width > props.src.width) {
|
||||
root.classList.add("compact");
|
||||
} else {
|
||||
root.classList.remove("compact");
|
||||
}
|
||||
});
|
||||
|
||||
const imgAverageColor = createMemo(() => {
|
||||
if (!props.src.image) return;
|
||||
return new Color(averageColorHex(props.src.blurhash));
|
||||
});
|
||||
|
||||
const prefersWhiteText = createMemo(() => {
|
||||
const oc = imgAverageColor();
|
||||
if (!oc) return;
|
||||
const colorWhite = new Color("white");
|
||||
|
||||
return colorWhite.luminance / oc.luminance > 3.5;
|
||||
});
|
||||
|
||||
const focusSurfaceColor = createMemo(() => {
|
||||
const oc = imgAverageColor();
|
||||
if (!oc) return;
|
||||
if (prefersWhiteText()) {
|
||||
return new Color(oc).darken(0.2);
|
||||
} else {
|
||||
return new Color(oc).lighten(0.2);
|
||||
}
|
||||
});
|
||||
|
||||
const textColorName = createMemo(() => {
|
||||
const useWhiteText = prefersWhiteText();
|
||||
if (typeof useWhiteText === "undefined") {
|
||||
return;
|
||||
}
|
||||
return useWhiteText ? "white" : "black";
|
||||
});
|
||||
|
||||
const secondaryTextColor = createMemo(() => {
|
||||
const tcn = textColorName();
|
||||
if (!tcn) return;
|
||||
const tc = new Color(tcn);
|
||||
tc.alpha = 0.75;
|
||||
return tc;
|
||||
});
|
||||
|
||||
return (
|
||||
<a
|
||||
ref={root!}
|
||||
class={"PreviewCard"}
|
||||
href={props.src.url}
|
||||
target="_blank"
|
||||
referrerPolicy="unsafe-url"
|
||||
style={{
|
||||
"--tutu-color-surface": imgAverageColor()?.toString(),
|
||||
"--tutu-color-surface-d": focusSurfaceColor()?.toString(),
|
||||
"--tutu-color-on-surface": textColorName(),
|
||||
"--tutu-color-secondary-text-on-surface":
|
||||
secondaryTextColor()?.toString(),
|
||||
}}
|
||||
>
|
||||
<Show when={props.src.image}>
|
||||
<img
|
||||
crossOrigin="anonymous"
|
||||
src={props.src.image!}
|
||||
width={props.src.width || undefined}
|
||||
height={props.src.height || undefined}
|
||||
loading="lazy"
|
||||
/>
|
||||
</Show>
|
||||
<Title component="h1">{props.src.title}</Title>
|
||||
<Body1 component="p">{props.src.description}</Body1>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export default PreviewCard;
|
Loading…
Add table
Add a link
Reference in a new issue