{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "item-motion",
  "title": "Motion item",
  "description": "Styled item: the Motion set. 5 decorative item variations (HoverItem, SlideItem, FadeItem, PopItem, RevealItem) on the ai2 token system, powered by framer-motion, reduced-motion aware and sized sm to xl. Part of the free styled layer.",
  "dependencies": [
    "motion@^12.42.2",
    "lucide-react@^1.23.0"
  ],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/item-motion.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronRight, Pencil, Sparkles, Star, Trash2 } from \"lucide-react\"\nimport { motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Item motion family: 5 list rows carrying motion. There are two kinds: a hover reaction (Hover, Reveal) and an entry animation (Slide, Fade, Pop). All motion is turned off with useReducedMotion() - in that case the row sits in its correct final state with no transform and no delay. The timing is deterministic (no random delays). Colour comes ONLY from tokens; alpha via color-mix. Every export renders without props too. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nconst box: Record<StyledSize, string> = {\n  sm: \"gap-2.5 rounded-lg p-2 text-sm\",\n  md: \"gap-3 rounded-lg p-3 text-sm\",\n  lg: \"gap-3.5 rounded-xl p-4 text-base\",\n  xl: \"gap-4 rounded-xl p-5 text-base\",\n}\n\nconst tile: Record<StyledSize, string> = {\n  sm: \"size-8 rounded-md [&_svg]:size-4 [&_i]:text-base\",\n  md: \"size-9 rounded-md [&_svg]:size-4 [&_i]:text-base\",\n  lg: \"size-10 rounded-lg [&_svg]:size-5 [&_i]:text-lg\",\n  xl: \"size-12 rounded-lg [&_svg]:size-5 [&_i]:text-lg\",\n}\n\nconst base =\n  \"flex w-full items-center [&_svg]:shrink-0 [&_i]:not-italic [&_i]:leading-none\"\n\nconst shell = \"border border-border bg-card text-card-foreground\"\n\nconst titleCls = \"truncate font-medium text-foreground\"\nconst descCls = \"truncate text-muted-foreground text-[0.85em]\"\n\nconst springy = { type: \"spring\" as const, stiffness: 420, damping: 28 }\n\ninterface Props {\n  className?: string\n  size?: StyledSize\n  title?: React.ReactNode\n  description?: React.ReactNode\n}\n\nfunction Body({\n  title,\n  description,\n}: {\n  title: React.ReactNode\n  description?: React.ReactNode\n}) {\n  return (\n    <div className=\"flex min-w-0 flex-1 flex-col\">\n      <span className={titleCls}>{title}</span>\n      {description ? <span className={descCls}>{description}</span> : null}\n    </div>\n  )\n}\n\n/* Ikon karesi: brand tonlu token yuzey. */\nfunction Tile({ size, children }: { size: StyledSize; children: React.ReactNode }) {\n  return (\n    <span\n      aria-hidden=\"true\"\n      className={cn(\n        \"inline-flex shrink-0 items-center justify-center text-brand\",\n        tile[size],\n        \"bg-[color-mix(in_oklab,var(--color-brand)_12%,transparent)]\"\n      )}\n    >\n      {children}\n    </span>\n  )\n}\n\n/* Hover: the row rises slightly under the cursor and the chevron slides right. */\nexport function HoverItem({\n  className,\n  size = \"md\",\n  title = \"Workspace settings\",\n  description = \"Hover the row to lift it\",\n}: Props) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.div\n      data-slot=\"styled-item\"\n      className={cn(\n        base,\n        box[size],\n        shell,\n        \"group transition-shadow duration-(--motion-fast) ease-(--motion-ease) hover:shadow-md motion-reduce:transition-none\",\n        className\n      )}\n      whileHover={reduce ? undefined : { y: -2 }}\n      transition={springy}\n    >\n      <Tile size={size}>\n        <Sparkles />\n      </Tile>\n      <Body title={title} description={description} />\n      <ChevronRight className=\"size-4 text-muted-foreground transition-transform duration-(--motion-fast) ease-(--motion-ease) group-hover:translate-x-0.5 motion-reduce:transition-none motion-reduce:group-hover:translate-x-0\" />\n    </motion.div>\n  )\n}\n\n/* Slide: the row enters sliding from the left. */\nexport function SlideItem({\n  className,\n  size = \"md\",\n  title = \"Invite teammates\",\n  description = \"The row slides in from the left\",\n}: Props) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.div\n      data-slot=\"styled-item\"\n      className={cn(base, box[size], shell, className)}\n      initial={reduce ? { opacity: 0 } : { opacity: 0, x: -16 }}\n      animate={reduce ? { opacity: 1 } : { opacity: 1, x: 0 }}\n      transition={{ duration: 0.28, ease: \"easeOut\" }}\n    >\n      <Tile size={size}>\n        <Star />\n      </Tile>\n      <Body title={title} description={description} />\n      <ChevronRight className=\"size-4 text-muted-foreground\" />\n    </motion.div>\n  )\n}\n\n/* Fade: the row enters in place with opacity only - the calmest entry. */\nexport function FadeItem({\n  className,\n  size = \"md\",\n  title = \"Usage report\",\n  description = \"The row fades in on mount\",\n}: Props) {\n  return (\n    <motion.div\n      data-slot=\"styled-item\"\n      className={cn(base, box[size], shell, className)}\n      initial={{ opacity: 0 }}\n      animate={{ opacity: 1 }}\n      transition={{ duration: 0.32, ease: \"easeOut\" }}\n    >\n      <Tile size={size}>\n        <Sparkles />\n      </Tile>\n      <Body title={title} description={description} />\n      <ChevronRight className=\"size-4 text-muted-foreground\" />\n    </motion.div>\n  )\n}\n\n/* Pop: yay (spring) ile buyuyerek girer, tiklamada hafifce basilir. */\nexport function PopItem({\n  className,\n  size = \"md\",\n  title = \"New achievement\",\n  description = \"Springs in and reacts to a tap\",\n}: Props) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.div\n      data-slot=\"styled-item\"\n      className={cn(base, box[size], shell, className)}\n      initial={reduce ? { opacity: 0 } : { opacity: 0, scale: 0.94 }}\n      animate={reduce ? { opacity: 1 } : { opacity: 1, scale: 1 }}\n      whileTap={reduce ? undefined : { scale: 0.98 }}\n      transition={springy}\n    >\n      <Tile size={size}>\n        <Star />\n      </Tile>\n      <Body title={title} description={description} />\n      <ChevronRight className=\"size-4 text-muted-foreground\" />\n    </motion.div>\n  )\n}\n\n/* Reveal: the trailing actions open on hover and focus. The hover state is held at the ROOT of the row and the actions always stay in the DOM (only their appearance changes) - so they are keyboard reachable too and the state does not live in an unmounting subtree. */\nexport function RevealItem({\n  className,\n  size = \"md\",\n  title = \"Landing page copy\",\n  description = \"Hover or focus to reveal actions\",\n}: Props) {\n  const reduce = useReducedMotion()\n  const [active, setActive] = React.useState(false)\n  const shown = reduce || active\n\n  const actionBtn =\n    \"relative inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground outline-none transition-colors duration-(--motion-fast) ease-(--motion-ease) hover:bg-accent hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 [&_svg]:size-3.5 [&_i]:text-sm\"\n\n  return (\n    <div\n      data-slot=\"styled-item\"\n      className={cn(base, box[size], shell, className)}\n      onPointerEnter={() => setActive(true)}\n      onPointerLeave={() => setActive(false)}\n      onFocus={() => setActive(true)}\n      onBlur={(e) => {\n        if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setActive(false)\n      }}\n    >\n      <Tile size={size}>\n        <Pencil />\n      </Tile>\n      <Body title={title} description={description} />\n      <motion.span\n        className=\"flex shrink-0 items-center gap-1\"\n        animate={shown ? { opacity: 1, x: 0 } : { opacity: 0, x: 8 }}\n        transition={reduce ? { duration: 0 } : { duration: 0.18, ease: \"easeOut\" }}\n      >\n        <button type=\"button\" aria-label=\"Edit\" className={actionBtn}>\n          <Pencil />\n        </button>\n        <button type=\"button\" aria-label=\"Delete\" className={actionBtn}>\n          <Trash2 />\n        </button>\n      </motion.span>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/item-motion.tsx"
    }
  ],
  "categories": [
    "styled",
    "item"
  ],
  "type": "registry:component"
}