mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-12 16:55:37 +02:00
🐛 fix: Use mute card colors
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { component$, useSignal, useVisibleTask$, $ } from "@builder.io/qwik";
|
import { component$ } from "@builder.io/qwik";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
game: {
|
game: {
|
||||||
@@ -9,87 +9,25 @@ type Props = {
|
|||||||
|
|
||||||
export const Card = component$(({ game }: Props) => {
|
export const Card = component$(({ game }: Props) => {
|
||||||
const imageUrl = `http://localhost:8787/image/cover/${game.id}.avif`
|
const imageUrl = `http://localhost:8787/image/cover/${game.id}.avif`
|
||||||
const backgroundColor = useSignal<string | undefined>(undefined);
|
|
||||||
const imgRef = useSignal<HTMLImageElement>();
|
|
||||||
|
|
||||||
const extractColor = $((img: HTMLImageElement) => {
|
|
||||||
const canvas = document.createElement('canvas');
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
if (!ctx) return "rgb(200,200,200)"; // Fallback light gray
|
|
||||||
|
|
||||||
canvas.width = img.naturalWidth;
|
|
||||||
canvas.height = img.naturalHeight;
|
|
||||||
ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight);
|
|
||||||
|
|
||||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
|
|
||||||
let r = 0, g = 0, b = 0, count = 0;
|
|
||||||
|
|
||||||
for (let i = 0; i < imageData.length; i += 4) {
|
|
||||||
// Only consider brighter pixels
|
|
||||||
if (imageData[i] > 150 || imageData[i + 1] > 150 || imageData[i + 2] > 150) {
|
|
||||||
r += imageData[i];
|
|
||||||
g += imageData[i + 1];
|
|
||||||
b += imageData[i + 2];
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count === 0) return "rgb(200,200,200)"; // Fallback if no bright pixels found
|
|
||||||
|
|
||||||
r = Math.floor(r / count);
|
|
||||||
g = Math.floor(g / count);
|
|
||||||
b = Math.floor(b / count);
|
|
||||||
|
|
||||||
|
|
||||||
// For light mode, keep the existing logic
|
|
||||||
const minBrightness = 100;
|
|
||||||
r = Math.max(r, minBrightness);
|
|
||||||
g = Math.max(g, minBrightness);
|
|
||||||
b = Math.max(b, minBrightness);
|
|
||||||
|
|
||||||
|
|
||||||
return `rgb(${r},${g},${b})`;
|
|
||||||
});
|
|
||||||
|
|
||||||
useVisibleTask$(async ({ track }) => {
|
|
||||||
track(() => imgRef.value);
|
|
||||||
|
|
||||||
const img = imgRef.value;
|
|
||||||
if (img) {
|
|
||||||
const processImage = async () => {
|
|
||||||
backgroundColor.value = await extractColor(img);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (img.complete) {
|
|
||||||
await processImage();
|
|
||||||
} else {
|
|
||||||
img.onload = processImage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<button
|
||||||
style={{
|
class="min-w-[250px] group hover:ring-primary-500 focus:ring-primary-500 outline-none cursor-pointer backdrop-blur-sm select-none w-full group rounded-[20px] duration-200 flex flex-col ring-gray-900/70 transition-all gap-2 px-4 py-3 ring-[3px] ring-neutral-300 dark:ring-gray-700 text-gray-900/70 dark:text-gray-100/70 bg-gray-300/70 dark:bg-gray-700/70">
|
||||||
"--bg-color": backgroundColor.value,
|
<header class="flex gap-4 max-w-full justify-between p-4">
|
||||||
}}
|
|
||||||
class="min-w-[250px] bg-[--bg-color] group cursor-pointer backdrop-blur-sm select-none w-full group rounded-3xl text-primary-950/70 duration-200 transition-colors flex flex-col">
|
|
||||||
<header class="flex gap-4 justify-between p-4">
|
|
||||||
<div class="flex relative pr-[22px] overflow-hidden overflow-ellipsis whitespace-nowrap" >
|
<div class="flex relative pr-[22px] overflow-hidden overflow-ellipsis whitespace-nowrap" >
|
||||||
<h3 class="overflow-hidden overflow-ellipsis whitespace-nowrap">{game.name}</h3>
|
<h3 class="overflow-hidden overflow-ellipsis whitespace-nowrap">{game.name}</h3>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<section class="flex justify-center items-center w-full py-7">
|
<section class="flex justify-center items-center w-full py-7">
|
||||||
<img
|
<img
|
||||||
ref={imgRef}
|
|
||||||
src={imageUrl}
|
src={imageUrl}
|
||||||
class="rounded-2xl ring-2 aspect-[2/3] w-full max-w-[90%] ring-gray-900/70 group-hover:scale-105 duration-200 transition-transform shadow-2xl shadow-gray-900"
|
class="rounded-2xl ring-2 aspect-[2/3] w-full max-w-[90%] ring-gray-900/70 group-hover:scale-105 group-focus:scale-105 duration-200 transition-transform shadow-2xl shadow-gray-950"
|
||||||
width={250}
|
width={250}
|
||||||
height={200}
|
height={200}
|
||||||
alt={game.name}
|
alt={game.name}
|
||||||
crossOrigin="anonymous"
|
crossOrigin="anonymous"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</button>
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@@ -29,13 +29,13 @@ export const HomeNavBar = component$(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="relative flex items-center">
|
<div class="relative flex items-center">
|
||||||
<hr class="w-[1px] h-7 bg-neutral-700 dark:bg-neutral-300 mx-3 rotate-[16deg]" />
|
<hr class="w-[1px] h-7 bg-neutral-700 dark:bg-neutral-300 mx-3 rotate-[16deg]" />
|
||||||
<button class="rounded-full transition-all flex items-center duration-200 px-3 h-8 gap-2 select-none cursor-pointer hover:bg-neutral-300/70 dark:hover:bg-neutral-700/70" >
|
<button class="rounded-full outline-none focus:ring-primary-500 focus:ring-2 transition-all flex items-center duration-200 px-3 h-8 gap-2 select-none cursor-pointer hover:bg-neutral-300/70 dark:hover:bg-neutral-700/70" >
|
||||||
<img src="http://localhost:8787/image/avatar/the-avengers.png" height={16} width={16} class="size-4 rounded-full" alt="Avatar" />
|
<img src="http://localhost:8787/image/avatar/the-avengers.png" height={16} width={16} class="size-4 rounded-full" alt="Avatar" />
|
||||||
<p class="whitespace-nowrap [text-overflow:ellipsis] overflow-hidden max-w-[20ch]">The Avengers</p>
|
<p class="whitespace-nowrap [text-overflow:ellipsis] overflow-hidden max-w-[20ch]">The Avengers</p>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width={16} height={16} viewBox="0 0 21 21"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m7.5 8.5l3-3l3 3m-6 5l3 3l3-3" /></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width={16} height={16} viewBox="0 0 21 21"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m7.5 8.5l3-3l3 3m-6 5l3 3l3-3" /></svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button class="ml-auto rounded-full transition-all flex items-center duration-200 px-3 h-8 gap-1 select-none cursor-pointer hover:bg-gray-300/70 dark:hover:bg-gray-700/70" >
|
<button class="ml-auto focus:ring-primary-500 focus:ring-2 outline-none rounded-full transition-all flex items-center duration-200 px-3 h-8 gap-1 select-none cursor-pointer hover:bg-gray-300/70 dark:hover:bg-gray-700/70" >
|
||||||
<img src="http://localhost:8787/image/avatar/wanjohi.png" height={16} width={16} class="size-4 rounded-full" alt="Avatar" />
|
<img src="http://localhost:8787/image/avatar/wanjohi.png" height={16} width={16} class="size-4 rounded-full" alt="Avatar" />
|
||||||
<p class="whitespace-nowrap [text-overflow:ellipsis] overflow-hidden max-w-[20ch]">Wanjohi</p>
|
<p class="whitespace-nowrap [text-overflow:ellipsis] overflow-hidden max-w-[20ch]">Wanjohi</p>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width={16} height={16} viewBox="0 0 21 21"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m7.5 8.5l3-3l3 3m-6 5l3 3l3-3" /></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width={16} height={16} viewBox="0 0 21 21"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m7.5 8.5l3-3l3 3m-6 5l3 3l3-3" /></svg>
|
||||||
|
|||||||
0
packages/ui/src/large-card.tsx
Normal file
0
packages/ui/src/large-card.tsx
Normal file
Reference in New Issue
Block a user