Please use Desktop to view and interact with components
Glassmorphism Portfolio
Personal portfolio spotlight with profile portrait, narrative highlights, and animated social links
Preview
Casper Lightman, Product Designer & Motion Director
Principal product designer pairing narrative motion with premium SaaS brands. Casper leads founders and product teams through expressive design systems that convert curiosity into momentum.
Collaborations
Linear, Framer, Gamma, Clearbit, and early-stage founders crafting premium launches.
Latest drop
Aurora OS motion system · 47 reusable blueprints, adaptive tokens, and launch storyboard.
Availability
2 advisory spots for Q1 · Remote friendly across EU & US time zones.
Casper Lightman
Product Designer · Motion Director
Partnering with future-facing teams to choreograph interfaces that feel cinematic yet effortless.
This component requires shadcn/ui
This component uses shadcn/ui components. Make sure you have shadcn/ui set up in your project.
- Install shadcn/ui:
npx shadcn-ui@latest init - Install required components based on the imports in the code (e.g.,
npx shadcn-ui@latest add button) - Ensure your
tailwind.config.tsandglobals.cssare configured as per shadcn/ui documentation
Code
'use client'
import { motion, Variants } from "framer-motion";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import type { LucideIcon } from "lucide-react";
import { ArrowUpRight, Dribbble, Github, Linkedin, Twitter } from "lucide-react";
type Highlight = {
title: string;
description: string;
};
type SocialLink = {
label: string;
handle: string;
href: string;
icon: LucideIcon;
};
const highlights: Highlight[] = [
{
title: "Collaborations",
description: "Linear, Framer, Gamma, Clearbit, and early-stage founders crafting premium launches.",
},
{
title: "Latest drop",
description: "Aurora OS motion system · 47 reusable blueprints, adaptive tokens, and launch storyboard.",
},
{
title: "Availability",
description: "2 advisory spots for Q1 · Remote friendly across EU & US time zones.",
},
];
const socialLinks: SocialLink[] = [
{
label: "Twitter",
handle: "@caspermotions",
href: "https://x.com/caspermotions",
icon: Twitter,
},
{
label: "LinkedIn",
handle: "Casper Lightman",
href: "https://linkedin.com/in/casperlightman",
icon: Linkedin,
},
{
label: "Dribbble",
handle: "caspermotion",
href: "https://dribbble.com/caspermotion",
icon: Dribbble,
},
{
label: "GitHub",
handle: "casper-studio",
href: "https://github.com/casper-studio",
icon: Github,
},
];
const listVariants: Variants = {
hidden: { opacity: 0, y: 16 },
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.4,
staggerChildren: 0.08,
},
},
};
const itemVariants: Variants = {
hidden: { opacity: 0, y: 12 },
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.35,
},
},
};
export function GlassmorphismPortfolioBlock() {
return (
<section className="relative min-h-screen overflow-hidden px-6 py-24 lg:py-32">
{/* Background gradient orbs */}
<div className="absolute inset-0 -z-10">
<div className="absolute left-1/2 top-0 h-[520px] w-[520px] -translate-x-1/2 rounded-full bg-foreground/[0.035] blur-[140px]" />
<div className="absolute bottom-0 right-0 h-[360px] w-[360px] rounded-full bg-foreground/[0.025] blur-[120px]" />
</div>
<div className="mx-auto max-w-6xl">
<motion.div
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.6, ease: "easeOut" }}
className="relative overflow-hidden rounded-3xl border border-border/50 bg-background/45 p-8 shadow-[0_45px_120px_rgba(15,23,42,0.28)] backdrop-blur-2xl md:p-12 dark:shadow-[0_45px_120px_rgba(0,0,0,0.5)]"
>
{/* Glass gradient overlay */}
<div className="absolute inset-0 bg-gradient-to-br from-foreground/[0.05] via-transparent to-transparent pointer-events-none" />
<div className="relative grid gap-12 lg:grid-cols-2">
{/* Left column - Main content */}
<div className="space-y-8">
<Badge
variant="outline"
className="inline-flex items-center gap-2 rounded-full border-border/50 bg-background/55 px-4 py-1.5 text-xs uppercase tracking-[0.3em] text-foreground/70 backdrop-blur transition-colors hover:bg-background/70"
>
Portfolio Insight
</Badge>
<div className="space-y-4">
<motion.h2
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.1 }}
className="text-2xl font-semibold tracking-tight text-foreground md:text-3xl"
>
Casper Lightman, Product Designer & Motion Director
</motion.h2>
<motion.p
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.2 }}
className="max-w-xl text-base leading-relaxed text-foreground/70 md:text-md"
>
Principal product designer pairing narrative motion with premium SaaS brands. Casper leads founders and product teams through expressive design systems that convert curiosity into momentum.
</motion.p>
</div>
{/* Highlights grid */}
<div className="grid gap-4 sm:grid-cols-1">
{highlights.map((item, index) => (
<motion.div
key={item.title}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.4, delay: 0.1 * index }}
whileHover={{ y: -4 }}
className="group relative overflow-hidden rounded-2xl border border-border/40 bg-background/60 p-5 backdrop-blur transition-all hover:border-border/60 hover:shadow-lg"
>
<div className="absolute inset-0 bg-gradient-to-br from-foreground/[0.04] via-transparent to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
<div className="relative space-y-2">
<p className="text-xs font-semibold uppercase tracking-[0.25em] text-foreground/40">{item.title}</p>
<p className="text-sm leading-relaxed text-foreground/70">{item.description}</p>
</div>
</motion.div>
))}
</div>
{/* CTA Buttons */}
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.3 }}
className="grid grid-cols-1 gap-4"
>
<Button
size="lg"
onClick={() => window.open('https://casper.studio/case-studies', '_blank')}
className="h-12 w-full gap-2 rounded-full px-8 text-sm uppercase tracking-[0.25em] transition-all hover:shadow-lg sm:w-auto"
>
View case studies
<ArrowUpRight className="h-4 w-4" />
</Button>
</motion.div>
</div>
{/* Right column - Profile card */}
<div className="relative">
<div className="absolute inset-0 rounded-[32px] bg-gradient-to-b from-primary/15 via-transparent to-transparent blur-3xl" />
<div className="relative flex h-full flex-col justify-between overflow-hidden rounded-[28px] border border-border/50 bg-background/60 p-8 backdrop-blur-xl">
<div className="flex flex-col items-center text-center">
{/* Avatar with glow */}
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="relative mb-6"
>
<div className="absolute left-1/2 top-1/2 h-32 w-32 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary/20 blur-2xl" />
<img
src="https://images.unsplash.com/photo-1544723795-3fb6469f5b39?w=640&q=80"
alt="Casper Lightman"
className="relative h-32 w-32 rounded-full border border-border/40 object-cover shadow-[0_25px_60px_rgba(15,23,42,0.3)] dark:shadow-[0_25px_60px_rgba(0,0,0,0.6)]"
/>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 10 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.2 }}
className="space-y-1"
>
<h3 className="text-2xl font-semibold tracking-tight text-foreground">Casper Lightman</h3>
<p className="text-xs font-semibold uppercase tracking-[0.35em] text-foreground/45">
Product Designer · Motion Director
</p>
</motion.div>
<motion.p
initial={{ opacity: 0, y: 10 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.3 }}
className="mt-4 max-w-sm text-sm leading-relaxed text-foreground/70"
>
Partnering with future-facing teams to choreograph interfaces that feel cinematic yet effortless.
</motion.p>
</div>
{/* Social links */}
<motion.div
variants={listVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true, margin: "-80px" }}
className="mt-8 flex flex-col gap-3"
>
{socialLinks.map((social) => {
const Icon = social.icon;
return (
<motion.a
key={social.label}
variants={itemVariants}
href={social.href}
target="_blank"
rel="noopener noreferrer"
className="group flex items-center justify-between rounded-2xl border border-border/40 bg-background/70 px-4 py-3 text-left transition-all hover:-translate-y-0.5 hover:border-border/60 hover:bg-background/80 hover:shadow-md"
whileHover={{ scale: 1.01 }}
whileTap={{ scale: 0.985 }}
>
<div className="flex items-center gap-3">
<span className="flex h-10 w-10 items-center justify-center rounded-full border border-border/40 bg-background/70 text-foreground/80 shadow-[0_10px_30px_rgba(15,23,42,0.2)] transition-all group-hover:shadow-[0_10px_30px_rgba(15,23,42,0.3)] dark:shadow-[0_10px_30px_rgba(0,0,0,0.4)] dark:group-hover:shadow-[0_10px_30px_rgba(0,0,0,0.5)]">
<Icon className="h-4 w-4" />
</span>
<div>
<p className="text-sm font-semibold text-foreground">{social.label}</p>
<p className="text-xs text-foreground/60">{social.handle}</p>
</div>
</div>
<ArrowUpRight className="h-4 w-4 text-foreground/40 transition-all group-hover:translate-x-0.5 group-hover:-translate-y-0.5 group-hover:text-foreground/70" />
</motion.a>
);
})}
</motion.div>
</div>
</div>
</div>
</motion.div>
</div>
</section>
);
}
How to Use
- 1Install Framer Motion:
npm install framer-motion - 2Set up shadcn/ui: Install shadcn/ui components used in this code. Check the imports in the code above and install the required components (e.g.,
npx shadcn-ui@latest add button card) - 3Copy the code from above
- 4Paste it into your project and customize as needed
- 5Colors are customizable via Tailwind CSS classes. The default theme uses dark mode colors defined in your globals.css file