Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 6 additions & 80 deletions components/NotFoundAnimation.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
"use client";

import dynamic from "next/dynamic";
import { Canvas, useFrame } from "@react-three/fiber";
import { TrackballControls, Environment } from "@react-three/drei";
import { useRef, useState } from "react";
import * as THREE from "three";
import { useTheme } from "next-themes";

const CANVAS_STYLES = {
width: "100%",
Expand All @@ -14,83 +9,14 @@ const CANVAS_STYLES = {
maxHeight: "600px",
} as const;

function MetallicKnot() {
const meshRef = useRef<THREE.Mesh>(null);
const { resolvedTheme } = useTheme();

useFrame((state) => {
if (meshRef.current) {
meshRef.current.rotation.x = state.clock.elapsedTime * 0.25;
meshRef.current.rotation.y = state.clock.elapsedTime * 0.2;
meshRef.current.rotation.z = state.clock.elapsedTime * 0.15;
}
});

return (
<mesh ref={meshRef}>
<torusKnotGeometry args={[0.8, 0.2, 200, 32]} />
<meshPhysicalMaterial
color={resolvedTheme === "dark" ? "#E11312" : "#0A60B5"}
metalness={0.9}
roughness={0.1}
clearcoat={1}
clearcoatRoughness={0.1}
reflectivity={1}
envMapIntensity={2}
/>
</mesh>
);
}

function NotFoundAnimationComponent() {
const [canvasKey, setCanvasKey] = useState(0);

return (
<Canvas
key={canvasKey}
camera={{ position: [0, 0, 5], fov: 45 }}
gl={{
antialias: true,
toneMapping: THREE.ACESFilmicToneMapping,
toneMappingExposure: 1.5,
powerPreference: "high-performance",
}}
style={CANVAS_STYLES}
onCreated={({ gl }) => {
gl.domElement.addEventListener("webglcontextlost", (e) => {
e.preventDefault();
// If the context isn't restored within 2 s, force a full remount
setTimeout(() => setCanvasKey((k) => k + 1), 2000);
});
}}
>
<ambientLight intensity={0.2} />
<ambientLight intensity={0.1} color="#E01211" />
<spotLight
position={[10, 10, 10]}
angle={0.15}
penumbra={1}
intensity={1}
color="#ffffff"
/>
<spotLight
position={[-10, -10, -10]}
angle={0.15}
penumbra={1}
intensity={0.5}
color="#E01211"
/>
<MetallicKnot />
<TrackballControls noZoom={true} rotateSpeed={4} />
<Environment preset="sunset" />
</Canvas>
);
}

// Real dynamic import: the three.js / @react-three modules only load when this
// component renders, so they stay out of the shared/root chunk. (Using
// `Promise.resolve(Component)` here does NOT split the bundle — it just delays
// rendering.)
export const NotFoundAnimation = dynamic(
() => Promise.resolve(NotFoundAnimationComponent),
() => import("./NotFoundAnimationImpl"),
{
ssr: false,
loading: () => <div style={CANVAS_STYLES} />,
}
);
);
87 changes: 87 additions & 0 deletions components/NotFoundAnimationImpl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"use client";

import { Canvas, useFrame } from "@react-three/fiber";
import { TrackballControls, Environment } from "@react-three/drei";
import { useRef, useState } from "react";
import * as THREE from "three";
import { useTheme } from "next-themes";

const CANVAS_STYLES = {
width: "100%",
height: "50vh",
minHeight: "400px",
maxHeight: "600px",
} as const;

function MetallicKnot() {
const meshRef = useRef<THREE.Mesh>(null);
const { resolvedTheme } = useTheme();

useFrame((state) => {
if (meshRef.current) {
meshRef.current.rotation.x = state.clock.elapsedTime * 0.25;
meshRef.current.rotation.y = state.clock.elapsedTime * 0.2;
meshRef.current.rotation.z = state.clock.elapsedTime * 0.15;
}
});

return (
<mesh ref={meshRef}>
<torusKnotGeometry args={[0.8, 0.2, 200, 32]} />
<meshPhysicalMaterial
color={resolvedTheme === "dark" ? "#E11312" : "#0A60B5"}
metalness={0.9}
roughness={0.1}
clearcoat={1}
clearcoatRoughness={0.1}
reflectivity={1}
envMapIntensity={2}
/>
</mesh>
);
}

export default function NotFoundAnimationComponent() {
const [canvasKey, setCanvasKey] = useState(0);

return (
<Canvas
key={canvasKey}
camera={{ position: [0, 0, 5], fov: 45 }}
gl={{
antialias: true,
toneMapping: THREE.ACESFilmicToneMapping,
toneMappingExposure: 1.5,
powerPreference: "high-performance",
}}
style={CANVAS_STYLES}
onCreated={({ gl }) => {
gl.domElement.addEventListener("webglcontextlost", (e) => {
e.preventDefault();
// If the context isn't restored within 2 s, force a full remount
setTimeout(() => setCanvasKey((k) => k + 1), 2000);
});
}}
>
<ambientLight intensity={0.2} />
<ambientLight intensity={0.1} color="#E01211" />
<spotLight
position={[10, 10, 10]}
angle={0.15}
penumbra={1}
intensity={1}
color="#ffffff"
/>
<spotLight
position={[-10, -10, -10]}
angle={0.15}
penumbra={1}
intensity={0.5}
color="#E01211"
/>
<MetallicKnot />
<TrackballControls noZoom={true} rotateSpeed={4} />
<Environment preset="sunset" />
</Canvas>
);
}
10 changes: 2 additions & 8 deletions components/home/AllTheTools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,8 @@ export function AllTheTools() {
<Image
src={tool.visual}
alt={tool.title}
width={100}
height={100}
className="object-contain w-full h-full"
quality={100}
unoptimized
sizes="(min-width: 1280px) 420px, (min-width: 640px) 50vw, 100vw"
/>
</div>
</div>
Expand Down Expand Up @@ -158,11 +155,8 @@ export function AllTheTools() {
<Image
src={tool.visual}
alt={tool.title}
width={100}
height={100}
className="object-contain w-full h-full"
quality={100}
unoptimized
sizes="(min-width: 1280px) 320px, 50vw"
/>
</div>
</div>
Expand Down
2 changes: 0 additions & 2 deletions components/home/feature-tabs/FeatureTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,6 @@ export const FeatureTabs = ({
src={feature.image.light}
alt=""
fill
quality={100}
sizes="806px"
loading={isNext ? "eager" : "lazy"}
/>
Expand Down Expand Up @@ -472,7 +471,6 @@ export const FeatureTabs = ({
alt={mobileFeature?.image.alt}
width={1360}
height={1640}
quality={100}
className="absolute left-0 top-0 min-w-full min-h-full object-cover object-top-left"
sizes="(min-width: 640px) 1360px"
priority
Expand Down
2 changes: 0 additions & 2 deletions components/home/feature-tabs/TabContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ export const TabContent = ({
src={feature.image.light}
alt={feature.image.alt}
fill
quality={100}
className="object-contain object-center sm:object-cover sm:object-top-left dark:hidden"
sizes={sizes}
priority={priority}
Expand All @@ -52,7 +51,6 @@ export const TabContent = ({
src={feature.image.dark}
alt={feature.image.alt}
fill
quality={100}
className="hidden object-contain object-center sm:object-cover sm:object-top-left dark:block"
sizes={sizes}
priority={priority}
Expand Down
Binary file modified components/home/img/rive-mock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading