{
  "schemaVersion": 2,
  "builtFrom": {
    "kind": "package",
    "repo": "estiva-ui",
    "package": "@estiva-app/ui",
    "packageVersion": "0.87.0",
    "exports": 210,
    "typeExports": 211,
    "files": null
  },
  "storybook": {
    "docsPath": "/?path=/docs/{docsId}",
    "storyPath": "/?path=/story/{storyId}",
    "devUrl": "http://localhost:6008"
  },
  "entries": [
    {
      "name": "AddReactionButton",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ReactionRow.tsx",
      "purpose": "The add button: `ReactionPicker` opens over it.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "options",
          "takes": "readonly ReactionOption[]",
          "required": true,
          "note": "The emoji offered, each named."
        },
        {
          "name": "onPick",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-reactionrow--docs",
      "storyId": "primitives-reactionrow--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "anchorOfSelection",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CommentHighlights.ts",
      "purpose": "The anchor a comment on the selection carries, as §13.6 writes it: the selected blocks, and the selected words in one block or the words where it starts and ends across several.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-commenthighlights--docs",
      "storyId": "primitives-commenthighlights--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "appendTableColumn",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorTableControls.tsx",
      "purpose": "A column after the last one: the ➕ right of the table.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editortablecontrols--docs",
      "storyId": "primitives-editortablecontrols--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "appendTableRow",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorTableControls.tsx",
      "purpose": "A row after the last one: the ➕ under the table.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editortablecontrols--docs",
      "storyId": "primitives-editortablecontrols--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "applyFormat",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "Apply one format to the current block. `set*` wherever Tiptap has one: choosing Heading should make a heading, not turn one off.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "AppProvider",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/AppProvider.tsx",
      "purpose": "What the parts need to know about the app they are in, said once at its root: where a person's picture comes from, and how to change page without a reload.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "pictureFor",
          "takes": "a handler",
          "required": false,
          "note": "Where this app keeps a person's picture."
        },
        {
          "name": "navigate",
          "takes": "a handler",
          "required": false,
          "note": "How this app changes page without reloading."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-appprovider--docs",
      "storyId": "frame-appprovider--pictures",
      "docPage": "src/AppProvider.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "AppShell",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/AppShell.tsx",
      "purpose": "The frame of an app, in three manners: `solid` — the structured frame, a solid TopBar over a Sidebar and the content beside it — `inset` — the same frame the other way round, the TopBar and the Sidebar standing on the ground and the content a lighter card beside them — and `floating` — the TopBar floating over the top edge, a Rail standing on the background, and the content living in the rounded card.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "variant",
          "takes": "solid | floating | inset",
          "required": false,
          "note": null
        },
        {
          "name": "menu",
          "takes": "anything",
          "required": false,
          "note": "The top bar's menu button, in an app whose navigation collapses."
        },
        {
          "name": "logo",
          "takes": "anything",
          "required": false,
          "note": "The top bar's left: the app's logo mark, or its name as text."
        },
        {
          "name": "search",
          "takes": "anything",
          "required": false,
          "note": "The top bar's centre: something of the caller's own."
        },
        {
          "name": "onSearch",
          "takes": "a handler",
          "required": false,
          "note": "What searching opens: the top bar then draws its search field and answers Ctrl+K (`TopBar`'s `onSearch`)."
        },
        {
          "name": "searchPlaceholder",
          "takes": "text",
          "required": false,
          "note": "The words in the top bar's search field."
        },
        {
          "name": "identity",
          "takes": "anything",
          "required": false,
          "note": "The top bar's right cluster — an `IdentityMenu`."
        },
        {
          "name": "banner",
          "takes": "anything",
          "required": false,
          "note": "A `Banner`, or nothing — drawn at the top of the content area."
        },
        {
          "name": "nav",
          "takes": "anything",
          "required": true,
          "note": "The navigation: a `Sidebar` in the solid manner, a `Rail` in the floating one."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "variant",
          "values": [
            "solid",
            "floating",
            "inset"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-appshell--docs",
      "storyId": "frame-appshell--solid",
      "docPage": "src/AppShell.mdx",
      "app": null,
      "looks": [
        "overflow-hidden rounded-2xl bg-bg-surface signal:border signal:border-border-subtle signal:shadow-highlight-inset"
      ]
    },
    {
      "name": "archivedLine",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/archivedLine.ts",
      "purpose": "The line in the comment box's place on an archived file (CommentBox's `closed.reason`), in every app's words alike.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "AttachmentCard",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/AttachmentCard.tsx",
      "purpose": "Something attached — a document or an image — drawn as a card: posted, or waiting to be sent.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "name",
          "takes": "text",
          "required": true,
          "note": "The name it was attached under, extension included: it decides the icon and the type label."
        },
        {
          "name": "size",
          "takes": "number",
          "required": false,
          "note": "In bytes."
        },
        {
          "name": "contentType",
          "takes": "text",
          "required": false,
          "note": "Its MIME type, where known: an `image/…` type is an image whatever its name."
        },
        {
          "name": "href",
          "takes": "text",
          "required": false,
          "note": "Where a document opens, in a new tab. Without it the row is dimmed and opens nothing."
        },
        {
          "name": "src",
          "takes": "text",
          "required": false,
          "note": "The picture an image card draws. Without it an image is drawn as a row."
        },
        {
          "name": "alt",
          "takes": "text",
          "required": false,
          "note": "What the picture shows, where the sender said — Ship carries one on every `imeta`."
        },
        {
          "name": "remoteSrc",
          "takes": "text",
          "required": false,
          "note": "A file the app has to *fetch* before it can be used — one on a relay, where reading it needs the reader's own authorization (UIG-35)."
        },
        {
          "name": "remoteFullSrc",
          "takes": "text",
          "required": false,
          "note": "The full-size picture, fetched only when someone opens it."
        },
        {
          "name": "fetchImage",
          "takes": "a handler",
          "required": false,
          "note": "How this app fetches a picture it is allowed to read: a URL in, a URL the browser can draw out (an object URL, usually)."
        },
        {
          "name": "onOpen",
          "takes": "a handler",
          "required": false,
          "note": "What a click on an image's picture does."
        },
        {
          "name": "onDownload",
          "takes": "a handler",
          "required": false,
          "note": "Shows a download control on hover or focus, and calls this."
        },
        {
          "name": "download",
          "takes": "true/false",
          "required": false,
          "note": "Shows the download control and saves the file itself, under `name`: the original where there is one (`remoteFullSrc`), otherwise what the card is drawing."
        },
        {
          "name": "pending",
          "takes": "true/false",
          "required": false,
          "note": "Waiting to be sent: the composer's 200px row, with a remove control on its corner."
        },
        {
          "name": "onRemove",
          "takes": "a handler",
          "required": false,
          "note": "Removes a pending card."
        },
        {
          "name": "state",
          "takes": "ready | loading | unreadable | uploading | failed | warning",
          "required": false,
          "note": "`ready` · `loading` (an image on its way) · `unreadable` (it could not be read) · `uploading`, `failed`, `warning` (while pending)."
        },
        {
          "name": "note",
          "takes": "text",
          "required": false,
          "note": "The line under the name, in place of its type and size — why it failed, or what the warning is."
        },
        {
          "name": "noteHint",
          "takes": "text",
          "required": false,
          "note": "The note's full words, on hover, where the line is short."
        }
      ],
      "variants": [
        {
          "prop": "state",
          "values": [
            "ready",
            "loading",
            "unreadable",
            "uploading",
            "failed",
            "warning"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-attachmentcard--docs",
      "storyId": "components-attachmentcard--document",
      "docPage": "src/AttachmentCard.mdx",
      "app": null,
      "looks": [
        "text-caption font-medium text-text-primary truncate",
        "text-small tracking-wide leading-tight truncate",
        "rounded-md bg-bg-active text-text-secondary overflow-hidden",
        "text-small tracking-wide leading-tight truncate text-error-default",
        "text-small tracking-wide leading-tight truncate text-warning-default",
        "text-small tracking-wide leading-tight truncate text-text-secondary",
        "-top-1.5 -right-1.5 rounded-full bg-bg-elevated border border-border-strong text-text-secondary hover:text-text-primary opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 transition-opacity",
        "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 transition-opacity"
      ]
    },
    {
      "name": "AttachmentNode",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/BlockNodes.tsx",
      "purpose": "A file placed in a document — SPEC §13.3's `attachment` block (SHI-2).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-blocknodes--docs",
      "storyId": "primitives-blocknodes--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Avatar",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Avatar.tsx",
      "purpose": "A person's face: their picture, or their initials on a colour that is theirs, or — when there is no name to take initials from — a silhouette.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "src",
          "takes": "text",
          "required": false,
          "note": "The picture URL, resolved by the caller — or, when none is given, by the app's `AppProvider`."
        },
        {
          "name": "name",
          "takes": "text",
          "required": false,
          "note": "The person's name — where the initials and the colour come from."
        },
        {
          "name": "alt",
          "takes": "text",
          "required": false,
          "note": "Alt text for the picture; the name when absent."
        },
        {
          "name": "size",
          "takes": "number",
          "required": false,
          "note": "Pixels. The scale: 16 · 24 · 32 · 36 (default)."
        },
        {
          "name": "label",
          "takes": "text",
          "required": false,
          "note": "Say the person's name out loud, for a face that stands on its own — `PersonTrigger`'s compact shape, a stack of members."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-avatar--docs",
      "storyId": "primitives-avatar--initials",
      "docPage": "src/Avatar.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "AvatarGroup",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/AvatarGroup.tsx",
      "purpose": "Up to three overlapping 24px faces with a surface-coloured ring — the member stack for anywhere a group is shown at a glance.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "members",
          "takes": "AvatarGroupMember[]",
          "required": true,
          "note": null
        },
        {
          "name": "size",
          "takes": "number",
          "required": false,
          "note": "Face size in pixels; the overlap follows it. 24 is the members pill, 18 the replies row (Katerina, 2026-09-03) — that row drew its own stack for two months for want of this one number, and drifted while it did."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-avatargroup--docs",
      "storyId": "primitives-avatargroup--three-members",
      "docPage": "src/AvatarGroup.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "Banner",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Banner.tsx",
      "purpose": "The strip under the header where the app says something happened: one line, one of four tones, gone when there is nothing to say.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "tone",
          "takes": "ok | error | info | warning",
          "required": true,
          "note": null
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The one line. Text, or text with a name in `font-medium`."
        },
        {
          "name": "icon",
          "takes": "anything",
          "required": false,
          "note": "A 16px icon before the line, in the tone's colour (Katerina, 2026-09-18: Peek's composer strip became a Banner)."
        },
        {
          "name": "action",
          "takes": "a handler",
          "required": false,
          "note": "The one thing to do: the package's Button, muted and small, at the end of the line."
        },
        {
          "name": "onDismiss",
          "takes": "a handler",
          "required": false,
          "note": "Adds an `✕` at the right-hand end. Absent: the app removes the banner."
        },
        {
          "name": "dismissLabel",
          "takes": "text",
          "required": false,
          "note": "The dismiss button's accessible name. Defaults to \"Dismiss\"."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "tone",
          "values": [
            "ok",
            "error",
            "info",
            "warning"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-banner--docs",
      "storyId": "feedback-banner--ok",
      "docPage": "src/Banner.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "blockAtY",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/BlockHandle.tsx",
      "purpose": "The last of `blocks` whose top is at or above `y` — the gap between two blocks belongs to the one before.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-blockhandle--docs",
      "storyId": "primitives-blockhandle--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "blockDropCursor",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorBlockHandle.tsx",
      "purpose": "The drop line a dragged block shows, in the package's accent instead of the editor's default (the text's colour).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editorblockhandle--docs",
      "storyId": "primitives-editorblockhandle--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "BlockHandle",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/BlockHandle.tsx",
      "purpose": "The handle left of the block under the pointer, as a block-document page has it, and the block's menu behind it.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "actions",
          "takes": "a handler",
          "required": false,
          "note": "The caller's own rows — a link to the block, a comment on it."
        },
        {
          "name": "editing",
          "takes": "BlockHandleEditing",
          "required": false,
          "note": "Given by `EditorBlockHandle` (from `@estiva-app/ui/editor`)."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "What the blocks are drawn in. Reading: a surface whose top-level elements carry `data-block-id`, as `RichText` draws."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-blockhandle--docs",
      "storyId": "primitives-blockhandle--default",
      "docPage": "src/BlockHandle.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "BlockId",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/BlockNodes.tsx",
      "purpose": "`id` on every block, carried as the `blockId` attribute.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-blocknodes--docs",
      "storyId": "primitives-blocknodes--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Breadcrumb",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Breadcrumb.tsx",
      "purpose": "A trail: where you are, and the way back up.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "items",
          "takes": "Crumb[]",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "navigation-breadcrumb--docs",
      "storyId": "navigation-breadcrumb--on-an-item",
      "docPage": "src/Breadcrumb.mdx",
      "app": null,
      "looks": [
        "font-mono text-caption text-text-muted hover:text-text-primary",
        "font-mono text-caption text-text-primary hover:text-text-primary",
        "font-mono text-caption text-text-secondary hover:text-text-primary",
        "truncate font-mono text-caption text-text-muted",
        "truncate font-mono text-caption text-text-primary",
        "truncate font-mono text-caption text-text-secondary"
      ]
    },
    {
      "name": "Button",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Button.tsx",
      "purpose": "The push-button for an action: a verb, clicked once — \"Create\", \"Save\", \"Delete\".",
      "purposeFrom": "page",
      "props": [
        {
          "name": "variant",
          "takes": "primary | outlined | muted | destructive | resolve",
          "required": false,
          "note": null
        },
        {
          "name": "size",
          "takes": "default | small",
          "required": false,
          "note": null
        },
        {
          "name": "leadingIcon",
          "takes": "anything",
          "required": false,
          "note": "16px, stroke 1.5 on the default size; 14px on small."
        },
        {
          "name": "disabledReason",
          "takes": "text",
          "required": false,
          "note": "Why the action cannot succeed right now."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "variant",
          "values": [
            "primary",
            "outlined",
            "muted",
            "destructive",
            "resolve"
          ]
        },
        {
          "prop": "size",
          "values": [
            "default",
            "small"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-button--docs",
      "storyId": "primitives-button--primary",
      "docPage": "src/Button.mdx",
      "app": null,
      "looks": [
        "rounded-md transition-colors font-sans font-medium",
        "bg-accent-primary hover:bg-accent-hover text-text-inverse cursor-pointer signal:font-semibold",
        "border border-border-default hover:bg-bg-hover text-text-primary cursor-pointer",
        "signal:bg-transparent signal:border signal:border-border-default signal:text-text-primary signal:shadow-none signal:hover:bg-success-muted signal:hover:border-success-outline signal:hover:text-success-default signal:transition-colors"
      ]
    },
    {
      "name": "Callout",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/BlockNodes.tsx",
      "purpose": "A callout — SPEC §13.3's `tone` on a quote (RIC-19): a quote drawn to stand out, in one of GitHub's alert kinds (`note`, `tip`, `important`, `warning`, `caution`).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-blocknodes--docs",
      "storyId": "primitives-blocknodes--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "calloutLook",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/RichText.tsx",
      "purpose": "The tone a callout is drawn in: its own, or `note` for one this part does not know (§13.3).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-richtext--docs",
      "storyId": "components-richtext--every-block",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "CaptionedReference",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "A reference mid-sentence, drawn as `label: snippet` and written as its `uri` verbatim (SPEC §13.1).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Card",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Card.tsx",
      "purpose": "A box that stands for one thing — drawn as its frame: 8px corners, a fill and a hairline.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "fill",
          "takes": "surface | elevated | inset | none",
          "required": false,
          "note": "What the card sits on. Default `surface`."
        },
        {
          "name": "href",
          "takes": "text",
          "required": false,
          "note": "The whole card is a link: an anchor, and its hairline answers the pointer."
        },
        {
          "name": "hover",
          "takes": "none | hairline | fill",
          "required": false,
          "note": "How it answers the pointer. Default `hairline` with an `href`, `none` without."
        },
        {
          "name": "quietUntilHover",
          "takes": "true/false",
          "required": false,
          "note": "No hairline until it is pointed at — a row in a feed that shows its edge only when you are on it."
        },
        {
          "name": "hovered",
          "takes": "true/false",
          "required": false,
          "note": "Draw the hover look now, whatever the pointer does."
        },
        {
          "name": "selected",
          "takes": "true/false",
          "required": false,
          "note": "The one you are on: the selected fill, a subtle hairline, and no hover."
        },
        {
          "name": "active",
          "takes": "true/false",
          "required": false,
          "note": "Being changed in place: the selected fill with the accent hairline, and no hover."
        },
        {
          "name": "attention",
          "takes": "accent | warning",
          "required": false,
          "note": "A hairline that asks to be looked at — something new (`accent`), or urgent (`warning`)."
        },
        {
          "name": "unreadable",
          "takes": "true/false",
          "required": false,
          "note": "It stands for something that could not be read: the hairline is dashed."
        },
        {
          "name": "clip",
          "takes": "true/false",
          "required": false,
          "note": "What is inside is cut to the card's rounded corners: a strip or a picture that runs edge to edge (UIG-9, 17 September; the apps passed `overflow-hidden`)."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "fill",
          "values": [
            "surface",
            "elevated",
            "inset",
            "none"
          ]
        },
        {
          "prop": "hover",
          "values": [
            "none",
            "hairline",
            "fill"
          ]
        },
        {
          "prop": "attention",
          "values": [
            "accent",
            "warning"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-card--docs",
      "storyId": "primitives-card--surface",
      "docPage": "src/Card.mdx",
      "app": null,
      "looks": [
        "rounded-lg border bg-bg-surface border-border-default",
        "rounded-lg border bg-bg-surface border-border-default overflow-hidden",
        "rounded-lg border bg-bg-surface border-border-default border-dashed",
        "rounded-lg border bg-bg-surface border-border-default border-dashed overflow-hidden",
        "rounded-lg border bg-bg-surface border-border-default border-accent-muted hover:border-accent-muted",
        "rounded-lg border bg-bg-surface border-border-default border-accent-muted hover:border-accent-muted overflow-hidden",
        "rounded-lg border bg-bg-surface border-border-default border-accent-muted hover:border-accent-muted border-dashed",
        "rounded-lg border bg-bg-surface border-border-default border-accent-muted hover:border-accent-muted border-dashed overflow-hidden",
        "rounded-lg border bg-bg-surface border-border-default border-warning-muted hover:border-warning-muted",
        "rounded-lg border bg-bg-surface border-border-default border-warning-muted hover:border-warning-muted overflow-hidden",
        "rounded-lg border bg-bg-surface border-border-default border-warning-muted hover:border-warning-muted border-dashed",
        "rounded-lg border bg-bg-surface border-border-default border-warning-muted hover:border-warning-muted border-dashed overflow-hidden"
      ]
    },
    {
      "name": "CardUnder",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/CardUnder.tsx",
      "purpose": "The one card added under a piece of text, and the ✕ that removes it.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "onRemove",
          "takes": "a handler",
          "required": false,
          "note": "Draws the ✕. Without it the card shows with none, as it does to anyone but the author."
        },
        {
          "name": "revealOnHover",
          "takes": "true/false",
          "required": false,
          "note": "The ✕ waits for hover or focus: under text already sent."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-cardunder--docs",
      "storyId": "components-cardunder--while-writing",
      "docPage": "src/CardUnder.mdx",
      "app": null,
      "looks": [
        "opacity-0 transition-opacity focus-within:opacity-100 [@media(hover:none)]:opacity-100"
      ]
    },
    {
      "name": "Checkbox",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Checkbox.tsx",
      "purpose": "A 16px square that fills with the accent when checked.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "checked",
          "takes": "true/false",
          "required": true,
          "note": null
        },
        {
          "name": "onChange",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "disabled",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "label",
          "takes": "text",
          "required": false,
          "note": "Words beside the box. With `onChange`, clicking them toggles it too, and they name it, so no `aria-label` is needed."
        },
        {
          "name": "row",
          "takes": "true/false",
          "required": false,
          "note": "The whole row is the target: `leading`, then the words, then the box at the end; the row fills on hover and while checked."
        },
        {
          "name": "leading",
          "takes": "anything",
          "required": false,
          "note": "In a `row`, a picture before the words: an icon, a status."
        },
        {
          "name": "aria-label",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "aria-required",
          "takes": "boolean | 'true' | 'false'",
          "required": false,
          "note": "Set by a `Field` with `required`; a caller inside one owes nothing."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-checkbox--docs",
      "storyId": "inputs-checkbox--unchecked",
      "docPage": "src/Checkbox.mdx",
      "app": null,
      "looks": [
        "rounded-lg transition-colors cursor-pointer hover:bg-bg-hover",
        "rounded-lg transition-colors bg-bg-selected cursor-pointer hover:bg-bg-hover"
      ]
    },
    {
      "name": "Checklist",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/BlockNodes.tsx",
      "purpose": "A checklist item — SPEC §13.3's `checked` on a list item (RIC-19): `true` ticked, `false` not, absent a plain item.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-blocknodes--docs",
      "storyId": "primitives-blocknodes--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Chip",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Chip.tsx",
      "purpose": "A 20px pill for a small piece of standing information — a status, a count, a category — in one of six colour types.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "type",
          "takes": "neutral | brand | info | warning | success | error",
          "required": false,
          "note": null
        },
        {
          "name": "label",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "leadingIcon",
          "takes": "anything",
          "required": false,
          "note": null
        },
        {
          "name": "trailingIcon",
          "takes": "anything",
          "required": false,
          "note": null
        },
        {
          "name": "href",
          "takes": "text",
          "required": false,
          "note": "The chip is a link: a real anchor with the chip's own round shape, so the keyboard ring is round too."
        },
        {
          "name": "onClick",
          "takes": "MouseEventHandler<HTMLAnchorElement>",
          "required": false,
          "note": "With `href`: a router app takes the click here, like `Link`."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "type",
          "values": [
            "neutral",
            "brand",
            "info",
            "warning",
            "success",
            "error"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-chip--docs",
      "storyId": "primitives-chip--neutral",
      "docPage": "src/Chip.mdx",
      "app": null,
      "looks": [
        "bg-accent-muted text-accent-text signal:border signal:border-accent-outline",
        "bg-info-muted text-info-default signal:border signal:border-info-outline",
        "bg-warning-muted text-warning-default signal:border signal:border-warning-outline signal:shadow-glow-warning",
        "bg-success-muted text-success-default signal:border signal:border-success-outline",
        "bg-error-muted text-error-default signal:border signal:border-error-outline",
        "overflow-x-clip text-ellipsis whitespace-nowrap signal:tracking-wide text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums",
        "overflow-x-clip text-ellipsis whitespace-nowrap signal:tracking-wide",
        "rounded-full bg-accent-muted text-accent-text signal:border signal:border-accent-outline",
        "rounded-full bg-info-muted text-info-default signal:border signal:border-info-outline",
        "rounded-full bg-warning-muted text-warning-default signal:border signal:border-warning-outline signal:shadow-glow-warning",
        "rounded-full bg-success-muted text-success-default signal:border signal:border-success-outline",
        "rounded-full bg-error-muted text-error-default signal:border signal:border-error-outline"
      ]
    },
    {
      "name": "ChipInput",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ChipInput.tsx",
      "purpose": "A multi-select input: chips for the chosen, a typeahead for the rest.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "value",
          "takes": "T[]",
          "required": true,
          "note": null
        },
        {
          "name": "onChange",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "options",
          "takes": "T[]",
          "required": true,
          "note": "The directory the typeahead searches."
        },
        {
          "name": "placeholder",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "autoFocus",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "excludeIds",
          "takes": "string[]",
          "required": false,
          "note": "Option ids excluded from the suggestion list (e.g., the current user)."
        },
        {
          "name": "chipLeading",
          "takes": "a handler",
          "required": false,
          "note": "Before a chip's label, 16px — a face, an icon."
        },
        {
          "name": "rowLeading",
          "takes": "a handler",
          "required": false,
          "note": "Before a suggestion row's label, 32px."
        },
        {
          "name": "aria-required",
          "takes": "boolean | 'true' | 'false'",
          "required": false,
          "note": "Set by a `Field` with `required`; a caller inside one owes nothing."
        },
        {
          "name": "aria-label",
          "takes": "text",
          "required": false,
          "note": "The field's name, for a caller that is not inside a `Field` — a `Field`'s label names it already."
        },
        {
          "name": "aria-labelledby",
          "takes": "text",
          "required": false,
          "note": "The id of what names the field on the page — a visible \"To:\", say."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        },
        {
          "id": "walking",
          "behaviour": "Moves through its items with the arrow keys"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-chipinput--docs",
      "storyId": "inputs-chipinput--type-to-search",
      "docPage": "src/ChipInput.mdx",
      "app": null,
      "looks": [
        "bg-bg-elevated border border-border-subtle rounded-md",
        "bg-bg-field border border-border-field shadow-field hover:border-border-strong rounded-lg transition-colors focus-within:border-border-focus focus-within:hover:border-border-focus cursor-text signal:transition-shadow signal:focus-within:shadow-focus-ring",
        "text-body-2 border-none bg-transparent text-text-primary placeholder:text-text-muted outline-none"
      ]
    },
    {
      "name": "chosenOf",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/linked.ts",
      "purpose": "A picker's chosen option, or none.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "cn",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/cn.ts",
      "purpose": "Merge class names, last-one-wins on conflicting Tailwind utilities.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "CodeBlockColours",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CodeBlockColours.ts",
      "purpose": "A code block in an editor, coloured by its language as you type.",
      "purposeFrom": "page",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-codeblockcolours--docs",
      "storyId": "primitives-codeblockcolours--in-an-editor",
      "docPage": "src/CodeBlockColours.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "CollapsibleSection",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/CollapsibleSection.tsx",
      "purpose": "A section that opens and closes: a SectionHeader whose title is the toggle, and the rows under it, sliding shut and open.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "title",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "defaultOpen",
          "takes": "true/false",
          "required": false,
          "note": "Open unless told otherwise."
        },
        {
          "name": "open",
          "takes": "true/false",
          "required": false,
          "note": "The caller owns the state."
        },
        {
          "name": "onOpenChange",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "pending",
          "takes": "true/false",
          "required": false,
          "note": "Opened, and its rows are not in yet: the title says open — the arrow turned, `aria-expanded`, `aria-busy` — and the panel stays shut until this is false, then slides open once, rows and all."
        },
        {
          "name": "storageKey",
          "takes": "text",
          "required": false,
          "note": "Remember open or closed in this browser, under this key."
        },
        {
          "name": "icon",
          "takes": "anything",
          "required": false,
          "note": "16px, before the title; the arrow takes its place on hover — `SectionHeader`'s."
        },
        {
          "name": "trailing",
          "takes": "anything",
          "required": false,
          "note": "Beside the title and always visible, before the actions — a count."
        },
        {
          "name": "actions",
          "takes": "SectionAction[]",
          "required": false,
          "note": "Beside the title, revealed while the row is hovered or keyboard-focused — `SectionHeader`'s."
        },
        {
          "name": "menu",
          "takes": "anything",
          "required": false,
          "note": "Beside the actions, revealed with them: the section's \"More options\" menu, `MenuItem`s — `SectionHeader`'s."
        },
        {
          "name": "menuLabel",
          "takes": "text",
          "required": false,
          "note": "The ⋮'s accessible name — `SectionHeader`'s."
        },
        {
          "name": "showActions",
          "takes": "hover | always",
          "required": false,
          "note": null
        },
        {
          "name": "look",
          "takes": "heading | row",
          "required": false,
          "note": "`heading` (default): the title is a section heading."
        },
        {
          "name": "indent",
          "takes": "true/false",
          "required": false,
          "note": "With the `heading` look: the rows start under the title, past the chevron — a folder in a sidebar, its files lightly indented under its name (Katerina, 2 October)."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The rows."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "On the section's box: `mt-2` between groups, `shrink-0` in a scrolling column."
        },
        {
          "name": "contentClassName",
          "takes": "text",
          "required": false,
          "note": "On the box the rows sit in: the gap between them."
        }
      ],
      "variants": [
        {
          "prop": "showActions",
          "values": [
            "hover",
            "always"
          ]
        },
        {
          "prop": "look",
          "values": [
            "heading",
            "row"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "navigation-collapsiblesection--docs",
      "storyId": "navigation-collapsiblesection--default",
      "docPage": "src/CollapsibleSection.mdx",
      "app": null,
      "looks": [
        "overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none"
      ]
    },
    {
      "name": "CommandPalette",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/CommandPalette.tsx",
      "purpose": "A window that searches and runs things: a field, rows in groups, and a footer naming the keys that work right now.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "open",
          "takes": "true/false",
          "required": true,
          "note": null
        },
        {
          "name": "onOpenChange",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": "The window's name for a screen reader — there is no title on screen."
        },
        {
          "name": "where",
          "takes": "text",
          "required": false,
          "note": "The footer's left side: where the palette was opened from."
        },
        {
          "name": "modKey",
          "takes": "text",
          "required": false,
          "note": "How the footer spells the modifier in `Ctrl+Backspace` and `Ctrl+Enter` — `Cmd` on a Mac."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "One level: a `CommandPaletteSearch` or a `CommandPaletteForm`."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "scroll-lock",
          "behaviour": "Stops the page behind it scrolling"
        },
        {
          "id": "walking",
          "behaviour": "Moves through its items with the arrow keys"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-commandpalette--docs",
      "storyId": "overlays-commandpalette--first-level",
      "docPage": "src/CommandPalette.mdx",
      "app": null,
      "looks": [
        "overflow-hidden rounded-lg border border-border-default bg-bg-elevated shadow-lg outline-none"
      ]
    },
    {
      "name": "CommandPaletteAnswer",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/CommandPalette.tsx",
      "purpose": "A written answer, with marks that point at the rows it came from.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "children",
          "takes": "text",
          "required": true,
          "note": "The answer's text. A blank line starts a new paragraph, and a number in square brackets — `[1]` — is drawn as a small mark pointing at the row of the same number below."
        },
        {
          "name": "note",
          "takes": "text",
          "required": false,
          "note": "A quiet line under the answer — what a key will do now."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-commandpalette--docs",
      "storyId": "overlays-commandpalette--first-level",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "CommandPaletteForm",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/CommandPalette.tsx",
      "purpose": "The palette as a form: fields, one submit button, and Ctrl+Enter — both ways in run Base UI's field check.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "chip",
          "takes": "CommandPaletteChip",
          "required": true,
          "note": "Names what the form makes, and goes back when removed."
        },
        {
          "name": "icon",
          "takes": "anything",
          "required": false,
          "note": "Before the chip, 16px — the mark of whatever the form writes to."
        },
        {
          "name": "submitLabel",
          "takes": "text",
          "required": true,
          "note": "The button's word, and the footer's beside Ctrl+Enter."
        },
        {
          "name": "onSubmit",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "submitWaits",
          "takes": "text",
          "required": false,
          "note": "Why submitting has to wait — nothing changed yet."
        },
        {
          "name": "working",
          "takes": "{ button: string; line: string }",
          "required": false,
          "note": "While the thing is being made: the fields lock, the button reads `button`, and `line` says what is happening."
        },
        {
          "name": "error",
          "takes": "text",
          "required": false,
          "note": "What went wrong, beside the button."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The fields, each in a `Field`."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-commandpalette--docs",
      "storyId": "overlays-commandpalette--first-level",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "CommandPaletteProposal",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/CommandPalette.tsx",
      "purpose": "Something the palette offers to make, before anything is made: a card with where it would be made on top, then what it would be.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "source",
          "takes": "text",
          "required": true,
          "note": "Where it would be made: the app and the action — \"App › New item\"."
        },
        {
          "name": "mark",
          "takes": "anything",
          "required": false,
          "note": "The app's mark before the source, as small as the line (about 10px)."
        },
        {
          "name": "children",
          "takes": "text",
          "required": true,
          "note": "What would be made, in a sentence."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-commandpalette--docs",
      "storyId": "overlays-commandpalette--first-level",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "CommandPaletteQuote",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/CommandPalette.tsx",
      "purpose": "Text written to be used elsewhere, set off by a rule at its left edge.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "children",
          "takes": "text",
          "required": true,
          "note": "Text written for someone to use — shown as it will be used, line breaks kept."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-commandpalette--docs",
      "storyId": "overlays-commandpalette--first-level",
      "docPage": null,
      "app": null,
      "looks": [
        "whitespace-pre-wrap border-l-2 border-border-default text-body-2 text-text-primary"
      ]
    },
    {
      "name": "CommandPaletteSearch",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/CommandPalette.tsx",
      "purpose": "The palette as a search: a query field, rows in labelled groups walked with the arrow keys, and what to show while nothing has arrived and when nothing matches.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "query",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "onQueryChange",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "placeholder",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "groups",
          "takes": "CommandPaletteGroup[]",
          "required": true,
          "note": null
        },
        {
          "name": "chip",
          "takes": "CommandPaletteChip",
          "required": false,
          "note": "The level you are in. Without one, this is the first level and there is nowhere to go back to."
        },
        {
          "name": "pending",
          "takes": "text",
          "required": false,
          "note": "A line under the rows while more are on their way — \"Searching…\"."
        },
        {
          "name": "notes",
          "takes": "string[]",
          "required": false,
          "note": "Quiet lines under the rows, for what a person should know about them and cannot act on — \"2 more where you cannot open them\", \"the search was refused, so this list is incomplete\"."
        },
        {
          "name": "empty",
          "takes": "text",
          "required": false,
          "note": "The line when there are no rows. Leave it out while rows are still on their way."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "Above the rows: a `CommandPaletteWorking`, `CommandPaletteAnswer` or `CommandPaletteQuote`."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "walking",
          "behaviour": "Moves through its items with the arrow keys"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-commandpalette--docs",
      "storyId": "overlays-commandpalette--first-level",
      "docPage": null,
      "app": null,
      "looks": [
        "bg-transparent text-input-value text-text-primary outline-none placeholder:text-text-muted"
      ]
    },
    {
      "name": "CommandPaletteWorking",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/CommandPalette.tsx",
      "purpose": "A line saying what is being worked on, with grey bars where the result will land.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "What is happening — \"Reading 12 messages…\"."
        },
        {
          "name": "bars",
          "takes": "0 | 1 | 2 | 3",
          "required": false,
          "note": "Grey bars under the line, where the result will be."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-commandpalette--docs",
      "storyId": "overlays-commandpalette--first-level",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "CommentBox",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CommentBox.tsx",
      "purpose": "The one box every app writes a comment, a reply and a line of a conversation in: `@`, `!@`, `[` and `/`, the keys, drafts, files, editing, sending and a refused send.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "people",
          "takes": "readonly MentionPerson[]",
          "required": true,
          "note": "Who `@` and `!@` offer."
        },
        {
          "name": "references",
          "takes": "a handler",
          "required": false,
          "note": "What `[` lists for what was typed, already in the app's order."
        },
        {
          "name": "referencesChanged",
          "takes": "a handler",
          "required": false,
          "note": "Called with a listener while `[` is open; call it when `references` would answer differently (a search landed)."
        },
        {
          "name": "referenceIcon",
          "takes": "a handler",
          "required": false,
          "note": "A `[` row's and chip's 16px icon from what it points at; absent, a neutral square."
        },
        {
          "name": "insert",
          "takes": "readonly SlashCommand[]",
          "required": false,
          "note": "The app's own `/` Insert rows, after the shared Format section: {@link commentBoxRows} and its own."
        },
        {
          "name": "code",
          "takes": "CodeFormat",
          "required": false,
          "note": "`/` → Code: a mark inside the line, or a block."
        },
        {
          "name": "send",
          "takes": "a handler",
          "required": true,
          "note": "Send what is written, with the files that are ready and the card still shown; resolves with the relay's answer."
        },
        {
          "name": "under",
          "takes": "BoxUnder",
          "required": false,
          "note": "The card and parts under the box while something is written, with ✕ on the card."
        },
        {
          "name": "showsAtOnce",
          "takes": "true/false",
          "required": false,
          "note": "The app shows a send before the relay answers: the box empties at once, and a refusal puts the words back."
        },
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": "The editor's accessible name: what the box is for."
        },
        {
          "name": "placeholder",
          "takes": "anything",
          "required": true,
          "note": "Said in the empty box."
        },
        {
          "name": "draft",
          "takes": "CommentBoxDraft",
          "required": false,
          "note": "Keeps what is written when the box goes away."
        },
        {
          "name": "edit",
          "takes": "CommentBoxEdit",
          "required": false,
          "note": "Editing something already sent."
        },
        {
          "name": "upload",
          "takes": "a handler",
          "required": false,
          "note": "Offers the paperclip, `/` → File, a pasted picture and a dropped file: uploads one, and answers."
        },
        {
          "name": "accept",
          "takes": "text",
          "required": false,
          "note": "The file picker's `accept`."
        },
        {
          "name": "closed",
          "takes": "{ reason: ReactNode }",
          "required": false,
          "note": "The box cannot write here (an archived file, signed out): a line saying why takes its place."
        },
        {
          "name": "referenceView",
          "takes": "ComponentType<ReferenceViewProps>",
          "required": false,
          "note": "How a `nostr:` reference the box holds is drawn — the app's own chip."
        },
        {
          "name": "extensions",
          "takes": "readonly AnyExtension[]",
          "required": false,
          "note": "The app's own extra editor extensions: link chips, highlights."
        },
        {
          "name": "autoFocus",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "onSent",
          "takes": "a handler",
          "required": false,
          "note": "Called with what was sent once it went out: at once when `showsAtOnce`, else on the answer."
        },
        {
          "name": "onRefused",
          "takes": "a handler",
          "required": false,
          "note": "Called when a send shown at once was refused, so the app takes it back."
        },
        {
          "name": "marked",
          "takes": "a handler",
          "required": false,
          "note": "The bar down the text's left edge shows while this holds, besides while an urgent mention is in the box: the app's own marks (a highlight)."
        },
        {
          "name": "onEditor",
          "takes": "a handler",
          "required": false,
          "note": "Called with the box's editor once it is drawn, and with `null` as it goes: an app's launcher inserts into the box last used."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-commentbox--docs",
      "storyId": "primitives-commentbox--empty",
      "docPage": "src/CommentBox.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "commentBoxRows",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CommentBox.tsx",
      "purpose": "The `/` Insert rows the kit offers. Pass the ones an app can perform, in its order, with its own after them; an edit drops Upload and Urgent itself.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-commentbox--docs",
      "storyId": "primitives-commentbox--empty",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "CommentCount",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkParts.tsx",
      "purpose": "The count of what was said, a link to where it is read.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "conversation",
          "takes": "LinkedConversation",
          "required": true,
          "note": null
        },
        {
          "name": "noun",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkparts--docs",
      "storyId": "components-linkparts--pickers",
      "docPage": null,
      "app": null,
      "looks": [
        "-mx-1 rounded-sm text-caption tabular-nums hover:bg-bg-active font-medium text-text-primary",
        "-mx-1 rounded-sm text-caption tabular-nums hover:bg-bg-active text-text-secondary",
        "-mx-1 rounded-sm text-caption tabular-nums hover:bg-bg-active"
      ]
    },
    {
      "name": "commentElement",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CommentHighlights.ts",
      "purpose": "What a comment's card stands beside: its drawn highlight, or — its words gone — its first block.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-commenthighlights--docs",
      "storyId": "primitives-commenthighlights--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "CommentHighlights",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CommentHighlights.ts",
      "purpose": "Comments drawn where they are in an editor of a block document: on a few words, on a passage across blocks, or on whole blocks, in a light fill, the open one underlined.",
      "purposeFrom": "page",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-commenthighlights--docs",
      "storyId": "primitives-commenthighlights--default",
      "docPage": "src/CommentHighlights.mdx",
      "app": null,
      "looks": [
        "cursor-pointer rounded-sm bg-warning-muted underline decoration-warning-default decoration-2 underline-offset-4"
      ]
    },
    {
      "name": "commentPlace",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CommentHighlights.ts",
      "purpose": "Where a comment is now: on its words or blocks, beside its blocks with its words gone, or detached.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-commenthighlights--docs",
      "storyId": "primitives-commenthighlights--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ConfirmDialog",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ConfirmDialog.tsx",
      "purpose": "A question with two answers, asked before something a person would want back.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "title",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The body — plain sentences, body-2."
        },
        {
          "name": "confirmLabel",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "destructive",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "onConfirm",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "onClose",
          "takes": "a handler",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "scroll-lock",
          "behaviour": "Stops the page behind it scrolling"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-confirmdialog--docs",
      "storyId": "overlays-confirmdialog--destructive",
      "docPage": "src/ConfirmDialog.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "ContainerHeader",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ContainerHeader.tsx",
      "purpose": "The bar across the top of a column — a list, a thread, a side panel: its title, and the buttons that act on the whole column at the right edge. 48px, with a hairline under it.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "title",
          "takes": "anything",
          "required": true,
          "note": "A string keeps the one-line treatment; a node is drawn as given."
        },
        {
          "name": "chevron",
          "takes": "true/false",
          "required": false,
          "note": "A chevron after the title, for a title that opens something."
        },
        {
          "name": "titleMenu",
          "takes": "anything",
          "required": false,
          "note": "The menu the title opens: `MenuItem`s — the column's views (Katerina, 5 October: Peek's Topics column, Topics or Folders)."
        },
        {
          "name": "actions",
          "takes": "anything",
          "required": false,
          "note": "The column's own buttons, at the right edge: IconButtons with tooltips, 4px apart."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "navigation-containerheader--docs",
      "storyId": "navigation-containerheader--with-title-menu",
      "docPage": "src/ContainerHeader.mdx",
      "app": null,
      "looks": [
        "cursor-pointer rounded-md transition-colors hover:bg-bg-hover"
      ]
    },
    {
      "name": "deleteBlock",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorBlockHandle.tsx",
      "purpose": "Removes the block, the caret where it was.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editorblockhandle--docs",
      "storyId": "primitives-editorblockhandle--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "deleteTableColumn",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorTableControls.tsx",
      "purpose": "The same for a column: the last one deletes the table.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editortablecontrols--docs",
      "storyId": "primitives-editortablecontrols--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "deleteTableRow",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorTableControls.tsx",
      "purpose": "The cell's row, or the whole table when it is its only one: a table holds at least one row (prosemirror-tables refuses to delete it).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editortablecontrols--docs",
      "storyId": "primitives-editortablecontrols--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "DialogShell",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/DialogShell.tsx",
      "purpose": "The dialog, minus what it says: the portal, the backdrop, a 502px card, a 48px header with the title and a close button, a body, and a 48px footer for the buttons.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "title",
          "takes": "text",
          "required": true,
          "note": "Labels the dialog for assistive tech, and renders as the header text unless `headerContent` replaces it."
        },
        {
          "name": "onClose",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "headerContent",
          "takes": "anything",
          "required": false,
          "note": "Replaces the title text in the header — a back button beside the title, a count chip after it."
        },
        {
          "name": "footer",
          "takes": "anything",
          "required": false,
          "note": "Absent: no footer row, and the body keeps the card's own bottom edge (a roster that simply ends)."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "bodyClassName",
          "takes": "text",
          "required": false,
          "note": "Extra classes on the body: its layout and any padding override (`flex flex-col gap-6`, `p-0 py-2`)."
        },
        {
          "name": "bodyMaxHeight",
          "takes": "text",
          "required": false,
          "note": "How tall the body may get before it scrolls, as the cap class — `max-h-[400px]`, `max-h-[70vh]`."
        },
        {
          "name": "width",
          "takes": "number",
          "required": false,
          "note": null
        },
        {
          "name": "alert",
          "takes": "true/false",
          "required": false,
          "note": "A question that has to be answered rather than clicked away: a press on the backdrop no longer closes it, and it announces itself as an alert."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "scroll-lock",
          "behaviour": "Stops the page behind it scrolling"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-dialogshell--docs",
      "storyId": "overlays-dialogshell--default",
      "docPage": "src/DialogShell.mdx",
      "app": null,
      "looks": [
        "bg-bg-elevated border border-border-subtle rounded-lg shadow-lg pointer-events-auto overflow-hidden outline-none"
      ]
    },
    {
      "name": "Divider",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Divider.tsx",
      "purpose": "A hairline in `border-subtle`. Horizontal it is inset 12px each side; `orientation=\"vertical\"` stands it up to its row's height, no inset.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "orientation",
          "takes": "horizontal | vertical",
          "required": false,
          "note": null
        },
        {
          "name": "label",
          "takes": "text",
          "required": false,
          "note": "Words in the middle of the line — \"New since you last read this\", a date."
        },
        {
          "name": "tone",
          "takes": "default | warning",
          "required": false,
          "note": "`warning` for a line that asks for attention: the label in the warning colour, the lines in its wash."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "orientation",
          "values": [
            "horizontal",
            "vertical"
          ]
        },
        {
          "prop": "tone",
          "values": [
            "default",
            "warning"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-divider--docs",
      "storyId": "primitives-divider--default",
      "docPage": "src/Divider.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "DocumentEditor",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/DocumentEditor.tsx",
      "purpose": "One document's text as one surface that is always an editor, the same in every app: `/`, `[` and `@`, links on words, files, checklists, callouts and tables, the block handle, saving when you leave, someone else's save arriving, and the text held when the sign-in ends.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "value",
          "takes": "text",
          "required": true,
          "note": "The saved text. A new value while the editor is open is somebody else's save, or your own coming back."
        },
        {
          "name": "format",
          "takes": "text",
          "required": true,
          "note": "The format `value` is in, handed to `codec.read`."
        },
        {
          "name": "codec",
          "takes": "DocumentCodec",
          "required": true,
          "note": null
        },
        {
          "name": "onCommit",
          "takes": "a handler",
          "required": true,
          "note": "Save. Called when you leave, never while typing, with the text, its format, and the saved text this edit started from — so the app can tell whom the save names anew."
        },
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": "The editor's accessible name."
        },
        {
          "name": "placeholder",
          "takes": "anything",
          "required": false,
          "note": "Muted words over an empty editor."
        },
        {
          "name": "readOnly",
          "takes": "true/false",
          "required": false,
          "note": "For reading: nothing is typed or saved; chips open, and comments on a selection work when on."
        },
        {
          "name": "changedBy",
          "takes": "{ name: string } | null",
          "required": false,
          "note": "Who saved the text last, when it was not you: named in \"… saved a newer version\"."
        },
        {
          "name": "onLeftUnsaved",
          "takes": "a handler",
          "required": false,
          "note": "A save refused after the editor closed, with nothing left on screen to say it."
        },
        {
          "name": "hold",
          "takes": "HeldTyping",
          "required": false,
          "note": "Where text typed when the sign-in ends is held, under `holdKey`."
        },
        {
          "name": "holdKey",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "references",
          "takes": "DocumentReferences",
          "required": false,
          "note": "`[` and `/` → File."
        },
        {
          "name": "mentions",
          "takes": "DocumentMentions",
          "required": false,
          "note": "`@` and `/` → Mention."
        },
        {
          "name": "linkChips",
          "takes": "LinkChipsOptions",
          "required": false,
          "note": "A pasted app URL drawn as the chip of what it names (`LinkChips`)."
        },
        {
          "name": "upload",
          "takes": "a handler",
          "required": false,
          "note": "`/` → Upload, and a pasted picture: upload one file and answer the attachment's attributes (its `imeta` fields)."
        },
        {
          "name": "readMarkdown",
          "takes": "a handler",
          "required": false,
          "note": "Plain text pasted as the blocks it spells: the app's reader of markdown, as the editor's document."
        },
        {
          "name": "table",
          "takes": "true/false",
          "required": false,
          "note": "`/` → Table. Default on."
        },
        {
          "name": "onCommentOnSelection",
          "takes": "a handler",
          "required": false,
          "note": "Comment on what is selected: the selection strip's Comment, and the comment highlights."
        },
        {
          "name": "blockRows",
          "takes": "a handler",
          "required": false,
          "note": "The app's rows in a block's handle menu, after the editing ones: Copy link, Comment."
        },
        {
          "name": "referenceView",
          "takes": "ComponentType<ReferenceViewProps>",
          "required": false,
          "note": "Draws a link: the app's own, which resolves what it names — its chip, its row or its card in the row's place, as `place` says (§13.3)."
        },
        {
          "name": "attachmentView",
          "takes": "ComponentType<AttachmentViewProps>",
          "required": false,
          "note": "Draws a placed file: the app's own card."
        },
        {
          "name": "wrap",
          "takes": "a handler",
          "required": false,
          "note": "Around everything the editor draws: the app's providers, which may read the editor."
        },
        {
          "name": "onEditor",
          "takes": "a handler",
          "required": false,
          "note": "The editor, once it is there, and `null` as it goes."
        },
        {
          "name": "extensions",
          "takes": "readonly AnyExtension[]",
          "required": false,
          "note": "More of the app's own extensions."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-documenteditor--docs",
      "storyId": "primitives-documenteditor--with-comments",
      "docPage": "src/DocumentEditor.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "duplicateBlock",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorBlockHandle.tsx",
      "purpose": "A copy of the block straight after it, the caret in the copy.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editorblockhandle--docs",
      "storyId": "primitives-editorblockhandle--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "EditableText",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/EditableText.tsx",
      "purpose": "Text you click to edit. It reads as text until clicked; then it is a field.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "value",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "placeholder",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "onCommit",
          "takes": "a handler",
          "required": true,
          "note": "Resolve `true` when saved; `false` (or throw) keeps the field open with the text."
        },
        {
          "name": "multiline",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "Applied to both the text and the field, so they are the same size."
        },
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": "The accessible name of the field — \"Title\", \"Description\"."
        },
        {
          "name": "display",
          "takes": "text",
          "required": false,
          "note": "What to *show* when not editing, when that differs from what is edited — a value carrying a raw reference that the caller renders as a live object below the text, say."
        },
        {
          "name": "displayNode",
          "takes": "anything",
          "required": false,
          "note": "What to *draw* when not editing, when the value is structured rather than a line of prose."
        },
        {
          "name": "readOnly",
          "takes": "true/false",
          "required": false,
          "note": "Show the value only — no edit affordance."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-editabletext--docs",
      "storyId": "inputs-editabletext--title",
      "docPage": "src/EditableText.mdx",
      "app": null,
      "looks": [
        "rounded-md border border-border-strong bg-bg-inset text-text-primary outline-none",
        "rounded-md border border-border-strong bg-bg-inset text-text-primary outline-none resize-none",
        "rounded-md border border-transparent text-left transition-colors hover:border-border-default text-text-primary",
        "rounded-md border border-transparent text-left transition-colors hover:border-border-default text-text-muted",
        "rounded-md border border-transparent text-left transition-colors hover:border-border-default whitespace-pre-wrap text-text-primary",
        "rounded-md border border-transparent text-left transition-colors hover:border-border-default whitespace-pre-wrap text-text-muted",
        "rounded-md border border-transparent text-left transition-colors hover:border-border-default"
      ]
    },
    {
      "name": "EditorBlockHandle",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorBlockHandle.tsx",
      "purpose": "`BlockHandle` in a Tiptap editor: drag the handle to move the block, press it for Turn into, Duplicate and Delete, then the app's rows.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "editor",
          "takes": "Editor | null",
          "required": true,
          "note": "The editor. Not editable, or not there yet, and the handle reads: the caller's rows only."
        },
        {
          "name": "turnInto",
          "takes": "a handler",
          "required": false,
          "note": "Turn into's rows for a block. By default `turnIntoRows`, the same in every app: a block of text, a list and a quote each get theirs."
        },
        {
          "name": "actions",
          "takes": "a handler",
          "required": false,
          "note": "The caller's own rows, after the editing ones."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The `EditorContent`."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editorblockhandle--docs",
      "storyId": "primitives-editorblockhandle--default",
      "docPage": "src/EditorBlockHandle.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "EditorTableControls",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorTableControls.tsx",
      "purpose": "A table's own controls in a Tiptap editor: point at a cell for a handle on its row and on its column, and a ➕ bar under the table and right of it.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "editor",
          "takes": "Editor | null",
          "required": true,
          "note": "The editor, with TableKit (`@tiptap/extension-table`) in its extensions."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The `EditorContent`."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editortablecontrols--docs",
      "storyId": "primitives-editortablecontrols--default",
      "docPage": "src/EditorTableControls.mdx",
      "app": null,
      "looks": [
        "rounded-lg border border-border-default bg-bg-elevated shadow-lg shadow-none -translate-x-1/2 -translate-y-1/2",
        "rounded-lg border border-border-default bg-bg-elevated shadow-lg shadow-none"
      ]
    },
    {
      "name": "EmptyState",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/EmptyState.tsx",
      "purpose": "The place where content will be once there is some, in two manners: a 16px icon over a centred line when the whole page is empty, the line alone and left-aligned when one section of a page is.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "icon",
          "takes": "anything",
          "required": false,
          "note": "16px, stroke 1.5. A speech bubble when absent."
        },
        {
          "name": "message",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "scope",
          "takes": "page | section",
          "required": false,
          "note": "`page` when the whole page is empty; `section` when one part of it is."
        },
        {
          "name": "action",
          "takes": "ButtonAction",
          "required": false,
          "note": "The one thing to do about it — \"New topic\", \"Try again\" — drawn 16px under the line as the package's Button, outlined (Katerina, 2026-09-18)."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "scope",
          "values": [
            "page",
            "section"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-emptystate--docs",
      "storyId": "feedback-emptystate--page",
      "docPage": "src/EmptyState.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "EnterHint",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Menu.tsx",
      "purpose": "The keyboard hint a picker row shows while highlighted — hand-rolled in five files before this (2026-09-01), and drawn as its own thing until 2026-09-05, when it became the `Kbd` chip every other key hint uses.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "target",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-menu--docs",
      "storyId": "overlays-menu--items",
      "docPage": null,
      "app": null,
      "looks": [
        "text-menu signal:font-mono signal:text-small signal:tracking-wider leaf:font-mono leaf:text-small leaf:tracking-wider"
      ]
    },
    {
      "name": "EntryShell",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/EntryShell.tsx",
      "purpose": "What an app shows while nobody is signed in to it: its logo, one line saying why, and at most one button.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "logo",
          "takes": "anything",
          "required": true,
          "note": "The app's own mark, drawn at the top in every state, as given: the app sizes it."
        },
        {
          "name": "busy",
          "takes": "true/false",
          "required": false,
          "note": "Entry is still being decided: the logo alone, faded in after 150ms (as a Skeleton is), so an entry that resolves at once flashes nothing."
        },
        {
          "name": "busyLabel",
          "takes": "text",
          "required": false,
          "note": "What a screen reader hears while `busy`; nothing is drawn for it."
        },
        {
          "name": "message",
          "takes": "anything",
          "required": false,
          "note": "The one line saying why nobody is signed in, announced politely when it appears."
        },
        {
          "name": "action",
          "takes": "ButtonAction & { disabled?: boolean }",
          "required": false,
          "note": "The one thing to do about it, drawn under the line (or alone, with no `message`) as the package's primary Button."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-entryshell--docs",
      "storyId": "frame-entryshell--message-with-action",
      "docPage": "src/EntryShell.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "ErrorBoundary",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ErrorBoundary.tsx",
      "purpose": "Keeps a crash inside what it holds: that part shows \"Something went wrong … Your data is safe — try again.\" with a Try again button, and the rest of the page keeps working.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "label",
          "takes": "text",
          "required": false,
          "note": "What it holds, said in the message and the console line: \"Something went wrong in the {label}.\""
        },
        {
          "name": "fallbackClassName",
          "takes": "text",
          "required": false,
          "note": "The room the message fills where no flex column holds it — the whole screen, for the app's own."
        },
        {
          "name": "frame",
          "takes": "a handler",
          "required": false,
          "note": "Draws the message inside a frame of yours, in the same place: `ListColumn` keeps its title this way."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-errorboundary--docs",
      "storyId": "feedback-errorboundary--in-a-panel",
      "docPage": "src/ErrorBoundary.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "Field",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Field.tsx",
      "purpose": "A label over a control — the form row. The label is the `input-label` token; `required` marks it with the error-coloured asterisk.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "required",
          "takes": "true/false",
          "required": false,
          "note": "Draws the asterisk and marks the control `aria-required`, so the mark means something to a reader who cannot see it."
        },
        {
          "name": "helper",
          "takes": "text",
          "required": false,
          "note": "A hint under the control — what the format is, what happens if it is left empty."
        },
        {
          "name": "error",
          "takes": "text",
          "required": false,
          "note": "What is wrong, in the same place as the helper and in the error colour."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-field--docs",
      "storyId": "inputs-field--default",
      "docPage": "src/Field.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "FieldLine",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Field.tsx",
      "purpose": "The small line a Field draws under a control — on its own, for the places where there is no single control to draw it under.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "tone",
          "takes": "helper | warning | error",
          "required": false,
          "note": "`helper` (muted) is a hint; `warning` (amber) and `error` (red) are outcomes."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "tone",
          "values": [
            "helper",
            "warning",
            "error"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-field-line--docs",
      "storyId": "inputs-field-line--helper",
      "docPage": "src/FieldLine.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "FilePicker",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/FilePicker.tsx",
      "purpose": "The browser's file picker, with nothing drawn.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "onPick",
          "takes": "a handler",
          "required": true,
          "note": "The chosen files, in the order the picker gave them."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-filepicker--docs",
      "storyId": "inputs-filepicker--default",
      "docPage": "src/FilePicker.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "filterPeople",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "The people whose name holds the query, the first {@link PEOPLE_LIMIT} of them.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "filterReferences",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "The references whose label or text holds the query — the last {@link REFERENCE_LIMIT}, in the order given: a thread is unbounded, and a list that grew with it would be a hundred rows of prose.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "filterSlashSections",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "The sections narrowed to a query — the text typed after the `/`.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "findLinkChips",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/LinkChips.ts",
      "purpose": "What to change in a document, and what to ask.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-linkchips--docs",
      "storyId": "primitives-linkchips--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Form",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Form.tsx",
      "purpose": "The fields and the button that sends them.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "onSubmit",
          "takes": "a handler",
          "required": true,
          "note": "Enter in a field, or a submit button. The page's own submit is already prevented."
        },
        {
          "name": "busy",
          "takes": "true/false",
          "required": false,
          "note": "While sending: every field and button inside is switched off, and focus waits on the form."
        },
        {
          "name": "enterSends",
          "takes": "true/false",
          "required": false,
          "note": "Whether Enter in a one-line field sends."
        },
        {
          "name": "layout",
          "takes": "fields | free",
          "required": false,
          "note": "`fields`, the default: everything inside stacks 24px apart."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "layout",
          "values": [
            "fields",
            "free"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-form--docs",
      "storyId": "inputs-form--default",
      "docPage": "src/Form.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "FORMATS",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "The formats `/` offers, in order. The hint is what you would type, not a key chord.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "formatSection",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "The Format section every app's `/` opens with.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "hueFor",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Avatar.tsx",
      "purpose": "The colour a person's initials sit on, chosen from a key: the same key always gives the same hue, so a face reads as theirs in every app.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-avatar--docs",
      "storyId": "primitives-avatar--initials",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "IconButton",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/IconButton.tsx",
      "purpose": "A square button around a 16px icon: 4px padding, 8px radius, three variants.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "variant",
          "takes": "muted | outlined | primary | current | resolve",
          "required": false,
          "note": "`current` takes the colour of what it sits in — the ✕ on a `Banner` wears the banner's tone."
        },
        {
          "name": "pressed",
          "takes": "true/false",
          "required": false,
          "note": "On, like a Bold button while the selection is bold: the active fill, and `aria-pressed`."
        },
        {
          "name": "glow",
          "takes": "true/false",
          "required": false,
          "note": "A glow in Signal — the send arrow while there is something to send."
        },
        {
          "name": "tooltip",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "tooltipShortcut",
          "takes": "text",
          "required": false,
          "note": "A key hint drawn as the `Kbd` chip inside the tooltip — for a button whose only other affordance is a keyboard shortcut."
        },
        {
          "name": "tooltipPlacement",
          "takes": "top | bottom",
          "required": false,
          "note": null
        },
        {
          "name": "disabledReason",
          "takes": "text",
          "required": false,
          "note": "Why the action cannot succeed right now."
        },
        {
          "name": "href",
          "takes": "text",
          "required": false,
          "note": "A link that looks like an icon button: an anchor, so the address stays real for a modified click or a new tab, as `Link` keeps it."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The icon: 16px, stroke 1.5."
        }
      ],
      "variants": [
        {
          "prop": "variant",
          "values": [
            "muted",
            "outlined",
            "primary",
            "current",
            "resolve"
          ]
        },
        {
          "prop": "tooltipPlacement",
          "values": [
            "top",
            "bottom"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-iconbutton--docs",
      "storyId": "primitives-iconbutton--muted",
      "docPage": "src/IconButton.mdx",
      "app": null,
      "looks": [
        "border border-border-default hover:bg-bg-hover text-text-secondary"
      ]
    },
    {
      "name": "IdentityMenu",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/IdentityMenu.tsx",
      "purpose": "Who you are, and where you are: the identity trigger for a top bar, and the menu it opens — ready-made, because every app needs one and it is built of nothing but shared parts.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "me",
          "takes": "Identity",
          "required": true,
          "note": null
        },
        {
          "name": "signedIn",
          "takes": "true/false",
          "required": true,
          "note": "Signed in through Estiva ID, as opposed to a browser-held key."
        },
        {
          "name": "relayUrl",
          "takes": "text",
          "required": false,
          "note": "Names the workspace; absent hides the workspace section."
        },
        {
          "name": "idBase",
          "takes": "text",
          "required": false,
          "note": "Estiva ID's base URL when this build offers sign-in; absent = anonymous-only build."
        },
        {
          "name": "onCopyKey",
          "takes": "a handler",
          "required": false,
          "note": "\"Copy public key\" appears only when the app can supply one."
        },
        {
          "name": "onSignOut",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "compact",
          "takes": "true/false",
          "required": false,
          "note": "Face-only trigger, 36px — no chevron, no name beside it."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "App-specific rows, drawn as their own group between the workspace section and the actions."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "navigation-identitymenu--docs",
      "storyId": "navigation-identitymenu--anonymous",
      "docPage": "src/IdentityMenu.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "IdentityPanel",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/IdentityMenu.tsx",
      "purpose": "The identity rows on a panel of their own, with no menu around them — for a docs page, or anywhere the panel is already placed.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "onClose",
          "takes": "a handler",
          "required": false,
          "note": "Called when a row asks the menu to close."
        },
        {
          "name": "me",
          "takes": "Identity",
          "required": true,
          "note": null
        },
        {
          "name": "signedIn",
          "takes": "true/false",
          "required": true,
          "note": "Signed in through Estiva ID, as opposed to a browser-held key."
        },
        {
          "name": "relayUrl",
          "takes": "text",
          "required": false,
          "note": "Names the workspace; absent hides the workspace section."
        },
        {
          "name": "idBase",
          "takes": "text",
          "required": false,
          "note": "Estiva ID's base URL when this build offers sign-in; absent = anonymous-only build."
        },
        {
          "name": "onCopyKey",
          "takes": "a handler",
          "required": false,
          "note": "\"Copy public key\" appears only when the app can supply one."
        },
        {
          "name": "onSignOut",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "App-specific rows, drawn as their own group between the workspace section and the actions."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "navigation-identitymenu--docs",
      "storyId": "navigation-identitymenu--anonymous",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "initialsFor",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Avatar.tsx",
      "purpose": "Peek's rule, sharpened: the first letter of the first two words — counting only words that begin with a letter or digit, so \"Claude (steered by Katerina Kelepouri)\" shows \"C\", never \"C(\" (Katerina, 2026-09-01: a name carrying such symbols gets a single letter rather than one of them).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-avatar--docs",
      "storyId": "primitives-avatar--initials",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "INLINE_CHIP_CLASSES",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/InlineChip.tsx",
      "purpose": "The shape every tone shares. Exported for a rich-text editor that renders chips from strings.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-inlinechip--docs",
      "storyId": "components-inlinechip--neutral",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "INLINE_CHIP_TONE_CLASSES",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/InlineChip.tsx",
      "purpose": "What a chip is made of, by what it stands for.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-inlinechip--docs",
      "storyId": "components-inlinechip--neutral",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "InlineChip",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/InlineChip.tsx",
      "purpose": "A word in a sentence that stands for something — a person, a place, a thing — drawn as a small tinted box exactly one line high, with its words level with the text around it.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "tone",
          "takes": "InlineChipTone",
          "required": false,
          "note": "What the chip stands for. Default `neutral`."
        },
        {
          "name": "icon",
          "takes": "anything",
          "required": false,
          "note": "Drawn before the label in a 16px box: a 16px icon, or a 14px one it centres."
        },
        {
          "name": "href",
          "takes": "text",
          "required": false,
          "note": "Where the chip leads. With it the chip is an anchor; without it, a span."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-inlinechip--docs",
      "storyId": "components-inlinechip--neutral",
      "docPage": "src/InlineChip.mdx",
      "app": null,
      "looks": [
        "rounded-sm align-top text-body-2 font-normal select-none",
        "bg-bg-active text-text-muted font-mono text-caption"
      ]
    },
    {
      "name": "inlineChipClassName",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/InlineChip.tsx",
      "purpose": "The chip's classes for a tone, with anything the caller adds.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-inlinechip--docs",
      "storyId": "components-inlinechip--neutral",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "InlineText",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/InlineText.tsx",
      "purpose": "A page's title, or the line under it, edited where it stands, as in a document: the text is the editor, with no box and nothing moving.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "value",
          "takes": "text",
          "required": true,
          "note": "The saved text. A new value is loaded when you are not in the field and hold nothing unsaved."
        },
        {
          "name": "placeholder",
          "takes": "text",
          "required": true,
          "note": "What it is for, muted, while it is empty: \"Untitled\", \"Add a summary\"."
        },
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": "The accessible name: \"Title\", \"Summary\"."
        },
        {
          "name": "onCommit",
          "takes": "a handler",
          "required": true,
          "note": "Save it: resolve `true` when saved; `false` keeps your text in place."
        },
        {
          "name": "onText",
          "takes": "a handler",
          "required": false,
          "note": "The text as it is being written, on focus and every change; `null` when you leave."
        },
        {
          "name": "onEnter",
          "takes": "a handler",
          "required": false,
          "note": "Enter, after the save has started: where the caret goes next."
        },
        {
          "name": "variant",
          "takes": "title | summary",
          "required": false,
          "note": "`title`: the page's heading. `summary`: the line under it, quieter."
        },
        {
          "name": "clearable",
          "takes": "true/false",
          "required": false,
          "note": "Empty is a value (a summary). Otherwise leaving it empty brings the saved one back (a title)."
        },
        {
          "name": "readOnly",
          "takes": "true/false",
          "required": false,
          "note": "Text only, the same size and place: nobody can change it, or the editor is not ready."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "Placement only."
        },
        {
          "name": "ref",
          "takes": "Ref<InlineTextHandle>",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "variant",
          "values": [
            "title",
            "summary"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-inlinetext--docs",
      "storyId": "primitives-inlinetext--default",
      "docPage": "src/InlineText.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "InputChip",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ChipInput.tsx",
      "purpose": "A chip standing on its own: a label, an optional leading icon, an optional ✕.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "leading",
          "takes": "anything",
          "required": false,
          "note": "Before the label, 16px — an Avatar, an icon."
        },
        {
          "name": "onRemove",
          "takes": "a handler",
          "required": false,
          "note": "Draws the ✕; absent, the chip is display-only."
        },
        {
          "name": "removeLabel",
          "takes": "text",
          "required": false,
          "note": "The ✕'s name for a screen reader. `Remove <label>` when not given."
        },
        {
          "name": "truncate",
          "takes": "true/false",
          "required": false,
          "note": "Cut a long label with an ellipsis once the chip is capped, by a `max-w-*` on `className`."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-chipinput--docs",
      "storyId": "inputs-chipinput--type-to-search",
      "docPage": null,
      "app": null,
      "looks": [
        "bg-bg-elevated border border-border-subtle rounded-md",
        "text-caption font-medium text-text-primary truncate"
      ]
    },
    {
      "name": "isApplePlatform",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/shortcuts.ts",
      "purpose": "Whether this machine calls the modifier Cmd rather than Ctrl.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "isChecklistTick",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/BlockNodes.tsx",
      "purpose": "Whether a change is a click on a checklist item's box.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-blocknodes--docs",
      "storyId": "primitives-blocknodes--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "isReferenceMenuOpen",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceMenu.tsx",
      "purpose": "Whether the menu is open, for an editor's own Escape: while it is, Escape closes it rather than leaving.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencemenu--docs",
      "storyId": "primitives-referencemenu--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "isSuggestionActive",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/suggestionPopup.tsx",
      "purpose": "Open, or closed less than 100ms ago — what an Enter handler asks.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "isSuggestionOpen",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/suggestionPopup.tsx",
      "purpose": "Open *now*, with no grace period — what an Escape handler asks.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Kbd",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Kbd.tsx",
      "purpose": "The small chip that names the key which does the same thing.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "tone",
          "takes": "default | tooltip",
          "required": false,
          "note": "`tooltip` draws the key in the tooltip's own key colours, for a theme whose tooltip is darker than its page (Katerina, 27 September)."
        }
      ],
      "variants": [
        {
          "prop": "tone",
          "values": [
            "default",
            "tooltip"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-kbd--docs",
      "storyId": "primitives-kbd--default",
      "docPage": "src/Kbd.mdx",
      "app": null,
      "looks": [
        "whitespace-nowrap rounded-sm border border-border-strong bg-bg-inset font-sans text-caption text-text-secondary signal:font-mono signal:text-small signal:border-b-2 signal:bg-bg-wash ship:border-b-2 ship:bg-bg-wash ship:font-mono ship:text-small leaf:font-mono leaf:text-small",
        "whitespace-nowrap rounded-sm border border-border-strong bg-bg-inset font-sans text-caption text-text-secondary signal:font-mono signal:text-small signal:border-b-2 signal:bg-bg-wash ship:border-b-2 ship:bg-bg-wash ship:font-mono ship:text-small leaf:font-mono leaf:text-small border-border-tooltip-key bg-bg-tooltip-key text-text-tooltip-key signal:bg-bg-tooltip-key ship:bg-bg-tooltip-key",
        "whitespace-nowrap rounded-sm border border-border-strong bg-bg-inset font-sans",
        "ship:border-b-2 ship:bg-bg-wash ship:font-mono ship:text-small",
        "border-border-tooltip-key bg-bg-tooltip-key text-text-tooltip-key signal:bg-bg-tooltip-key ship:bg-bg-tooltip-key"
      ]
    },
    {
      "name": "keepCommentBoxWarm",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CommentBox.tsx",
      "purpose": "Keeps an editor built ahead for the next empty box given these `extensions` and `referenceView`, so it opens at once.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "extensions",
          "takes": "readonly AnyExtension[]",
          "required": false,
          "note": null
        },
        {
          "name": "referenceView",
          "takes": "ComponentType<ReferenceViewProps>",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-commentbox--docs",
      "storyId": "primitives-commentbox--empty",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "keepSelection",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/SelectionToolbar.tsx",
      "purpose": "Draw the selection as it is now, until `releaseSelection`.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-selectiontoolbar--docs",
      "storyId": "primitives-selectiontoolbar--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "KeptSelection",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/SelectionToolbar.tsx",
      "purpose": "The extension an editor registers so a selection can stay drawn while a field has the focus.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-selectiontoolbar--docs",
      "storyId": "primitives-selectiontoolbar--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "KindIcon",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/KindIcon.tsx",
      "purpose": "The icon before a thing's name that says what kind of thing it is: a topic, a project, an issue, another app's file, or a message.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "kind",
          "takes": "topic | project | issue | file | message",
          "required": true,
          "note": null
        },
        {
          "name": "size",
          "takes": "14 | 16",
          "required": false,
          "note": "16 in a row or a list; 14 inside a chip."
        },
        {
          "name": "tone",
          "takes": "secondary | inherit",
          "required": false,
          "note": "`secondary`: the quieter grey a list row's icon wears."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "Space and position only."
        }
      ],
      "variants": [
        {
          "prop": "kind",
          "values": [
            "topic",
            "project",
            "issue",
            "file",
            "message"
          ]
        },
        {
          "prop": "tone",
          "values": [
            "secondary",
            "inherit"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-kindicon--docs",
      "storyId": "primitives-kindicon--default",
      "docPage": "src/KindIcon.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "Lightbox",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Lightbox.tsx",
      "purpose": "A picture, full screen, on a scrim — what a thumbnail opens into.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "src",
          "takes": "text",
          "required": true,
          "note": "The picture to show. Swapping it — a thumbnail for the original, once it arrives — swaps what is on screen, with no flash of nothing."
        },
        {
          "name": "alt",
          "takes": "text",
          "required": true,
          "note": "What the picture is. Names the viewer for assistive tech too."
        },
        {
          "name": "onClose",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "Extra classes on the picture itself."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "scroll-lock",
          "behaviour": "Stops the page behind it scrolling"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-lightbox--docs",
      "storyId": "overlays-lightbox--a-picture",
      "docPage": "src/Lightbox.mdx",
      "app": null,
      "looks": [
        "rounded-full bg-bg-tooltip border border-border-tooltip-key text-text-tooltip-key hover:text-text-tooltip"
      ]
    },
    {
      "name": "Link",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Link.tsx",
      "purpose": "A link, in one of four looks. It is a real anchor with a real address, and the app decides how it navigates.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "href",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "variant",
          "takes": "text | quiet | underlined | plain",
          "required": false,
          "note": "Default `text`."
        },
        {
          "name": "external",
          "takes": "true/false",
          "required": false,
          "note": "Another site, or another app: opens in a new tab, with `noopener noreferrer` so the page it opens cannot reach back into this one."
        },
        {
          "name": "truncate",
          "takes": "true/false",
          "required": false,
          "note": "One line, cut with an ellipsis when it does not fit — a title that is a link."
        },
        {
          "name": "cover",
          "takes": "true/false",
          "required": false,
          "note": "The link covers the row it sits in: a click anywhere on the row opens it, and the keyboard ring goes round the whole row."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "variant",
          "values": [
            "text",
            "quiet",
            "underlined",
            "plain"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "navigation-link--docs",
      "storyId": "navigation-link--text",
      "docPage": "src/Link.mdx",
      "app": null,
      "looks": [
        "text-text-interactive underline underline-offset-2 hover:opacity-80",
        "text-text-interactive underline underline-offset-2 hover:opacity-80 after:rounded-md focus-visible:outline-none",
        "text-text-interactive underline underline-offset-2 hover:opacity-80 truncate",
        "text-text-interactive underline underline-offset-2 hover:opacity-80 truncate after:rounded-md focus-visible:outline-none",
        "hover:underline truncate after:rounded-md focus-visible:outline-none",
        "underline underline-offset-2 hover:text-text-primary after:rounded-md focus-visible:outline-none",
        "underline underline-offset-2 hover:text-text-primary truncate",
        "underline underline-offset-2 hover:text-text-primary truncate after:rounded-md focus-visible:outline-none"
      ]
    },
    {
      "name": "LinkCard",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkCard.tsx",
      "purpose": "A link's card: what a row cannot hold, and the changes the reader may make from it.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "link",
          "takes": "LinkState",
          "required": true,
          "note": null
        },
        {
          "name": "readOnly",
          "takes": "true/false",
          "required": false,
          "note": "The values read as words, never pickers: the hover preview."
        },
        {
          "name": "bare",
          "takes": "true/false",
          "required": false,
          "note": "No frame of its own: inside a box that draws one, as the hover preview's."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkcard--docs",
      "storyId": "components-linkcard--default",
      "docPage": "src/LinkCard.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "LinkCardLoading",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkCard.tsx",
      "purpose": "The card it will become, drawn in bars at the card's own height.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "kind",
          "takes": "LinkedKind",
          "required": true,
          "note": null
        },
        {
          "name": "shape",
          "takes": "LoadingShape",
          "required": false,
          "note": "What the card will hold (`loadingShapeOf` from the last time it drew); the kind's usual card otherwise."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkcard--docs",
      "storyId": "components-linkcard--default",
      "docPage": null,
      "app": null,
      "looks": [
        "divide-y divide-border-subtle rounded-md border border-border-subtle leaf:divide-border-strong leaf:border-border-strong",
        "rounded-md border border-border-subtle leaf:border-border-strong"
      ]
    },
    {
      "name": "LinkChip",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkChip.tsx",
      "purpose": "A link in a sentence: its icon, its key, its title cut short, and its status as a shape.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "link",
          "takes": "LinkState",
          "required": true,
          "note": null
        },
        {
          "name": "preview",
          "takes": "true/false",
          "required": false,
          "note": "Hovering shows its card. Off where a card would cover what the reader is choosing from."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkchip--docs",
      "storyId": "components-linkchip--in-a-sentence",
      "docPage": "src/LinkChip.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "LinkChips",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/LinkChips.ts",
      "purpose": "A URL in a document that the app recognises reads as a chip of what it points at, and stays that URL when the document is saved.",
      "purposeFrom": "page",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-linkchips--docs",
      "storyId": "primitives-linkchips--in-an-editor",
      "docPage": "src/LinkChips.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "linkedFrom",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/linkedFrom.ts",
      "purpose": "The file a reference names, as the kit's chip, row and card draw it.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "LinkedIcon",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkParts.tsx",
      "purpose": "The icon for what a link stands for. A page of text has its own.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "kind",
          "takes": "LinkedKind",
          "required": true,
          "note": null
        },
        {
          "name": "size",
          "takes": "14 | 16",
          "required": false,
          "note": null
        },
        {
          "name": "tone",
          "takes": "secondary | inherit",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "tone",
          "values": [
            "secondary",
            "inherit"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkparts--docs",
      "storyId": "components-linkparts--pickers",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "LinkKey",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkParts.tsx",
      "purpose": "A key, the way people say it (\"ABC-2\"): before the title, quieter than it.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "children",
          "takes": "text",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkparts--docs",
      "storyId": "components-linkparts--pickers",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "LinkPickers",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkParts.tsx",
      "purpose": "A status and an owner, where the reader can change them from the card.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "status",
          "takes": "LinkedPicker",
          "required": false,
          "note": null
        },
        {
          "name": "owner",
          "takes": "LinkedPicker",
          "required": false,
          "note": null
        },
        {
          "name": "ownerLabel",
          "takes": "text",
          "required": false,
          "note": "The owner's word: \"Assignee\", \"Lead\"."
        },
        {
          "name": "readOnly",
          "takes": "true/false",
          "required": false,
          "note": "Draws the values as words even where they could be changed: the hover preview."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkparts--docs",
      "storyId": "components-linkparts--pickers",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "linkPlaceAt",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/LinkPlaces.ts",
      "purpose": "How the reference node at `pos` draws. Anything that is not a reference with a `uri` draws as a chip.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-linkplaces--docs",
      "storyId": "primitives-linkplaces--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "LinkPlaces",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/LinkPlaces.ts",
      "purpose": "Where a link in a document sits decides how it draws: its chip in a sentence, its row alone on its line, and its card in the row's place when its writer chose one (`embed` `detailed`).",
      "purposeFrom": "page",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-linkplaces--docs",
      "storyId": "primitives-linkplaces--in-an-editor",
      "docPage": "src/LinkPlaces.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "LinkPreview",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkPreview.tsx",
      "purpose": "A link's card on hover over its chip or its row, read only, in the package's one elevated box.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "linked",
          "takes": "Linked",
          "required": true,
          "note": null
        },
        {
          "name": "block",
          "takes": "true/false",
          "required": false,
          "note": "The trigger fills its column, as a row does; a chip is inline."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkpreview--docs",
      "storyId": "components-linkpreview--on-hover",
      "docPage": "src/LinkPreview.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "LinkPreviewOpen",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkPreview.tsx",
      "purpose": "The preview drawn open, for a still picture of it: the same box PreviewCard draws.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "linked",
          "takes": "Linked",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkpreview--docs",
      "storyId": "components-linkpreview--on-hover",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "LinkRow",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkRow.tsx",
      "purpose": "A link alone on its line: one 36px row for every kind, with what it has in its corner.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "link",
          "takes": "LinkState",
          "required": true,
          "note": null
        },
        {
          "name": "preview",
          "takes": "true/false",
          "required": false,
          "note": "Hovering shows its card."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkrow--docs",
      "storyId": "components-linkrow--default",
      "docPage": "src/LinkRow.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "linkStateFrom",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/linkedFrom.ts",
      "purpose": "Where a reference's read stands, for the kit: `undefined` is still read, `null` an answer of nothing.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "LinkUnavailable",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkRow.tsx",
      "purpose": "Not available: deleted, or not this reader's to see, which read the same.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "kind",
          "takes": "LinkedKind",
          "required": true,
          "note": null
        },
        {
          "name": "noun",
          "takes": "text",
          "required": true,
          "note": "What it is, in a word: \"Item\". Drawn as \"Item — not available.\"."
        },
        {
          "name": "openIn",
          "takes": "{ app: string; href: string }",
          "required": false,
          "note": "Where it may still open, for someone who can: its app and address."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkrow--docs",
      "storyId": "components-linkrow--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ListColumn",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ListColumn.tsx",
      "purpose": "The list column of a page: 290px wide with a line on its right, its name in a `ContainerHeader`, and the list under it, which scrolls.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "title",
          "takes": "anything",
          "required": true,
          "note": "The column's name, in its header. A node for a title that is more than words."
        },
        {
          "name": "chevron",
          "takes": "true/false",
          "required": false,
          "note": "A chevron after the title, as `ContainerHeader` draws it."
        },
        {
          "name": "titleMenu",
          "takes": "anything",
          "required": false,
          "note": "The menu the title opens — `ContainerHeader`'s: the column's views."
        },
        {
          "name": "actions",
          "takes": "anything",
          "required": false,
          "note": "The column's own actions, at the header's right — a `Toolbar` of `ToolbarButton`s, or one `IconButton`."
        },
        {
          "name": "above",
          "takes": "anything",
          "required": false,
          "note": "A row between the header and the list that stays put while the list scrolls — a field that adds to the list."
        },
        {
          "name": "collapsed",
          "takes": "true/false",
          "required": false,
          "note": "Closes the column with the rail: it narrows to nothing and fades."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The rows, 2px apart. Groups are headed by a `CollapsibleSection` or a `SectionHeader`."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "Placement only."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "layout-listcolumn--docs",
      "storyId": "layout-listcolumn--default",
      "docPage": "src/ListColumn.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "loadingShapeOf",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/linked.ts",
      "purpose": "The shape `linked`'s card takes, for its placeholder the next time it loads.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "id",
          "takes": "text",
          "required": true,
          "note": "Its address. Two `Linked` with the same `id` are the same thing (identity by value, not by object)."
        },
        {
          "name": "kind",
          "takes": "LinkedKind",
          "required": true,
          "note": null
        },
        {
          "name": "title",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "href",
          "takes": "text",
          "required": true,
          "note": "Opens it. An address in this app goes through `AppProvider`'s `navigate`."
        },
        {
          "name": "key",
          "takes": "text",
          "required": false,
          "note": "What the reader calls it, quietly before the title: \"ABC-2\"."
        },
        {
          "name": "subtitle",
          "takes": "text",
          "required": false,
          "note": "The line under a card's title: what it is in."
        },
        {
          "name": "summary",
          "takes": "text",
          "required": false,
          "note": "Its short summary, a sentence or two. Without one a card shows the title alone."
        },
        {
          "name": "status",
          "takes": "LinkedPicker",
          "required": false,
          "note": "Its status: each option carries its `colour`."
        },
        {
          "name": "owner",
          "takes": "LinkedPicker",
          "required": false,
          "note": "Who owns it, by the word the app uses (`ownerLabel`: \"Assignee\", \"Lead\")."
        },
        {
          "name": "ownerLabel",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "conversation",
          "takes": "LinkedConversation & { noun?: string }",
          "required": false,
          "note": "What was said about it. `noun` names it for a screen reader: \"comments\" by default."
        },
        {
          "name": "children",
          "takes": "LinkedChild[]",
          "required": false,
          "note": "Items inside it, drawn as rows in its card."
        },
        {
          "name": "done",
          "takes": "{ done: number; total: number }",
          "required": false,
          "note": "How far along it is, drawn as a ring."
        },
        {
          "name": "members",
          "takes": "LinkedPerson[]",
          "required": false,
          "note": "Who is in it, as faces."
        },
        {
          "name": "authors",
          "takes": "LinkedPerson[]",
          "required": false,
          "note": "Who wrote it, as faces."
        },
        {
          "name": "updated",
          "takes": "text",
          "required": false,
          "note": "When it last changed, in the app's words: \"2h ago\"."
        },
        {
          "name": "latest",
          "takes": "{ author: LinkedPerson; body: string; at: string }",
          "required": false,
          "note": "The newest thing said in it, drawn only when the reader may read it."
        },
        {
          "name": "body",
          "takes": "text",
          "required": false,
          "note": "Words a person wrote, linked as themselves: drawn with `author`'s face, not an icon."
        },
        {
          "name": "author",
          "takes": "LinkedPerson",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "MembersDialog",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/MembersDialog.tsx",
      "purpose": "Who is in this, with joining, leaving and adding people — the list a MembersPill opens.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "members",
          "takes": "MembersDialogMember[]",
          "required": true,
          "note": "The roster, in the order to draw it. The viewer's own row is the caller's to name (\"You\")."
        },
        {
          "name": "count",
          "takes": "number",
          "required": false,
          "note": "The number in the title's chip. Defaults to how many rows there are."
        },
        {
          "name": "self",
          "takes": "a handler",
          "required": false,
          "note": "What the viewer can do: \"Leave\" on their own row when they are in, which is drawn first; a \"Join\" row on top when they are not."
        },
        {
          "name": "candidates",
          "takes": "MembersDialogCandidate[]",
          "required": false,
          "note": "Who \"Add members\" may offer. Members are left out by id."
        },
        {
          "name": "onAdd",
          "takes": "a handler",
          "required": false,
          "note": "Adds the people chosen. With it, the \"Add members\" row shows and opens the add layer."
        },
        {
          "name": "note",
          "takes": "anything",
          "required": false,
          "note": "One line under the roster — what membership does and does not cover."
        },
        {
          "name": "initialView",
          "takes": "list | add",
          "required": false,
          "note": "`add` opens straight on the add layer."
        },
        {
          "name": "onClose",
          "takes": "a handler",
          "required": true,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "initialView",
          "values": [
            "list",
            "add"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "scroll-lock",
          "behaviour": "Stops the page behind it scrolling"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-membersdialog--docs",
      "storyId": "primitives-membersdialog--member",
      "docPage": "src/MembersDialog.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "MembersPill",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/MembersPill.tsx",
      "purpose": "Who is in this: up to three faces and the total, in a small outlined pill that opens the full list.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "members",
          "takes": "AvatarGroupMember[]",
          "required": true,
          "note": "Who is in it, in order. Up to three faces are drawn."
        },
        {
          "name": "count",
          "takes": "number",
          "required": false,
          "note": "The number beside the faces. Defaults to how many members there are."
        },
        {
          "name": "onClick",
          "takes": "a handler",
          "required": false,
          "note": "Opens the list — usually a `MembersDialog`."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-memberspill--docs",
      "storyId": "primitives-memberspill--two-members",
      "docPage": "src/MembersPill.mdx",
      "app": null,
      "looks": [
        "text-caption text-text-secondary signal:font-mono signal:text-small signal:tabular-nums"
      ]
    },
    {
      "name": "Menu",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Menu.tsx",
      "purpose": "A list of actions from a trigger. The menu owns the trigger, so a caller writes no open state, no placement and no dismiss — it hands over the control and the rows, and everything else is Base UI's.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "trigger",
          "takes": "anything",
          "required": true,
          "note": "The control that opens the menu. Any element that forwards its ref and spreads its props — this package's `Button`, `IconButton` and `PersonTrigger` all do."
        },
        {
          "name": "align",
          "takes": "left | right",
          "required": false,
          "note": "Which of the menu's edges hangs from the trigger's."
        },
        {
          "name": "openOnHover",
          "takes": "true/false",
          "required": false,
          "note": "Open on hover, and close shortly after the pointer leaves — for a control that only appears while the pointer is on a card."
        },
        {
          "name": "open",
          "takes": "true/false",
          "required": false,
          "note": "Controlled, for a caller that must know or must force it."
        },
        {
          "name": "onOpenChange",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "actionsRef",
          "takes": "a handler",
          "required": false,
          "note": "Base UI's imperative handle. `actions.current?.close()` shuts the menu — for a row that must close it before opening what it opens."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "On the menu's surface — its width. Not its padding: see `contentClassName`."
        },
        {
          "name": "contentClassName",
          "takes": "text",
          "required": false,
          "note": "The padding around the rows, as a class."
        }
      ],
      "variants": [
        {
          "prop": "align",
          "values": [
            "left",
            "right"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        },
        {
          "id": "walking",
          "behaviour": "Moves through its items with the arrow keys"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-menu--docs",
      "storyId": "overlays-menu--items",
      "docPage": "src/Menu.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "MenuItem",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Menu.tsx",
      "purpose": "The row of a menu: label, and around it everything a row can carry — a `leading` icon or face, a `description` second line, a `shortcut` kbd chip, a `submenu` chevron, a `trailing` anything (which wins over the other two), `destructive` in the error colour, `selected` as the fill.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "Replaces the label/description block — for rows whose middle is richer than text (the launcher's form rows)."
        },
        {
          "name": "size",
          "takes": "default | tall",
          "required": false,
          "note": "`tall` is the picker row — content height with a 40px floor, px-3, gap-3, room for a 32px face or icon tile and the description line."
        },
        {
          "name": "description",
          "takes": "text",
          "required": false,
          "note": "A second line under the label — a role, an address — 12px, secondary, truncating."
        },
        {
          "name": "aside",
          "takes": "text",
          "required": false,
          "note": "After the label, on its line — 12px, muted, never cut: where a file sits (an issue's ref and project) when its second line is its summary (SUM-7)."
        },
        {
          "name": "leading",
          "takes": "anything",
          "required": false,
          "note": "Before the label: a 16px icon (stroke 1.5, secondary), or an Avatar, for rows led by a face."
        },
        {
          "name": "trailing",
          "takes": "anything",
          "required": false,
          "note": "At the right edge: a hint, a value — anything."
        },
        {
          "name": "hint",
          "takes": "anything",
          "required": false,
          "note": "Shown at the right edge only while this row is the one you are pointing at or have arrowed onto — an `EnterHint`, typically."
        },
        {
          "name": "shortcut",
          "takes": "text",
          "required": false,
          "note": "A keyboard hint, drawn as the kbd chip."
        },
        {
          "name": "submenu",
          "takes": "true/false",
          "required": false,
          "note": "The row opens another menu: draws the chevron at the right edge."
        },
        {
          "name": "destructive",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "selected",
          "takes": "true/false",
          "required": false,
          "note": "The row the menu currently points at (a submenu's chosen value)."
        }
      ],
      "variants": [
        {
          "prop": "size",
          "values": [
            "default",
            "tall"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-menuitem--docs",
      "storyId": "overlays-menuitem--default",
      "docPage": "src/MenuItem.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "MenuPanel",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Menu.tsx",
      "purpose": "The menu's surface without the menu: the elevated box, the rows' padding, and a divider that runs the full width of what it separates.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "Optional only because Base UI fills it in when this is a `render` target: `Menu.Popup` supplies the children."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-menu--docs",
      "storyId": "overlays-menu--items",
      "docPage": null,
      "app": null,
      "looks": [
        "rounded-lg border border-border-default bg-bg-elevated shadow-lg"
      ]
    },
    {
      "name": "MenuRow",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Menu.tsx",
      "purpose": "A non-interactive row inside a menu, at the item's own geometry.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-menu--docs",
      "storyId": "overlays-menu--items",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "MenuSection",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Menu.tsx",
      "purpose": "A section heading inside a menu: the 32px row with a SectionLabel, read secondary — a heading inside a menu labels the rows, it is not one of them (Katerina, 2026-09-01).",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-menu--docs",
      "storyId": "overlays-menu--items",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "MenuSeparator",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Menu.tsx",
      "purpose": "The line between two groups of a menu, with its own 4px above and below (UIG-14, Katerina 19 September).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-menu--docs",
      "storyId": "overlays-menu--items",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "MenuSub",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Menu.tsx",
      "purpose": "A row that opens another menu beside it; its rows are this row's children.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": "The trigger row's label."
        },
        {
          "name": "leading",
          "takes": "anything",
          "required": false,
          "note": null
        },
        {
          "name": "selected",
          "takes": "true/false",
          "required": false,
          "note": "Mark the trigger row as holding a current value."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The submenu's rows."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "On the submenu panel."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-menu--docs",
      "storyId": "overlays-menu--items",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "moveBlock",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorBlockHandle.tsx",
      "purpose": "Moves the block at `from` to `to` (a position between top-level blocks), the caret in it: what a drop in the gutter does, where the editor has no drop of its own.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editorblockhandle--docs",
      "storyId": "primitives-editorblockhandle--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "NavItem",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/NavItem.tsx",
      "purpose": "One row of a sidebar: an optional 16px icon, a label, and an optional count — a muted mono number whose tooltip says what it counts.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "href",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "count",
          "takes": "number",
          "required": false,
          "note": "`0` or absent renders no counter."
        },
        {
          "name": "countLabel",
          "takes": "text",
          "required": false,
          "note": "What the count counts, for the tooltip — \"18 open\", \"5 active\"."
        },
        {
          "name": "active",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "icon",
          "takes": "anything",
          "required": false,
          "note": "16px, stroke 1.5."
        },
        {
          "name": "menu",
          "takes": "anything",
          "required": false,
          "note": "The row's \"More options\" menu: `MenuItem`s."
        },
        {
          "name": "menuLabel",
          "takes": "text",
          "required": false,
          "note": "The ⋮'s accessible name and tooltip. Default \"More options for {label}\"."
        },
        {
          "name": "action",
          "takes": "SectionAction",
          "required": false,
          "note": "One button beside the ⋮, shown with it: any 16px icon, its tooltip and its handler — a `SectionHeader` action's shape."
        },
        {
          "name": "hint",
          "takes": "anything",
          "required": false,
          "note": "Shown only while the row is pointed at or focused, left of the count: a neutral `Chip`, typically."
        },
        {
          "name": "tooltip",
          "takes": "text",
          "required": false,
          "note": "A sentence about the item, in the package's tooltip while the label is pointed at; the row stays one line."
        },
        {
          "name": "unread",
          "takes": "true/false",
          "required": false,
          "note": "Something new here: brighter words, the label in medium, and the `UnreadDot` at the right."
        },
        {
          "name": "urgent",
          "takes": "true/false",
          "required": false,
          "note": "With `unread`: the warning badge in the dot's place."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "Rows under this one, folding under it: `NavItem`s."
        },
        {
          "name": "defaultOpen",
          "takes": "true/false",
          "required": false,
          "note": "With `children`: open unless told otherwise."
        },
        {
          "name": "open",
          "takes": "true/false",
          "required": false,
          "note": "With `children`: the caller owns the state."
        },
        {
          "name": "onOpenChange",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-navitem--docs",
      "storyId": "frame-navitem--default",
      "docPage": "src/NavItem.mdx",
      "app": null,
      "looks": [
        "text-body-2 rounded-lg transition-colors bg-bg-nav-active text-text-primary",
        "text-body-2 rounded-lg transition-colors text-text-primary hover:bg-bg-hover",
        "text-body-2 rounded-lg transition-colors text-text-secondary hover:text-text-primary hover:bg-bg-hover",
        "text-center font-mono text-caption tabular-nums text-text-muted",
        "text-center font-mono text-caption tabular-nums text-text-muted transition-opacity [@media(hover:none)]:opacity-0",
        "overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none"
      ]
    },
    {
      "name": "NavTree",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/NavTree.tsx",
      "purpose": "A sidebar's tree from one nested list: a quiet label, groups that fold under the standard heading with their rows lightly indented, and rows under rows to any depth.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "title",
          "takes": "text",
          "required": false,
          "note": "The quiet label over the groups. Absent, none is drawn."
        },
        {
          "name": "titleActions",
          "takes": "SectionAction[]",
          "required": false,
          "note": "Beside the label, always shown: \"New\", typically."
        },
        {
          "name": "groups",
          "takes": "NavTreeGroup[] | null",
          "required": false,
          "note": "`null` while the first read is on its way: a skeleton in the groups' place."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "The groups, drawn by the app: `NavTreeSection`s with `NavItem` rows — for an app whose groups and rows each read their own data."
        },
        {
          "name": "selected",
          "takes": "text",
          "required": false,
          "note": "The row that is current: `active`, and its group starts open."
        },
        {
          "name": "onSelect",
          "takes": "a handler",
          "required": false,
          "note": "A row was clicked. A router app prevents the default and navigates."
        },
        {
          "name": "emptyMessage",
          "takes": "text",
          "required": false,
          "note": "What to say when `groups` is empty. The words are the caller's; absent, nothing is said."
        },
        {
          "name": "storageKey",
          "takes": "text",
          "required": false,
          "note": "Remember each group open or closed in this browser, under this key and the group's id."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-navtree--docs",
      "storyId": "frame-navtree--default",
      "docPage": "src/NavTree.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "NavTreeSection",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/NavTree.tsx",
      "purpose": "One group of a `NavTree`, for an app that draws its own: the standard heading folding its rows, lightly indented under its title, with the group's line, skeleton, actions and `onIntent`.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "title",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "id",
          "takes": "text",
          "required": false,
          "note": "Marks the group's box as `data-nav-group`, for tests and photo runs to find it."
        },
        {
          "name": "message",
          "takes": "text",
          "required": false,
          "note": "Said in the rows' place, level with them."
        },
        {
          "name": "trailing",
          "takes": "anything",
          "required": false,
          "note": "Beside the title, always shown: an `UnreadDot`, typically."
        },
        {
          "name": "actions",
          "takes": "SectionAction[]",
          "required": false,
          "note": "Beside the title, shown while the row is hovered or keyboard-focused: \"Open\", typically."
        },
        {
          "name": "menu",
          "takes": "anything",
          "required": false,
          "note": "The group's \"More options\" menu, after its actions: `MenuItem`s."
        },
        {
          "name": "icon",
          "takes": "anything",
          "required": false,
          "note": "16px, before the title; the arrow takes its place on hover."
        },
        {
          "name": "defaultOpen",
          "takes": "true/false",
          "required": false,
          "note": "Open unless told otherwise."
        },
        {
          "name": "open",
          "takes": "true/false",
          "required": false,
          "note": "The caller owns whether the group is open."
        },
        {
          "name": "onOpenChange",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "onIntent",
          "takes": "a handler",
          "required": false,
          "note": "The pointer rests on the group, or the keyboard reaches it: read its rows now."
        },
        {
          "name": "loading",
          "takes": "true/false",
          "required": false,
          "note": "Its rows are being read: a skeleton in their place."
        },
        {
          "name": "pending",
          "takes": "true/false",
          "required": false,
          "note": "Opened, and its rows are being read: the arrow turns and the group stays shut until they are in, then opens once — `CollapsibleSection`'s."
        },
        {
          "name": "storageKey",
          "takes": "text",
          "required": false,
          "note": "Remember it open or closed in this browser, under this key."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "The rows: `NavItem`s."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-navtree--docs",
      "storyId": "frame-navtree--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "normalizeHref",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/SelectionToolbar.tsx",
      "purpose": "What somebody typed into the link field → an `href`, or null when it cannot be one.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-selectiontoolbar--docs",
      "storyId": "primitives-selectiontoolbar--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Panel",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Panel.tsx",
      "purpose": "A panel of a page: its name in a header, a body that scrolls whenever it is taller than the room it has, and a row fixed at the bottom when there is one.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "title",
          "takes": "anything",
          "required": true,
          "note": "The panel's name, in its header. A node for a title that is more than words."
        },
        {
          "name": "chevron",
          "takes": "true/false",
          "required": false,
          "note": "A chevron after the title, as `ContainerHeader` draws it."
        },
        {
          "name": "actions",
          "takes": "anything",
          "required": false,
          "note": "The panel's own actions, at the header's right — a `Toolbar` of `ToolbarButton`s, or one `IconButton`."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The body. It scrolls when it is taller than the panel."
        },
        {
          "name": "footer",
          "takes": "anything",
          "required": false,
          "note": "A row fixed under the body that never scrolls — a reply box."
        },
        {
          "name": "bodyClassName",
          "takes": "text",
          "required": false,
          "note": "The body's own box: its padding, gap and layout — `px-4 pt-3 pb-4`, `flex flex-col gap-2`."
        },
        {
          "name": "bodyRef",
          "takes": "Ref<HTMLDivElement>",
          "required": false,
          "note": "The body's scrolling box, for a panel that reads or drives its scroll: a thread that opens at its newest reply."
        },
        {
          "name": "onBodyScroll",
          "takes": "UIEventHandler<HTMLDivElement>",
          "required": false,
          "note": "Fires as the body scrolls."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "Placement only: a cap such as `max-h-[60%]` when it shares a column."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "layout-panel--docs",
      "storyId": "layout-panel--default",
      "docPage": "src/Panel.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "PartCard",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/PartCard.tsx",
      "purpose": "A part of something longer, shared live: its blocks as they are now, under the header of what it is part of.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "state",
          "takes": "ready | loading | unavailable",
          "required": false,
          "note": "Where its lookup stands. Default `ready`."
        },
        {
          "name": "kind",
          "takes": "LinkedKind",
          "required": true,
          "note": "What it is part of, by its icon."
        },
        {
          "name": "heading",
          "takes": "text",
          "required": false,
          "note": "The title of what it is part of."
        },
        {
          "name": "href",
          "takes": "text",
          "required": false,
          "note": "Opens what it is part of, at the part."
        },
        {
          "name": "partKey",
          "takes": "text",
          "required": false,
          "note": "The key of what it is part of: \"ABC-2\"."
        },
        {
          "name": "noun",
          "takes": "text",
          "required": false,
          "note": "What it is part of, in a word, for \"A part of this item — not available.\"."
        },
        {
          "name": "openIn",
          "takes": "{ app: string; href: string }",
          "required": false,
          "note": "Where it may still open, for someone who can, when it is not available."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "The part's blocks, drawn by the app."
        }
      ],
      "variants": [
        {
          "prop": "state",
          "values": [
            "ready",
            "loading",
            "unavailable"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-partcard--docs",
      "storyId": "components-partcard--default",
      "docPage": "src/PartCard.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "pastedImageName",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/PastedImages.ts",
      "purpose": "`'Screenshot 2026-09-07 14-32-05.png'`: sortable, and readable on a file card.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-pastedimages--docs",
      "storyId": "primitives-pastedimages--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "pastedImages",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/PastedImages.ts",
      "purpose": "The pictures on the clipboard, named — `[]` when there is nothing to attach.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-pastedimages--docs",
      "storyId": "primitives-pastedimages--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "PastedImages",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/PastedImages.ts",
      "purpose": "Pasting a picture into an editor attaches it.",
      "purposeFrom": "page",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-pastedimages--docs",
      "storyId": "primitives-pastedimages--in-an-editor",
      "docPage": "src/PastedImages.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "PastedMarkdown",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/PastedMarkdown.ts",
      "purpose": "Markdown pasted into an editor as plain text lands as what it spells: a heading, a list, a checklist, a quote or callout, a table.",
      "purposeFrom": "page",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-pastedmarkdown--docs",
      "storyId": "primitives-pastedmarkdown--in-an-editor",
      "docPage": "src/PastedMarkdown.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "peopleMenu",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "The people list `@` and `!@` open: the face, the name, the second line, and the Enter hint while highlighted — `MenuItem` at its tall size.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Person",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Person.tsx",
      "purpose": "A face beside a name — the inline mention of a human.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "name",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "picture",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "fallback",
          "takes": "text",
          "required": false,
          "note": "Shown in place of a missing name."
        },
        {
          "name": "size",
          "takes": "number",
          "required": false,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-person--docs",
      "storyId": "components-person--named",
      "docPage": "src/Person.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "PersonMention",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "`@` — a person, as a chip that writes their key (SPEC §13.1).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "PersonReference",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "`@` in a document — a person, written as a reference to them: a `ReferenceNode` whose `uri` is their `nostr:npub…` (SPEC §13.1, §13.3).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "PersonTrigger",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/PersonTrigger.tsx",
      "purpose": "The person, as the button that opens a menu.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "open",
          "takes": "true/false",
          "required": false,
          "note": "Whether what it opens is open — the row shape holds its hover fill while so."
        },
        {
          "name": "compact",
          "takes": "true/false",
          "required": false,
          "note": "Face only — no chevron, no hover fill. Defaults the face to 36px; the row shape to 22px."
        },
        {
          "name": "name",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "picture",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "fallback",
          "takes": "text",
          "required": false,
          "note": "Shown in place of a missing name."
        },
        {
          "name": "size",
          "takes": "number",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-persontrigger--docs",
      "storyId": "components-persontrigger--row",
      "docPage": "src/PersonTrigger.mdx",
      "app": null,
      "looks": [
        "text-body-2 text-text-primary cursor-pointer rounded-md transition-colors hover:bg-bg-hover",
        "text-body-2 text-text-primary cursor-pointer rounded-md transition-colors hover:bg-bg-hover bg-bg-hover"
      ]
    },
    {
      "name": "Popover",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Popover.tsx",
      "purpose": "A floating panel from a trigger: the same elevated surface a Menu draws, with none of a menu's semantics.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "trigger",
          "takes": "anything",
          "required": false,
          "note": "The control that opens the panel. Any element that forwards its ref and spreads its props — this package's `Button`, `IconButton` and `PersonTrigger` all do."
        },
        {
          "name": "anchor",
          "takes": "HTMLElement | DOMRect | null",
          "required": false,
          "note": "For a panel with no trigger element: an element, or a rect the caller measured — a text selection's."
        },
        {
          "name": "align",
          "takes": "left | center | right",
          "required": false,
          "note": "Which of the panel's edges hangs from the trigger's, or `center` to put the panel's middle over the anchor's."
        },
        {
          "name": "side",
          "takes": "top | bottom",
          "required": false,
          "note": "Which side of the trigger, or of the anchor, the panel prefers."
        },
        {
          "name": "open",
          "takes": "true/false",
          "required": false,
          "note": "Controlled, for a caller that must know or must force it."
        },
        {
          "name": "onOpenChange",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "finalFocus",
          "takes": "RefObject<HTMLElement | null> | false",
          "required": false,
          "note": "Where focus goes when the panel closes. With a `trigger` it goes back to the trigger and this is not needed."
        },
        {
          "name": "actionsRef",
          "takes": "a handler",
          "required": false,
          "note": "Base UI's imperative handle. `actions.current?.close()` shuts the panel — for the Cancel and Save buttons a form panel ends with."
        },
        {
          "name": "ariaLabel",
          "takes": "text",
          "required": false,
          "note": "Names the panel for assistive tech. A panel with a visible heading can point at it instead, with `aria-labelledby`."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "On the panel's surface — its width. Not its padding: see `contentClassName`."
        },
        {
          "name": "contentClassName",
          "takes": "text",
          "required": false,
          "note": "The padding around the children, as a class."
        },
        {
          "name": "maxHeight",
          "takes": "text",
          "required": false,
          "note": "A cap on the scrolling box, as a class — `max-h-[360px]`."
        }
      ],
      "variants": [
        {
          "prop": "align",
          "values": [
            "left",
            "center",
            "right"
          ]
        },
        {
          "prop": "side",
          "values": [
            "top",
            "bottom"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-popover--docs",
      "storyId": "overlays-popover--default",
      "docPage": "src/Popover.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "PreviewCard",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/PreviewCard.tsx",
      "purpose": "More of a thing, on hover.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "content",
          "takes": "anything",
          "required": true,
          "note": "What the card holds. Rendered only while it is open."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The row, name or avatar the card previews."
        },
        {
          "name": "side",
          "takes": "top | bottom | left | right",
          "required": false,
          "note": "Which side of the trigger to prefer. It flips when that side has no room."
        },
        {
          "name": "delay",
          "takes": "number",
          "required": false,
          "note": "Before it opens, in ms. Long enough that crossing a list does not flash a card at every row."
        },
        {
          "name": "closeDelay",
          "takes": "number",
          "required": false,
          "note": "After the pointer leaves, in ms — the grace that lets you cross the gap into the card."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "On the card's surface: its width."
        },
        {
          "name": "contentClassName",
          "takes": "text",
          "required": false,
          "note": "On the scrolling content: its padding (default 12px) and rhythm."
        },
        {
          "name": "wrapperClassName",
          "takes": "text",
          "required": false,
          "note": "Extra classes on the trigger wrapper — e.g."
        }
      ],
      "variants": [
        {
          "prop": "side",
          "values": [
            "top",
            "bottom",
            "left",
            "right"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "overlays-previewcard--docs",
      "storyId": "overlays-previewcard--default",
      "docPage": "src/PreviewCard.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "ProgressBar",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ProgressBar.tsx",
      "purpose": "How much of something is done: a thin rounded track with a success-coloured fill.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "value",
          "takes": "number",
          "required": true,
          "note": "How many are done."
        },
        {
          "name": "max",
          "takes": "number",
          "required": true,
          "note": "How many there are. At `0` the bar is empty."
        },
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": "The accessible name — \"Items done\"."
        },
        {
          "name": "variant",
          "takes": "default | quiet",
          "required": false,
          "note": "Default `default`."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "Placement only: a width, a margin, `flex-1` in a row."
        }
      ],
      "variants": [
        {
          "prop": "variant",
          "values": [
            "default",
            "quiet"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-progressbar--docs",
      "storyId": "feedback-progressbar--default",
      "docPage": "src/ProgressBar.mdx",
      "app": null,
      "looks": [
        "rounded-full bg-success-muted transition-[width] duration-300"
      ]
    },
    {
      "name": "ProgressRing",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkParts.tsx",
      "purpose": "Progress as a small ring, with the count beside it.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "done",
          "takes": "number",
          "required": true,
          "note": null
        },
        {
          "name": "total",
          "takes": "number",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkparts--docs",
      "storyId": "components-linkparts--pickers",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Property",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Property.tsx",
      "purpose": "A labelled property — \"Status\", \"Lead\", and whatever else a surface declares.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "layout",
          "takes": "row | stacked",
          "required": false,
          "note": null
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "layout",
          "values": [
            "row",
            "stacked"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-property--docs",
      "storyId": "primitives-property--row",
      "docPage": "src/Property.mdx",
      "app": null,
      "looks": [
        "text-menu uppercase tracking-widest text-text-secondary"
      ]
    },
    {
      "name": "quoteText",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CommentHighlights.ts",
      "purpose": "A quote in one line, as a card says it: its start and end words around an ellipsis.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "start",
          "takes": "text",
          "required": true,
          "note": "The selection's words in one block, or its first words when it runs across blocks."
        },
        {
          "name": "end",
          "takes": "text",
          "required": false,
          "note": "Its last words, in the run's last block."
        },
        {
          "name": "prefix",
          "takes": "text",
          "required": false,
          "note": "A few characters before `start`, only when the words repeat in their block."
        },
        {
          "name": "suffix",
          "takes": "text",
          "required": false,
          "note": "A few characters after the end, only when the words repeat in their block."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-commenthighlights--docs",
      "storyId": "primitives-commenthighlights--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Rail",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Rail.tsx",
      "purpose": "The 64px strip of icon tiles down the left of an app.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "aria-label",
          "takes": "text",
          "required": false,
          "note": "Names the navigation region for assistive tech."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-rail--docs",
      "storyId": "frame-rail--default",
      "docPage": "src/Rail.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "RailItem",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/RailItem.tsx",
      "purpose": "One tile of an icon rail: the icon in its hover tile, a 9px label under it.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "href",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "icon",
          "takes": "anything",
          "required": true,
          "note": "16px, stroke 1.5."
        },
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "active",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-railitem--docs",
      "storyId": "frame-railitem--default",
      "docPage": "src/RailItem.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "Reaction",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Reaction.tsx",
      "purpose": "An emoji, how many people chose it, and whether you are one of them.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "emoji",
          "takes": "anything",
          "required": true,
          "note": "The emoji, drawn decoratively — name the control with `aria-label`."
        },
        {
          "name": "count",
          "takes": "number",
          "required": true,
          "note": "How many people reacted. Drawn as it is."
        },
        {
          "name": "pressed",
          "takes": "true/false",
          "required": false,
          "note": "You are one of them: the accent tint and edge, and `aria-pressed`."
        },
        {
          "name": "aria-label",
          "takes": "text",
          "required": true,
          "note": "Names the control. Required — the emoji is decorative and the count is the only visible text, so without this it is announced as a bare number."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-reaction--docs",
      "storyId": "components-reaction--default",
      "docPage": "src/Reaction.mdx",
      "app": null,
      "looks": [
        "rounded-full border transition-colors disabled:cursor-not-allowed disabled:opacity-50 border-accent-primary bg-accent-muted text-accent-text hover:border-accent-hover ship:text-text-primary",
        "rounded-full border transition-colors disabled:cursor-not-allowed disabled:opacity-50 border-border-default bg-bg-inset text-text-primary hover:border-border-strong hover:bg-bg-hover",
        "border-accent-primary bg-accent-muted text-accent-text hover:border-accent-hover ship:text-text-primary",
        "border-border-default bg-bg-inset text-text-primary hover:border-border-strong hover:bg-bg-hover",
        "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums"
      ]
    },
    {
      "name": "ReactionPicker",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ReactionPicker.tsx",
      "purpose": "The reactions on offer, to choose one from — icon buttons holding emoji, on a Toolbar.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "options",
          "takes": "ReactionOption[]",
          "required": true,
          "note": "What is on offer, in the order it is drawn."
        },
        {
          "name": "onSelect",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "aria-label",
          "takes": "text",
          "required": false,
          "note": "Names the row. Default \"Reactions\"."
        },
        {
          "name": "surface",
          "takes": "true/false",
          "required": false,
          "note": "The elevated box around the row, from `Toolbar`."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "The row's layout — its gap, its padding."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-reactionpicker--docs",
      "storyId": "components-reactionpicker--default",
      "docPage": "src/ReactionPicker.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "ReactionRow",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ReactionRow.tsx",
      "purpose": "The one row of reactions under a comment or a line, in every app: Reaction pills in the order first chosen, yours lit, who reacted on hover, and the add button with ReactionPicker.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "reactions",
          "takes": "readonly ReactionCount[]",
          "required": true,
          "note": "Each emoji and who chose it, in the order first chosen."
        },
        {
          "name": "options",
          "takes": "readonly ReactionOption[]",
          "required": true,
          "note": "The emoji offered, each named; also what a pill's name is read from."
        },
        {
          "name": "nameOf",
          "takes": "a handler",
          "required": true,
          "note": "A reactor's name, as \"who reacted\" says it."
        },
        {
          "name": "viewer",
          "takes": "text",
          "required": false,
          "note": "Who is looking: their pills are lit, and \"who reacted\" says \"you\"."
        },
        {
          "name": "onToggle",
          "takes": "a handler",
          "required": false,
          "note": "Your reaction on or off. Absent, the row only shows (read-only, signed out)."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-reactionrow--docs",
      "storyId": "primitives-reactionrow--default",
      "docPage": "src/ReactionRow.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "referenceAtSelection",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceCards.ts",
      "purpose": "The chip the person has selected, with what it names and its card — or null.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencecards--docs",
      "storyId": "primitives-referencecards--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "referenceCardPlacements",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceCards.ts",
      "purpose": "Every line that asks for a card, in document order.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencecards--docs",
      "storyId": "primitives-referencecards--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ReferenceCards",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceCards.ts",
      "purpose": "A chip in a document can ask for a card after its line: compact, detailed or none.",
      "purposeFrom": "page",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencecards--docs",
      "storyId": "primitives-referencecards--in-an-editor",
      "docPage": "src/ReferenceCards.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "referenceMenu",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "The list `[` opens: `label: snippet` rows, the same box as the people list.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "ariaLabel",
          "takes": "text",
          "required": true,
          "note": "Names the list, e.g. what can be referenced."
        },
        {
          "name": "sectionLabel",
          "takes": "text",
          "required": true,
          "note": "The section's heading."
        },
        {
          "name": "icon",
          "takes": "anything",
          "required": true,
          "note": "At each row's start: a 16px icon — unless the row brings its own (`CaptionedItem.icon`), or `iconFor` answers."
        },
        {
          "name": "iconFor",
          "takes": "a handler",
          "required": false,
          "note": "A row's 16px icon from what it points at — its `uri` — when the list holds several kinds of thing; `undefined` from it draws `icon`."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ReferenceMenu",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceMenu.tsx",
      "purpose": "What a link in a document offers whoever is writing it: Open, and — when it is alone on its line — Show as Row or Card.",
      "purposeFrom": "page",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencemenu--docs",
      "storyId": "primitives-referencemenu--in-an-editor",
      "docPage": "src/ReferenceMenu.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "referenceMenuClick",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceMenu.tsx",
      "purpose": "A click on the chip at `pos`, from its node view: while editing, with the menu installed, it opens the menu, and the caller stops the click there.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencemenu--docs",
      "storyId": "primitives-referencemenu--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ReferenceMenuView",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceMenu.tsx",
      "purpose": "The menu `ReferenceMenu` holds, hung under its chip.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "editor",
          "takes": "Editor | null",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencemenu--docs",
      "storyId": "primitives-referencemenu--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ReferenceNode",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/BlockNodes.tsx",
      "purpose": "A `nostr:` reference, drawn as the thing it points at — SPEC §13.1.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-blocknodes--docs",
      "storyId": "primitives-blocknodes--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ReferenceTrigger",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "`[` — reference something, inserted as a {@link CaptionedReference} chip.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "refreshLinkChips",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/LinkChips.ts",
      "purpose": "Look at the document again — after the app learned what more URLs name some other way.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-linkchips--docs",
      "storyId": "primitives-linkchips--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "releaseSelection",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/SelectionToolbar.tsx",
      "purpose": "Stop drawing it. Nothing kept, nothing dispatched.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-selectiontoolbar--docs",
      "storyId": "primitives-selectiontoolbar--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "RichText",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/RichText.tsx",
      "purpose": "Formatted text, drawn from a parsed tree: headings, paragraphs, both lists, a quote, code, a divider, a table and links, in one look for every app.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "blocks",
          "takes": "readonly RichTextBlock[]",
          "required": true,
          "note": "The tree, already parsed."
        },
        {
          "name": "size",
          "takes": "default | small",
          "required": false,
          "note": "Default `default`, the size of text you read."
        },
        {
          "name": "renderText",
          "takes": "a handler",
          "required": false,
          "note": "Draws plain text: what is left of a run once its links are drawn."
        },
        {
          "name": "renderReference",
          "takes": "a handler",
          "required": false,
          "note": "Draws a run that stands for an address. By default its text."
        },
        {
          "name": "renderBlock",
          "takes": "a handler",
          "required": false,
          "note": "Draws a block this part has no design for (an attachment, a widget)."
        },
        {
          "name": "renderAfter",
          "takes": "a handler",
          "required": false,
          "note": "Draws something after a line of text: after a paragraph, a heading or a quote, and inside a list item or a table cell after its words — where a document's chip asks for its card (SPEC §13.3)."
        },
        {
          "name": "onTick",
          "takes": "a handler",
          "required": false,
          "note": "Ticks or unticks a checklist item, by its block id: its box is then a control, one click where the text is read."
        }
      ],
      "variants": [
        {
          "prop": "size",
          "values": [
            "default",
            "small"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-richtext--docs",
      "storyId": "components-richtext--every-block",
      "docPage": "src/RichText.mdx",
      "app": null,
      "looks": [
        "[&_:is(ul,ol)]:pl-5 [&_li>p]:m-0 [&_li]:break-words [&_li]:marker:text-text-secondary [&_ol]:list-decimal [&_ul]:list-disc",
        "[&_blockquote>p]:m-0 [&_blockquote]:border-l-[3px] [&_blockquote]:border-text-muted [&_blockquote]:pl-2.5",
        "[&_:not(pre)>code]:rounded-sm [&_:not(pre)>code]:bg-bg-code [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:border [&_:not(pre)>code]:border-border-default [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-text-primary",
        "[&_pre>code]:text-[1em] [&_pre]:whitespace-pre-wrap [&_pre]:break-words [&_pre]:rounded-md [&_pre]:bg-bg-code [&_pre]:px-3 [&_pre]:py-2.5 [&_pre]:font-mono [&_pre]:text-[0.85em] [&_pre]:leading-relaxed [&_pre]:text-text-primary",
        "[&_:is(.hljs-keyword,.hljs-doctag,.hljs-type,.hljs-template-tag,.hljs-template-variable)]:text-syntax-keyword [&_.hljs-title]:text-syntax-function [&_:is(.hljs-number,.hljs-literal,.hljs-attr,.hljs-attribute,.hljs-meta,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id)]:text-syntax-constant [&_:is(.hljs-string,.hljs-regexp)]:text-syntax-string [&_:is(.hljs-built_in,.hljs-symbol)]:text-syntax-variable [&_.hljs-comment]:text-syntax-comment [&_:is(.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo)]:text-syntax-tag",
        "[&_:is(th,td)>p]:m-0 [&_:is(th,td)]:border [&_:is(th,td)]:border-border-default [&_:is(th,td)]:px-2 [&_:is(th,td)]:py-1 [&_:is(th,td)]:text-left [&_:is(th,td)]:align-top [&_table]:my-2 [&_table]:w-full [&_table]:border-collapse [&_th]:bg-bg-code [&_th]:font-medium [&_th]:text-text-primary",
        "[&_em]:italic [&_strong]:font-semibold [&_strong]:text-text-primary [&_u]:underline [&_u]:decoration-text-muted [&_u]:underline-offset-2",
        "text-body-2 leading-normal [&>:is(h2,h3)]:text-body-2 [&>:is(h2,h3)]:font-semibold [&>h1]:text-h4",
        "text-caption leading-snug [&>:is(h1,h2,h3)]:mb-0.5 [&>:is(h1,h2,h3)]:mt-1.5 [&>:is(h1,h2,h3)+:is(h1,h2,h3)]:mt-1 [&>:is(h1,h2,h3):last-child]:mb-0 [&>:is(h2,h3)]:text-caption [&>:is(h2,h3)]:font-semibold [&>h1]:text-body-2 [&>h1]:font-semibold"
      ]
    },
    {
      "name": "richTextClassName",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/RichText.tsx",
      "purpose": "RichText's look, for a box you draw yourself: an editor's, so that what is being written looks the same as what is read.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-richtext--docs",
      "storyId": "components-richtext--every-block",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ScrollArea",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ScrollArea.tsx",
      "purpose": "A region that scrolls without taking width for its scrollbar.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "orientation",
          "takes": "vertical | horizontal | both",
          "required": false,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "On the region: its size and placement."
        },
        {
          "name": "viewportClassName",
          "takes": "text",
          "required": false,
          "note": "On the viewport, the box that scrolls: a `max-h-*` cap."
        },
        {
          "name": "contentClassName",
          "takes": "text",
          "required": false,
          "note": "On the content, the box the children sit in: padding, gap, layout."
        },
        {
          "name": "viewportRef",
          "takes": "Ref<HTMLDivElement>",
          "required": false,
          "note": "The scrolling box itself, for a region that reads or drives its own scrolling: `ref.current.scrollTop`, `scrollTo`, `scrollHeight`."
        },
        {
          "name": "onScroll",
          "takes": "UIEventHandler<HTMLDivElement>",
          "required": false,
          "note": "Fires as the viewport scrolls — the unread policy's input, beside `viewportRef`."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "orientation",
          "values": [
            "vertical",
            "horizontal",
            "both"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        },
        {
          "id": "scroll",
          "behaviour": "Scrolls with our scrollbar"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "layout-scrollarea--docs",
      "storyId": "layout-scrollarea--default",
      "docPage": "src/ScrollArea.mdx",
      "app": null,
      "looks": [
        "touch-none select-none rounded-full opacity-0 transition-opacity delay-300"
      ]
    },
    {
      "name": "SearchInput",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/SearchInput.tsx",
      "purpose": "An inset field with a hairline border that strengthens on hover and on focus, and an optional keyboard hint at the right edge.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "shortcut",
          "takes": "text",
          "required": false,
          "note": "A keyboard hint drawn at the right edge, e.g."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-searchinput--docs",
      "storyId": "inputs-searchinput--default",
      "docPage": "src/SearchInput.mdx",
      "app": null,
      "looks": [
        "bg-bg-field border border-border-field shadow-field hover:border-border-strong rounded-lg transition-colors focus-within:border-border-strong",
        "text-input-value bg-transparent text-text-primary placeholder:text-text-muted outline-none"
      ]
    },
    {
      "name": "SectionHeader",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/SectionHeader.tsx",
      "purpose": "The 32px row a section starts with: a SectionLabel, and actions that appear while the row is hovered or keyboard-focused, as IconButtons with tooltips — always, on a screen with no hover.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "title",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "chevron",
          "takes": "true/false",
          "required": false,
          "note": "Collapsible: draws the chevron and makes the title a button that toggles."
        },
        {
          "name": "icon",
          "takes": "anything",
          "required": false,
          "note": "16px, stroke 1.5, before the title — a folder's (Katerina, 5 October: Peek's Folders, the standard heading with a folder icon)."
        },
        {
          "name": "isExpanded",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "onToggle",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "trailing",
          "takes": "anything",
          "required": false,
          "note": "Beside the title and always visible, before the actions — a count."
        },
        {
          "name": "count",
          "takes": "number",
          "required": false,
          "note": "How many there are, 8px after the title — not at the row's end, where `trailing` goes (Katerina, 7 October: a heading over a list says its count beside its name, as a tab does)."
        },
        {
          "name": "actions",
          "takes": "SectionAction[]",
          "required": false,
          "note": "Right-aligned, in the order given."
        },
        {
          "name": "menu",
          "takes": "anything",
          "required": false,
          "note": "The heading's \"More options\" menu: `MenuItem`s — what acts on the whole section, a folder's Rename or Archive (Katerina, 5 October: Peek's Folders page goes, and its folder actions move onto the folder's heading)."
        },
        {
          "name": "menuLabel",
          "takes": "text",
          "required": false,
          "note": "The ⋮'s accessible name. Default \"More options for\" the title."
        },
        {
          "name": "showActions",
          "takes": "hover | always",
          "required": false,
          "note": "`hover` reveals the actions while the row is hovered or keyboard-focused (always on a screen with no hover); `always` keeps them."
        },
        {
          "name": "hover",
          "takes": "fill | none",
          "required": false,
          "note": "`fill` lights the row under the pointer when it does something (a toggle, actions); `none` keeps it still — a heading whose actions are always shown, where the buttons light up on their own (UIG-14, Katerina, 19 September)."
        },
        {
          "name": "look",
          "takes": "heading | quiet | row",
          "required": false,
          "note": "`heading` (default): a section's title, the `SectionLabel`."
        },
        {
          "name": "render",
          "takes": "useRender.RenderProp",
          "required": false,
          "note": "What the title renders as, in Base UI's manner."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "showActions",
          "values": [
            "hover",
            "always"
          ]
        },
        {
          "prop": "hover",
          "values": [
            "fill",
            "none"
          ]
        },
        {
          "prop": "look",
          "values": [
            "heading",
            "quiet",
            "row"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "navigation-sectionheader--docs",
      "storyId": "navigation-sectionheader--plain",
      "docPage": "src/SectionHeader.mdx",
      "app": null,
      "looks": [
        "opacity-0 transition-[opacity,transform] duration-150 group-hover:opacity-100",
        "opacity-0 transition-[opacity,transform] duration-150 group-hover:opacity-100 rotate-90",
        "transition-transform duration-150 text-text-secondary rotate-90",
        "font-mono text-caption tabular-nums text-text-muted",
        "rounded-lg transition-colors text-text-secondary hover:text-text-primary",
        "rounded-lg transition-colors text-text-secondary hover:text-text-primary hover:bg-bg-hover",
        "opacity-0 transition-opacity group-hover:opacity-100 [@media(hover:none)]:opacity-100"
      ]
    },
    {
      "name": "SectionLabel",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/SectionLabel.tsx",
      "purpose": "The section-title span. Every section heading — sidebar sections, menu headings, panel titles — renders through it, so a change of voice is one edit. 12px / 500, primary text; some themes restyle it (the toolbar shows how).",
      "purposeFrom": "page",
      "props": [
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "tone",
          "takes": "primary | secondary | muted",
          "required": false,
          "note": null
        },
        {
          "name": "truncate",
          "takes": "true/false",
          "required": false,
          "note": "Cut a long label short with an ellipsis instead of letting it wrap or spill."
        },
        {
          "name": "folds",
          "takes": "true/false",
          "required": false,
          "note": "The title of a group that opens and closes."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "tone",
          "values": [
            "primary",
            "secondary",
            "muted"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-sectionlabel--docs",
      "storyId": "primitives-sectionlabel--default",
      "docPage": "src/SectionLabel.mdx",
      "app": null,
      "looks": [
        "text-h5 leading-3 text-text-secondary truncate",
        "text-h5 leading-3 text-text-muted truncate",
        "text-h5 leading-3 text-text-primary truncate",
        "text-h5 leading-3 leaf:font-mono leaf:text-small leaf:uppercase leaf:tracking-widest text-text-secondary",
        "text-h5 leading-3 leaf:font-mono leaf:text-small leaf:uppercase leaf:tracking-widest text-text-secondary truncate",
        "text-h5 leading-3 leaf:font-mono leaf:text-small leaf:uppercase leaf:tracking-widest text-text-muted",
        "text-h5 leading-3 leaf:font-mono leaf:text-small leaf:uppercase leaf:tracking-widest text-text-muted truncate",
        "text-h5 leading-3 leaf:font-mono leaf:text-small leaf:uppercase leaf:tracking-widest text-text-primary",
        "text-h5 leading-3 leaf:font-mono leaf:text-small leaf:uppercase leaf:tracking-widest text-text-primary truncate",
        "leaf:font-mono leaf:text-small leaf:uppercase leaf:tracking-widest"
      ]
    },
    {
      "name": "Select",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Select.tsx",
      "purpose": "One value for a form field: a button that shows the choice and opens a portalled listbox under itself.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "value",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "onChange",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "options",
          "takes": "SelectOption[]",
          "required": true,
          "note": null
        },
        {
          "name": "size",
          "takes": "default | small",
          "required": false,
          "note": null
        },
        {
          "name": "ariaLabel",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "aria-required",
          "takes": "boolean | 'true' | 'false'",
          "required": false,
          "note": "Set by a `Field` with `required`; a caller inside one owes nothing."
        },
        {
          "name": "placeholder",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "disabled",
          "takes": "true/false",
          "required": false,
          "note": null
        },
        {
          "name": "disabledReason",
          "takes": "text",
          "required": false,
          "note": "Why it cannot be changed right now (UIG-14, Katerina, 19 September)."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "size",
          "values": [
            "default",
            "small"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        },
        {
          "id": "walking",
          "behaviour": "Moves through its items with the arrow keys"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-select--docs",
      "storyId": "inputs-select--default",
      "docPage": "src/Select.mdx",
      "app": null,
      "looks": [
        "rounded-lg border bg-bg-field shadow-field text-left border-border-field outline-none transition-colors text-text-primary placeholder:text-text-muted disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field focus-visible:border-border-focus aria-expanded:border-border-focus signal:transition-shadow signal:focus-visible:shadow-focus-ring text-input-value",
        "rounded-lg border bg-bg-field shadow-field text-left border-border-field outline-none transition-colors text-text-primary placeholder:text-text-muted disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field focus-visible:border-border-focus aria-expanded:border-border-focus signal:transition-shadow signal:focus-visible:shadow-focus-ring text-caption",
        "rounded-lg border bg-bg-field shadow-field text-left border-border-field outline-none transition-colors text-text-primary placeholder:text-text-muted disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field cursor-not-allowed bg-bg-disabled text-text-disabled focus-visible:border-border-focus aria-expanded:border-border-focus signal:transition-shadow signal:focus-visible:shadow-focus-ring text-input-value",
        "rounded-lg border bg-bg-field shadow-field text-left border-border-field outline-none transition-colors text-text-primary placeholder:text-text-muted disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field cursor-not-allowed bg-bg-disabled text-text-disabled focus-visible:border-border-focus aria-expanded:border-border-focus signal:transition-shadow signal:focus-visible:shadow-focus-ring text-caption",
        "rounded-lg border bg-bg-field shadow-field text-left border-border-field outline-none transition-colors text-text-primary placeholder:text-text-muted hover:border-border-strong focus-visible:hover:border-border-focus aria-expanded:hover:border-border-focus disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field focus-visible:border-border-focus aria-expanded:border-border-focus signal:transition-shadow signal:focus-visible:shadow-focus-ring text-input-value",
        "rounded-lg border bg-bg-field shadow-field text-left border-border-field outline-none transition-colors text-text-primary placeholder:text-text-muted hover:border-border-strong focus-visible:hover:border-border-focus aria-expanded:hover:border-border-focus disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field focus-visible:border-border-focus aria-expanded:border-border-focus signal:transition-shadow signal:focus-visible:shadow-focus-ring text-caption",
        "rounded-lg border bg-bg-field shadow-field text-left border-border-field outline-none transition-colors text-text-primary placeholder:text-text-muted hover:border-border-strong focus-visible:hover:border-border-focus aria-expanded:hover:border-border-focus disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field cursor-not-allowed bg-bg-disabled text-text-disabled focus-visible:border-border-focus aria-expanded:border-border-focus signal:transition-shadow signal:focus-visible:shadow-focus-ring text-input-value",
        "rounded-lg border bg-bg-field shadow-field text-left border-border-field outline-none transition-colors text-text-primary placeholder:text-text-muted hover:border-border-strong focus-visible:hover:border-border-focus aria-expanded:hover:border-border-focus disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field cursor-not-allowed bg-bg-disabled text-text-disabled focus-visible:border-border-focus aria-expanded:border-border-focus signal:transition-shadow signal:focus-visible:shadow-focus-ring text-caption",
        "rounded-lg border bg-bg-field shadow-field text-left"
      ]
    },
    {
      "name": "SelectionToolbar",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/SelectionToolbar.tsx",
      "purpose": "Bold, italic and underline — and code or a link where the editor has them — over text you have already selected in an editor.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "editor",
          "takes": "Editor | null",
          "required": true,
          "note": "The editor whose selection the strip follows."
        },
        {
          "name": "marks",
          "takes": "readonly MarkId[]",
          "required": false,
          "note": "Which marks the strip toggles, in order."
        },
        {
          "name": "link",
          "takes": "true/false",
          "required": false,
          "note": "The Link button and its address field. Needs a link mark in the editor and `KeptSelection`."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": false,
          "note": "More of the strip, after the marks: the app's own `ToolbarButton`s for what is selected — a chip's card, say."
        },
        {
          "name": "actions",
          "takes": "readonly SelectionAction[]",
          "required": false,
          "note": "The app's own buttons after the marks, past a separator: \"Comment\"."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-selectiontoolbar--docs",
      "storyId": "primitives-selectiontoolbar--default",
      "docPage": "src/SelectionToolbar.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "setCommentAnchors",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/CommentHighlights.ts",
      "purpose": "Draw these comments, `active` the one being read.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-commenthighlights--docs",
      "storyId": "primitives-commenthighlights--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "setReferenceCard",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceCards.ts",
      "purpose": "Sets the card of the selected chip. `none` removes it.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencecards--docs",
      "storyId": "primitives-referencecards--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "setReferenceCardAt",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceCards.ts",
      "purpose": "Sets the card of the chip at `pos` — one that names something.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencecards--docs",
      "storyId": "primitives-referencecards--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "shortcutLabel",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/shortcuts.ts",
      "purpose": "`Mod-B` → `Cmd+B` on a Mac, `Ctrl+B` elsewhere.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ShowMore",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ShowMore.tsx",
      "purpose": "Long content cut at a height behind a fade, with \"Show more\" under it.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "maxHeight",
          "takes": "number",
          "required": false,
          "note": "The height to cut at, in px. Default 96: about seven lines of caption text."
        },
        {
          "name": "surface",
          "takes": "surface | inset",
          "required": false,
          "note": "What the content sits on, for the fade to end in: a panel's `surface` (default), or an inset card's `inset`."
        },
        {
          "name": "action",
          "takes": "anything",
          "required": false,
          "note": "A small muted `Button` with a leading icon, at the right of the toggle's row: the way out to where the content lives."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "surface",
          "values": [
            "surface",
            "inset"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "layout-showmore--docs",
      "storyId": "layout-showmore--long",
      "docPage": "src/ShowMore.mdx",
      "app": null,
      "looks": [
        "pointer-events-none bg-gradient-to-t to-transparent from-bg-surface",
        "pointer-events-none bg-gradient-to-t to-transparent from-bg-inset"
      ]
    },
    {
      "name": "Sidebar",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Sidebar.tsx",
      "purpose": "The navigation column: 240px, a hairline on its right, the surface behind it, scrolling independently of the content beside it.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "aria-label",
          "takes": "text",
          "required": false,
          "note": "Names the navigation region for assistive tech."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-sidebar--docs",
      "storyId": "frame-sidebar--composed",
      "docPage": "src/Sidebar.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "SkeletonBar",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Skeleton.tsx",
      "purpose": "One pulsing bar at the inset colour: the piece every placeholder here is built from.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "style",
          "takes": "CSSProperties",
          "required": false,
          "note": null
        },
        {
          "name": "on",
          "takes": "surface | inset",
          "required": false,
          "note": null
        },
        {
          "name": "shape",
          "takes": "keyof typeof SKELETON_SHAPE",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "on",
          "values": [
            "surface",
            "inset"
          ]
        }
      ],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-skeleton--docs",
      "storyId": "feedback-skeleton--list",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "SkeletonList",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Skeleton.tsx",
      "purpose": "Rows of varied widths, so the placeholder does not read as a pattern.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "rows",
          "takes": "number",
          "required": false,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-skeleton--docs",
      "storyId": "feedback-skeleton--list",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "SkeletonRow",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Skeleton.tsx",
      "purpose": "A 32px row: a 16px square and a bar, like a row with a face and a name.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "barWidth",
          "takes": "number",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-skeleton--docs",
      "storyId": "feedback-skeleton--list",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "SlashCommands",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "`/` — format the line or insert something, at the caret, mid-sentence too.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "startBlockDrag",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorBlockHandle.tsx",
      "purpose": "Starts the browser's own drag of the block, as ProseMirror starts one of a selected node: the block selected, its slice on `view.dragging` with `move`, and its HTML on the transfer.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editorblockhandle--docs",
      "storyId": "primitives-editorblockhandle--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "StatusMark",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkParts.tsx",
      "purpose": "A status as its shape, which reads without colour; its words on hover and to a screen reader.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "status",
          "takes": "LinkedStatus",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkparts--docs",
      "storyId": "components-linkparts--pickers",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "staysChip",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/LinkPlaces.ts",
      "purpose": "Whether what `uri` names stays a chip alone on its line: a person (`npub`, `nprofile`) or a Folder (an `naddr` of kind 39000).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-linkplaces--docs",
      "storyId": "primitives-linkplaces--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "SuggestionMenu",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/SuggestionMenu.tsx",
      "purpose": "The list a text editor opens as you type — `/` for commands, `@` for people — while focus stays in the text.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "rect",
          "takes": "DOMRect | null",
          "required": true,
          "note": "The caret's rect, from the editor. `null` closes the box."
        },
        {
          "name": "editorElement",
          "takes": "HTMLElement | null",
          "required": false,
          "note": "The editor's own element — told which row is active."
        },
        {
          "name": "ariaLabel",
          "takes": "text",
          "required": true,
          "note": "Names the list — \"Commands\", \"People\"."
        },
        {
          "name": "width",
          "takes": "text",
          "required": true,
          "note": "The box's width, e.g. `w-[300px]`."
        },
        {
          "name": "maxHeight",
          "takes": "text",
          "required": true,
          "note": "The cap before the rows scroll, e.g. `max-h-[400px]`."
        },
        {
          "name": "sections",
          "takes": "readonly SuggestionMenuSection<T>[]",
          "required": true,
          "note": null
        },
        {
          "name": "itemKey",
          "takes": "a handler",
          "required": true,
          "note": "A stable key for a row."
        },
        {
          "name": "row",
          "takes": "a handler",
          "required": true,
          "note": "What a row shows."
        },
        {
          "name": "onSelect",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "handle",
          "takes": "Ref<SuggestionMenuHandle>",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "focus",
          "behaviour": "Holds focus inside while open, and gives it back"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        },
        {
          "id": "walking",
          "behaviour": "Moves through its items with the arrow keys"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-suggestionmenu--docs",
      "storyId": "primitives-suggestionmenu--default",
      "docPage": "src/SuggestionMenu.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "suggestionPopup",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/suggestionPopup.tsx",
      "purpose": "The `render` of a Tiptap suggestion plugin, drawn as a `SuggestionMenu` — the popup controller Peek wrote four times (`mention.tsx`, `slashCommands.tsx`), once.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "ariaLabel",
          "takes": "text",
          "required": true,
          "note": "Names the list — \"Commands\", \"People\"."
        },
        {
          "name": "width",
          "takes": "text",
          "required": true,
          "note": "The box's width, e.g. `w-[300px]`."
        },
        {
          "name": "maxHeight",
          "takes": "text",
          "required": true,
          "note": "The cap before the rows scroll, e.g. `max-h-[400px]`."
        },
        {
          "name": "sections",
          "takes": "a handler",
          "required": false,
          "note": "The plugin's items, and the typed query, → the sections to draw."
        },
        {
          "name": "itemKey",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "row",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "subscribe",
          "takes": "a handler",
          "required": false,
          "note": "With `refresh`: called with a listener while the list is open; the app calls it when its data has changed (a search landing), and the open list is drawn again for the same query."
        },
        {
          "name": "refresh",
          "takes": "a handler",
          "required": false,
          "note": "The items for a query, as the plugin's `items` answers — asked again when `subscribe` fires."
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Tabs",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Tabs.tsx",
      "purpose": "A row of tabs for switching between views of one thing.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "tabs",
          "takes": "TabDef<T>[]",
          "required": true,
          "note": null
        },
        {
          "name": "active",
          "takes": "T",
          "required": true,
          "note": null
        },
        {
          "name": "onChange",
          "takes": "a handler",
          "required": true,
          "note": null
        },
        {
          "name": "size",
          "takes": "default | small",
          "required": false,
          "note": "`default` 14px; `small` 12px, the denser geometry."
        },
        {
          "name": "aria-label",
          "takes": "text",
          "required": false,
          "note": "Names the row for assistive tech — \"Views\", \"Filters\"."
        },
        {
          "name": "aria-labelledby",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "Lands on the outer box, around the row."
        }
      ],
      "variants": [
        {
          "prop": "size",
          "values": [
            "default",
            "small"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "walking",
          "behaviour": "Moves through its items with the arrow keys"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "navigation-tabs--docs",
      "storyId": "navigation-tabs--with-counts",
      "docPage": "src/Tabs.mdx",
      "app": null,
      "looks": [
        "font-mono text-caption tabular-nums text-text-secondary"
      ]
    },
    {
      "name": "Textarea",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Textarea.tsx",
      "purpose": "TextInput's look on a multi-line field that does not resize.",
      "purposeFrom": "page",
      "props": [],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-textarea--docs",
      "storyId": "inputs-textarea--empty",
      "docPage": "src/Textarea.mdx",
      "app": null,
      "looks": [
        "bg-bg-field border border-border-field shadow-field hover:border-border-strong focus:border-border-focus rounded-lg text-input-value text-text-primary placeholder:text-text-muted resize-none outline-none transition-colors disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field signal:transition-shadow signal:focus:shadow-focus-ring"
      ]
    },
    {
      "name": "TextInput",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/TextInput.tsx",
      "purpose": "The single-line field: inset surface, 8px radius, 14px text, a stronger border on hover, the focus border in every theme.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "size",
          "takes": "default | small",
          "required": false,
          "note": "`small` is 24px tall with 12px text — the small `Select`'s size, so a field can share a dense row with small selects (D67, 2026-09-13: Peek's reference widget hand-built one because this was 38px)."
        }
      ],
      "variants": [
        {
          "prop": "size",
          "values": [
            "default",
            "small"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "inputs-textinput--docs",
      "storyId": "inputs-textinput--empty",
      "docPage": "src/TextInput.mdx",
      "app": null,
      "looks": [
        "bg-bg-field border border-border-field shadow-field hover:border-border-strong focus:border-border-focus rounded-lg text-input-value text-text-primary placeholder:text-text-muted outline-none transition-colors disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field signal:transition-shadow signal:focus:shadow-focus-ring",
        "bg-bg-field border border-border-field shadow-field hover:border-border-strong focus:border-border-focus rounded-lg text-caption text-text-primary placeholder:text-text-muted outline-none transition-colors disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field signal:transition-shadow signal:focus:shadow-focus-ring"
      ]
    },
    {
      "name": "thingKindOf",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/KindIcon.tsx",
      "purpose": "The kind of thing behind an event kind: a message is a message, a channel or a bare file is a topic, a project and an issue are themselves, and anything else is another app's file.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-kindicon--docs",
      "storyId": "primitives-kindicon--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Toast",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Toast.tsx",
      "purpose": "A pill that says what just happened — three types, an optional leading check, an optional action — and ToastProvider/useToast, which own the positioning (bottom-left), the portal, and the auto-dismiss.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "type",
          "takes": "success | brand | neutral | warning | error",
          "required": false,
          "note": "Which of the five this is. It decides the surface in the light themes, and under Signal — where every pill is the same dark overlay — the icon and its colour."
        },
        {
          "name": "leadingIcon",
          "takes": "true/false",
          "required": false,
          "note": "Show the leading icon — a check, a `!` or an `×`, per `type`."
        },
        {
          "name": "actionLabel",
          "takes": "text",
          "required": false,
          "note": "When set together with onAction, renders a clickable action on the right side."
        },
        {
          "name": "onAction",
          "takes": "a handler",
          "required": false,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "type",
          "values": [
            "success",
            "brand",
            "neutral",
            "warning",
            "error"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-toast--docs",
      "storyId": "feedback-toast--neutral",
      "docPage": "src/Toast.mdx",
      "app": null,
      "looks": [
        "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
        "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
        "bg-bg-inset border border-border-subtle signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
        "bg-warning-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
        "bg-error-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md"
      ]
    },
    {
      "name": "ToastProvider",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Toast.tsx",
      "purpose": "Mount once, near the top of an app. It owns the stack, the timers and the portal every toast goes through, and it is what `useToast` talks to.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-toast--docs",
      "storyId": "feedback-toast--neutral",
      "docPage": null,
      "app": null,
      "looks": [
        "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
        "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
        "bg-bg-inset border border-border-subtle signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
        "bg-warning-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
        "bg-error-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md"
      ]
    },
    {
      "name": "toggleTableHeaderRow",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorTableControls.tsx",
      "purpose": "The table's first row becomes its header row, or an ordinary row again: whichever cell of the table `cell` is.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editortablecontrols--docs",
      "storyId": "primitives-editortablecontrols--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Toolbar",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Toolbar.tsx",
      "purpose": "A strip of controls that behaves as one control: Tab in, arrow keys along, Tab out — on the elevated box a floating strip needs.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "aria-label",
          "takes": "text",
          "required": true,
          "note": "Names the strip for assistive tech — \"Formatting\", \"Reactions\"."
        },
        {
          "name": "orientation",
          "takes": "horizontal | vertical",
          "required": false,
          "note": "`horizontal` walks with ← →, `vertical` with ↑ ↓."
        },
        {
          "name": "loopFocus",
          "takes": "true/false",
          "required": false,
          "note": "Whether the arrow keys wrap at the ends."
        },
        {
          "name": "surface",
          "takes": "true/false",
          "required": false,
          "note": "The elevated box around the strip. On by default — a toolbar floats, and this is what floating looks like here."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": "The row's own layout — its gap, its padding, its wrapping."
        }
      ],
      "variants": [
        {
          "prop": "orientation",
          "values": [
            "horizontal",
            "vertical"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "walking",
          "behaviour": "Moves through its items with the arrow keys"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-toolbar--docs",
      "storyId": "primitives-toolbar--default",
      "docPage": "src/Toolbar.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "ToolbarButton",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Toolbar.tsx",
      "purpose": "An `IconButton` that is an item of a `Toolbar`: the arrow keys reach it, and a disabled one stays in the walk so its reason can still be read.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "ref",
          "takes": "Ref<HTMLButtonElement>",
          "required": false,
          "note": null
        },
        {
          "name": "variant",
          "takes": "muted | outlined | primary | current | resolve",
          "required": false,
          "note": "`current` takes the colour of what it sits in — the ✕ on a `Banner` wears the banner's tone."
        },
        {
          "name": "pressed",
          "takes": "true/false",
          "required": false,
          "note": "On, like a Bold button while the selection is bold: the active fill, and `aria-pressed`."
        },
        {
          "name": "glow",
          "takes": "true/false",
          "required": false,
          "note": "A glow in Signal — the send arrow while there is something to send."
        },
        {
          "name": "tooltip",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "tooltipShortcut",
          "takes": "text",
          "required": false,
          "note": "A key hint drawn as the `Kbd` chip inside the tooltip — for a button whose only other affordance is a keyboard shortcut."
        },
        {
          "name": "tooltipPlacement",
          "takes": "top | bottom",
          "required": false,
          "note": null
        },
        {
          "name": "disabledReason",
          "takes": "text",
          "required": false,
          "note": "Why the action cannot succeed right now."
        },
        {
          "name": "href",
          "takes": "text",
          "required": false,
          "note": "A link that looks like an icon button: an anchor, so the address stays real for a modified click or a new tab, as `Link` keeps it."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The icon: 16px, stroke 1.5."
        }
      ],
      "variants": [
        {
          "prop": "variant",
          "values": [
            "muted",
            "outlined",
            "primary",
            "current",
            "resolve"
          ]
        },
        {
          "prop": "tooltipPlacement",
          "values": [
            "top",
            "bottom"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-toolbar--docs",
      "storyId": "primitives-toolbar--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ToolbarInput",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Toolbar.tsx",
      "purpose": "A `TextInput` that is an item of a `Toolbar`, so the arrow keys walk into the field and out of it again.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "size",
          "takes": "default | small",
          "required": false,
          "note": "`small` is 24px tall with 12px text — the small `Select`'s size, so a field can share a dense row with small selects (D67, 2026-09-13: Peek's reference widget hand-built one because this was 38px)."
        }
      ],
      "variants": [
        {
          "prop": "size",
          "values": [
            "default",
            "small"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-toolbar--docs",
      "storyId": "primitives-toolbar--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ToolbarLink",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Toolbar.tsx",
      "purpose": "An `IconButton` that is a link, and an item of a `Toolbar`: the arrow keys reach it like the buttons beside it.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "href",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "ref",
          "takes": "Ref<HTMLAnchorElement>",
          "required": false,
          "note": null
        },
        {
          "name": "variant",
          "takes": "muted | outlined | primary | current | resolve",
          "required": false,
          "note": "`current` takes the colour of what it sits in — the ✕ on a `Banner` wears the banner's tone."
        },
        {
          "name": "glow",
          "takes": "true/false",
          "required": false,
          "note": "A glow in Signal — the send arrow while there is something to send."
        },
        {
          "name": "tooltip",
          "takes": "text",
          "required": false,
          "note": null
        },
        {
          "name": "tooltipShortcut",
          "takes": "text",
          "required": false,
          "note": "A key hint drawn as the `Kbd` chip inside the tooltip — for a button whose only other affordance is a keyboard shortcut."
        },
        {
          "name": "tooltipPlacement",
          "takes": "top | bottom",
          "required": false,
          "note": null
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": "The icon: 16px, stroke 1.5."
        }
      ],
      "variants": [
        {
          "prop": "variant",
          "values": [
            "muted",
            "outlined",
            "primary",
            "current",
            "resolve"
          ]
        },
        {
          "prop": "tooltipPlacement",
          "values": [
            "top",
            "bottom"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-toolbar--docs",
      "storyId": "primitives-toolbar--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "ToolbarSeparator",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Toolbar.tsx",
      "purpose": "The hairline between two groups of controls.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-toolbar--docs",
      "storyId": "primitives-toolbar--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "Tooltip",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Tooltip.tsx",
      "purpose": "A 30px elevated pill with a caption, and WithTooltip, the wrapper that shows it beside a trigger — on hover, and on keyboard focus.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "shortcut",
          "takes": "text",
          "required": false,
          "note": "The key that does the same thing, drawn as the `Kbd` chip after the label."
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-tooltip--docs",
      "storyId": "primitives-tooltip--default",
      "docPage": "src/Tooltip.mdx",
      "app": null,
      "looks": [
        "rounded-lg border border-border-default bg-bg-elevated shadow-lg border-border-tooltip bg-bg-tooltip"
      ]
    },
    {
      "name": "TooltipProvider",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Tooltip.tsx",
      "purpose": "Mount once at the top of an app: it makes every tooltip below it share one delay, so the second and third open instantly while the group is warm.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "delay",
          "takes": "number",
          "required": false,
          "note": "Before the first tooltip in the group opens."
        },
        {
          "name": "closeDelay",
          "takes": "number",
          "required": false,
          "note": "Before one closes. Default: immediately, as it always has."
        },
        {
          "name": "timeout",
          "takes": "number",
          "required": false,
          "note": "How long after one closes its neighbours still open instantly."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-tooltip--docs",
      "storyId": "primitives-tooltip--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "TopBar",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/TopBar.tsx",
      "purpose": "The 52px top bar: `menu` and `logo` on the left, the search field in the centre, the identity cluster on the right.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "variant",
          "takes": "solid | floating | inset",
          "required": false,
          "note": null
        },
        {
          "name": "menu",
          "takes": "anything",
          "required": false,
          "note": "Far left: the menu button, in an app whose navigation collapses."
        },
        {
          "name": "logo",
          "takes": "anything",
          "required": false,
          "note": "Beside the menu button: the app's logo mark, or its name as text."
        },
        {
          "name": "search",
          "takes": "anything",
          "required": false,
          "note": "The centre: something of the caller's own."
        },
        {
          "name": "onSearch",
          "takes": "a handler",
          "required": false,
          "note": "What searching opens — the app's command launcher."
        },
        {
          "name": "searchPlaceholder",
          "takes": "text",
          "required": false,
          "note": "The words in the bar's own search field."
        },
        {
          "name": "right",
          "takes": "anything",
          "required": false,
          "note": "The right cluster — an `IdentityMenu` and its neighbours."
        },
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "variant",
          "values": [
            "solid",
            "floating",
            "inset"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        },
        {
          "id": "tab-stop",
          "behaviour": "Is reachable with Tab"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "frame-topbar--docs",
      "storyId": "frame-topbar--solid",
      "docPage": "src/TopBar.mdx",
      "app": null,
      "looks": [
        "cursor-pointer bg-bg-field border border-border-field shadow-field hover:border-border-strong rounded-lg transition-colors",
        "truncate text-left text-input-value text-text-muted"
      ]
    },
    {
      "name": "turnIntoRows",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorBlockHandle.tsx",
      "purpose": "The block menu's Turn into for one block, the same in every app (Miky, LEAF-11's kickoff, 15 October):",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editorblockhandle--docs",
      "storyId": "primitives-editorblockhandle--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "turnListInto",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorBlockHandle.tsx",
      "purpose": "Turns the whole list at `pos`, every item, the nested ones too.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editorblockhandle--docs",
      "storyId": "primitives-editorblockhandle--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "turnQuoteInto",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/EditorBlockHandle.tsx",
      "purpose": "Turns the quote at `pos`: a plain quote, a Note or Warning callout (the tone changes, the id stays), or its text, whose first paragraph takes the quote's id, as lifting it out does (MAN-12).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-editorblockhandle--docs",
      "storyId": "primitives-editorblockhandle--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "typeTrigger",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "A row that types another trigger, so its own list opens — `@` from `/`.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "unavailableMemory",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/linked.ts",
      "purpose": "The device's memory of links it could not show, under the app's own `storageKey`, keeping the newest `limit`.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": null,
      "storyId": null,
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "UnknownBlock",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/BlockNodes.tsx",
      "purpose": "A block this editor has no design for, kept whole.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-blocknodes--docs",
      "storyId": "primitives-blocknodes--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "UnreadDot",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/UnreadDot.tsx",
      "purpose": "The accent dot that says \"something new here\": a 6px disc centred in a 24px slot, so it sits exactly where a control would and the row does not shift when one replaces the other.",
      "purposeFrom": "page",
      "props": [
        {
          "name": "className",
          "takes": "text",
          "required": false,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-unreaddot--docs",
      "storyId": "primitives-unreaddot--default",
      "docPage": "src/UnreadDot.mdx",
      "app": null,
      "looks": []
    },
    {
      "name": "UrgentPersonMention",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "`!@` — a person, urgently: the same chip in the urgent tone.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "urgentPubkeys",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ComposerTriggers.tsx",
      "purpose": "The keys the document's urgent mentions name — what the write turns into `[\"urgent\", <pubkey>]` tags.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "state",
          "takes": "{ doc: Doc }",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-composertriggers--docs",
      "storyId": "primitives-composertriggers--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "useCanHover",
      "repo": "estiva-ui",
      "kind": "hook",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/LinkPreview.tsx",
      "purpose": "Whether this screen can hover. Without `matchMedia` (a test, a server) it is taken to.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "components-linkpreview--docs",
      "storyId": "components-linkpreview--on-hover",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "useReferenceCards",
      "repo": "estiva-ui",
      "kind": "hook",
      "importPath": "@estiva-app/ui/editor",
      "sourceFile": "src/ReferenceCards.ts",
      "purpose": "The slots to draw cards into, kept current as the document changes.",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-referencecards--docs",
      "storyId": "primitives-referencecards--in-an-editor",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "useToast",
      "repo": "estiva-ui",
      "kind": "hook",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Toast.tsx",
      "purpose": "How anything under a `ToastProvider` raises a toast (`showToast`) or takes one away (`dismissToast`).",
      "purposeFrom": "comment",
      "props": [],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "feedback-toast--docs",
      "storyId": "feedback-toast--neutral",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "whoReacted",
      "repo": "estiva-ui",
      "kind": "helper",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/ReactionRow.tsx",
      "purpose": "\"Person one, Person two and you reacted with Makes sense\".",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "emoji",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "by",
          "takes": "readonly string[]",
          "required": true,
          "note": null
        }
      ],
      "variants": [],
      "ownsBehaviours": [],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-reactionrow--docs",
      "storyId": "primitives-reactionrow--default",
      "docPage": null,
      "app": null,
      "looks": []
    },
    {
      "name": "WithTooltip",
      "repo": "estiva-ui",
      "kind": "component",
      "importPath": "@estiva-app/ui",
      "sourceFile": "src/Tooltip.tsx",
      "purpose": "A tooltip on something that cannot be its own trigger — a span, a `Chip`, an icon.",
      "purposeFrom": "comment",
      "props": [
        {
          "name": "label",
          "takes": "text",
          "required": true,
          "note": null
        },
        {
          "name": "shortcut",
          "takes": "text",
          "required": false,
          "note": "Passed straight to the surface — see `TooltipProps.shortcut`."
        },
        {
          "name": "placement",
          "takes": "top | bottom",
          "required": false,
          "note": null
        },
        {
          "name": "wrapperClassName",
          "takes": "text",
          "required": false,
          "note": "Extra classes on the wrapper — e.g. `min-w-0 shrink` so a truncating label keeps truncating inside it."
        },
        {
          "name": "inline",
          "takes": "true/false",
          "required": false,
          "note": "For a trigger inside a line of text — a reference, a name in a sentence: the wrapper is a `<span>`, because a `<div>` is not allowed inside a paragraph (UIG-14, Katerina, 19 September)."
        },
        {
          "name": "children",
          "takes": "anything",
          "required": true,
          "note": null
        }
      ],
      "variants": [
        {
          "prop": "placement",
          "values": [
            "top",
            "bottom"
          ]
        }
      ],
      "ownsBehaviours": [
        {
          "id": "base-ui",
          "behaviour": "Is built on Base UI"
        },
        {
          "id": "portal",
          "behaviour": "Floats on top of the page"
        },
        {
          "id": "press-outside",
          "behaviour": "Closes on a press outside"
        },
        {
          "id": "page-keys",
          "behaviour": "Takes its keys by itself"
        },
        {
          "id": "follow",
          "behaviour": "Stays attached to its anchor on scroll and resize"
        },
        {
          "id": "role",
          "behaviour": "Says what it is to assistive technology"
        }
      ],
      "status": "stable",
      "migrationStage": null,
      "docsId": "primitives-tooltip--docs",
      "storyId": "primitives-tooltip--default",
      "docPage": null,
      "app": null,
      "looks": []
    }
  ],
  "excluded": [],
  "filesWithoutParts": []
}
