"use client" /** * CoachMark — contextual onboarding / feature-discovery popover * * Targets elements by CSS selector, scrolls them into view, and positions * the popover relative to the target using Radix's virtual anchor. * * Variants: * • single — standalone tip anchored to a target element * • flow — multi-step walkthrough with prev/next and step indicator * • image — includes a hero image above the content * • no-image — text-only (title + description) * * Brand-colored background with spotlight overlay on the target element. * * WCAG 2.1 AA: * • Focus trapped inside while open * • Escape dismisses * • aria-labelledby / aria-describedby wired automatically * • Step indicator announced via aria-live */ import * as React from "react" import { createPortal } from "react-dom" import { Popover as PopoverPrimitive } from "radix-ui" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "../../lib/utils" import type { CoachMarkState } from "../../hooks/use-coach-mark" /* ── Variant styles ─────────────────────────────────────────────────────── */ const coachMarkVariants = cva( "z-[60] flex flex-col overflow-hidden rounded-xl bg-brand-deep text-white shadow-xl outline-none [&_h3]:text-white hc:!bg-background hc:!text-foreground hc:[&_h3]:!text-foreground hc:!border-2 hc:!border-foreground hc:!shadow-none", { variants: { size: { default: "w-[320px]", sm: "w-[260px]", lg: "w-[400px]", }, }, defaultVariants: { size: "default", }, } ) /* ── Sub-components ─────────────────────────────────────────────────────── */ function CoachMarkImage({ src, alt, }: { src: string alt: string }) { return (
{alt}
) } /** Decorative hero block when image variant is shown without an asset (catalog / placeholder). */ export function CoachMarkImagePlaceholder() { return (