{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "breadcrumb",
  "title": "Breadcrumb",
  "description": "The path, divided by drawn hairlines leaning like slashes; or a stair that ends in the large italic of where you are; or a long path with a full stop for each step left out.",
  "dependencies": [
    "@radix-ui/react-slot"
  ],
  "registryDependencies": [
    "https://thedirectors.agency/ui/r/0nlytype.json"
  ],
  "files": [
    {
      "path": "registry/0nlytype/ui/breadcrumb.tsx",
      "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype BreadcrumbProps = React.ComponentProps<\"nav\"> & {\n  /**\n   * slashes: one line, divided by leaning hairlines.\n   * stack: a stair, one step a line, each set in a little further; where you are is the large italic at the foot.\n   * elide: the steps between the first and the last two elided, one full stop for each; they open back into words for a still pointer or focus.\n   */\n  variant?: \"slashes\" | \"stack\" | \"elide\"\n}\n\nfunction Breadcrumb({ variant = \"slashes\", className, ...props }: BreadcrumbProps) {\n  return <nav data-slot=\"breadcrumb\" data-variant={variant} aria-label=\"Breadcrumb\" className={cn(\"ot-crumbs\", className)} {...props} />\n}\n\nfunction BreadcrumbList({ className, ...props }: React.ComponentProps<\"ol\">) {\n  return <ol data-slot=\"breadcrumb-list\" className={className} {...props} />\n}\n\nfunction BreadcrumbItem({ className, ...props }: React.ComponentProps<\"li\">) {\n  return <li data-slot=\"breadcrumb-item\" className={className} {...props} />\n}\n\n/** A step above this page. Point at it and the hairlines beside it lean in to hold it. */\nfunction BreadcrumbLink({ asChild = false, ...props }: React.ComponentProps<\"a\"> & { asChild?: boolean }) {\n  const Comp = asChild ? Slot : \"a\"\n  return <Comp data-slot=\"breadcrumb-link\" {...props} />\n}\n\n/** Where you are. It's yours, so it's italic. */\nfunction BreadcrumbPage({ className, ...props }: React.ComponentProps<\"span\">) {\n  return <span data-slot=\"breadcrumb-page\" aria-current=\"page\" className={cn(\"ot-yours\", className)} {...props} />\n}\n\n/** A hairline drawn leaning like a slash (nothing, in a stack; elided with its steps, in elide). Put one between each pair of items. */\nfunction BreadcrumbSeparator({ className, ...props }: React.ComponentProps<\"li\">) {\n  return <li data-slot=\"breadcrumb-separator\" role=\"presentation\" aria-hidden=\"true\" className={className} {...props} />\n}\n\nexport { type BreadcrumbProps, Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator }\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/0nlytype/styles/breadcrumb.css",
      "content": "@layer components {\n  /* ── ot-crumbs ── steps divided by drawn hairlines, leaning like slashes.\n     Point at a step and the hairlines either side lean in (14deg and -14deg) to hold it.\n     Each hairline runs the whole line, descender to cap, so it reads as drawn, not typed. */\n  .ot-crumbs { font-size: var(--ot-mp); line-height: var(--ot-mp-lh); letter-spacing: var(--ot-mp-tr); }\n  .ot-crumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 0.8em; }\n  .ot-crumbs [data-slot=\"breadcrumb-separator\"] {\n    align-self: center; inline-size: var(--ot-hairline); block-size: 1.4em; margin-inline: 0.1em;\n    background: var(--ot-rule-strong); rotate: 24deg;\n    transition: rotate var(--ot-andante) var(--ot-spiccato), background-color var(--ot-allegro);\n  }\n  .ot-crumbs [data-slot=\"breadcrumb-separator\"]:has(+ li > a:is(:hover, :focus-visible, [data-force~=\"hover\"])) { rotate: 14deg; background-color: var(--ot-ink); }\n  .ot-crumbs li:has(> a:is(:hover, :focus-visible, [data-force~=\"hover\"])) + [data-slot=\"breadcrumb-separator\"] { rotate: -14deg; background-color: var(--ot-ink); }\n  :is([dir=\"rtl\"], [dir=\"rtl\"] *) .ot-crumbs [data-slot=\"breadcrumb-separator\"] { rotate: -24deg; }\n  :is([dir=\"rtl\"], [dir=\"rtl\"] *) .ot-crumbs [data-slot=\"breadcrumb-separator\"]:has(+ li > a:is(:hover, :focus-visible, [data-force~=\"hover\"])) { rotate: -14deg; }\n  :is([dir=\"rtl\"], [dir=\"rtl\"] *) .ot-crumbs li:has(> a:is(:hover, :focus-visible, [data-force~=\"hover\"])) + [data-slot=\"breadcrumb-separator\"] { rotate: 14deg; }\n  .ot-crumbs a { color: var(--ot-graphite); text-decoration: none; transition: color var(--ot-allegro); }\n  .ot-crumbs a:is(:hover, [data-force~=\"hover\"]) { color: var(--ot-ink); }\n  .ot-crumbs [aria-current=\"page\"] { color: var(--ot-ink); }\n\n  /* stack: \"It / has / to be / design.\" A stair, one step a line, each a little further in; heavy narrow roman\n     for the way here, and where you are is the large italic at the foot. Pointing at a step sets what you would\n     leave (every step below it) back in pencil. */\n  .ot-crumbs[data-variant=\"stack\"] ol { display: grid; justify-items: start; }\n  .ot-crumbs[data-variant=\"stack\"] [data-slot=\"breadcrumb-separator\"] { display: none; }\n  .ot-crumbs[data-variant=\"stack\"] [data-slot=\"breadcrumb-item\"] { --d: 0; margin-inline-start: calc(var(--d) * 1.2em); transition: color var(--ot-moderato) var(--ot-breath); }\n  .ot-crumbs[data-variant=\"stack\"] [data-slot=\"breadcrumb-item\"]:nth-child(3) { --d: 1; }\n  .ot-crumbs[data-variant=\"stack\"] [data-slot=\"breadcrumb-item\"]:nth-child(5) { --d: 2; }\n  .ot-crumbs[data-variant=\"stack\"] [data-slot=\"breadcrumb-item\"]:nth-child(7) { --d: 3; }\n  .ot-crumbs[data-variant=\"stack\"] [data-slot=\"breadcrumb-item\"]:nth-child(n + 9) { --d: 4; }\n  .ot-crumbs[data-variant=\"stack\"] a { font-weight: 700; font-stretch: 75%; letter-spacing: -0.02em; line-height: 1.1; }\n  .ot-crumbs[data-variant=\"stack\"] [aria-current=\"page\"] { font-size: calc(var(--ot-f) * var(--ot-expression-scale)); line-height: 0.95; margin-block-start: 0.04em; transition: color var(--ot-moderato) var(--ot-breath); }\n  .ot-crumbs[data-variant=\"stack\"] li:has(> a:is(:hover, :focus-visible, [data-force~=\"hover\"])) ~ li :is(a, [aria-current=\"page\"]) { color: var(--ot-pencil); }\n  .ot-crumbs[data-variant=\"stack\"] a:is(:hover, :focus-visible, [data-force~=\"hover\"]) { color: var(--ot-ink); }\n\n  /* elide: a long path keeps its first step and the last two; each step between is elided to a full stop, so the\n     ellipsis counts what it holds. For a still pointer, or focus, each stop opens back into its word, in turn. */\n  .ot-crumbs[data-variant=\"elide\"] ol { column-gap: 0; }\n  .ot-crumbs[data-variant=\"elide\"] [data-slot=\"breadcrumb-separator\"] { margin-inline: 0.6em; }\n  .ot-crumbs[data-variant=\"elide\"] li:not(:nth-child(-n + 2), :nth-last-child(-n + 4)) {\n    --open: 0s; transition: margin-inline var(--ot-andante) var(--ot-exhale) var(--open), opacity var(--ot-moderato) var(--open);\n  }\n  .ot-crumbs[data-variant=\"elide\"] li:not(:nth-child(-n + 2), :nth-last-child(-n + 4)) > a {\n    display: inline-block; overflow: clip; vertical-align: bottom; white-space: nowrap;\n    transition: inline-size var(--ot-andante) var(--ot-exhale) var(--open), opacity var(--ot-moderato) var(--open);\n  }\n  .ot-crumbs[data-variant=\"elide\"] li[data-slot=\"breadcrumb-item\"]:not(:nth-child(-n + 2), :nth-last-child(-n + 4))::before {\n    content: \".\" / \"\"; display: inline-block; overflow: clip; inline-size: 0.36em; color: var(--ot-pencil); vertical-align: bottom;\n    transition: inline-size var(--ot-andante) var(--ot-exhale) var(--open), opacity var(--ot-allegro) var(--open);\n  }\n  /* Elided: the words and the hairlines between them close to nothing; only the stops stay. */\n  .ot-crumbs[data-variant=\"elide\"] ol:not(:hover, :focus-within, [data-force~=\"hover\"]) li:not(:nth-child(-n + 2), :nth-last-child(-n + 4)) > a { inline-size: 0; opacity: 0; }\n  .ot-crumbs[data-variant=\"elide\"] ol:not(:hover, :focus-within, [data-force~=\"hover\"]) li[data-slot=\"breadcrumb-separator\"]:not(:nth-child(-n + 2), :nth-last-child(-n + 4)) { margin-inline: 0; opacity: 0; block-size: 0; inline-size: 0; }\n  /* Open: the stops give way to their words. A pointer has to rest first; focus opens at once. */\n  .ot-crumbs[data-variant=\"elide\"] ol:is(:hover, :focus-within, [data-force~=\"hover\"]) li[data-slot=\"breadcrumb-item\"]:not(:nth-child(-n + 2), :nth-last-child(-n + 4))::before { inline-size: 0; opacity: 0; }\n  .ot-crumbs[data-variant=\"elide\"] ol:hover li:not(:nth-child(-n + 2), :nth-last-child(-n + 4)) { --open: calc(240ms + var(--i, 0) * var(--ot-arpeggio) * 2); }\n  .ot-crumbs[data-variant=\"elide\"] li:nth-child(4) { --i: 1; }\n  .ot-crumbs[data-variant=\"elide\"] li:nth-child(5) { --i: 2; }\n  .ot-crumbs[data-variant=\"elide\"] li:nth-child(6) { --i: 3; }\n  .ot-crumbs[data-variant=\"elide\"] li:nth-child(n + 7) { --i: 4; }\n\n  @media (forced-colors: active) {\n    .ot-crumbs [data-slot=\"breadcrumb-separator\"] { forced-color-adjust: none; background-color: CanvasText; }\n  }\n}\n",
      "type": "registry:file",
      "target": "styles/0nlytype/breadcrumb.css"
    }
  ],
  "css": {
    "@import \"../styles/0nlytype/breadcrumb.css\"": {}
  },
  "meta": {
    "movement": "VIII",
    "underneath": "native",
    "contract": "ot-crumbs"
  },
  "type": "registry:ui"
}
