{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "agenda-rail", "title": "Agenda Rail", "description": "A right-aligned run of pills with a deliberately ragged left edge, for itineraries and schedules.", "dependencies": [ "class-variance-authority" ], "registryDependencies": [ "http://localhost:5173/r/liquid-theme.json", "http://localhost:5173/r/info-pill.json" ], "files": [ { "path": "src/components/ui/agenda-rail.tsx", "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { InfoPill } from \"@/components/ui/info-pill\"\n\n/**\n * The itinerary column from the reference hero — `Morning Yoga`,\n * `Free Movement Practice`, `50/50 Surfing & Beach Time`,\n * `7:15PM Lunch by the Shore`.\n *\n * The whole point is that the rows do not line up on the left. Right-aligning\n * a run of pills of unequal width leaves a ragged left edge, and that rag is\n * what stops four stacked pills reading as a table. The rag is generated from\n * a fixed repeating pattern rather than at random so it is stable across\n * renders — a layout that reshuffles on every paint is a bug, not a texture.\n *\n * Rows also lose a little opacity as they descend, which puts the top of the\n * list first in the reading order without changing any type sizes.\n */\nconst rail = cva(\"flex flex-col\", {\n variants: {\n align: {\n end: \"items-end text-right\",\n start: \"items-start text-left\",\n },\n gap: { tight: \"gap-1.5\", normal: \"gap-2.5\", loose: \"gap-3.5\" },\n },\n defaultVariants: { align: \"end\", gap: \"normal\" },\n})\n\n/** Fractions of `stagger` added to each row's trailing width, cycled. */\nconst RAG = [0, 0.58, 1, 0.34, 0.76, 0.16]\n\nexport type AgendaItem = {\n /** Leading glyph. Mutually exclusive with `marker` in practice. */\n icon?: React.ReactNode\n /** Leading value — `50/50`, `7:15PM`. */\n marker?: React.ReactNode\n label: React.ReactNode\n}\n\nexport interface AgendaRailProps\n extends React.ComponentProps<\"ul\">,\n VariantProps {\n items: AgendaItem[]\n material?: React.ComponentProps[\"material\"]\n size?: React.ComponentProps[\"size\"]\n /** Peak extra width, in px, that the rag adds to a row. */\n stagger?: number\n /** How much opacity the last row has lost. 0 keeps every row equal. */\n falloff?: number\n}\n\nexport function AgendaRail({\n items,\n material = \"glass\",\n size = \"md\",\n align,\n gap,\n stagger = 56,\n falloff = 0.3,\n className,\n ...props\n}: AgendaRailProps) {\n return (\n \n {items.map((item, i) => {\n const pad = RAG[i % RAG.length] * stagger\n const dim = items.length > 1 ? (i / (items.length - 1)) * falloff : 0\n return (\n
  • \n \n {item.label}\n \n
  • \n )\n })}\n \n )\n}\n", "type": "registry:ui" } ], "type": "registry:ui" }