{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "animated-list",
  "title": "Animated List",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "A live feed where new items spring in at the top and the rest glide down, with leave animations, an item cap, an optional fading tail and a polite announcement for new entries.",
  "dependencies": [
    "motion@^12"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/animated-list.tsx",
      "content": "// Ballmac UI: Animated List. https://ui.ballmac.com/components/animated-list\n\"use client\"\n\nimport * as React from \"react\"\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype AnimatedListProps = Omit<React.ComponentProps<\"ul\">, \"ref\"> & {\n  /** Most items drawn. Extra items beyond this are left out. */\n  max?: number\n  /** Fade the last visible items out so a long feed trails off. */\n  fadeEnd?: boolean\n  /** Read new items aloud politely, for feeds people rely on. */\n  announce?: boolean\n  /** Accessible name of the feed. */\n  label?: string\n}\n\n/** A feed where new items spring in and the rest glide down. Put an AnimatedListItem with a stable `key` for each entry. */\nfunction AnimatedList({ max, fadeEnd = false, announce = false, label, className, children, ...props }: AnimatedListProps) {\n  const items = React.Children.toArray(children)\n  const shown = typeof max === \"number\" ? items.slice(0, max) : items\n  return (\n    <ul\n      data-slot=\"animated-list\"\n      aria-label={label}\n      aria-live={announce ? \"polite\" : undefined}\n      aria-relevant={announce ? \"additions\" : undefined}\n      className={cn(\"relative flex flex-col\", fadeEnd && \"[mask-image:linear-gradient(to_bottom,black_70%,transparent)]\", className)}\n      {...props}\n    >\n      <AnimatePresence initial={false} mode=\"popLayout\">\n        {shown}\n      </AnimatePresence>\n    </ul>\n  )\n}\n\ntype AnimatedListItemProps = Omit<React.ComponentProps<\"li\">, \"ref\">\n\nfunction AnimatedListItem({ className, children, ...props }: AnimatedListItemProps) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.li\n      data-slot=\"animated-list-item\"\n      layout={reduce ? false : \"position\"}\n      initial={reduce ? { opacity: 0 } : { opacity: 0, scale: 0.85, y: -24 }}\n      animate={{ opacity: 1, scale: 1, y: 0 }}\n      exit={reduce ? { opacity: 0 } : { opacity: 0, scale: 0.9, transition: { duration: 0.18 } }}\n      transition={{ type: \"spring\", stiffness: 380, damping: 32 }}\n      style={{ originY: 0 }}\n      className={cn(className)}\n      {...(props as object)}\n    >\n      {children}\n    </motion.li>\n  )\n}\n\nexport { AnimatedList, AnimatedListItem, type AnimatedListProps, type AnimatedListItemProps }\n",
      "type": "registry:ui",
      "target": "@components/ballmac/animated-list.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "list",
      "feed",
      "notifications",
      "live",
      "spring"
    ],
    "version": "1.0.0",
    "updated": "2026-10-01",
    "ai": {
      "summary": "<AnimatedList max fadeEnd announce><AnimatedListItem key={id}>…</AnimatedListItem></AnimatedList>. Each item needs a stable key. Prepend new entries to your array; layout animation does the rest.",
      "whenToUse": [
        "Live activity, notification and event feeds",
        "Chat-like logs where entries arrive over time"
      ],
      "whenNotToUse": [
        "Static lists (stagger-list)",
        "Hundreds of rows (virtualize instead)"
      ],
      "composesWith": [
        "notification-stack",
        "activity-feed",
        "stagger-list"
      ],
      "a11y": [
        {
          "keys": "Screen readers",
          "action": "announce turns on a polite live region that reads additions only"
        },
        {
          "keys": "Reduced motion",
          "action": "Items fade in without moving or scaling"
        }
      ],
      "customization": [
        "max",
        "fadeEnd",
        "announce",
        "label",
        "item content is yours"
      ]
    },
    "examples": [
      "animated-list-demo",
      "animated-list-log"
    ],
    "url": "https://ui.ballmac.com/components/animated-list"
  },
  "categories": [
    "motion"
  ],
  "type": "registry:ui"
}