From 7251b39cc3e3fffdd94120f67208692ca89fbd04 Mon Sep 17 00:00:00 2001
From: mrjvs <jellevs@gmail.com>
Date: Sun, 20 Aug 2023 21:03:59 +0200
Subject: [PATCH] Add media card flare

---
 src/components/media/MediaCard.tsx | 45 +++++++++++++++++-----------
 src/components/utils/Flare.tsx     |  9 +++---
 src/components/utils/Lightbar.css  | 48 ++++++++++++++++++++++++------
 src/components/utils/Lightbar.tsx  |  1 +
 tailwind.config.js                 | 12 ++++++++
 5 files changed, 83 insertions(+), 32 deletions(-)

diff --git a/src/components/media/MediaCard.tsx b/src/components/media/MediaCard.tsx
index 828f6bd7..608458a8 100644
--- a/src/components/media/MediaCard.tsx
+++ b/src/components/media/MediaCard.tsx
@@ -1,9 +1,11 @@
+import c from "classnames";
 import { useTranslation } from "react-i18next";
 import { Link } from "react-router-dom";
 
 import { TMDBMediaToId } from "@/backend/metadata/tmdb";
 import { MWMediaMeta } from "@/backend/metadata/types/mw";
 import { DotList } from "@/components/text/DotList";
+import { Flare } from "@/components/utils/Flare";
 
 import { IconPatch } from "../buttons/IconPatch";
 import { Icons } from "../Icon";
@@ -39,19 +41,27 @@ function MediaCardContent({
   if (media.year) dotListContent.push(media.year);
 
   return (
-    <div
-      className={`group -m-3 mb-2 rounded-xl bg-denim-300 bg-opacity-0 transition-colors duration-100 ${
-        canLink ? "hover:bg-opacity-100" : ""
+    <Flare.Base
+      className={`group -m-3 mb-2 rounded-xl bg-background-main transition-colors duration-100 ${
+        canLink ? "hover:bg-mediaCard-hoverBackground" : ""
       }`}
     >
-      <article
+      <Flare.Light
+        flareSize={300}
+        cssColorVar="--colors-mediaCard-hoverAccent"
+        backgroundClass="bg-mediaCard-hoverBackground duration-100"
+        className={c({
+          "rounded-xl bg-background-main group-hover:opacity-100": canLink,
+        })}
+      />
+      <Flare.Child
         className={`pointer-events-auto relative mb-2 p-3 transition-transform duration-100 ${
           canLink ? "group-hover:scale-95" : ""
         }`}
       >
         <div
           className={[
-            "relative mb-4 aspect-[2/3] w-full overflow-hidden rounded-xl bg-denim-500 bg-cover bg-center transition-[border-radius] duration-100",
+            "relative mb-4 aspect-[2/3] w-full overflow-hidden rounded-xl bg-mediaCard-hoverBackground bg-cover bg-center transition-[border-radius] duration-100",
             closable ? "" : "group-hover:rounded-lg",
           ].join(" ")}
           style={{
@@ -61,13 +71,12 @@ function MediaCardContent({
           {series ? (
             <div
               className={[
-                "absolute right-2 top-2 rounded-md bg-denim-200 px-2 py-1 transition-colors",
-                closable ? "" : "group-hover:bg-denim-500",
+                "absolute right-2 top-2 rounded-md bg-mediaCard-badge px-2 py-1 transition-colors",
               ].join(" ")}
             >
               <p
                 className={[
-                  "text-center text-xs font-bold text-slate-400 transition-colors",
+                  "text-center text-xs font-bold text-mediaCard-badgeText transition-colors",
                   closable ? "" : "group-hover:text-white",
                 ].join(" ")}
               >
@@ -82,19 +91,19 @@ function MediaCardContent({
           {percentage !== undefined ? (
             <>
               <div
-                className={`absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-denim-300 to-transparent transition-colors ${
-                  canLink ? "group-hover:from-denim-100" : ""
+                className={`absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-mediaCard-shadow to-transparent transition-colors ${
+                  canLink ? "group-hover:from-mediaCard-hoverShadow" : ""
                 }`}
               />
               <div
-                className={`absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-denim-300 to-transparent transition-colors ${
-                  canLink ? "group-hover:from-denim-100" : ""
+                className={`absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-mediaCard-shadow to-transparent transition-colors ${
+                  canLink ? "group-hover:from-mediaCard-hoverShadow" : ""
                 }`}
               />
               <div className="absolute inset-x-0 bottom-0 p-3">
-                <div className="relative h-1 overflow-hidden rounded-full bg-denim-600">
+                <div className="relative h-1 overflow-hidden rounded-full bg-mediaCard-barColor">
                   <div
-                    className="absolute inset-y-0 left-0 rounded-full bg-bink-700"
+                    className="absolute inset-y-0 left-0 rounded-full bg-mediaCard-barFillColor"
                     style={{
                       width: percentageString,
                     }}
@@ -105,13 +114,13 @@ function MediaCardContent({
           ) : null}
 
           <div
-            className={`absolute inset-0 flex items-center justify-center bg-denim-200 bg-opacity-80 transition-opacity duration-200 ${
+            className={`absolute inset-0 flex items-center justify-center bg-mediaCard-badge bg-opacity-80 transition-opacity duration-200 ${
               closable ? "opacity-100" : "pointer-events-none opacity-0"
             }`}
           >
             <IconPatch
               clickable
-              className="text-2xl text-slate-400"
+              className="text-2xl text-mediaCard-badgeText"
               onClick={() => closable && onClose?.()}
               icon={Icons.X}
             />
@@ -121,8 +130,8 @@ function MediaCardContent({
           <span>{media.title}</span>
         </h1>
         <DotList className="text-xs" content={dotListContent} />
-      </article>
-    </div>
+      </Flare.Child>
+    </Flare.Base>
   );
 }
 
diff --git a/src/components/utils/Flare.tsx b/src/components/utils/Flare.tsx
index 86ea0bfe..267f4c85 100644
--- a/src/components/utils/Flare.tsx
+++ b/src/components/utils/Flare.tsx
@@ -30,13 +30,14 @@ function Light(props: FlareProps) {
     function mouseMove(e: MouseEvent) {
       if (!outerRef.current) return;
       const rect = outerRef.current.getBoundingClientRect();
+      const halfSize = size / 2;
       outerRef.current.style.setProperty(
         "--bg-x",
-        `${(e.clientX - rect.left - size / 2).toFixed(0)}px`
+        `${(e.clientX - rect.left - halfSize).toFixed(0)}px`
       );
       outerRef.current.style.setProperty(
         "--bg-y",
-        `${(e.clientY - rect.top - size / 2).toFixed(0)}px`
+        `${(e.clientY - rect.top - halfSize).toFixed(0)}px`
       );
     }
     document.addEventListener("mousemove", mouseMove);
@@ -58,13 +59,12 @@ function Light(props: FlareProps) {
         backgroundImage: `radial-gradient(circle at center, rgba(var(${cssVar}), 1), rgba(var(${cssVar}), 0) 70%)`,
         backgroundPosition: `var(--bg-x) var(--bg-y)`,
         backgroundRepeat: "no-repeat",
-        backgroundAttachment: "fixed",
         backgroundSize: `${size.toFixed(0)}px ${size.toFixed(0)}px`,
       }}
     >
       <div
         className={c(
-          "absolute inset-[2px] overflow-hidden",
+          "absolute inset-[1px] overflow-hidden",
           props.className,
           props.backgroundClass
         )}
@@ -75,7 +75,6 @@ function Light(props: FlareProps) {
             background: `radial-gradient(circle at center, rgba(var(${cssVar}), 1), rgba(var(${cssVar}), 0) 70%)`,
             backgroundPosition: `var(--bg-x) var(--bg-y)`,
             backgroundRepeat: "no-repeat",
-            backgroundAttachment: "fixed",
             backgroundSize: `${size.toFixed(0)}px ${size.toFixed(0)}px`,
           }}
         />
diff --git a/src/components/utils/Lightbar.css b/src/components/utils/Lightbar.css
index c49e144f..d2eb265c 100644
--- a/src/components/utils/Lightbar.css
+++ b/src/components/utils/Lightbar.css
@@ -1,11 +1,24 @@
-.lightbar {
-	position: absolute;
-	left: -25vw;
-	top: 0;
-	width: 150vw;
+.lightbar, .lightbar-visual {
+    position: absolute;
+    top: 0;
+    width: 150vw;
     height: 800px;
     pointer-events: none;
     user-select: none;
+}
+
+.lightbar {
+    left: -25vw;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+    --d: 3s;
+    --animation: cubic-bezier(.75,-0.00,.25,1);
+    animation: boot var(--d) var(--animation) forwards;
+}
+
+.lightbar-visual {
+    left: 0;
     --top: theme('colors.background.main');
     --bottom: theme('colors.lightBar.light');
     --first: conic-gradient(from 90deg at 80% 50%,var(--top),var(--bottom));
@@ -19,13 +32,30 @@
     transform: rotate(180deg) translateZ(0px) translateY(400px);
     transform-origin: center center;
     background-repeat: no-repeat;
-	display: flex;
-	justify-content: center;
-	align-items: center;
+    animation: lightbarBoot var(--d) var(--animation) forwards;
 }
 
 .lightbar canvas {
 	width: 40%;
 	height: 300px;
-	transform: translateY(-50%) rotate(180deg);
+	transform: translateY(-250px);
+}
+
+@keyframes boot {
+    from {
+
+        opacity: 0.25;
+    }
+    to {
+        opacity: 1;
+    }
+}
+
+@keyframes lightbarBoot {
+    0% {
+        transform: rotate(180deg) translateZ(0px) translateY(400px) scaleX(0.8);
+    }
+    100% {
+        transform: rotate(180deg) translateZ(0px) translateY(400px) scaleX(1);
+    }
 }
diff --git a/src/components/utils/Lightbar.tsx b/src/components/utils/Lightbar.tsx
index bfcfd592..a1ca0fe6 100644
--- a/src/components/utils/Lightbar.tsx
+++ b/src/components/utils/Lightbar.tsx
@@ -139,6 +139,7 @@ export function Lightbar(props: { className?: string }) {
     <div className={props.className}>
       <div className="lightbar">
         <ParticlesCanvas />
+        <div className="lightbar-visual" />
       </div>
     </div>
   );
diff --git a/tailwind.config.js b/tailwind.config.js
index 7fd185a2..17534fe1 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -83,6 +83,18 @@ module.exports = {
               placeholder: "#4A4A71",
               icon: "#545476",
               text: "#FFFFFF"
+            },
+
+            // media cards
+            mediaCard: {
+              hoverBackground: "#161622",
+              hoverAccent: "#4D79A8",
+              hoverShadow: "#0A0A10",
+              shadow: "#161622",
+              barColor: "#4B4B63",
+              barFillColor: "#BA7FD6",
+              badge: "#151522",
+              badgeText: "#5F5F7A"
             }
           }
         }