_โฏHolographic Project Card

A project card with mouse-driven CSS 3D tilt, holographic sheen, and image+tag parallax layers โ€” no WebGL.

CSS 3Dtiltparallaxholographic
1import { useState } from "react";
2import { ProjectCard } from "@/features/projects/components/project-card/project-card.component";
3import { LabsDemoLayout } from "../../components/labs-experiment-frame/labs-experiment-frame.component";
4import {
5 ButtonGroupControl,
6 ControlGroup,
7 ControlPanel,
8 ResetButton,
9 SliderControl,
10} from "../../components/labs-control/labs-control.component";
11import * as styles from "./project-card-3d.demo.css";
12
13// Real project entry reused from projects-data โ€” "My website"
14const SAMPLE_PROJECT = {
15 title: "My website",
16 description:
17 "My personal portfolio with a neo-retro futuristic design system, built with React Router v7 and Vanilla Extract.",
18 date: "2026-04-27",
19 tags: ["React", "TypeScript", "Vanilla Extract", "React Router"],
20 image: "/images/projects/website-card.webp",
21 url: "https://github.com/netoun/netoun.github.io",
22};
23
24const FEATURED_OPTIONS = ["off", "on"] as const;
25type FeaturedOption = (typeof FEATURED_OPTIONS)[number];
26
27const DEFAULT_FEATURED: FeaturedOption = "on";
28const DEFAULT_ROTATE = 0;
29
30export function ProjectCard3dDemo() {
31 const [featured, setFeatured] = useState<FeaturedOption>(DEFAULT_FEATURED);
32 const [rotate, setRotate] = useState(DEFAULT_ROTATE);
33
34 const reset = () => {
35 setFeatured(DEFAULT_FEATURED);
36 setRotate(DEFAULT_ROTATE);
37 };
38
39 return (
40 <LabsDemoLayout
41 stage={
42 <div className={styles.stageInner}>
43 <div className={styles.cardWrapper}>
44 <ProjectCard
45 title={SAMPLE_PROJECT.title}
46 description={SAMPLE_PROJECT.description}
47 date={SAMPLE_PROJECT.date}
48 tags={SAMPLE_PROJECT.tags}
49 image={SAMPLE_PROJECT.image}
50 url={SAMPLE_PROJECT.url}
51 featured={featured === "on"}
52 type="personal"
53 rotate={rotate}
54 animationsEnabled={true}
55 />
56 </div>
57 </div>
58 }
59 controls={
60 <ControlPanel>
61 <ControlGroup title="Card">
62 <ButtonGroupControl
63 label="Featured"
64 options={FEATURED_OPTIONS}
65 value={featured}
66 onChange={setFeatured}
67 />
68 </ControlGroup>
69
70 <ControlGroup title="Rotation">
71 <SliderControl
72 label="Rotate"
73 value={rotate}
74 min={-15}
75 max={15}
76 step={1}
77 onChange={setRotate}
78 format={(v) => `${v}ยฐ`}
79 />
80 </ControlGroup>
81
82 <ResetButton onReset={reset} />
83 </ControlPanel>
84 }
85 />
86 );
87}