feat: add smooth site-wide animations with framer-motion
Local Build and Deploy / deploy (push) Successful in 53s
Local Build and Deploy / deploy (push) Successful in 53s
- Add framer-motion and tailwindcss-animate for transitions - Add page transitions via AnimatePresence in the site layout - Convert nav dropdown and mobile menu to animated motion components - Add entry animation to the radio player widget - Add reveal/stagger animations to the home page views - Add shared motion utilities and reusable animated components
This commit is contained in:
1 parent
ac1b412756
commit
a3b077c488
13 files changed
+624
-142
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import type { ReactNode } from "react";
|
||||
import MotionPageWrapper from "@/components/motion-page-wrapper";
|
||||
import { Navigation } from "@/components/navigation";
|
||||
import RadioPlayerGate from "@/components/public/radio-player-gate";
|
||||
import { SiteFooter } from "@/components/site-footer";
|
||||
@@ -17,7 +18,9 @@ export default function SiteLayout({ children }: { children: ReactNode }) {
|
||||
<Navigation />
|
||||
<main>
|
||||
<div className="mx-auto mt-6 grid max-w-7xl grid-cols-12 gap-x-3 gap-y-6 px-4 py-4 md:mt-0 md:p-6">
|
||||
<div className="col-span-12 min-w-0">{children}</div>
|
||||
<div className="col-span-12 min-w-0">
|
||||
<MotionPageWrapper>{children}</MotionPageWrapper>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<SiteFooter />
|
||||
|
||||
+92
-24
@@ -1,6 +1,7 @@
|
||||
@import "tailwindcss";
|
||||
@plugin "@tailwindcss/forms";
|
||||
@plugin "@tailwindcss/typography";
|
||||
@plugin "tailwindcss-animate";
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
@theme {
|
||||
@@ -270,7 +271,6 @@ html.dark body.site-bg:has([data-admin]) {
|
||||
background-blend-mode: normal;
|
||||
}
|
||||
|
||||
|
||||
.article-body {
|
||||
line-height: 1.7;
|
||||
}
|
||||
@@ -382,7 +382,11 @@ a:hover {
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.18s ease;
|
||||
background: color-mix(in srgb, var(--color-text-muted) 14%, var(--color-surface));
|
||||
background: color-mix(
|
||||
in srgb,
|
||||
var(--color-text-muted) 14%,
|
||||
var(--color-surface)
|
||||
);
|
||||
color: var(--color-text-readable, var(--color-text));
|
||||
text-decoration: none;
|
||||
}
|
||||
@@ -642,8 +646,16 @@ tbody tr:hover {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
background: var(--color-surface);
|
||||
color: var(--color-surface-text-readable, var(--color-text-readable, var(--color-text)));
|
||||
border: 1px solid color-mix(in srgb, var(--color-text-muted-readable, var(--color-text-muted)) 12%, transparent);
|
||||
color: var(
|
||||
--color-surface-text-readable,
|
||||
var(--color-text-readable, var(--color-text))
|
||||
);
|
||||
border: 1px solid
|
||||
color-mix(
|
||||
in srgb,
|
||||
var(--color-text-muted-readable, var(--color-text-muted)) 12%,
|
||||
transparent
|
||||
);
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: var(--shadow-card);
|
||||
overflow: hidden;
|
||||
@@ -663,7 +675,11 @@ tbody tr:hover {
|
||||
color-mix(in srgb, var(--color-primary) 5%, var(--color-surface))
|
||||
);
|
||||
border-bottom: 1px solid
|
||||
color-mix(in srgb, var(--color-text-muted-readable, var(--color-text-muted)) 8%, transparent);
|
||||
color-mix(
|
||||
in srgb,
|
||||
var(--color-text-muted-readable, var(--color-text-muted)) 8%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
.content-card-icon {
|
||||
flex: none;
|
||||
@@ -690,7 +706,10 @@ tbody tr:hover {
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
line-height: 1.3;
|
||||
color: var(--color-surface-text-readable, var(--color-text-readable, var(--color-text)));
|
||||
color: var(
|
||||
--color-surface-text-readable,
|
||||
var(--color-text-readable, var(--color-text))
|
||||
);
|
||||
}
|
||||
.content-card-subtitle {
|
||||
margin: 0.15rem 0 0;
|
||||
@@ -740,7 +759,12 @@ tbody tr:hover {
|
||||
}
|
||||
.stat-block {
|
||||
background: var(--color-background);
|
||||
border: 1px solid color-mix(in srgb, var(--color-text-muted-readable, var(--color-text-muted)) 12%, transparent);
|
||||
border: 1px solid
|
||||
color-mix(
|
||||
in srgb,
|
||||
var(--color-text-muted-readable, var(--color-text-muted)) 12%,
|
||||
transparent
|
||||
);
|
||||
border-radius: 12px;
|
||||
padding: 0.85rem 1rem;
|
||||
text-align: center;
|
||||
@@ -776,7 +800,11 @@ tbody tr:hover {
|
||||
font-weight: 700;
|
||||
padding: 0.1rem 0.55rem 0.1rem 0.45rem;
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--color-text-muted-readable, var(--color-text-muted)) 14%, transparent);
|
||||
background: color-mix(
|
||||
in srgb,
|
||||
var(--color-text-muted-readable, var(--color-text-muted)) 14%,
|
||||
transparent
|
||||
);
|
||||
color: var(--color-text-muted-readable, var(--color-text-muted));
|
||||
}
|
||||
.online-badge.online {
|
||||
@@ -806,7 +834,12 @@ tbody tr:hover {
|
||||
font-weight: 800;
|
||||
font-size: 0.95rem;
|
||||
background: var(--color-background);
|
||||
border: 1px solid color-mix(in srgb, var(--color-text-muted-readable, var(--color-text-muted)) 18%, transparent);
|
||||
border: 1px solid
|
||||
color-mix(
|
||||
in srgb,
|
||||
var(--color-text-muted-readable, var(--color-text-muted)) 18%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
.rank-badge.rank-1 {
|
||||
background: color-mix(in srgb, var(--color-warning) 20%, transparent);
|
||||
@@ -852,7 +885,11 @@ tbody tr:hover {
|
||||
gap: 0.25rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 1px solid
|
||||
color-mix(in srgb, var(--color-text-muted-readable, var(--color-text-muted)) 14%, transparent);
|
||||
color-mix(
|
||||
in srgb,
|
||||
var(--color-text-muted-readable, var(--color-text-muted)) 14%,
|
||||
transparent
|
||||
);
|
||||
overflow-x: auto;
|
||||
}
|
||||
.radio-sidebar-head {
|
||||
@@ -917,7 +954,11 @@ tbody tr:hover {
|
||||
position: relative;
|
||||
width: min(440px, 100%);
|
||||
border: 1px solid
|
||||
color-mix(in srgb, var(--color-primary) 30%, color-mix(in srgb, var(--color-text-muted) 22%, transparent));
|
||||
color-mix(
|
||||
in srgb,
|
||||
var(--color-primary) 30%,
|
||||
color-mix(in srgb, var(--color-text-muted) 22%, transparent)
|
||||
);
|
||||
border-radius: 8px;
|
||||
background:
|
||||
linear-gradient(
|
||||
@@ -927,7 +968,10 @@ tbody tr:hover {
|
||||
),
|
||||
var(--color-surface);
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.34);
|
||||
color: var(--color-surface-text-readable, var(--color-text-readable, var(--color-text)));
|
||||
color: var(
|
||||
--color-surface-text-readable,
|
||||
var(--color-text-readable, var(--color-text))
|
||||
);
|
||||
padding: 1.25rem;
|
||||
}
|
||||
.cms-info-close {
|
||||
@@ -938,7 +982,12 @@ tbody tr:hover {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
place-items: center;
|
||||
border: 1px solid color-mix(in srgb, var(--color-text-muted-readable, var(--color-text-muted)) 18%, transparent);
|
||||
border: 1px solid
|
||||
color-mix(
|
||||
in srgb,
|
||||
var(--color-text-muted-readable, var(--color-text-muted)) 18%,
|
||||
transparent
|
||||
);
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--color-surface) 84%, transparent);
|
||||
color: var(--color-text-muted-readable, var(--color-text-muted));
|
||||
@@ -947,7 +996,10 @@ tbody tr:hover {
|
||||
line-height: 1;
|
||||
}
|
||||
.cms-info-close:hover {
|
||||
color: var(--color-surface-text-readable, var(--color-text-readable, var(--color-text)));
|
||||
color: var(
|
||||
--color-surface-text-readable,
|
||||
var(--color-text-readable, var(--color-text))
|
||||
);
|
||||
border-color: color-mix(in srgb, var(--color-primary) 40%, transparent);
|
||||
}
|
||||
.cms-info-kicker {
|
||||
@@ -970,7 +1022,10 @@ tbody tr:hover {
|
||||
border: 1px solid color-mix(in srgb, var(--color-primary) 34%, transparent);
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--color-primary) 14%, transparent);
|
||||
color: var(--color-surface-text-readable, var(--color-text-readable, var(--color-text)));
|
||||
color: var(
|
||||
--color-surface-text-readable,
|
||||
var(--color-text-readable, var(--color-text))
|
||||
);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 900;
|
||||
padding: 0.3rem 0.6rem;
|
||||
@@ -988,7 +1043,12 @@ tbody tr:hover {
|
||||
margin: 1rem 0 0;
|
||||
}
|
||||
.cms-info-grid div {
|
||||
border: 1px solid color-mix(in srgb, var(--color-text-muted-readable, var(--color-text-muted)) 14%, transparent);
|
||||
border: 1px solid
|
||||
color-mix(
|
||||
in srgb,
|
||||
var(--color-text-muted-readable, var(--color-text-muted)) 14%,
|
||||
transparent
|
||||
);
|
||||
border-radius: 8px;
|
||||
background: color-mix(in srgb, var(--color-background) 68%, transparent);
|
||||
padding: 0.7rem;
|
||||
@@ -1001,7 +1061,10 @@ tbody tr:hover {
|
||||
}
|
||||
.cms-info-grid dd {
|
||||
margin: 0.18rem 0 0;
|
||||
color: var(--color-surface-text-readable, var(--color-text-readable, var(--color-text)));
|
||||
color: var(
|
||||
--color-surface-text-readable,
|
||||
var(--color-text-readable, var(--color-text))
|
||||
);
|
||||
font-size: 0.8rem;
|
||||
font-weight: 900;
|
||||
line-height: 1.25;
|
||||
@@ -1022,7 +1085,10 @@ tbody tr:hover {
|
||||
padding: 0.65rem 0.75rem;
|
||||
}
|
||||
.cms-info-credit span {
|
||||
color: var(--color-surface-text-readable, var(--color-text-readable, var(--color-text)));
|
||||
color: var(
|
||||
--color-surface-text-readable,
|
||||
var(--color-text-readable, var(--color-text))
|
||||
);
|
||||
font-weight: 900;
|
||||
}
|
||||
.cms-info-credit small {
|
||||
@@ -1174,9 +1240,10 @@ body:has([data-admin]) {
|
||||
}
|
||||
|
||||
/* Admin forms / boxes follow admin tokens in both light and dark. */
|
||||
body:has([data-admin]) input:not([type="checkbox"]):not([type="radio"]):not(
|
||||
[type="range"]
|
||||
):not([type="file"]):not([type="color"]),
|
||||
body:has([data-admin])
|
||||
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not(
|
||||
[type="file"]
|
||||
):not([type="color"]),
|
||||
body:has([data-admin]) select,
|
||||
body:has([data-admin]) textarea {
|
||||
background-color: var(--admin-surface-elevated);
|
||||
@@ -1210,9 +1277,10 @@ body:has([data-admin]) .btn-outline:hover {
|
||||
color: var(--admin-text);
|
||||
}
|
||||
/* Override public html.dark input hardcodes inside admin. */
|
||||
html.dark body:has([data-admin]) input:not([type="checkbox"]):not(
|
||||
[type="radio"]
|
||||
):not([type="range"]):not([type="file"]):not([type="color"]),
|
||||
html.dark body:has([data-admin])
|
||||
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not(
|
||||
[type="file"]
|
||||
):not([type="color"]),
|
||||
html.dark body:has([data-admin]) select,
|
||||
html.dark body:has([data-admin]) textarea {
|
||||
background: var(--admin-surface-elevated);
|
||||
|
||||
Reference in new issue
Block a user