/** * Material 3: the surfaces. * * Tonal rather than outlined — a widget is told from the ground by being a * step further toward the primary, which is what lets a palette recolour the * whole look. Nothing here holds state: the behaviour is in `ui/core`. */ import { Link } from "@tanstack/react-router" import { Lock } from "lucide-react" import { motion } from "motion/react" import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip" import { cn } from "@/lib/utils" import { ICONS } from "../../icons" import type { BackdropProps, FrameProps, NoticeProps, RailProps, } from "../core/contract" import { TESTID } from "../core/contract" import { LOOK } from "../core/motion" /** Material's ground is the surface colour itself; only an image is drawn. */ export function Backdrop({ image }: BackdropProps) { if (!image) return null return (
) } function Issue({ issue }: { issue: string }) { return ( {issue} ) } export function Frame({ title, issue, grip, scroll, selected, onClick, children, }: FrameProps) { return ( // A card is not a control: the click only picks it in edit mode, and every // interactive element inside keeps its own role and keyboard handling. // biome-ignore lint/a11y/useKeyWithClickEvents: see above. // biome-ignore lint/a11y/noStaticElementInteractions: see above.
{title ? (
{title} {issue ? : null}
) : null}
{children}
{/* No header to sit in, so the fault takes the corner instead — a widget drawn without its title still says when it is mis-wired. */} {!title && issue ? (
) : null} {/* And the editor still needs something to drag it by. */} {!title && grip ? ( ) : null}
) } /** Two letters off the title, so a rail of four reads as four different things. */ function initials(label: string): string { const words = label.split(/[\s_-]+/).filter(Boolean) if (words.length === 0) return "?" if (words.length === 1) return words[0].slice(0, 2).toUpperCase() return (words[0][0] + words[1][0]).toUpperCase() } export function Rail({ entries }: RailProps) { return ( ) } export function Notice({ children }: NoticeProps) { return (
{children}
) }