feat: Add Image and Link components

This commit is contained in:
Gauthier Daniels 2025-04-19 14:08:54 +02:00
parent 67140bb47e
commit da5b2a1c23
6 changed files with 94 additions and 48 deletions

3
app/bun.lock Executable file → Normal file
View File

@ -7,6 +7,7 @@
"@fastify/static": "^8.1.1", "@fastify/static": "^8.1.1",
"@universal-middleware/core": "^0.4.7", "@universal-middleware/core": "^0.4.7",
"@universal-middleware/fastify": "^0.5.16", "@universal-middleware/fastify": "^0.5.16",
"clsx": "^2.1.1",
"fastify": "^5.3.0", "fastify": "^5.3.0",
"solid-js": "^1.9.5", "solid-js": "^1.9.5",
"telefunc": "^0.2.3", "telefunc": "^0.2.3",
@ -369,6 +370,8 @@
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
"code-block-writer": ["code-block-writer@12.0.0", "", {}, "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w=="], "code-block-writer": ["code-block-writer@12.0.0", "", {}, "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],

18
app/components/Image.tsx Normal file
View File

@ -0,0 +1,18 @@
import type { JSX } from "solid-js";
type ImageProps = JSX.IntrinsicElements["img"] & { src: string; alt: string };
export function Image(props: ImageProps) {
const isDecorationImage = props.alt === "";
return (
<img
{...props}
src={props.src}
role={isDecorationImage ? "presentation" : "img"}
aria-hidden={isDecorationImage ? "true" : undefined}
alt={isDecorationImage ? undefined : props.alt}
loading="lazy"
/>
);
}

View File

@ -1,14 +1,35 @@
import { createMemo } from "solid-js"; import type { JSX } from "solid-js";
import { usePageContext } from "vike-solid/usePageContext"; import { usePageContext } from "vike-solid/usePageContext";
export function Link(props: { href: string; children: string }) { type LinkProps = JSX.IntrinsicElements["a"] & { href: string };
const pageContext = usePageContext();
const isActive = createMemo(() => export function Link(props: LinkProps) {
props.href === "/" ? pageContext.urlPathname === props.href : pageContext.urlPathname.startsWith(props.href), const { urlPathname } = usePageContext();
);
return ( const isActive =
<a href={props.href} class={isActive() ? "is-active" : undefined}> props.href === "/"
{props.children} ? urlPathname === props.href
</a> : urlPathname.startsWith(props.href);
);
const isSameDomain = !(
props.href.startsWith("http") || props.href.startsWith("mailto")
);
const downloadExtensions = [".pdf", ".zip"];
const isDownload = downloadExtensions.some(props.href.endsWith);
return (
<a
{...props}
{...(isActive && { ariaCurrent: "page" })}
{...(isDownload && { download: true })}
{...(!isSameDomain || isDownload
? { target: "_blank", rel: "noopener noreferrer" }
: { target: "_self" })}
>
{props.children}
</a>
);
} }

View File

@ -8,15 +8,16 @@
"format": "biome format --write ." "format": "biome format --write ."
}, },
"dependencies": { "dependencies": {
"vike": "^0.4.228",
"@fastify/middie": "^9.0.3", "@fastify/middie": "^9.0.3",
"@fastify/static": "^8.1.1", "@fastify/static": "^8.1.1",
"@universal-middleware/fastify": "^0.5.16",
"fastify": "^5.3.0",
"@universal-middleware/core": "^0.4.7", "@universal-middleware/core": "^0.4.7",
"@universal-middleware/fastify": "^0.5.16",
"clsx": "^2.1.1",
"fastify": "^5.3.0",
"solid-js": "^1.9.5", "solid-js": "^1.9.5",
"vike-solid": "^0.7.9", "telefunc": "^0.2.3",
"telefunc": "^0.2.3" "vike": "^0.4.228",
"vike-solid": "^0.7.9"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "1.9.4", "@biomejs/biome": "1.9.4",

View File

@ -1,28 +1,23 @@
{ {
"compilerOptions": { "compilerOptions": {
"strict": true, "strict": true,
"esModuleInterop": true, "esModuleInterop": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"skipLibCheck": true, "skipLibCheck": true,
"sourceMap": true, "sourceMap": true,
"module": "ESNext", "module": "ESNext",
"noEmit": true, "noEmit": true,
"moduleResolution": "Bundler", "moduleResolution": "Bundler",
"target": "ES2022", "target": "ES2022",
"lib": [ "lib": ["DOM", "DOM.Iterable", "ESNext"],
"DOM", "types": ["vite/client", "vike-solid/client"],
"DOM.Iterable", "jsx": "react-jsx",
"ESNext" "jsxImportSource": "solid-js",
], "baseUrl": ".",
"types": [ "paths": {
"vite/client", "@/*": ["./*"]
"vike-solid/client" }
], },
"jsx": "react-jsx", "exclude": ["dist"]
"jsxImportSource": "solid-js"
},
"exclude": [
"dist"
]
} }

View File

@ -1,12 +1,20 @@
import { telefunc } from "telefunc/vite";
import tailwindcss from "@tailwindcss/vite"; import tailwindcss from "@tailwindcss/vite";
import { telefunc } from "telefunc/vite";
import vikeSolid from "vike-solid/vite"; import vikeSolid from "vike-solid/vite";
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import vike from "vike/plugin"; import vike from "vike/plugin";
import path from "node:path";
const __dirname = path.resolve();
export default defineConfig({ export default defineConfig({
plugins: [vike(), vikeSolid(), tailwindcss(), telefunc()], plugins: [vike(), vikeSolid(), tailwindcss(), telefunc()],
build: { build: {
target: "es2022", target: "es2022",
}, },
resolve: {
alias: {
"@": __dirname,
},
},
}); });