Loading...
Loading...
Cinematic UI Design Guidelines. For high-expression applications such as personal brands, creative galleries, and premium players. Mandatory use of Framer Motion, Tailwind CSS, and React. Use cases: (1) Building projects requiring a "high-end feel", "cinematic feel", or "immersive feel", (2) Auditing UI code for compliance with Kinetic Minimalism specifications, (3) When users request effects similar to Apple Music, Linear, or high-end portfolios.
npx skill4agent add sweetretry/skills expressive-style-guide| Element | Specification |
|---|---|
| Background Color | |
| Foreground Color | |
| Accent Color | |
| Border Radius | |
| Animation Engine | Framer Motion, Spring Physics preferred |
| Visual Patterns | Spotlight / Parallax / Morph / Ambient Gradient / Mask Reveal / Frosted Overlay / Kinetic Typography (combinable) |
| Contrast | WCAG AA (≥4.5:1), text on dark backgrounds must meet the standard |
| Hardcoded Hex | Forbidden — Strictly use semantic Tokens at component layer |
shadcn/uicn()Tailwind CSSFramer Motion--backgroundbg-background:root {
/* Light Mode is rarely used in cinematic scenarios but must be defined */
--background: 0 0% 98%; /* Near-white */
--foreground: 0 0% 4%; /* Near-black */
--card: 0 0% 96%;
--card-foreground: 0 0% 4%;
--primary: 220 90% 56%; /* Brand accent color */
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 92%;
--secondary-foreground: 0 0% 10%;
--muted: 0 0% 90%;
--muted-foreground: 0 0% 40%;
--accent: 0 0% 92%;
--accent-foreground: 0 0% 10%;
--border: 0 0% 85%;
--ring: 220 90% 56%;
}
.dark {
/* Cinematic core palette - near-black high contrast */
--background: 0 0% 2%; /* Near-pure black canvas */
--foreground: 0 0% 95%; /* Highlighted white foreground */
--card: 0 0% 4%; /* Slightly brightened card */
--card-foreground: 0 0% 92%;
--primary: 220 85% 65%; /* Accent color after spectral shift */
--primary-foreground: 0 0% 2%;
--secondary: 0 0% 8%;
--secondary-foreground: 0 0% 88%;
--muted: 0 0% 12%;
--muted-foreground: 0 0% 55%;
--accent: 0 0% 10%;
--accent-foreground: 0 0% 90%;
--border: 0 0% 14%; /* Extremely subtle border */
--ring: 220 85% 65%;
}// ✅ Correct — Use semantic tokens
<div className="bg-background text-foreground">
<div className="bg-card border-border">
<span className="text-muted-foreground">
// ❌ Forbidden — Hardcoded Hex
<div className="bg-[#030303] text-[#ffffff]">
<div style={{ background: '#000000' }}>borderopacityborder-t border-foreground/20border border-borderbg-primary/5bg-primary/8backdrop-blur-xlbg-background/80 backdrop-blur-xlconst dolly = { type: "spring", stiffness: 280, damping: 28, mass: 1 };const tactile = { type: "spring", stiffness: 380, damping: 30, mass: 0.8 };const reveal = { duration: 1, ease: [0.16, 1, 0.3, 1] };useScrolluseTransformconst { scrollYProgress } = useScroll({ target: ref });
const y = useTransform(scrollYProgress, [0, 1], ["0%", "-20%"]);clipPathopacityscrollYProgressconst opacity = useTransform(scrollYProgress, [0.2, 0.6], [0, 1]);
const clipPath = useTransform(scrollYProgress, [0, 1],
["inset(100% 0 0 0)", "inset(0% 0 0 0)"]
);staggerChildrenconst container = { animate: { transition: { staggerChildren: 0.08 } } };
const item = {
initial: { opacity: 0, y: 24 },
animate: { opacity: 1, y: 0, transition: reveal }
};text-5xltext-9xltracking-tightertext-foregroundJetBrains MonoGeist Monotext-muted-foregroundleading-relaxeduseMotionTemplateuseMotionValueradial-gradienttranslateYuseScrolluseTransformscalelayoutIdAnimatePresencebg-gradient-to-*from-background via-muted/10 to-backgroundanimateclipPathopacitybg-background/60 backdrop-blur-xl border border-borderscale(1.02)blur(4px)dollyrevealstaggerChildren: 0.03-0.06opacityyfilter: blur()cn()// Primary — High-contrast action button
<Button className={cn(
"bg-primary text-primary-foreground",
"rounded-lg tracking-wide font-medium",
"transition-none" // Handled by Framer Motion
)}>
<motion.span whileTap={{ scale: 0.97 }} transition={tactile}>
Action
</motion.span>
</Button>
// Ghost — Cinematic ghost button
<Button variant="ghost" className={cn(
"text-muted-foreground hover:text-foreground",
"hover:bg-accent/50"
)}>
Secondary
</Button><motion.div className={cn(
"bg-card border border-border rounded-xl overflow-hidden",
"border-t-foreground/15" // Top reflective sheen
)}>
{/* Cover image defaults to reduced brightness, restores on interaction */}
<motion.img
className="w-full object-cover brightness-[0.6]"
whileHover={{ brightness: 1 }}
/>
<div className="p-6">
<h3 className="text-foreground text-lg font-semibold tracking-tight">
{title}
</h3>
<p className="text-muted-foreground text-sm font-mono mt-1">
{metadata}
</p>
</div>
</motion.div><Dialog>
<DialogOverlay className={cn(
"bg-background/80 backdrop-blur-xl"
)} />
<DialogContent className={cn(
"bg-card border border-border rounded-xl",
"shadow-none"
)}>
{/* Content uses AnimatePresence for entry orchestration */}
<AnimatePresence mode="wait">
<motion.div
initial={{ opacity: 0, y: 16 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -8 }}
transition={dolly}
>
{children}
</motion.div>
</AnimatePresence>
</DialogContent>
</Dialog><nav className={cn(
"fixed top-0 w-full z-50",
"bg-background/60 backdrop-blur-lg border-b border-border"
)}>
<div className="flex items-center justify-between px-8 h-16">
<span className="text-foreground font-semibold tracking-tight">
{brand}
</span>
<div className="flex gap-6 text-muted-foreground">
{links.map(link => (
<motion.a
key={link.href}
className="hover:text-foreground transition-colors"
whileHover={{ y: -1 }}
transition={tactile}
>
{link.label}
</motion.a>
))}
</div>
</div>
</nav>col-span-2 row-span-2gap-4gap-6gap-2p-4<div className="grid grid-cols-2 md:grid-cols-4 gap-4 md:gap-6">
<div className="col-span-2 row-span-2">{/* Hero Card */}</div>
<div className="col-span-1">{/* Vertical Card */}</div>
<div className="col-span-1">{/* Square Card */}</div>
</div>layoutIdAnimatePresence<motion.div layoutId={`card-${id}`} transition={dolly}>
<motion.img layoutId={`image-${id}`} src={cover} />
</motion.div>#030303#ffffffbg-backgroundtext-foregroundborder-border:root.darkborder-t-foreground/15border-borderlayoutIdAnimatePresencetext-muted-foregroundprefers-reduced-motionexample/This section is for theskill to use in multi-style fusion scenarios. Define which attributes in this style guide are hard constraints (cannot be overridden even in mixed modes) and which are soft constraints (can be adjusted by the Director based on project needs).design-director
| ID | Attribute | Specification Value | Reason |
|---|---|---|---|
| E.H1 | Animation Engine | Framer Motion, Spring Physics preferred | Core driver of cinematic texture. Replacing with CSS transitions will lose all visual characteristics |
| E.H2 | Dark Canvas | Dark background as default canvas (within Expressive areas) | Light and shadow drama relies on dark base. Light backgrounds cannot implement core visual patterns like spotlight and ambient gradient |
| E.H3 | Tokenization | Hardcoded Hex forbidden, semantic tokens used at component layer | Infrastructure for cross-style fusion, shared by all styles |
| E.H4 | Content as Hero | Decorative elements must recede behind content (images, music, works) | Core philosophy of this style — interface recedes, content takes center stage |
| E.H5 | Contrast | WCAG AA (≥4.5:1) | Mandatory accessibility requirement, especially for light text on dark backgrounds |
| ID | Attribute | Default Value | Director Adjustable Range | Trigger Condition |
|---|---|---|---|---|
| E.S1 | Border Radius | | Can be reduced to | When Minimal is the main project style and Expressive is only used for auxiliary areas |
| E.S2 | Animation Duration Upper Limit | 0.3–1.5s (complete cinematic camera movement) | Upper limit can be reduced to 0.8s | When the overall project rhythm is fast, or Minimal/Swiss is the main style |
| E.S3 | Color Space | HSL | Can be converted to oklch | Recommended to unify with oklch in mixed projects — better perceptual uniformity, more natural gradient seams |
| E.S4 | Dark Background Lightness | | Can be brightened to | When needing to unify dark mode baseline with Minimal/Swiss areas |
| E.S5 | Asymmetric Bento Grid | Free asymmetric layout | Can be aligned to 8pt baseline grid (column width and spacing are multiples of 8px) | When Swiss is one of the project styles and global grid alignment is required |
| E.S6 | Stagger Interval | 0.08s | Can be shortened to 0.04–0.06s | When the overall project rhythm is fast |
| E.S7 | Parallax Scroll Intensity | 0.3–0.5x speed difference | Can be reduced to 0.1–0.2x speed difference | When Minimal is the main style and a more restrained scrolling experience is needed |