Replace the hello-world shell with the elevated design system, bilingual screens, recipe/extras data, and the interactive Mein Teller view. Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
2.4 KiB
TypeScript
63 lines
2.4 KiB
TypeScript
import { forwardRef, type HTMLAttributes } from "react";
|
|
import { cx } from "../lib/cx";
|
|
|
|
export interface GlassCardProps extends HTMLAttributes<HTMLDivElement> {
|
|
/**
|
|
* `default` — static, sits at rest elevation.
|
|
* `interactive` — lifts on hover-capable devices, settles down 1px + shadow
|
|
* softens on press (not a full inward "pressed" look — that's reserved
|
|
* for `Button`; a card is a container you tap into, not a switch).
|
|
*/
|
|
variant?: "default" | "interactive";
|
|
}
|
|
|
|
/**
|
|
* Elevated Surface Card — the primary container of the design system.
|
|
*
|
|
* Low-transparency (not see-through glass): a solid-reading surface fill
|
|
* (~90% opaque) with a visible drop shadow for real elevation, plus a faint
|
|
* top-light/bottom-shadow bevel on the edge so it reads as raised off the
|
|
* page rather than flat or floating-glass.
|
|
*
|
|
* Structure (three stacked layers, all inside one rounded-3xl shell):
|
|
* 1. Base: subtle surface gradient (--surface-gradient) for texture.
|
|
* 2. Surface fill: ~90% opaque fill + 8px blur (softens whatever's behind
|
|
* it without reading as transparent) + masked bevel border.
|
|
* 3. Content: rendered above both, in normal flow.
|
|
*/
|
|
export const GlassCard = forwardRef<HTMLDivElement, GlassCardProps>(
|
|
({ variant = "default", className, children, ...props }, ref) => {
|
|
const interactive = variant === "interactive";
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
role={interactive ? "button" : undefined}
|
|
tabIndex={interactive ? 0 : undefined}
|
|
className={cx(
|
|
"elevation-transition relative rounded-3xl no-select",
|
|
"shadow-[var(--shadow-elevated)]",
|
|
interactive && "cursor-pointer active:translate-y-px active:shadow-[var(--shadow-resting)]",
|
|
className
|
|
)}
|
|
style={{ backgroundImage: "var(--surface-gradient)" }}
|
|
{...props}
|
|
>
|
|
{/* surface fill + blur */}
|
|
<div
|
|
className="absolute inset-0 rounded-3xl"
|
|
style={{
|
|
background: "var(--glass-fill)",
|
|
backdropFilter: "blur(var(--glass-blur))",
|
|
WebkitBackdropFilter: "blur(var(--glass-blur))",
|
|
}}
|
|
/>
|
|
{/* bevel border, 1px, radius-safe */}
|
|
<div className="glass-border pointer-events-none absolute inset-0 rounded-3xl" />
|
|
{/* content */}
|
|
<div className="relative z-10">{children}</div>
|
|
</div>
|
|
);
|
|
}
|
|
);
|
|
GlassCard.displayName = "GlassCard";
|