Skip to content

Commit a810bbb

Browse files
authored
style: refine site motion and branding (#75)
1 parent 830d2b5 commit a810bbb

9 files changed

Lines changed: 106 additions & 30 deletions

File tree

‎app/blog/[slug]/page.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export default async function BlogPostPage({ params }: BlogPostPageProps) {
6666

6767
return (
6868
<main className="relative flex-1">
69-
<article className="border-y border-border text-foreground">
69+
<article className="border-b border-border text-foreground">
7070
<header className="mx-auto max-w-7xl px-4 py-12 sm:px-6 sm:py-16 lg:px-8">
7171
<div className="pt-8">
7272
<Link

‎app/globals.css‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,18 +280,41 @@
280280
.motion-reveal[data-motion-delay="3"] {
281281
animation-delay: 210ms;
282282
}
283+
284+
[data-scroll-reveal] {
285+
transition-duration: 640ms;
286+
transition-property: opacity, transform;
287+
transition-timing-function: var(--motion-ease-emphasized);
288+
}
289+
290+
[data-scroll-reveal="pending"] {
291+
opacity: 0;
292+
transform: translate3d(0, 18px, 0);
293+
will-change: opacity, transform;
294+
}
295+
296+
[data-scroll-reveal="visible"] {
297+
opacity: 1;
298+
transform: none;
299+
will-change: auto;
300+
}
283301
}
284302

285303
@media (prefers-reduced-motion: reduce) {
286304
.motion-button,
287305
.motion-card,
288306
.motion-icon-tile,
289307
.motion-arrow,
290-
.motion-reveal {
308+
.motion-reveal,
309+
[data-scroll-reveal] {
291310
animation: none !important;
292311
transform: none !important;
293312
transition: none !important;
294313
}
314+
315+
[data-scroll-reveal="pending"] {
316+
opacity: 1 !important;
317+
}
295318
}
296319

297320
@keyframes motion-reveal {

‎app/layout.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import AppHeader from '@/components/business/app-header';
88
import FixedContactButton from '@/components/business/buttons/fixed-contact-button';
99
import { CookieConsentProvider } from '@/components/business/cookie-consent';
1010
import FixedLanguageBanner from '@/components/business/fixed-language-banner';
11+
import SiteScrollMotion from '@/components/business/site-scroll-motion';
1112
import SkipLink from '@/components/business/skip-link';
1213
import BackgroundGrid from '@/components/ui/background-grid';
1314
import "./globals.css";
@@ -88,6 +89,7 @@ export default async function RootLayout({
8889
<BackgroundGrid />
8990
<FixedLanguageBanner />
9091
<AppHeader />
92+
<SiteScrollMotion />
9193
<div
9294
id="main-content"
9395
tabIndex={-1}

‎components/business/app-header.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,15 @@ export default function AppHeader() {
194194
>
195195
<div className="px-2 pb-2 text-xs font-semibold uppercase text-muted-foreground">Product</div>
196196
{productNavigation.map((item) => (
197-
<a key={item.title} className="block w-full p-2 text-sm hover:bg-muted/50" href={item.href}>{item.title}</a>
197+
<a key={item.title} className="block w-full p-2 text-base hover:bg-muted/50" href={item.href}>{item.title}</a>
198198
))}
199199
<div className="mt-3 px-2 pb-2 text-xs font-semibold uppercase text-muted-foreground">Resources</div>
200200
{resourceNavigation.map((item) => (
201-
<a key={item.title} className="block w-full p-2 text-sm hover:bg-muted/50" href={item.href}>{item.title}</a>
201+
<a key={item.title} className="block w-full p-2 text-base hover:bg-muted/50" href={item.href}>{item.title}</a>
202202
))}
203203
<div className="mt-3 px-2 pb-2 text-xs font-semibold uppercase text-muted-foreground">Links</div>
204204
{navs.map((item, index) => (
205-
<a key={index} className="block w-full p-2 text-sm hover:bg-muted/50" href={item.url}>{item.label}</a>
205+
<a key={index} className="block w-full p-2 text-base hover:bg-muted/50" href={item.url}>{item.label}</a>
206206
))}
207207
</Popover.Panel>
208208
</Transition>

‎components/business/home-multi-clouds.tsx‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ export default function HomeMultiClouds() {
4242
className="motion-card group flex min-h-[30rem] flex-col bg-card transition-colors hover:bg-muted/20 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"
4343
aria-label={stories[0].linkText}
4444
>
45-
<div className="relative flex h-60 shrink-0 items-center overflow-hidden bg-background p-8 sm:p-10">
45+
<div className="relative flex h-60 shrink-0 items-center justify-center overflow-hidden bg-background p-8 sm:p-10">
4646
<div
4747
aria-hidden="true"
4848
className="absolute inset-0 opacity-50 [background-image:linear-gradient(90deg,var(--border)_1px,transparent_1px),linear-gradient(0deg,var(--border)_1px,transparent_1px)] [background-size:34px_34px]"
4949
/>
5050
<Image
51-
src="/images/brands/nvidia-inception-badge.webp"
52-
alt="NVIDIA Inception Program member"
53-
width={494}
54-
height={198}
51+
src="/images/nvidia-inception-program-badge.png"
52+
alt="NVIDIA Inception Program member badge"
53+
width={501}
54+
height={217}
5555
unoptimized
5656
className="relative h-auto w-full max-w-sm"
5757
/>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"use client";
2+
3+
import { usePathname } from "next/navigation";
4+
import { useEffect } from "react";
5+
6+
const REVEAL_SELECTOR = [
7+
"main section",
8+
"main > article > header",
9+
"main > article > div",
10+
"footer",
11+
].join(",");
12+
13+
export default function SiteScrollMotion() {
14+
const pathname = usePathname();
15+
16+
useEffect(() => {
17+
const elements = Array.from(
18+
document.querySelectorAll<HTMLElement>(REVEAL_SELECTOR)
19+
);
20+
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
21+
22+
if (reduceMotion || !("IntersectionObserver" in window)) {
23+
elements.forEach((element) => {
24+
element.dataset.scrollReveal = "visible";
25+
});
26+
27+
return () => {
28+
elements.forEach((element) => delete element.dataset.scrollReveal);
29+
};
30+
}
31+
32+
const viewportThreshold = window.innerHeight * 0.9;
33+
const observer = new IntersectionObserver(
34+
(entries) => {
35+
entries.forEach((entry) => {
36+
if (!entry.isIntersecting) {
37+
return;
38+
}
39+
40+
const element = entry.target as HTMLElement;
41+
element.dataset.scrollReveal = "visible";
42+
observer.unobserve(element);
43+
});
44+
},
45+
{
46+
threshold: 0.08,
47+
rootMargin: "0px 0px -8% 0px",
48+
}
49+
);
50+
51+
elements.forEach((element) => {
52+
const bounds = element.getBoundingClientRect();
53+
const initiallyVisible = bounds.top < viewportThreshold && bounds.bottom > 0;
54+
55+
element.dataset.scrollReveal = initiallyVisible ? "visible" : "pending";
56+
57+
if (!initiallyVisible) {
58+
observer.observe(element);
59+
}
60+
});
61+
62+
return () => {
63+
observer.disconnect();
64+
elements.forEach((element) => delete element.dataset.scrollReveal);
65+
};
66+
}, [pathname]);
67+
68+
return null;
69+
}

‎components/magicui/marquee.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export function Marquee({
5858
.map((_, i) => (
5959
<div
6060
key={i}
61-
className={cn("flex shrink-0 justify-around gap-(--gap)", {
61+
className={cn("flex shrink-0 justify-around gap-(--gap) motion-reduce:animate-none", {
6262
"animate-marquee flex-row": !vertical,
6363
"animate-marquee-vertical flex-col": vertical,
6464
"group-hover:paused": pauseOnHover,
3.94 KB
Loading

‎public/svgs/brands/linux.svg‎

Lines changed: 1 addition & 19 deletions
Loading

0 commit comments

Comments
 (0)