feat: use srcset/sizes for all images
This commit is contained in:
parent
0acbbd6905
commit
0eb8ebdd16
@ -1,5 +1,34 @@
|
|||||||
import { asset } from "$fresh/runtime.ts";
|
import { asset } from "$fresh/runtime.ts";
|
||||||
import * as CSS from "https://esm.sh/csstype@3.1.2";
|
import * as CSS from "https://esm.sh/csstype@3.1.2";
|
||||||
|
import { isLocalImage } from "@lib/string.ts";
|
||||||
|
|
||||||
|
interface ResponsiveAttributes {
|
||||||
|
srcset: string;
|
||||||
|
sizes: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateResponsiveAttributes(
|
||||||
|
imageUrl: string,
|
||||||
|
widths: number[],
|
||||||
|
baseApiUrl: string,
|
||||||
|
sizes = "100vw",
|
||||||
|
): ResponsiveAttributes {
|
||||||
|
const srcsets: string[] = [];
|
||||||
|
|
||||||
|
for (const width of widths) {
|
||||||
|
const apiUrl = `${baseApiUrl}?image=${imageUrl}&width=${width}`;
|
||||||
|
srcsets.push(`${apiUrl} ${width}w`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const srcset = srcsets.join(", ");
|
||||||
|
|
||||||
|
return {
|
||||||
|
srcset,
|
||||||
|
sizes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const widths = [320, 640, 960, 1280]; // List of widths for srcset
|
||||||
|
|
||||||
const Image = (
|
const Image = (
|
||||||
props: {
|
props: {
|
||||||
@ -12,6 +41,12 @@ const Image = (
|
|||||||
style?: CSS.HtmlAttributes;
|
style?: CSS.HtmlAttributes;
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
|
const responsiveAttributes: ResponsiveAttributes = isLocalImage(props.src)
|
||||||
|
? generateResponsiveAttributes(props.src, widths, "/api/images")
|
||||||
|
: { srcset: "", sizes: "" };
|
||||||
|
|
||||||
|
console.log({ src: props.src, responsiveAttributes });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
@ -28,6 +63,8 @@ const Image = (
|
|||||||
loading="lazy"
|
loading="lazy"
|
||||||
alt={props.alt}
|
alt={props.alt}
|
||||||
style={props.style}
|
style={props.style}
|
||||||
|
srcset={responsiveAttributes.srcset}
|
||||||
|
sizes={responsiveAttributes.sizes}
|
||||||
src={asset(props.src)}
|
src={asset(props.src)}
|
||||||
width={props.width}
|
width={props.width}
|
||||||
height={props.height}
|
height={props.height}
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
IconEdit,
|
IconEdit,
|
||||||
IconExternalLink,
|
IconExternalLink,
|
||||||
} from "@components/icons.tsx";
|
} from "@components/icons.tsx";
|
||||||
import { isLocalImage } from "@lib/string.ts";
|
|
||||||
import Image from "@components/Image.tsx";
|
import Image from "@components/Image.tsx";
|
||||||
|
|
||||||
export function RecipeHero(
|
export function RecipeHero(
|
||||||
@ -20,20 +19,16 @@ export function RecipeHero(
|
|||||||
) {
|
) {
|
||||||
const { meta: { image } = {} } = data;
|
const { meta: { image } = {} } = data;
|
||||||
|
|
||||||
const imageUrl = (image && isLocalImage(image))
|
|
||||||
? `/api/images?image=${image}&width=800`
|
|
||||||
: image;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={`flex justify-between flex-col relative w-full min-h-[${
|
class={`flex justify-between flex-col relative w-full min-h-[${
|
||||||
imageUrl ? 400 : 200
|
image ? 400 : 200
|
||||||
}px] rounded-3xl overflow-hidden`}
|
}px] rounded-3xl overflow-hidden`}
|
||||||
>
|
>
|
||||||
{imageUrl &&
|
{image &&
|
||||||
(
|
(
|
||||||
<Image
|
<Image
|
||||||
src={imageUrl}
|
src={image}
|
||||||
thumbnail={data.meta?.thumbnail}
|
thumbnail={data.meta?.thumbnail}
|
||||||
alt="Recipe Banner"
|
alt="Recipe Banner"
|
||||||
style={{ objectPosition: "0% 25%" }}
|
style={{ objectPosition: "0% 25%" }}
|
||||||
@ -52,7 +47,7 @@ export function RecipeHero(
|
|||||||
(
|
(
|
||||||
<a
|
<a
|
||||||
class={`px-4 py-2 ${
|
class={`px-4 py-2 ${
|
||||||
imageUrl ? "bg-gray-300 text-gray-800" : "text-gray-200"
|
image ? "bg-gray-300 text-gray-800" : "text-gray-200"
|
||||||
} rounded-lg flex gap-1 items-center`}
|
} rounded-lg flex gap-1 items-center`}
|
||||||
href={editLink}
|
href={editLink}
|
||||||
>
|
>
|
||||||
@ -62,18 +57,16 @@ export function RecipeHero(
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`relative inset-x-0 py-4 px-8 ${imageUrl ? "py-8" : ""} `}
|
class={`relative inset-x-0 py-4 px-8 ${image ? "py-8" : ""} `}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class={`${
|
class={`${
|
||||||
imageUrl ? "noisy-gradient" : ""
|
image ? "noisy-gradient" : ""
|
||||||
} after:opacity-90 flex gap-4 items-center ${
|
} after:opacity-90 flex gap-4 items-center ${image ? "pt-12" : ""}`}
|
||||||
imageUrl ? "pt-12" : ""
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<h2
|
<h2
|
||||||
class="relative text-4xl font-bold z-10"
|
class="relative text-4xl font-bold z-10"
|
||||||
style={{ color: imageUrl ? "#1F1F1F" : "white" }}
|
style={{ color: image ? "#1F1F1F" : "white" }}
|
||||||
>
|
>
|
||||||
{data.name}
|
{data.name}
|
||||||
{data.meta?.link &&
|
{data.meta?.link &&
|
||||||
@ -95,7 +88,7 @@ export function RecipeHero(
|
|||||||
(
|
(
|
||||||
<div
|
<div
|
||||||
class={`relative z-50 flex gap-5 font-sm text-light mt-3`}
|
class={`relative z-50 flex gap-5 font-sm text-light mt-3`}
|
||||||
style={{ color: imageUrl ? "#1F1F1F" : "white" }}
|
style={{ color: image ? "#1F1F1F" : "white" }}
|
||||||
>
|
>
|
||||||
{subline.filter((s) => s && s?.length > 1).map((s) => {
|
{subline.filter((s) => s && s?.length > 1).map((s) => {
|
||||||
return <span>{s}</span>;
|
return <span>{s}</span>;
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 936 KiB After Width: | Height: | Size: 15 KiB |
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user