{
  "v": 0,
  "components": {
    "components-clamped": {
      "id": "components-clamped",
      "name": "Clamped",
      "path": "./ui/src/components/Clamped.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Clamped } from \"#ui/components/Clamped.tsx\";"
        ]
      },
      "description": "Caps content at `maxHeight` with a fade and a toggle, folding only when\ncontent is actually taller than the cap (or than `foldOver`, when given).\nContent that changes size after mount (lazy images, async syntax\nhighlighting) re-measures via a ResizeObserver on the inner wrapper, and\nviewport resizes re-measure the vh-based caps.",
      "reactComponentMeta": {
        "displayName": "Clamped",
        "exportName": "Clamped",
        "filePath": "/home/runner/work/gitbutler/gitbutler/apps/lite/ui/src/components/Clamped.tsx",
        "description": "Caps content at `maxHeight` with a fade and a toggle, folding only when\ncontent is actually taller than the cap (or than `foldOver`, when given).\nContent that changes size after mount (lazy images, async syntax\nhighlighting) re-measures via a ResizeObserver on the inner wrapper, and\nviewport resizes re-measure the vh-based caps.",
        "jsDocTags": {
          "import": [
            "import { Clamped } from \"#ui/components/Clamped.tsx\";"
          ]
        },
        "props": {
          "maxHeight": {
            "name": "maxHeight",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "A px, vh or lh length, e.g. `\"240px\"`, `\"80vh\"` or `\"3lh\"`.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "ui/src/components/Clamped.tsx"
              }
            ]
          },
          "foldOver": {
            "name": "foldOver",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Fold only once the content is taller than this, so that a fold never\nhides just a line or two behind a click. Defaults to `maxHeight`.",
            "defaultValue": {
              "value": "maxHeight"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "ui/src/components/Clamped.tsx"
              }
            ]
          },
          "skipWhenViewportFits": {
            "name": "skipWhenViewportFits",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Don't fold when the full content already fits within the viewport.",
            "defaultValue": {
              "value": "false"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "ui/src/components/Clamped.tsx"
              }
            ]
          },
          "variant": {
            "name": "variant",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"text\" | \"card\"",
              "value": [
                {
                  "value": "\"text\""
                },
                {
                  "value": "\"card\""
                }
              ]
            },
            "description": "`text` (the default) seats a Show more link on the fade and a Show less\nlink under the unfolded content. `card` sets the folded content on a\nquiet card with a chevron at its corner; unfolded, the content lies flat\nwith the chevron at its top right, where the eye was left.",
            "defaultValue": {
              "value": "\"text\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "ui/src/components/Clamped.tsx"
              }
            ]
          },
          "children": {
            "name": "children",
            "required": true,
            "type": {
              "name": "ReactNode"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "ui/src/components/Clamped.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-clamped--folded",
          "name": "Folded",
          "snippet": "const Folded = () => <div style={{ maxWidth: 480, display: \"flex\", flexDirection: \"column\" }}>\n    <Clamped maxHeight=\"240px\">{paragraphs(12)}</Clamped>\n</div>;",
          "description": "Content well over the cap folds behind Show more, with the fade."
        },
        {
          "id": "components-clamped--short-content",
          "name": "Short Content",
          "snippet": "const ShortContent = () => <div style={{ maxWidth: 480, display: \"flex\", flexDirection: \"column\" }}>\n    <Clamped maxHeight=\"240px\">{paragraphs(2)}</Clamped>\n</div>;",
          "description": "Content shorter than the cap renders with no toggle and no fade."
        },
        {
          "id": "components-clamped--barely-overflowing",
          "name": "Barely Overflowing",
          "snippet": "const BarelyOverflowing = () => <div style={{ maxWidth: 480, display: \"flex\", flexDirection: \"column\" }}>\n    <Clamped maxHeight=\"240px\">{paragraphs(4)}</Clamped>\n</div>;",
          "description": "Content only a hair taller than the cap still folds — expanding reveals\nalmost nothing. Exhibit A for giving the fold trigger some slack over\nthe clamp height."
        },
        {
          "id": "components-clamped--card",
          "name": "Card",
          "snippet": "const Card = () => <div\n    style={{ maxWidth: 480, display: \"flex\", flexDirection: \"column\", rowGap: 12 }}>\n    <Clamped maxHeight=\"4lh\" foldOver=\"6lh\" variant=\"card\">\n        <div className=\"text-13 text-body\">{paragraphs(3)}</div>\n    </Clamped>\n    <Clamped maxHeight=\"4lh\" foldOver=\"6lh\" variant=\"card\">\n        <div className=\"text-13 text-body\">{paragraphs(1)}</div>\n    </Clamped>\n</div>;",
          "description": "The card variant, as the PR description uses it: four lines on a quiet\ncard with a chevron, folding only past six so a click always reveals\nmore than a line or two."
        },
        {
          "id": "components-clamped--grows-after-mount",
          "name": "Grows After Mount",
          "snippet": "const GrowsAfterMount = () => <LateGrowth maxHeight=\"240px\" />;",
          "description": "Content that grows after mount (lazy images, async highlighting) still\ngets its Show more — the ResizeObserver re-measures on growth."
        }
      ],
      "import": "import { Clamped } from '#ui/components/Clamped.tsx';"
    },
    "components-graphsegment": {
      "id": "components-graphsegment",
      "name": "GraphSegment",
      "path": "./ui/src/components/GraphSegment.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { GraphSegment } from \"#ui/components/GraphSegment.tsx\";"
        ]
      },
      "reactComponentMeta": {
        "displayName": "GraphSegment",
        "exportName": "GraphSegment",
        "filePath": "/home/runner/work/gitbutler/gitbutler/apps/lite/ui/src/components/GraphSegment.tsx",
        "description": "",
        "jsDocTags": {
          "import": [
            "import { GraphSegment } from \"#ui/components/GraphSegment.tsx\";"
          ]
        },
        "props": {
          "glyph": {
            "name": "glyph",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"parent\" | \"horizontal\" | \"space\" | \"forkLeft\" | \"forkRight\" | \"notch\" | \"hook\" | \"forkBoth\" | \"mergeLeft\" | \"mergeRight\" | \"mergeBoth\" | \"joinLeft\" | \"joinRight\" | \"joinBoth\" | \"commit\" | \"group\"",
              "value": [
                {
                  "value": "\"parent\""
                },
                {
                  "value": "\"horizontal\""
                },
                {
                  "value": "\"space\""
                },
                {
                  "value": "\"forkLeft\""
                },
                {
                  "value": "\"forkRight\""
                },
                {
                  "value": "\"notch\""
                },
                {
                  "value": "\"hook\""
                },
                {
                  "value": "\"forkBoth\""
                },
                {
                  "value": "\"mergeLeft\""
                },
                {
                  "value": "\"mergeRight\""
                },
                {
                  "value": "\"mergeBoth\""
                },
                {
                  "value": "\"joinLeft\""
                },
                {
                  "value": "\"joinRight\""
                },
                {
                  "value": "\"joinBoth\""
                },
                {
                  "value": "\"commit\""
                },
                {
                  "value": "\"group\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          },
          "status": {
            "name": "status",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"Diverged\" | \"Upstream\" | \"LocalOnly\" | \"LocalAndRemote\" | \"Integrated\"",
              "value": [
                {
                  "value": "\"Diverged\""
                },
                {
                  "value": "\"Upstream\""
                },
                {
                  "value": "\"LocalOnly\""
                },
                {
                  "value": "\"LocalAndRemote\""
                },
                {
                  "value": "\"Integrated\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          },
          "railEnds": {
            "name": "railEnds",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "The rail ends on this row: no tail below the icon, nothing stretched under a taller row.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          },
          "folded": {
            "name": "folded",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "What lies below the row is folded away: the trunk's tail behind the row fades out, a hint of it.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          },
          "centered": {
            "name": "centered",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "The rings sit on the row's centre line, for a single-line row of their own.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          },
          "above": {
            "name": "above",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"Diverged\" | \"Upstream\" | \"LocalOnly\" | \"LocalAndRemote\" | \"Integrated\"",
              "value": [
                {
                  "value": "\"Diverged\""
                },
                {
                  "value": "\"Upstream\""
                },
                {
                  "value": "\"LocalOnly\""
                },
                {
                  "value": "\"LocalAndRemote\""
                },
                {
                  "value": "\"Integrated\""
                }
              ]
            },
            "description": "The rail above or below the icon in another status's colour; a stretch between two icons is the lower one's.",
            "defaultValue": null,
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          },
          "below": {
            "name": "below",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"Diverged\" | \"Upstream\" | \"LocalOnly\" | \"LocalAndRemote\" | \"Integrated\"",
              "value": [
                {
                  "value": "\"Diverged\""
                },
                {
                  "value": "\"Upstream\""
                },
                {
                  "value": "\"LocalOnly\""
                },
                {
                  "value": "\"LocalAndRemote\""
                },
                {
                  "value": "\"Integrated\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          },
          "fromTrunk": {
            "name": "fromTrunk",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Bend from the trunk one column left into this commit's ring.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          },
          "behind": {
            "name": "behind",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "How many columns of the main line run behind the row, left of the glyph.",
            "defaultValue": {
              "value": "0"
            },
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          },
          "trunk": {
            "name": "trunk",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "The glyph is the trunk's own, or a leg onto it, and goes when the trunk is hidden.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "GraphSegmentProps",
              "fileName": "ui/src/components/GraphSegment.tsx"
            },
            "declarations": [
              {
                "name": "GraphSegmentProps",
                "fileName": "ui/src/components/GraphSegment.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-graphsegment--default",
          "name": "Default",
          "snippet": "const Default = () => <div\n    style={{\n        height: 100,\n        backgroundColor: \"var(--bg-2)\",\n        display: \"flex\",\n    }}>\n    <GraphSegment glyph=\"parent\" status=\"LocalOnly\" />\n</div>;"
        },
        {
          "id": "components-graphsegment--all-glyphs",
          "name": "All Glyphs",
          "snippet": "const AllGlyphs = () => (\n    <div style={{ display: \"flex\", gap: 16 }}>\n        {glyphs.map((glyph) => (\n            <div\n                key={glyph}\n                style={{\n                    display: \"flex\",\n                    alignItems: \"flex-start\",\n                    flexDirection: \"column\",\n                    gap: 12,\n                }}\n            >\n                <div style={{ backgroundColor: \"var(--bg-2)\", display: \"flex\" }}>\n                    <GraphSegment glyph={glyph} status=\"LocalOnly\" />\n                </div>\n                <div style={{ fontSize: 10 }}>{glyph}</div>\n            </div>\n        ))}\n    </div>\n);"
        }
      ],
      "import": "import { GraphSegment } from '#ui/components/GraphSegment.tsx';"
    },
    "components-markdown": {
      "id": "components-markdown",
      "name": "Markdown",
      "path": "./ui/src/components/Markdown.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Markdown } from \"#ui/components/Markdown.tsx\";"
        ]
      },
      "description": "Renders forge-flavored markdown with GitHub-parity restrictions:\n\n- Raw HTML renders through {@link sanitizeSchema} — GitHub's safe subset,\n  so `<details>` folds here like it does on github.com, while scripts,\n  styles, event handlers, and unsafe URL schemes are stripped.\n- Markdown-authored URLs additionally pass react-markdown's default\n  transform; links only open via the system browser, and the Electron\n  shell blocks all in-app navigation.\n- Images inline only from GitHub-operated hosts (which don't expose\n  request logs to authors, so they can't track viewers); any other host\n  renders as a link and is never fetched. See {@link isGitHubHostedImage}.",
      "reactComponentMeta": {
        "displayName": "Markdown",
        "exportName": "Markdown",
        "filePath": "/home/runner/work/gitbutler/gitbutler/apps/lite/ui/src/components/Markdown.tsx",
        "description": "Renders forge-flavored markdown with GitHub-parity restrictions:\n\n- Raw HTML renders through {@link sanitizeSchema} — GitHub's safe subset,\n  so `<details>` folds here like it does on github.com, while scripts,\n  styles, event handlers, and unsafe URL schemes are stripped.\n- Markdown-authored URLs additionally pass react-markdown's default\n  transform; links only open via the system browser, and the Electron\n  shell blocks all in-app navigation.\n- Images inline only from GitHub-operated hosts (which don't expose\n  request logs to authors, so they can't track viewers); any other host\n  renders as a link and is never fetched. See {@link isGitHubHostedImage}.",
        "jsDocTags": {
          "import": [
            "import { Markdown } from \"#ui/components/Markdown.tsx\";"
          ]
        },
        "props": {
          "children": {
            "name": "children",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "ui/src/components/Markdown.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-markdown--sample",
          "name": "Sample",
          "snippet": "const Sample = () => <Markdown>{`# Summary\n\nAdds a description editor to the PR create form. When the body is empty, the editor offers a one-line prompt instead of a blank field, so a short description is one click away.\n\n## What changed\n\n- The empty state is a button that opens the editor with the commit messages pasted in\n- Existing descriptions open as before\n\nRun it locally with the CLI:\n\n\\`\\`\\`sh\n$ but commit -m \"Add description editor\"\n$ but push\n\\`\\`\\`\n\n### Notes for reviewers\n\n> Reviewers asked for a shorter first paragraph, so the summary now leads with what changed.\n\n| File | Change | Status |\n| --- | --- | --- |\n| Markdown.tsx | Description editor | Done |\n| Field.tsx | Empty prompt | In review |\n\n- [ ] Update the screenshots in the PR\n- [ ] Add the DESIGN.md section\n\n![App preview](https://raw.githubusercontent.com/gitbutlerapp/gitbutler/master/apps/web/static/images/app-preview-light.png)\n\n---\n\n[See the design notes](https://github.com/gitbutlerapp/gitbutler/blob/master/packages/ui-react/DESIGN.md)\n\nThen run \\`but status\\` to check.`}</Markdown>;",
          "description": "The same document as the default content of \"Markdown / slot\" in ⚛️ Lite\nCore: every block the kit has a component for, in the app's rhythm.\nCompare the two when either side changes."
        },
        {
          "id": "components-markdown--headings",
          "name": "Headings",
          "snippet": "const Headings = () => <Markdown>{`# Heading 1\n\nBody text at 13px on a 160% line.\n\n## Heading 2\n\nBody text at 13px on a 160% line.\n\n### Heading 3\n\nBody text at 13px on a 160% line.\n\n#### Heading 4\n\nLevels four to six stay at the body size and only go semibold.`}</Markdown>;",
          "description": "The three heading levels next to body text, and the levels below them that share the body size."
        },
        {
          "id": "components-markdown--inline",
          "name": "Inline",
          "snippet": "const Inline = () => <Markdown>{`Press <kbd>⌘</kbd> <kbd>Enter</kbd> to commit, or run \\`but commit\\` from a shell.\n\n<details>\n<summary>Why a fold?</summary>\n\nLong logs and stack traces go behind a fold so the description stays readable.\n\n</details>`}</Markdown>;",
          "description": "Inline chips, a keycap, and a fold: the pieces Figma can't run inside a text line."
        }
      ],
      "import": "import { Markdown } from '#ui/components/Markdown.tsx';\nimport { QueryClientProvider } from '@tanstack/react-query';"
    },
    "components-avatar": {
      "id": "components-avatar",
      "name": "Avatar",
      "path": "../../packages/ui-react/src/Avatar.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Avatar } from \"@gitbutler/ui-react/Avatar.tsx\";"
        ]
      },
      "description": "A person's picture in a circle. Without one, or when it fails to load, the real Gravatar\nphoto for an email `seed`; failing that, the person's glitch in a colour picked from\n`seed` (a login or an email), the same one that shows while a picture loads and the one\n`ProfileImage` draws. Never a generated face, a blank or a broken image.\nDecorative by default: the name beside it is what a screen reader reads, so give `alt`\nonly where it stands alone.",
      "reactComponentMeta": {
        "displayName": "Avatar",
        "exportName": "Avatar",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Avatar.tsx",
        "description": "A person's picture in a circle. Without one, or when it fails to load, the real Gravatar\nphoto for an email `seed`; failing that, the person's glitch in a colour picked from\n`seed` (a login or an email), the same one that shows while a picture loads and the one\n`ProfileImage` draws. Never a generated face, a blank or a broken image.\nDecorative by default: the name beside it is what a screen reader reads, so give `alt`\nonly where it stands alone.",
        "jsDocTags": {
          "import": [
            "import { Avatar } from \"@gitbutler/ui-react/Avatar.tsx\";"
          ]
        },
        "props": {
          "src": {
            "name": "src",
            "required": true,
            "type": {
              "name": "string | null | undefined"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Avatar.tsx"
              }
            ]
          },
          "seed": {
            "name": "seed",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "Who this is, for the fallback: an email finds their Gravatar, and either picks the colour.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Avatar.tsx"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "14 | 16 | 18",
              "value": [
                {
                  "value": "14"
                },
                {
                  "value": "16"
                },
                {
                  "value": "18"
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "16"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Avatar.tsx"
              }
            ]
          },
          "alt": {
            "name": "alt",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": {
              "value": "\"\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Avatar.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Avatar.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-avatar--default",
          "name": "Default",
          "snippet": "const Default = () => <Avatar\n    src=\"https://avatars.githubusercontent.com/u/7453394?v=4\"\n    seed=\"PavelLaptev\" />;"
        },
        {
          "id": "components-avatar--no-picture",
          "name": "No Picture",
          "snippet": "const NoPicture = (args) => (\n    <div\n        style={{\n            display: \"grid\",\n            gridTemplateColumns: \"repeat(4, auto)\",\n            gap: 12,\n            width: \"fit-content\",\n        }}\n    >\n        {[\n            \"krlvi\",\n            \"schacon\",\n            \"Caleb-T-Owens\",\n            \"mtsgrd\",\n            \"slarse\",\n            \"samhh\",\n            \"estib-vega\",\n            \"PavelLaptev\",\n        ].map((login) => (\n            <div key={login} style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n                {sizes.map((size) => (\n                    <Avatar key={size} {...args} seed={login} size={size} />\n                ))}\n            </div>\n        ))}\n    </div>\n);",
          "description": "No picture: the person's glitch, in a colour picked from the login, the same wherever they appear."
        },
        {
          "id": "components-avatar--sizes",
          "name": "Sizes",
          "snippet": "const Sizes = (args) => (\n    <div style={{ display: \"flex\", gap: 12, alignItems: \"center\" }}>\n        {sizes.map((size) => (\n            <Avatar key={size} {...args} size={size} />\n        ))}\n        {sizes.map((size) => (\n            <Avatar key={`p${size}`} src={null} seed={args.seed} size={size} />\n        ))}\n    </div>\n);"
        },
        {
          "id": "components-avatar--broken",
          "name": "Broken",
          "snippet": "const Broken = () => <Avatar src=\"https://example.invalid/missing.png\" seed=\"PavelLaptev\" />;",
          "description": "A picture that fails to load: the glitch takes its place, not a broken image."
        }
      ],
      "import": "import { Avatar } from '@gitbutler/ui-react/Avatar.tsx';"
    },
    "components-badge": {
      "id": "components-badge",
      "name": "Badge",
      "path": "../../packages/ui-react/src/Badge.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Badge } from \"@gitbutler/ui-react/Badge.tsx\";"
        ]
      },
      "description": "A small pill carrying a count, a status or a short label.\n\nAn icon leads the label or stands alone; it never trails, and a badge is\nnever a control. Something that opens a menu or acts is a `Button` beside\nthe badge.",
      "reactComponentMeta": {
        "displayName": "Badge",
        "exportName": "Badge",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Badge.tsx",
        "description": "A small pill carrying a count, a status or a short label.\n\nAn icon leads the label or stands alone; it never trails, and a badge is\nnever a control. Something that opens a menu or acts is a `Button` beside\nthe badge.",
        "jsDocTags": {
          "import": [
            "import { Badge } from \"@gitbutler/ui-react/Badge.tsx\";"
          ]
        },
        "props": {
          "variant": {
            "name": "variant",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"pop\" | \"fillGray\" | \"lightGray\" | \"safe\" | \"warn\" | \"danger\" | \"purple\" | \"blue\"",
              "value": [
                {
                  "value": "\"pop\""
                },
                {
                  "value": "\"fillGray\""
                },
                {
                  "value": "\"lightGray\""
                },
                {
                  "value": "\"safe\""
                },
                {
                  "value": "\"warn\""
                },
                {
                  "value": "\"danger\""
                },
                {
                  "value": "\"purple\""
                },
                {
                  "value": "\"blue\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Badge.tsx"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"regular\" | \"large\"",
              "value": [
                {
                  "value": "\"regular\""
                },
                {
                  "value": "\"large\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"regular\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Badge.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-badge--default",
          "name": "Default",
          "snippet": "const Default = () => <Badge variant=\"fillGray\">42</Badge>;"
        },
        {
          "id": "components-badge--all-variants",
          "name": "All Variants",
          "snippet": "const AllVariants = () => (\n    <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n        <Badge variant=\"fillGray\">fillGray</Badge>\n        <Badge variant=\"lightGray\">lightGray</Badge>\n        <Badge variant=\"safe\">safe</Badge>\n        <Badge variant=\"warn\">warn</Badge>\n        <Badge variant=\"danger\">danger</Badge>\n        <Badge variant=\"purple\">purple</Badge>\n        <Badge variant=\"blue\">blue</Badge>\n    </div>\n);"
        },
        {
          "id": "components-badge--all-sizes",
          "name": "All Sizes",
          "snippet": "const AllSizes = () => (\n    <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n        <Badge variant=\"fillGray\">regular</Badge>\n        <Badge variant=\"fillGray\" size=\"large\">\n            large\n        </Badge>\n        <Badge variant=\"safe\">42</Badge>\n        <Badge variant=\"safe\" size=\"large\">\n            42\n        </Badge>\n    </div>\n);"
        },
        {
          "id": "components-badge--inverted",
          "name": "Inverted",
          "snippet": "const Inverted = () => (\n    <div\n        style={{\n            [\"--selection-inverted\" as string]: \"true\",\n            display: \"flex\",\n            gap: 8,\n            alignItems: \"center\",\n            padding: 8,\n            borderRadius: 6,\n            backgroundColor: \"var(--fill-gray-bg)\",\n            color: \"var(--fill-gray-fg)\",\n        }}\n    >\n        <Badge variant=\"fillGray\">fillGray</Badge>\n        <Badge variant=\"lightGray\">lightGray</Badge>\n        <Badge variant=\"safe\">safe</Badge>\n        <Badge variant=\"warn\">warn</Badge>\n        <Badge variant=\"danger\">danger</Badge>\n    </div>\n);"
        },
        {
          "id": "components-badge--with-icon",
          "name": "With Icon",
          "snippet": "const WithIcon = () => (\n    <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n        <Badge variant=\"safe\">\n            <Icon name=\"tick\" size={12} />\n        </Badge>\n        <Badge variant=\"danger\">\n            <Icon name=\"cross\" size={12} />\n        </Badge>\n        <Badge variant=\"lightGray\">\n            <Icon name=\"spinner\" size={12} />\n        </Badge>\n        <Badge variant=\"warn\">\n            <Icon name=\"warning\" size={12} />\n        </Badge>\n        <Badge variant=\"safe\">\n            <Icon name=\"tick\" size={12} />\n            Passed\n        </Badge>\n        <Badge variant=\"safe\" size=\"large\">\n            <Icon name=\"tick\" size={12} />\n            Passed\n        </Badge>\n    </div>\n);"
        },
        {
          "id": "components-badge--ci-states",
          "name": "CI States",
          "snippet": "const CIStates = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n        {ciStates.map(({ label, variant, icon }) => (\n            <div key={label} style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n                <Badge variant={variant}>\n                    <Icon name={icon} size={12} />\n                </Badge>\n                <span className=\"text-12\">{label}</span>\n            </div>\n        ))}\n    </div>\n);",
          "description": "A pull request's checks as an app shows them: every CI state and the icon-only badge it\ntakes, its variant chosen by what the state asks of the reader. A run still going that already has a failure is red with\nthe spinner: the failure is the news, the spinner says more may come."
        }
      ],
      "import": "import { Badge } from '@gitbutler/ui-react/Badge.tsx';\nimport { Icon } from '@gitbutler/ui-react';"
    },
    "components-banner": {
      "id": "components-banner",
      "name": "Banner",
      "path": "../../packages/ui-react/src/Banner.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Banner } from \"@gitbutler/ui-react/Banner.tsx\";"
        ]
      },
      "description": "A condition that holds right now, set into the layout above the thing it affects: live updates\npaused, a machine offline, a server that won't answer. It stays while the condition is true and\nleaves when it clears, so it has no close button; the caller renders it only while it applies.\n\nThe title is the one line every banner has. `children` is an optional second sentence under it.\nThe icon and the action line up with the title. The action is the fix (Retry, Reconnect, Pull):\none small ghost `Button`, which takes the banner's colour.\n\nUse a Snackbar for the outcome of something the user just did; a banner is for state.",
      "reactComponentMeta": {
        "displayName": "Banner",
        "exportName": "Banner",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Banner.tsx",
        "description": "A condition that holds right now, set into the layout above the thing it affects: live updates\npaused, a machine offline, a server that won't answer. It stays while the condition is true and\nleaves when it clears, so it has no close button; the caller renders it only while it applies.\n\nThe title is the one line every banner has. `children` is an optional second sentence under it.\nThe icon and the action line up with the title. The action is the fix (Retry, Reconnect, Pull):\none small ghost `Button`, which takes the banner's colour.\n\nUse a Snackbar for the outcome of something the user just did; a banner is for state.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Banner } from \"@gitbutler/ui-react/Banner.tsx\";"
          ]
        },
        "props": {
          "variant": {
            "name": "variant",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"pop\" | \"safe\" | \"warn\" | \"danger\" | \"gray\"",
              "value": [
                {
                  "value": "\"pop\""
                },
                {
                  "value": "\"safe\""
                },
                {
                  "value": "\"warn\""
                },
                {
                  "value": "\"danger\""
                },
                {
                  "value": "\"gray\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Banner.tsx"
              }
            ]
          },
          "title": {
            "name": "title",
            "required": true,
            "type": {
              "name": "ReactNode"
            },
            "description": "One line saying the condition.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Banner.tsx"
              }
            ]
          },
          "icon": {
            "name": "icon",
            "required": false,
            "type": {
              "name": "false | IconName | undefined"
            },
            "description": "Overrides the variant's own glyph; `false` drops it.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Banner.tsx"
              }
            ]
          },
          "action": {
            "name": "action",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "One small ghost `Button`.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Banner.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-banner--default",
          "name": "Default",
          "snippet": "const Default = () => <Banner\n    variant=\"warn\"\n    title=\"Live updates paused · may be out of date\"\n    action={(<Button variant=\"ghost\" size=\"small\">Retry\n                    </Button>)} />;",
          "description": "The banner as the design states it: a glyph, a title, and the fix."
        },
        {
          "id": "components-banner--all-variants",
          "name": "All Variants",
          "snippet": "const AllVariants = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n        {([\"warn\", \"danger\", \"pop\", \"safe\", \"gray\"] satisfies Array<BannerVariant>).map((variant) => (\n            <Banner\n                key={variant}\n                variant={variant}\n                title=\"Live updates paused · may be out of date\"\n                action={\n                    <Button variant=\"ghost\" size=\"small\">\n                        Retry\n                    </Button>\n                }\n            />\n        ))}\n    </div>\n);",
          "description": "Five variants, chosen by meaning. Gray carries no verdict, so its title keeps the body colour."
        },
        {
          "id": "components-banner--live-updates-paused",
          "name": "Live Updates Paused",
          "snippet": "const LiveUpdatesPaused = () => (\n    <Banner\n        variant=\"warn\"\n        title=\"Live updates paused · may be out of date\"\n        action={\n            <Button variant=\"ghost\" size=\"small\">\n                Retry\n            </Button>\n        }\n    />\n);",
          "description": "The live channel dropped and hasn't come back: the page still works, but may be stale."
        },
        {
          "id": "components-banner--machine-offline",
          "name": "Machine Offline",
          "snippet": "const MachineOffline = () => (\n    <Banner\n        variant=\"gray\"\n        title=\"pavel-macbook-pro-2 is offline\"\n        action={\n            <Button variant=\"ghost\" size=\"small\">\n                Copy command\n            </Button>\n        }\n    >\n        Last seen 3d ago. Wake it up, or run but mesh service restart there.\n    </Banner>\n);",
          "description": "A machine stopped sending heartbeats; the description says what the user can do about it."
        },
        {
          "id": "components-banner--unreachable",
          "name": "Unreachable",
          "snippet": "const Unreachable = () => (\n    <Banner\n        variant=\"danger\"\n        title=\"Couldn't reach your mesh\"\n        action={\n            <Button variant=\"ghost\" size=\"small\">\n                Try again\n            </Button>\n        }\n    >\n        The server answered “502 Bad Gateway”. Trying again every few seconds.\n    </Banner>\n);",
          "description": "The server won't answer. `danger` announces itself to screen readers as an alert."
        },
        {
          "id": "components-banner--moved-elsewhere",
          "name": "Moved Elsewhere",
          "snippet": "const MovedElsewhere = () => (\n    <Banner\n        variant=\"pop\"\n        title=\"review-cards moved on pavel-mini\"\n        action={\n            <Button variant=\"ghost\" size=\"small\">\n                Show\n            </Button>\n        }\n    >\n        3 new commits since you opened it.\n    </Banner>\n);",
          "description": "Something new happened elsewhere that the user can act on."
        },
        {
          "id": "components-banner--without-action-or-icon",
          "name": "Without Action Or Icon",
          "snippet": "const WithoutActionOrIcon = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n        <Banner variant=\"gray\" title=\"This branch is read-only on this machine\" />\n        <Banner variant=\"warn\" icon={false} title=\"Updates arrive every minute while offline\" />\n    </div>\n);",
          "description": "With nothing to do about it, the banner drops the action; `icon={false}` drops the glyph."
        }
      ],
      "import": "import { Banner } from '@gitbutler/ui-react/Banner.tsx';\nimport { Button } from '@gitbutler/ui-react';\nimport { Button } from './Button.tsx';"
    },
    "components-button": {
      "id": "components-button",
      "name": "Button",
      "path": "../../packages/ui-react/src/Button.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Button } from \"@gitbutler/ui-react/Button.tsx\";"
        ]
      },
      "description": "The button: Base UI's, so `focusableWhenDisabled` and `render` work, styled by variant and size.\nAn icon goes in as a child, before or after the label; an icon-only button takes `iconOnly` and\nneeds an `aria-label`. It is `type=\"button\"` unless told otherwise, so one inside a form doesn't\nsubmit it by accident.\n\nTo make another component look like a button — a toolbar item, a number field's stepper — give it\n`getButtonClassName` instead; to make a Base UI trigger one, pass this as its `render`.",
      "reactComponentMeta": {
        "displayName": "Button",
        "exportName": "Button",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Button.tsx",
        "description": "The button: Base UI's, so `focusableWhenDisabled` and `render` work, styled by variant and size.\nAn icon goes in as a child, before or after the label; an icon-only button takes `iconOnly` and\nneeds an `aria-label`. It is `type=\"button\"` unless told otherwise, so one inside a form doesn't\nsubmit it by accident.\n\nTo make another component look like a button — a toolbar item, a number field's stepper — give it\n`getButtonClassName` instead; to make a Base UI trigger one, pass this as its `render`.",
        "jsDocTags": {
          "import": [
            "import { Button } from \"@gitbutler/ui-react/Button.tsx\";"
          ]
        },
        "props": {
          "focusableWhenDisabled": {
            "name": "focusableWhenDisabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the button should be focusable when disabled.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "ButtonProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/button/Button.d.mts"
            },
            "declarations": [
              {
                "name": "ButtonProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/button/Button.d.mts"
              }
            ]
          },
          "nativeButton": {
            "name": "nativeButton",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the component renders a native `<button>` element when replacing it\nvia the `render` prop.\nSet to `false` if the rendered element is not a button (for example, `<div>`).",
            "defaultValue": {
              "value": "true"
            },
            "parent": {
              "name": "NativeButtonProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "NativeButtonProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "ref": {
            "name": "ref",
            "required": false,
            "type": {
              "name": "((((instance: HTMLButtonElement | null) => void | (() => VoidOrUndefinedOnly)) | RefObject<HTMLButtonElement | null>) & (((instance: HTMLElement | null) => void | (() => VoidOrUndefinedOnly)) | RefObject<...>)) | null | undefined"
            },
            "description": "Allows getting a ref to the component instance.\nOnce the component unmounts, React will set `ref.current` to `null`\n(or call the ref with `null` if you passed a callback ref).",
            "defaultValue": null,
            "parent": {
              "name": "RefAttributes",
              "fileName": "../../node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/index.d.ts"
            },
            "declarations": [
              {
                "name": "RefAttributes",
                "fileName": "../../node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/index.d.ts"
              },
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Button.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string | ((state: ButtonState) => string | undefined) | undefined"
            },
            "description": "CSS class applied to the element, or a function that\nreturns a class based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "render": {
            "name": "render",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ButtonState> | undefined"
            },
            "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "style": {
            "name": "style",
            "required": false,
            "type": {
              "name": "CSSProperties | ((state: ButtonState) => CSSProperties | undefined) | undefined"
            },
            "description": "Style applied to the element, or a function that\nreturns a style object based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "variant": {
            "name": "variant",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"pop\" | \"danger\" | \"gray\" | \"outline\" | \"outline-inverted\" | \"ghost\" | \"ghost-inverted\"",
              "value": [
                {
                  "value": "\"pop\""
                },
                {
                  "value": "\"danger\""
                },
                {
                  "value": "\"gray\""
                },
                {
                  "value": "\"outline\""
                },
                {
                  "value": "\"outline-inverted\""
                },
                {
                  "value": "\"ghost\""
                },
                {
                  "value": "\"ghost-inverted\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "ButtonStyleProps",
              "fileName": "../../packages/ui-react/src/Button.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Button.tsx"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"small\" | \"regular\"",
              "value": [
                {
                  "value": "\"small\""
                },
                {
                  "value": "\"regular\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "ButtonStyleProps",
              "fileName": "../../packages/ui-react/src/Button.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Button.tsx"
              }
            ]
          },
          "iconOnly": {
            "name": "iconOnly",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "ButtonStyleProps",
              "fileName": "../../packages/ui-react/src/Button.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Button.tsx"
              }
            ]
          },
          "disableTransition": {
            "name": "disableTransition",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "ButtonStyleProps",
              "fileName": "../../packages/ui-react/src/Button.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Button.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-button--default",
          "name": "Default",
          "snippet": "const Default = (args: ButtonProps & { showIcon?: boolean }) => {\n    const { showIcon, children, ...buttonArgs } = args;\n\n    const button = (\n        <Button {...buttonArgs}>\n            {showIcon ? (\n                <>\n                    <Icon name=\"plus\" />\n                    {children}\n                </>\n            ) : (\n                children\n            )}\n        </Button>\n    );\n\n    if (args.variant === \"ghost-inverted\") return <div style={invertedDemoStyle}>{button}</div>;\n\n    return button;\n};"
        },
        {
          "id": "components-button--variants",
          "name": "Variants",
          "snippet": "const Variants = () => (\n    <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(7, max-content)\", gap: 12 }}>\n        <Button variant=\"pop\">Button</Button>\n        <Button variant=\"gray\">Button</Button>\n        <Button variant=\"outline\">Button</Button>\n        <div style={invertedDemoStyle}>\n            <Button variant=\"outline-inverted\">Button</Button>\n        </div>\n        <Button variant=\"ghost\">Button</Button>\n        <div style={invertedDemoStyle}>\n            <Button variant=\"ghost-inverted\">Button</Button>\n        </div>\n        <Button variant=\"danger\">Button</Button>\n    </div>\n);"
        },
        {
          "id": "components-button--icon-only",
          "name": "Icon Only",
          "snippet": "const IconOnly = () => (\n    <div style={{ display: \"flex\", gap: 12 }}>\n        <Button variant=\"pop\" iconOnly aria-label=\"Pop action\">\n            <Icon name=\"plus\" />\n        </Button>\n        <Button variant=\"gray\" iconOnly aria-label=\"Gray action\">\n            <Icon name=\"plus\" />\n        </Button>\n        <Button variant=\"outline\" iconOnly aria-label=\"Outline action\">\n            <Icon name=\"plus\" />\n        </Button>\n        <div style={invertedDemoStyle}>\n            <Button variant=\"outline-inverted\" iconOnly aria-label=\"Outline inverted action\">\n                <Icon name=\"plus\" />\n            </Button>\n        </div>\n        <Button variant=\"ghost\" iconOnly aria-label=\"Ghost action\">\n            <Icon name=\"plus\" />\n        </Button>\n        <div style={invertedDemoStyle}>\n            <Button variant=\"ghost-inverted\" iconOnly aria-label=\"Ghost inverted action\">\n                <Icon name=\"plus\" />\n            </Button>\n        </div>\n        <Button variant=\"danger\" iconOnly aria-label=\"Danger action\">\n            <Icon name=\"plus\" />\n        </Button>\n    </div>\n);"
        },
        {
          "id": "components-button--with-icon-start-and-end",
          "name": "With Icon Start And End",
          "snippet": "const WithIconStartAndEnd = () => (\n    <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(2, max-content)\", gap: 12 }}>\n        <Button variant=\"outline\">\n            <Icon name=\"branch\" />\n            New Branch\n        </Button>\n        <Button variant=\"outline\">\n            New Branch\n            <Icon name=\"branch\" />\n        </Button>\n    </div>\n);"
        }
      ],
      "import": "import { Button } from '@gitbutler/ui-react/Button.tsx';\nimport { Icon } from '@gitbutler/ui-react';"
    },
    "components-changescale": {
      "id": "components-changescale",
      "name": "ChangeScale",
      "path": "../../packages/ui-react/src/ChangeScale.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { ChangeScale } from \"@gitbutler/ui-react/ChangeScale.tsx\";"
        ]
      },
      "description": "The green/red squares beside a diff's `+N -N` counts, showing at a glance how\nmuch of a change is additions and how much is deletions. Decorative: the\ncounts next to it carry the numbers, so it is hidden from screen readers.\n\nRenders nothing when nothing changed.",
      "reactComponentMeta": {
        "displayName": "ChangeScale",
        "exportName": "ChangeScale",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/ChangeScale.tsx",
        "description": "The green/red squares beside a diff's `+N -N` counts, showing at a glance how\nmuch of a change is additions and how much is deletions. Decorative: the\ncounts next to it carry the numbers, so it is hidden from screen readers.\n\nRenders nothing when nothing changed.",
        "jsDocTags": {
          "import": [
            "import { ChangeScale } from \"@gitbutler/ui-react/ChangeScale.tsx\";"
          ]
        },
        "props": {
          "added": {
            "name": "added",
            "required": true,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ChangeScale.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ChangeScale.tsx"
              }
            ]
          },
          "removed": {
            "name": "removed",
            "required": true,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ChangeScale.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ChangeScale.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-changescale--default",
          "name": "Default",
          "snippet": "const Default = () => <ChangeScale added={34} removed={28} />;"
        },
        {
          "id": "components-changescale--mostly-additions",
          "name": "Mostly Additions",
          "snippet": "const MostlyAdditions = () => <ChangeScale added={364} removed={20} />;"
        },
        {
          "id": "components-changescale--barely-any-additions",
          "name": "Barely Any Additions",
          "snippet": "const BarelyAnyAdditions = () => <ChangeScale added={1} removed={900} />;",
          "description": "One addition among many deletions still keeps a square."
        },
        {
          "id": "components-changescale--only-deletions",
          "name": "Only Deletions",
          "snippet": "const OnlyDeletions = () => <ChangeScale added={0} removed={12} />;"
        }
      ],
      "import": "import { ChangeScale } from '@gitbutler/ui-react/ChangeScale.tsx';"
    },
    "components-checkbox": {
      "id": "components-checkbox",
      "name": "Checkbox",
      "path": "../../packages/ui-react/src/Checkbox.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Checkbox } from \"@gitbutler/ui-react/Checkbox.tsx\";"
        ]
      },
      "reactComponentMeta": {
        "displayName": "Checkbox",
        "exportName": "Checkbox",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Checkbox.tsx",
        "description": "",
        "jsDocTags": {
          "import": [
            "import { Checkbox } from \"@gitbutler/ui-react/Checkbox.tsx\";"
          ]
        },
        "props": {
          "style": {
            "name": "style",
            "required": false,
            "type": {
              "name": "CSSProperties | ((state: CheckboxRootState) => CSSProperties | undefined) | undefined"
            },
            "description": "Style applied to the element, or a function that\nreturns a style object based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "render": {
            "name": "render",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, CheckboxRootState> | undefined"
            },
            "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "id": {
            "name": "id",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The id of the input element.",
            "defaultValue": null,
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string | ((state: CheckboxRootState) => string | undefined) | undefined"
            },
            "description": "CSS class applied to the element, or a function that\nreturns a class based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "name": {
            "name": "name",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Identifies the field when a form is submitted.",
            "defaultValue": {
              "value": "undefined"
            },
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "form": {
            "name": "form",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Identifies the form that owns the hidden input.\nUseful when the checkbox is rendered outside the form.",
            "defaultValue": null,
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "defaultChecked": {
            "name": "defaultChecked",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the checkbox is initially ticked.\n\nTo render a controlled checkbox, use the `checked` prop instead.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the component should ignore user interaction.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "value": {
            "name": "value",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The value of the selected checkbox.",
            "defaultValue": null,
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "nativeButton": {
            "name": "nativeButton",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the component renders a native `<button>` element when replacing it\nvia the `render` prop.\nSet to `true` if the rendered element is a native button.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "NonNativeButtonProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "NonNativeButtonProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "checked": {
            "name": "checked",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the checkbox is currently ticked.\n\nTo render an uncontrolled checkbox, use the `defaultChecked` prop instead.",
            "defaultValue": {
              "value": "undefined"
            },
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "onCheckedChange": {
            "name": "onCheckedChange",
            "required": false,
            "type": {
              "name": "(checked: boolean, eventDetails: { reason: \"none\"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void"
            },
            "description": "Event handler called when the checkbox is ticked or unticked.",
            "defaultValue": null,
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "readOnly": {
            "name": "readOnly",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the user should be unable to tick or untick the checkbox.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "required": {
            "name": "required",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the user must tick the checkbox before submitting a form.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "indeterminate": {
            "name": "indeterminate",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the checkbox is in a mixed state: neither ticked, nor unticked.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "inputRef": {
            "name": "inputRef",
            "required": false,
            "type": {
              "name": "Ref<HTMLInputElement> | undefined"
            },
            "description": "A ref to access the hidden `<input>` element.",
            "defaultValue": null,
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "parent": {
            "name": "parent",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the checkbox controls a group of child checkboxes.\n\nMust be used in a [Checkbox Group](https://base-ui.com/react/components/checkbox-group).",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          },
          "uncheckedValue": {
            "name": "uncheckedValue",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The value submitted with the form when the checkbox is unchecked.\nBy default, unchecked checkboxes do not submit any value, matching native checkbox behavior.",
            "defaultValue": null,
            "parent": {
              "name": "CheckboxRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
            },
            "declarations": [
              {
                "name": "CheckboxRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/checkbox/root/CheckboxRoot.d.mts"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-checkbox--default",
          "name": "Default",
          "snippet": "const Default = () => <Toggleable />;"
        },
        {
          "id": "components-checkbox--indeterminate",
          "name": "Indeterminate",
          "snippet": "const Indeterminate = () => <Checkbox indeterminate />;",
          "description": "Indeterminate stands for a folder with some of its files checked, so it is filled like a checked\nbox rather than shown as a third, emptier state."
        },
        {
          "id": "components-checkbox--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => (\n    <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n        <Checkbox checked disabled />\n        <Checkbox checked={false} disabled />\n        <Checkbox indeterminate disabled />\n    </div>\n);"
        },
        {
          "id": "components-checkbox--on-a-tinted-row",
          "name": "On A Tinted Row",
          "snippet": "const OnATintedRow = () => (\n    <div\n        style={{\n            [\"--checkbox-bg\" as string]: \"var(--bg-2)\",\n            display: \"flex\",\n            gap: 8,\n            alignItems: \"center\",\n            padding: 8,\n            borderRadius: 6,\n            backgroundColor: \"var(--bg-2)\",\n        }}\n    >\n        <Checkbox checked={false} />\n        <Checkbox checked />\n        <Checkbox indeterminate />\n    </div>\n);",
          "description": "The box takes its ground from `--checkbox-bg`, left undeclared so a row can set it without a\nspecificity fight. Here the row is tinted to show the checkbox following it."
        }
      ],
      "import": "import { Checkbox } from '@gitbutler/ui-react/Checkbox.tsx';"
    },
    "components-conflicticon": {
      "id": "components-conflicticon",
      "name": "ConflictIcon",
      "path": "../../packages/ui-react/src/ConflictIcon.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { ConflictIcon } from \"@gitbutler/ui-react/ConflictIcon.tsx\";"
        ]
      },
      "reactComponentMeta": {
        "displayName": "ConflictIcon",
        "exportName": "ConflictIcon",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/ConflictIcon.tsx",
        "description": "",
        "jsDocTags": {
          "import": [
            "import { ConflictIcon } from \"@gitbutler/ui-react/ConflictIcon.tsx\";"
          ]
        },
        "props": {
          "variant": {
            "name": "variant",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"minus\" | \"plus\" | \"conflict\"",
              "value": [
                {
                  "value": "\"minus\""
                },
                {
                  "value": "\"plus\""
                },
                {
                  "value": "\"conflict\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ConflictIcon.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ConflictIcon.tsx"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": {
              "value": "16"
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ConflictIcon.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ConflictIcon.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-conflicticon--default",
          "name": "Default",
          "snippet": "const Default = () => <ConflictIcon variant=\"conflict\" size={16} />;"
        },
        {
          "id": "components-conflicticon--all-variants",
          "name": "All Variants",
          "snippet": "const AllVariants = (args) => (\n    <div style={{ display: \"flex\", gap: 16, alignItems: \"center\" }}>\n        {([\"conflict\", \"plus\", \"minus\"] as const).map((variant) => (\n            <div\n                key={variant}\n                style={{ display: \"flex\", flexDirection: \"column\", gap: 8, alignItems: \"center\" }}\n            >\n                <ConflictIcon variant={variant} size={args.size} />\n                <span style={{ fontSize: 11, opacity: 0.5 }}>{variant}</span>\n            </div>\n        ))}\n    </div>\n);"
        }
      ],
      "import": "import { ConflictIcon } from '@gitbutler/ui-react/ConflictIcon.tsx';"
    },
    "components-copyableid": {
      "id": "components-copyableid",
      "name": "CopyableId",
      "path": "../../packages/ui-react/src/CopyableId.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { CopyableId } from \"@gitbutler/ui-react/CopyableId.tsx\";"
        ]
      },
      "description": "An ID that copies itself when pressed: a commit's or a change's, in a meta line. It shows the\nshort form and copies the whole one, and says \"Copied!\" in its place for a moment.\n\nThe copying is the host's, through `onCopy`, since the library doesn't know the clipboard: Lite\nhands the value to Electron, a web page to `navigator.clipboard`.",
      "reactComponentMeta": {
        "displayName": "CopyableId",
        "exportName": "CopyableId",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/CopyableId.tsx",
        "description": "An ID that copies itself when pressed: a commit's or a change's, in a meta line. It shows the\nshort form and copies the whole one, and says \"Copied!\" in its place for a moment.\n\nThe copying is the host's, through `onCopy`, since the library doesn't know the clipboard: Lite\nhands the value to Electron, a web page to `navigator.clipboard`.",
        "jsDocTags": {
          "import": [
            "import { CopyableId } from \"@gitbutler/ui-react/CopyableId.tsx\";"
          ]
        },
        "props": {
          "label": {
            "name": "label",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "What is copied, for the tooltip and the button's name: \"Copy commit ID\".",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/CopyableId.tsx"
              }
            ]
          },
          "icon": {
            "name": "icon",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"search\" | \"link\" | \"filter\" | \"contrast\" | \"docs\" | \"file\" | \"copy\" | \"danger\" | \"absorb\" | \"ai\" | \"ai-text\" | \"arrow-corner-down-left\" | \"arrow-corner-left-up\" | \"arrow-corner-right-down\" | \"arrow-corner-up-right\" | \"arrow-double-down\" | \"arrow-double-up\" | \"arrow-down\" | \"arrow-down-left\" | \"arrow-down-right\" | \"arrow-in-box\" | \"arrow-left\" | \"arrow-line-down\" | \"arrow-line-up\" | \"arrow-right\" | \"arrow-up\" | \"arrow-up-left\" | \"arrow-up-right\" | \"bell\" | \"bin\" | \"branch\" | \"branch-merge\" | \"bullet-disc\" | \"bullet-list\" | \"bullseye\" | \"camera\" | \"checklist\" | \"checklist-remove\" | \"chevron-down\" | \"chevron-left\" | \"chevron-right\" | \"chevron-up\" | \"clock\" | \"cloud\" | \"collapse-vertical\" | \"commit\" | \"commit-fill\" | \"cross\" | \"cross-circle\" | \"diff\" | \"discord\" | \"drag-horizontal\" | \"drag-square\" | \"drag-vertical\" | \"edit\" | \"expand-vertical\" | \"eye\" | \"eye-closed\" | \"file-diff\" | \"file-minus\" | \"file-plus\" | \"file-text\" | \"files-sidebar\" | \"finger-print\" | \"folder\" | \"folder-copy\" | \"folder-fork\" | \"folder-lock\" | \"folder-tree\" | \"fork\" | \"globe\" | \"hash\" | \"history\" | \"home\" | \"inbox\" | \"inbox-fill\" | \"info\" | \"kebab\" | \"kebab-vertical\" | \"lab\" | \"list\" | \"lock\" | \"lock-auth\" | \"lock-open\" | \"login\" | \"logout\" | \"minus\" | \"mixer\" | \"number-list\" | \"paperclip\" | \"plug\" | \"plus\" | \"pr\" | \"pr-close\" | \"pr-draft\" | \"question\" | \"question-circle\" | \"refresh\" | \"repo\" | \"resize-handle\" | \"robot\" | \"settings\" | \"sidebar\" | \"sidebar-narrow\" | \"smiley\" | \"spinner\" | \"stack\" | \"tag\" | \"text-block\" | \"text-bold\" | \"text-code\" | \"text-contain\" | \"text-h2\" | \"text-h3\" | \"text-italic\" | \"text-plain\" | \"text-quote\" | \"text-strikethrough\" | \"text-wrap\" | \"theme-dark\" | \"theme-light\" | \"theme-system\" | \"tick\" | \"tick-circle\" | \"tick-double\" | \"undo\" | \"user\" | \"warning\" | \"workbench\"",
              "value": [
                {
                  "value": "\"search\""
                },
                {
                  "value": "\"link\""
                },
                {
                  "value": "\"filter\""
                },
                {
                  "value": "\"contrast\""
                },
                {
                  "value": "\"docs\""
                },
                {
                  "value": "\"file\""
                },
                {
                  "value": "\"copy\""
                },
                {
                  "value": "\"danger\""
                },
                {
                  "value": "\"absorb\""
                },
                {
                  "value": "\"ai\""
                },
                {
                  "value": "\"ai-text\""
                },
                {
                  "value": "\"arrow-corner-down-left\""
                },
                {
                  "value": "\"arrow-corner-left-up\""
                },
                {
                  "value": "\"arrow-corner-right-down\""
                },
                {
                  "value": "\"arrow-corner-up-right\""
                },
                {
                  "value": "\"arrow-double-down\""
                },
                {
                  "value": "\"arrow-double-up\""
                },
                {
                  "value": "\"arrow-down\""
                },
                {
                  "value": "\"arrow-down-left\""
                },
                {
                  "value": "\"arrow-down-right\""
                },
                {
                  "value": "\"arrow-in-box\""
                },
                {
                  "value": "\"arrow-left\""
                },
                {
                  "value": "\"arrow-line-down\""
                },
                {
                  "value": "\"arrow-line-up\""
                },
                {
                  "value": "\"arrow-right\""
                },
                {
                  "value": "\"arrow-up\""
                },
                {
                  "value": "\"arrow-up-left\""
                },
                {
                  "value": "\"arrow-up-right\""
                },
                {
                  "value": "\"bell\""
                },
                {
                  "value": "\"bin\""
                },
                {
                  "value": "\"branch\""
                },
                {
                  "value": "\"branch-merge\""
                },
                {
                  "value": "\"bullet-disc\""
                },
                {
                  "value": "\"bullet-list\""
                },
                {
                  "value": "\"bullseye\""
                },
                {
                  "value": "\"camera\""
                },
                {
                  "value": "\"checklist\""
                },
                {
                  "value": "\"checklist-remove\""
                },
                {
                  "value": "\"chevron-down\""
                },
                {
                  "value": "\"chevron-left\""
                },
                {
                  "value": "\"chevron-right\""
                },
                {
                  "value": "\"chevron-up\""
                },
                {
                  "value": "\"clock\""
                },
                {
                  "value": "\"cloud\""
                },
                {
                  "value": "\"collapse-vertical\""
                },
                {
                  "value": "\"commit\""
                },
                {
                  "value": "\"commit-fill\""
                },
                {
                  "value": "\"cross\""
                },
                {
                  "value": "\"cross-circle\""
                },
                {
                  "value": "\"diff\""
                },
                {
                  "value": "\"discord\""
                },
                {
                  "value": "\"drag-horizontal\""
                },
                {
                  "value": "\"drag-square\""
                },
                {
                  "value": "\"drag-vertical\""
                },
                {
                  "value": "\"edit\""
                },
                {
                  "value": "\"expand-vertical\""
                },
                {
                  "value": "\"eye\""
                },
                {
                  "value": "\"eye-closed\""
                },
                {
                  "value": "\"file-diff\""
                },
                {
                  "value": "\"file-minus\""
                },
                {
                  "value": "\"file-plus\""
                },
                {
                  "value": "\"file-text\""
                },
                {
                  "value": "\"files-sidebar\""
                },
                {
                  "value": "\"finger-print\""
                },
                {
                  "value": "\"folder\""
                },
                {
                  "value": "\"folder-copy\""
                },
                {
                  "value": "\"folder-fork\""
                },
                {
                  "value": "\"folder-lock\""
                },
                {
                  "value": "\"folder-tree\""
                },
                {
                  "value": "\"fork\""
                },
                {
                  "value": "\"globe\""
                },
                {
                  "value": "\"hash\""
                },
                {
                  "value": "\"history\""
                },
                {
                  "value": "\"home\""
                },
                {
                  "value": "\"inbox\""
                },
                {
                  "value": "\"inbox-fill\""
                },
                {
                  "value": "\"info\""
                },
                {
                  "value": "\"kebab\""
                },
                {
                  "value": "\"kebab-vertical\""
                },
                {
                  "value": "\"lab\""
                },
                {
                  "value": "\"list\""
                },
                {
                  "value": "\"lock\""
                },
                {
                  "value": "\"lock-auth\""
                },
                {
                  "value": "\"lock-open\""
                },
                {
                  "value": "\"login\""
                },
                {
                  "value": "\"logout\""
                },
                {
                  "value": "\"minus\""
                },
                {
                  "value": "\"mixer\""
                },
                {
                  "value": "\"number-list\""
                },
                {
                  "value": "\"paperclip\""
                },
                {
                  "value": "\"plug\""
                },
                {
                  "value": "\"plus\""
                },
                {
                  "value": "\"pr\""
                },
                {
                  "value": "\"pr-close\""
                },
                {
                  "value": "\"pr-draft\""
                },
                {
                  "value": "\"question\""
                },
                {
                  "value": "\"question-circle\""
                },
                {
                  "value": "\"refresh\""
                },
                {
                  "value": "\"repo\""
                },
                {
                  "value": "\"resize-handle\""
                },
                {
                  "value": "\"robot\""
                },
                {
                  "value": "\"settings\""
                },
                {
                  "value": "\"sidebar\""
                },
                {
                  "value": "\"sidebar-narrow\""
                },
                {
                  "value": "\"smiley\""
                },
                {
                  "value": "\"spinner\""
                },
                {
                  "value": "\"stack\""
                },
                {
                  "value": "\"tag\""
                },
                {
                  "value": "\"text-block\""
                },
                {
                  "value": "\"text-bold\""
                },
                {
                  "value": "\"text-code\""
                },
                {
                  "value": "\"text-contain\""
                },
                {
                  "value": "\"text-h2\""
                },
                {
                  "value": "\"text-h3\""
                },
                {
                  "value": "\"text-italic\""
                },
                {
                  "value": "\"text-plain\""
                },
                {
                  "value": "\"text-quote\""
                },
                {
                  "value": "\"text-strikethrough\""
                },
                {
                  "value": "\"text-wrap\""
                },
                {
                  "value": "\"theme-dark\""
                },
                {
                  "value": "\"theme-light\""
                },
                {
                  "value": "\"theme-system\""
                },
                {
                  "value": "\"tick\""
                },
                {
                  "value": "\"tick-circle\""
                },
                {
                  "value": "\"tick-double\""
                },
                {
                  "value": "\"undo\""
                },
                {
                  "value": "\"user\""
                },
                {
                  "value": "\"warning\""
                },
                {
                  "value": "\"workbench\""
                }
              ]
            },
            "description": "`hash` for a commit ID, `finger-print` for a change ID.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/CopyableId.tsx"
              }
            ]
          },
          "value": {
            "name": "value",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "The whole ID, which is what is copied.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/CopyableId.tsx"
              }
            ]
          },
          "display": {
            "name": "display",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The short form shown; the whole `value` when omitted.",
            "defaultValue": {
              "value": "value"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/CopyableId.tsx"
              }
            ]
          },
          "onCopy": {
            "name": "onCopy",
            "required": true,
            "type": {
              "name": "(value: string) => void"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/CopyableId.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-copyableid--default",
          "name": "Default",
          "snippet": "const Default = () => <CopyableId\n    label=\"Copy commit ID\"\n    icon=\"hash\"\n    value=\"1cd28ec4f0a9b3e1d2c7a6f5e4b3a2918d7c6b5a\"\n    display=\"1cd28ec\"\n    onCopy={(value: string) => void navigator.clipboard.writeText(value)} />;"
        },
        {
          "id": "components-copyableid--change-and-commit",
          "name": "Change And Commit",
          "snippet": "const ChangeAndCommit = () => (\n    <div className=\"text-13\" style={{ display: \"flex\", gap: 8 }}>\n        <CopyableId\n            label=\"Copy change ID\"\n            icon=\"finger-print\"\n            value=\"kzqtpwoylnsrkrkmxqzvwtuoyrpslmnk\"\n            display=\"kzqtpwo\"\n            onCopy={copyToClipboard}\n        />\n        <CopyableId\n            label=\"Copy commit ID\"\n            icon=\"hash\"\n            value=\"1cd28ec4f0a9b3e1d2c7a6f5e4b3a2918d7c6b5a\"\n            display=\"1cd28ec\"\n            onCopy={copyToClipboard}\n        />\n    </div>\n);",
          "description": "A commit's two IDs side by side, as its author line shows them."
        }
      ],
      "import": "import { CopyableId } from '@gitbutler/ui-react/CopyableId.tsx';"
    },
    "components-difffile": {
      "id": "components-difffile",
      "name": "DiffFile",
      "path": "../../packages/ui-react/src/DiffFile.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { DiffFile } from \"@gitbutler/ui-react/DiffFile.tsx\";"
        ]
      },
      "description": "One file of a diff as a card: its header, and the diff under it. While the\nreader scrolls through the file the header stays at the top of the\nscroller. As the file scrolls away the card shrinks from the bottom around\nthe still header, its corners easing flat, so the frame stays whole until\nthe next file takes the top.\n\nThe card doesn't draw the diff. The host renders it as the children with\nits renderer's own header off (Pierre's `disableFileHeader`), so the card\nworks with any renderer and the library stays free of one. Lay cards out\nwith `DiffFileList`.\n\nThe header sticks to the nearest scrolling ancestor, so nothing between the\ncard and that scroller may clip its overflow.",
      "reactComponentMeta": {
        "displayName": "DiffFile",
        "exportName": "DiffFile",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/DiffFile.tsx",
        "description": "One file of a diff as a card: its header, and the diff under it. While the\nreader scrolls through the file the header stays at the top of the\nscroller. As the file scrolls away the card shrinks from the bottom around\nthe still header, its corners easing flat, so the frame stays whole until\nthe next file takes the top.\n\nThe card doesn't draw the diff. The host renders it as the children with\nits renderer's own header off (Pierre's `disableFileHeader`), so the card\nworks with any renderer and the library stays free of one. Lay cards out\nwith `DiffFileList`.\n\nThe header sticks to the nearest scrolling ancestor, so nothing between the\ncard and that scroller may clip its overflow.",
        "jsDocTags": {
          "import": [
            "import { DiffFile } from \"@gitbutler/ui-react/DiffFile.tsx\";"
          ]
        },
        "props": {
          "header": {
            "name": "header",
            "required": true,
            "type": {
              "name": "ReactNode"
            },
            "description": "The file's header, usually a `DiffFileHeader`. It sticks to the top of the scroller while its file is in view.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFile.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFile.tsx"
              }
            ]
          },
          "collapsed": {
            "name": "collapsed",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Drops the diff and leaves the header.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFile.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFile.tsx"
              }
            ]
          },
          "stickyTop": {
            "name": "stickyTop",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "How far below the scroller's top edge the header sticks, for a scroller with a bar pinned over it. Inside a `DiffFileList` it defaults to the list's top spacing, elsewhere to 0.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFile.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFile.tsx"
              }
            ]
          },
          "children": {
            "name": "children",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "The diff itself: whatever the host renders it with, its own file header turned off.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFile.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFile.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-difffile--default",
          "name": "Default",
          "snippet": "const Default = () => <DiffFile\n    collapsed={false}\n    header={<DiffFileHeader path=\"src/components/Button.svelte\" added={4} removed={3} />}><SampleDiff /></DiffFile>;",
          "warning": "Incomplete snippet: `SampleDiff` could not be resolved statically."
        },
        {
          "id": "components-difffile--folded",
          "name": "Folded",
          "snippet": "const Folded = function Render() {\n    const [collapsed, setCollapsed] = useState(true);\n\n    return (\n        <DiffFile\n            collapsed={collapsed}\n            header={\n                <DiffFileHeader\n                    path=\"src/components/Button.svelte\"\n                    added={4}\n                    removed={3}\n                    collapsed={collapsed}\n                    onCollapsedChange={setCollapsed}\n                />\n            }\n        >\n            <SampleDiff />\n        </DiffFile>\n    );\n};",
          "description": "Folding keeps the header and drops the diff; the header's divider goes with it."
        },
        {
          "id": "components-difffile--files",
          "name": "Files",
          "snippet": "const Files = function Render() {\n    const [collapsed, setCollapsed] = useState<ReadonlySet<string>>(() => new Set());\n    const [reviewed, setReviewed] = useState<ReadonlySet<string>>(\n        () => new Set([\"src/lib/router.ts\"]),\n    );\n    const toggle = (set: ReadonlySet<string>, path: string, on: boolean): ReadonlySet<string> => {\n        const next = new Set(set);\n        if (on) next.add(path);\n        else next.delete(path);\n        return next;\n    };\n\n    return (\n        <ScrollArea style={{ height: 420 }}>\n            <DiffFileList>\n                {files.map((path) => {\n                    const isCollapsed = collapsed.has(path);\n                    const reviewState: DiffFileReviewState = reviewed.has(path) ? \"reviewed\" : \"unreviewed\";\n\n                    return (\n                        <DiffFile\n                            key={path}\n                            collapsed={isCollapsed}\n                            header={\n                                <DiffFileHeader\n                                    path={path}\n                                    added={4}\n                                    removed={3}\n                                    collapsed={isCollapsed}\n                                    onCollapsedChange={(on) => setCollapsed((set) => toggle(set, path, on))}\n                                    reviewState={reviewState}\n                                    onReviewedChange={(on) => setReviewed((set) => toggle(set, path, on))}\n                                    onMenu={() => {}}\n                                />\n                            }\n                        >\n                            <SampleDiff lines={[...sampleLines, ...sampleLines]} />\n                        </DiffFile>\n                    );\n                })}\n            </DiffFileList>\n        </ScrollArea>\n    );\n};",
          "description": "A branch's diff, one card per file in a scroller. Scroll it: each header\nholds the top while its file passes; as the file leaves, its card shrinks\naround the header until the next file takes the top."
        }
      ],
      "import": "import { DiffFile } from '@gitbutler/ui-react/DiffFile.tsx';\nimport { DiffFileHeader, DiffFileList, ScrollArea } from '@gitbutler/ui-react';\nimport { DiffFileHeader } from './DiffFileHeader.tsx';"
    },
    "components-difffileheader": {
      "id": "components-difffileheader",
      "name": "DiffFileHeader",
      "path": "../../packages/ui-react/src/DiffFileHeader.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { DiffFileHeader } from \"@gitbutler/ui-react/DiffFileHeader.tsx\";"
        ]
      },
      "description": "The header over one file's diff: the file, what it changed, and what you can\ndo about it. Every control is optional and appears only when its handler is\ngiven, so a read-only diff gets just the name and the counts.\n\nIt draws no border and doesn't stick on its own: `DiffFile` does both when\nit holds the header over a diff, and a virtualized viewer that places its\nown headers does them itself.",
      "reactComponentMeta": {
        "displayName": "DiffFileHeader",
        "exportName": "DiffFileHeader",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/DiffFileHeader.tsx",
        "description": "The header over one file's diff: the file, what it changed, and what you can\ndo about it. Every control is optional and appears only when its handler is\ngiven, so a read-only diff gets just the name and the counts.\n\nIt draws no border and doesn't stick on its own: `DiffFile` does both when\nit holds the header over a diff, and a virtualized viewer that places its\nown headers does them itself.",
        "jsDocTags": {
          "import": [
            "import { DiffFileHeader } from \"@gitbutler/ui-react/DiffFileHeader.tsx\";"
          ]
        },
        "props": {
          "path": {
            "name": "path",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "The file's path. The header leads with its name and dims the folder after it.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "added": {
            "name": "added",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "The file's changed line counts. Leave both out when there is no patch to count.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "removed": {
            "name": "removed",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "collapsed": {
            "name": "collapsed",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "onCollapsedChange": {
            "name": "onCollapsedChange",
            "required": false,
            "type": {
              "name": "(collapsed: boolean) => void"
            },
            "description": "Shows the fold button. Without it the header has none.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "collapseKbd": {
            "name": "collapseKbd",
            "required": false,
            "type": {
              "name": "string | HotkeySequence | undefined"
            },
            "description": "The shortcut that folds the file, shown in the fold button's tooltip.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "collapseKbdScope": {
            "name": "collapseKbdScope",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The focus scope that shortcut acts in; see `Tooltip`'s `kbdScope`.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "reviewState": {
            "name": "reviewState",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"unreviewed\" | \"reviewed\" | \"changed\"",
              "value": [
                {
                  "value": "\"unreviewed\""
                },
                {
                  "value": "\"reviewed\""
                },
                {
                  "value": "\"changed\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"unreviewed\""
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "onReviewedChange": {
            "name": "onReviewedChange",
            "required": false,
            "type": {
              "name": "(reviewed: boolean) => void"
            },
            "description": "Shows the Reviewed button. Without it the header has none.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "onMenu": {
            "name": "onMenu",
            "required": false,
            "type": {
              "name": "(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void"
            },
            "description": "Shows the kebab button; opens the host's file menu from it.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          },
          "children": {
            "name": "children",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "Anything the file needs said before its actions, such as a `Badge`.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffFileHeader.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-difffileheader--default",
          "name": "Default",
          "snippet": "const Default = () => <DiffFileHeader\n    path=\"src/components/Button.svelte\"\n    added={34}\n    removed={28}\n    collapsed={false}\n    reviewState=\"unreviewed\"\n    onCollapsedChange={() => {}}\n    onReviewedChange={() => {}}\n    onMenu={() => {}} />;"
        },
        {
          "id": "components-difffileheader--review",
          "name": "Review",
          "snippet": "const Review = () => {\n    const [reviewState, setReviewState] = useState<DiffFileReviewState>(\"changed\");\n\n    return (\n        <DiffFileHeader\n            path=\"src/components/Button.svelte\"\n            added={34}\n            removed={28}\n            collapsed={false}\n            onCollapsedChange={() => {}}\n            onMenu={() => {}}\n            reviewState={reviewState}\n            onReviewedChange={(reviewed) => setReviewState(reviewed ? \"reviewed\" : \"unreviewed\")} />\n    );\n};",
          "description": "Reviewed, then changed since: the box goes mixed until the reader looks again."
        },
        {
          "id": "components-difffileheader--read-only",
          "name": "Read Only",
          "snippet": "const ReadOnly = () => <DiffFileHeader\n    path=\"src/components/Button.svelte\"\n    added={34}\n    removed={28}\n    collapsed={false}\n    reviewState=\"unreviewed\"\n    onCollapsedChange={undefined}\n    onReviewedChange={undefined}\n    onMenu={undefined} />;",
          "description": "A diff shown for reading only, as a pull request's comment anchors it: the file and its counts."
        },
        {
          "id": "components-difffileheader--conflicted",
          "name": "Conflicted",
          "snippet": "const Conflicted = () => <DiffFileHeader\n    path=\"crates/but-workspace/src/commit.rs\"\n    added={undefined}\n    removed={undefined}\n    collapsed={false}\n    reviewState=\"unreviewed\"\n    onCollapsedChange={() => {}}\n    onReviewedChange={undefined}\n    onMenu={undefined}><Badge variant=\"danger\">Conflicted</Badge></DiffFileHeader>;",
          "description": "Something the file needs said goes before its actions."
        },
        {
          "id": "components-difffileheader--long-path",
          "name": "Long Path",
          "snippet": "const LongPath = () => <DiffFileHeader\n    path=\"apps/lite/ui/src/routes/project/$id/workspace/WorkspaceLists/UncommittedChangesRow.tsx\"\n    added={1204}\n    removed={3}\n    collapsed={false}\n    reviewState=\"unreviewed\"\n    onCollapsedChange={() => {}}\n    onReviewedChange={() => {}}\n    onMenu={() => {}} />;",
          "description": "A deep path gives way before the name does."
        }
      ],
      "import": "import { Badge } from '@gitbutler/ui-react';\nimport { DiffFileHeader } from '@gitbutler/ui-react/DiffFileHeader.tsx';\nimport { Badge } from './Badge.tsx';"
    },
    "components-difffilelist": {
      "id": "components-difffilelist",
      "name": "DiffFileList",
      "path": "../../packages/ui-react/src/DiffFileList.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { DiffFileList } from \"@gitbutler/ui-react/DiffFileList.tsx\";"
        ]
      },
      "description": "A diff's files as a column of `DiffFile` cards, spaced by\n`diffFileSpacing` (`diffFileLayout.ts`). It sets `--diff-file-inset` on\nitself for anything inside that lines up with the cards.\n\nThe space above the first card stays while the diff scrolls: the cards'\nheaders stick that far below the scroller's edge, where the first card\nbegan, and a strip of the pane's background covers the code passing above\nthem.\n\nPut it inside the scroller, such as a `ScrollArea`, rather than making it\nthe scroller: browsers inset sticky elements by a scroller's own padding,\nwhich would add to that space.",
      "reactComponentMeta": {
        "displayName": "DiffFileList",
        "exportName": "DiffFileList",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/DiffFileList.tsx",
        "description": "A diff's files as a column of `DiffFile` cards, spaced by\n`diffFileSpacing` (`diffFileLayout.ts`). It sets `--diff-file-inset` on\nitself for anything inside that lines up with the cards.\n\nThe space above the first card stays while the diff scrolls: the cards'\nheaders stick that far below the scroller's edge, where the first card\nbegan, and a strip of the pane's background covers the code passing above\nthem.\n\nPut it inside the scroller, such as a `ScrollArea`, rather than making it\nthe scroller: browsers inset sticky elements by a scroller's own padding,\nwhich would add to that space.",
        "jsDocTags": {
          "import": [
            "import { DiffFileList } from \"@gitbutler/ui-react/DiffFileList.tsx\";"
          ]
        },
        "props": {}
      },
      "stories": [
        {
          "id": "components-difffilelist--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <DiffFileList style={{ width: 546 }}>\n        {files.map((file, index) => (\n            <DiffFile\n                key={file.path}\n                collapsed={index === 1}\n                header={\n                    <DiffFileHeader\n                        path={file.path}\n                        added={file.added}\n                        removed={file.removed}\n                        collapsed={index === 1}\n                        onCollapsedChange={() => {}}\n                    />\n                }\n            >\n                <pre\n                    className=\"text-12\"\n                    style={{ margin: 0, padding: \"4px 12px\", fontFamily: \"var(--font-family-mono)\" }}\n                >\n                    {\"const router = useRouter()\\nconst theme = useTheme()\"}\n                </pre>\n            </DiffFile>\n        ))}\n    </DiffFileList>\n);",
          "description": "Cards spaced the way every app spaces its diffs. The folded file shows a\ncard that is only its header."
        }
      ],
      "import": "import { DiffFile, DiffFileHeader } from '@gitbutler/ui-react';\nimport { DiffFileList } from '@gitbutler/ui-react/DiffFileList.tsx';"
    },
    "components-diffstats": {
      "id": "components-diffstats",
      "name": "DiffStats",
      "path": "../../packages/ui-react/src/DiffStats.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { DiffStats } from \"@gitbutler/ui-react/DiffStats.tsx\";"
        ]
      },
      "description": "The `+N -N` line counts of a diff. Renders nothing when nothing changed, and\ndrops either side when it is zero, so a header shows only what it has to say.",
      "reactComponentMeta": {
        "displayName": "DiffStats",
        "exportName": "DiffStats",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/DiffStats.tsx",
        "description": "The `+N -N` line counts of a diff. Renders nothing when nothing changed, and\ndrops either side when it is zero, so a header shows only what it has to say.",
        "jsDocTags": {
          "import": [
            "import { DiffStats } from \"@gitbutler/ui-react/DiffStats.tsx\";"
          ]
        },
        "props": {
          "added": {
            "name": "added",
            "required": true,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffStats.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffStats.tsx"
              }
            ]
          },
          "removed": {
            "name": "removed",
            "required": true,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DiffStats.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DiffStats.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-diffstats--default",
          "name": "Default",
          "snippet": "const Default = () => <DiffStats added={364} removed={20} />;"
        },
        {
          "id": "components-diffstats--only-additions",
          "name": "Only Additions",
          "snippet": "const OnlyAdditions = () => <DiffStats added={6} removed={0} />;"
        },
        {
          "id": "components-diffstats--only-deletions",
          "name": "Only Deletions",
          "snippet": "const OnlyDeletions = () => <DiffStats added={0} removed={12} />;"
        }
      ],
      "import": "import { DiffStats } from '@gitbutler/ui-react/DiffStats.tsx';"
    },
    "components-dropdown": {
      "id": "components-dropdown",
      "name": "Dropdown",
      "path": "../../packages/ui-react/src/Dropdown.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Dropdown } from \"@gitbutler/ui-react/Popup.tsx\";"
        ]
      },
      "description": "A popup anchored to the control that opened it, with nothing dimmed behind it. Wears the same\ncontainer as {@link Modal}, minus the backdrop.\n\nThis is for anchored *panels* — a notification list, a reaction picker, a filter. A list of\nactions is a `Menu`, from `Menu.tsx`; a dropdown is not the place to rebuild one.\n\nIt is as wide as its content, and never narrower than its trigger: a short list under a wide\ncontrol lines up with it, and a long one grows past it.",
      "reactComponentMeta": {
        "displayName": "Dropdown",
        "exportName": "Dropdown",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Popup.tsx",
        "description": "A popup anchored to the control that opened it, with nothing dimmed behind it. Wears the same\ncontainer as {@link Modal}, minus the backdrop.\n\nThis is for anchored *panels* — a notification list, a reaction picker, a filter. A list of\nactions is a `Menu`, from `Menu.tsx`; a dropdown is not the place to rebuild one.\n\nIt is as wide as its content, and never narrower than its trigger: a short list under a wide\ncontrol lines up with it, and a long one grows past it.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Dropdown } from \"@gitbutler/ui-react/Popup.tsx\";"
          ]
        },
        "props": {
          "open": {
            "name": "open",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Omit to leave the dropdown uncontrolled and drive it from `trigger` alone.",
            "defaultValue": null,
            "parent": {
              "name": "DropdownProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "onOpenChange": {
            "name": "onOpenChange",
            "required": false,
            "type": {
              "name": "(open: boolean) => void"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "DropdownProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "trigger": {
            "name": "trigger",
            "required": true,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>>"
            },
            "description": "Rendered as the dropdown's trigger, and what it anchors to.",
            "defaultValue": null,
            "parent": {
              "name": "DropdownProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "side": {
            "name": "side",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"top\" | \"bottom\" | \"left\" | \"right\"",
              "value": [
                {
                  "value": "\"top\""
                },
                {
                  "value": "\"bottom\""
                },
                {
                  "value": "\"left\""
                },
                {
                  "value": "\"right\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"bottom\""
            },
            "parent": {
              "name": "DropdownProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "align": {
            "name": "align",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"center\" | \"end\" | \"start\"",
              "value": [
                {
                  "value": "\"center\""
                },
                {
                  "value": "\"end\""
                },
                {
                  "value": "\"start\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"start\""
            },
            "parent": {
              "name": "DropdownProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "sideOffset": {
            "name": "sideOffset",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": {
              "value": "4"
            },
            "parent": {
              "name": "DropdownProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-dropdown--default",
          "name": "Default",
          "snippet": "const Default = () => <Dropdown\n    side=\"bottom\"\n    align=\"start\"\n    sideOffset={4}\n    aria-label=\"Show\"\n    trigger={<Button>Filter</Button>}>(<PopupSection>\n        <PopupItem aria-pressed trailing=\"tick\">\n            Local branches\n        </PopupItem>\n        <PopupItem aria-pressed trailing=\"tick\">\n            Remote branches\n        </PopupItem>\n        <PopupItem aria-pressed={false}>Pull requests</PopupItem>\n    </PopupSection>)</Dropdown>;",
          "description": "A filter anchored under its control: each row shows or hides one kind, ticked while shown. Not a\nmenu of actions — that is a `Menu`."
        },
        {
          "id": "components-dropdown--panel",
          "name": "Panel",
          "snippet": "const Panel = () => <Dropdown\n    side=\"bottom\"\n    align=\"start\"\n    sideOffset={4}\n    aria-label=\"Notifications\"\n    style={{ width: 380 }}\n    trigger={(<Button iconOnly>\n        <Icon name=\"bell\" />\n    </Button>)}>(<div style={{ display: \"flex\", flexDirection: \"column\", gap: 8, padding: 12 }}>\n        <strong className=\"text-12 text-semibold\">Notifications</strong>\n        <span className=\"text-13\">\n            A dropdown carries anchored panels as readily as it carries rows — the container does not\n            care what fills it.\n        </span>\n    </div>)</Dropdown>;",
          "description": "A panel rather than rows: `children` can be anything, and the container does not change for it."
        }
      ],
      "import": "import { Button, Icon, PopupItem, PopupSection } from '@gitbutler/ui-react';\nimport { Dropdown } from '@gitbutler/ui-react/Popup.tsx';\nimport { Button } from './Button.tsx';\nimport { PopupSection, PopupItem } from './Popup.tsx';\nimport { Icon } from './Icon.tsx';"
    },
    "components-dropdownbutton": {
      "id": "components-dropdownbutton",
      "name": "DropdownButton",
      "path": "../../packages/ui-react/src/DropdownButton.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { DropdownButton } from \"@gitbutler/ui-react/DropdownButton.tsx\";"
        ]
      },
      "description": "A primary action joined to a chevron that opens its menu, reading as one\ncontrol split by a seam rather than two buttons side by side.\n\nBoth halves stay focusable while disabled so keyboard users can reach them\nand find out why they're unavailable — which also keeps a disabled action\nhoverable, so `actionTooltip` needs no wrapper element to carry it.",
      "reactComponentMeta": {
        "displayName": "DropdownButton",
        "exportName": "DropdownButton",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/DropdownButton.tsx",
        "description": "A primary action joined to a chevron that opens its menu, reading as one\ncontrol split by a seam rather than two buttons side by side.\n\nBoth halves stay focusable while disabled so keyboard users can reach them\nand find out why they're unavailable — which also keeps a disabled action\nhoverable, so `actionTooltip` needs no wrapper element to carry it.",
        "jsDocTags": {
          "import": [
            "import { DropdownButton } from \"@gitbutler/ui-react/DropdownButton.tsx\";"
          ]
        },
        "props": {
          "children": {
            "name": "children",
            "required": true,
            "type": {
              "name": "ReactNode"
            },
            "description": "Contents of the main action button.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          },
          "menuLabel": {
            "name": "menuLabel",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "Accessible name for the chevron trigger, e.g. \"Commit options\".",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          },
          "onMenuTrigger": {
            "name": "onMenuTrigger",
            "required": true,
            "type": {
              "name": "(trigger: HTMLButtonElement) => void"
            },
            "description": "Called with the chevron trigger element, so the caller can anchor its menu\nto it — the menu itself is the caller's, since a native one and a rendered\none attach the same way.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          },
          "actionTooltip": {
            "name": "actionTooltip",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "Shown on hovering the main action — typically why it is unavailable.\nOmitting it leaves the tooltip disabled rather than unmounting it, so the\nbutton keeps its tree position (and its focus) as the reason comes and goes.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          },
          "variant": {
            "name": "variant",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"pop\" | \"gray\" | \"outline\"",
              "value": [
                {
                  "value": "\"pop\""
                },
                {
                  "value": "\"gray\""
                },
                {
                  "value": "\"outline\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"outline\""
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          },
          "onClick": {
            "name": "onClick",
            "required": false,
            "type": {
              "name": "() => void"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          },
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Disables the main action; the chevron trigger keeps its own flag.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          },
          "menuDisabled": {
            "name": "menuDisabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          },
          "id": {
            "name": "id",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/DropdownButton.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-dropdownbutton--default",
          "name": "Default",
          "snippet": "const Default = () => <DropdownButton\n    menuLabel=\"Button options\"\n    variant=\"pop\"\n    disabled={false}\n    menuDisabled={false}\n    onMenuTrigger={() => {}}>Button</DropdownButton>;"
        },
        {
          "id": "components-dropdownbutton--variants",
          "name": "Variants",
          "snippet": "const Variants = () => (\n    <div style={{ display: \"flex\", gap: 12, flexDirection: \"column\", alignItems: \"flex-start\" }}>\n        {variants.map((variant) => (\n            <Demo key={variant} variant={variant} />\n        ))}\n    </div>\n);",
          "description": "Pop carries the primary action; gray and outline sit lower in the hierarchy."
        },
        {
          "id": "components-dropdownbutton--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => (\n    <div style={{ display: \"flex\", gap: 12, flexDirection: \"column\", alignItems: \"flex-start\" }}>\n        <Demo variant=\"pop\" disabled />\n        <Demo variant=\"pop\" menuDisabled />\n        <Demo variant=\"outline\" disabled menuDisabled />\n    </div>\n);",
          "description": "The halves disable independently: an unavailable action can still offer its menu."
        },
        {
          "id": "components-dropdownbutton--stretched",
          "name": "Stretched",
          "snippet": "const Stretched = () => (\n    // A column flex container stretches its item across, as the sidebar does.\n    (<div style={{ display: \"flex\", flexDirection: \"column\", width: 220 }}>\n        <DropdownButton variant=\"pop\" menuLabel=\"Commit options\" onMenuTrigger={() => {}}>\n            Start commit\n            <Kbd hotkey=\"Mod+Enter\" variant=\"button\" />\n        </DropdownButton>\n    </div>)\n);",
          "description": "The action fills the space it's given and ellipsises, while the chevron keeps\nits width — as in the sidebar, where the button spans the panel."
        },
        {
          "id": "components-dropdownbutton--disabled-with-tooltip",
          "name": "Disabled With Tooltip",
          "snippet": "const DisabledWithTooltip = () => (\n    <DropdownButton\n        variant=\"pop\"\n        disabled\n        actionTooltip=\"Blocked: required approvals or checks are not satisfied\"\n        menuLabel=\"Merge method\"\n        onMenuTrigger={() => {}}\n    >\n        Merge\n    </DropdownButton>\n);",
          "description": "`actionTooltip` on a disabled action says why it is disabled: both halves stay\nhoverable while disabled, so the tooltip needs no wrapper element."
        }
      ],
      "import": "import { DropdownButton } from '@gitbutler/ui-react/DropdownButton.tsx';\nimport { Kbd } from '@gitbutler/ui-react';\nimport { Tooltip } from '@base-ui/react';"
    },
    "components-emptystate": {
      "id": "components-emptystate",
      "name": "EmptyState",
      "path": "../../packages/ui-react/src/EmptyState.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { EmptyState } from \"@gitbutler/ui-react/EmptyState.tsx\";"
        ]
      },
      "description": "A surface at rest with nothing in it — the \"Empty state\" component in\n⚛️ Core, whose description carries the rules for what to put in it.\n\nFor a surface that is empty, not one still loading: that says so in a line\nwhere the list would be. A filter that matched nothing takes the block in a\npanel with room for it, and a line in a short strip; see\n`packages/ui-react/design/patterns/empty-states.md`.",
      "reactComponentMeta": {
        "displayName": "EmptyState",
        "exportName": "EmptyState",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/EmptyState.tsx",
        "description": "A surface at rest with nothing in it — the \"Empty state\" component in\n⚛️ Core, whose description carries the rules for what to put in it.\n\nFor a surface that is empty, not one still loading: that says so in a line\nwhere the list would be. A filter that matched nothing takes the block in a\npanel with room for it, and a line in a short strip; see\n`packages/ui-react/design/patterns/empty-states.md`.",
        "jsDocTags": {
          "import": [
            "import { EmptyState } from \"@gitbutler/ui-react/EmptyState.tsx\";"
          ]
        },
        "props": {
          "illustration": {
            "name": "illustration",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"terminal\" | \"cactus\" | \"id-card\" | \"papers\" | \"sleep\" | \"waving\"",
              "value": [
                {
                  "value": "\"terminal\""
                },
                {
                  "value": "\"cactus\""
                },
                {
                  "value": "\"id-card\""
                },
                {
                  "value": "\"papers\""
                },
                {
                  "value": "\"sleep\""
                },
                {
                  "value": "\"waving\""
                }
              ]
            },
            "description": "Omit on a surface too short to hold one; the title and actions carry it.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/EmptyState.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/EmptyState.tsx"
              }
            ]
          },
          "title": {
            "name": "title",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "One short line naming the state. Sentence case, no full stop. Wraps\nbalanced, so write it as a sentence and let the lines fall where they may.\n\nOmit where the body line says it all — a picker that found nothing\nreports the miss in one line, and a heading over it would only repeat it.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/EmptyState.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/EmptyState.tsx"
              }
            ]
          },
          "description": {
            "name": "description",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "1–2 short sentences, around 10–25 words. Say what happens next, or report\nthe live answer — a count, a name, a time — rather than restating the title.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/EmptyState.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/EmptyState.tsx"
              }
            ]
          },
          "children": {
            "name": "children",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "The actions slot: at most two buttons, and never `pop`.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/EmptyState.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/EmptyState.tsx"
              }
            ]
          },
          "align": {
            "name": "align",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"center\" | \"start\"",
              "value": [
                {
                  "value": "\"center\""
                },
                {
                  "value": "\"start\""
                }
              ]
            },
            "description": "`start` for an empty section in a list that reads from the left edge, as a sidebar's stack of\ncards does: flush with the rows it stands in for rather than centred in the panel.",
            "defaultValue": {
              "value": "\"center\""
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/EmptyState.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/EmptyState.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-emptystate--default",
          "name": "Default",
          "snippet": "const Default = () => <EmptyState\n    illustration=\"cactus\"\n    title=\"Your workspace is empty\"\n    description=\"You have 5 branches to pick from\">(<>\n        <Button variant=\"gray\">\n            See all\n            <Icon name=\"list\" />\n        </Button>\n        <Button variant=\"outline\">\n            New branch\n            <Icon name=\"plus\" />\n        </Button>\n    </>)</EmptyState>;"
        },
        {
          "id": "components-emptystate--one-action",
          "name": "One Action",
          "snippet": "const OneAction = () => <EmptyState\n    illustration=\"cactus\"\n    title=\"No branches yet\"\n    description=\"Your first commit will start one\">(<Button variant=\"outline\">New branch\n                        <Icon name=\"plus\" />\n    </Button>)</EmptyState>;",
          "description": "One action stays quiet: there is no second button for it to rank above."
        },
        {
          "id": "components-emptystate--no-actions",
          "name": "No Actions",
          "snippet": "const NoActions = () => <EmptyState\n    illustration=\"cactus\"\n    title=\"Nothing to review\"\n    description=\"Pull requests you are asked to look at will show up here\" />;",
          "description": "Nothing to do about it, so nothing to press."
        },
        {
          "id": "components-emptystate--without-illustration",
          "name": "Without Illustration",
          "snippet": "const WithoutIllustration = () => <EmptyState\n    illustration={undefined}\n    title=\"Your workspace is empty\"\n    description=\"You have 5 branches to pick from\">(<Button variant=\"outline\">New branch\n                        <Icon name=\"plus\" />\n    </Button>)</EmptyState>;",
          "description": "Dropped where a panel is too short to hold one."
        }
      ],
      "import": "import { Button, Icon } from '@gitbutler/ui-react';\nimport { EmptyState } from '@gitbutler/ui-react/EmptyState.tsx';\nimport { Button } from './Button.tsx';\nimport { Icon } from './Icon.tsx';"
    },
    "components-entityavatar": {
      "id": "components-entityavatar",
      "name": "EntityAvatar",
      "path": "../../packages/ui-react/src/EntityAvatar.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { EntityAvatar } from \"@gitbutler/ui-react/EntityAvatar.tsx\";"
        ]
      },
      "description": "What an entity — a project, a machine, a cloud session — wears in place of a photo: the\nrepository glyph in one of seven colours, an emoji, or a picture the host supplies (a machine's\nkind). An avatar is 38px wherever it stands, the avatar slot of `ViewHeader`, a page of its own\nor the picker's choice of a machine's pictures; leave `size` at `regular`. `small` is the picker's\nemoji and colours, at 28px.\n\nA picture of the thing, not a control: to let someone change it, use `EntityAvatarPicker`.",
      "reactComponentMeta": {
        "displayName": "EntityAvatar",
        "exportName": "EntityAvatar",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/EntityAvatar.tsx",
        "description": "What an entity — a project, a machine, a cloud session — wears in place of a photo: the\nrepository glyph in one of seven colours, an emoji, or a picture the host supplies (a machine's\nkind). An avatar is 38px wherever it stands, the avatar slot of `ViewHeader`, a page of its own\nor the picker's choice of a machine's pictures; leave `size` at `regular`. `small` is the picker's\nemoji and colours, at 28px.\n\nA picture of the thing, not a control: to let someone change it, use `EntityAvatarPicker`.",
        "jsDocTags": {
          "import": [
            "import { EntityAvatar } from \"@gitbutler/ui-react/EntityAvatar.tsx\";"
          ]
        },
        "props": {
          "value": {
            "name": "value",
            "required": true,
            "type": {
              "name": "EntityAvatarValue"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/EntityAvatar.tsx"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"small\" | \"regular\"",
              "value": [
                {
                  "value": "\"small\""
                },
                {
                  "value": "\"regular\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"regular\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/EntityAvatar.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-entityavatar--default",
          "name": "Default",
          "snippet": "const Default = () => <EntityAvatar value={{ _tag: \"Glyph\", colour: \"outline\" }} size=\"regular\" />;"
        },
        {
          "id": "components-entityavatar--choices",
          "name": "Choices",
          "snippet": "const Choices = () => (\n    <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n        {entityAvatarColours.map((colour) => (\n            <EntityAvatar key={colour} value={{ _tag: \"Glyph\", colour }} />\n        ))}\n        <EntityAvatar value={{ _tag: \"Emoji\", emoji: \"☁️\" }} />\n        <EntityAvatar value={{ _tag: \"Picture\", src: machinePictures[0].src }} />\n    </div>\n);",
          "description": "The glyph in each of its colours, an emoji and a machine's picture: every avatar is 38px."
        },
        {
          "id": "components-entityavatar--picking-for-a-project",
          "name": "Picking For A Project",
          "snippet": "const PickingForAProject = () => <ProjectPicker />;",
          "description": "A project's avatar: a colour for the glyph, or an emoji found by name."
        },
        {
          "id": "components-entityavatar--picking-for-a-machine",
          "name": "Picking For A Machine",
          "snippet": "const PickingForAMachine = () => <MachinePicker />;",
          "description": "A machine's picture: few enough kinds to show them at full size in the picker, with no search."
        }
      ],
      "import": "import { EntityAvatar } from '@gitbutler/ui-react/EntityAvatar.tsx';\nimport { EntityAvatarPicker } from '@gitbutler/ui-react';"
    },
    "components-errorboundary": {
      "id": "components-errorboundary",
      "name": "ErrorBoundary",
      "path": "../../packages/ui-react/src/ErrorBoundary.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { ErrorBoundary } from \"@gitbutler/ui-react/ErrorBoundary.tsx\";"
        ]
      },
      "description": "Confines a render failure to the subtree it happened in. React boundaries\nonly see errors thrown while rendering below them: a throw in an event\nhandler, a timer, or in the parent that builds this subtree's elements\nescapes to the toast in `main.tsx` instead.",
      "reactComponentMeta": {
        "displayName": "ErrorBoundary",
        "exportName": "ErrorBoundary",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/ErrorBoundary.tsx",
        "description": "Confines a render failure to the subtree it happened in. React boundaries\nonly see errors thrown while rendering below them: a throw in an event\nhandler, a timer, or in the parent that builds this subtree's elements\nescapes to the toast in `main.tsx` instead.",
        "jsDocTags": {
          "import": [
            "import { ErrorBoundary } from \"@gitbutler/ui-react/ErrorBoundary.tsx\";"
          ]
        },
        "props": {
          "children": {
            "name": "children",
            "required": true,
            "type": {
              "name": "ReactNode"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ErrorBoundary.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ErrorBoundary.tsx"
              }
            ]
          },
          "title": {
            "name": "title",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "Names what couldn't be drawn, from where the boundary is mounted: \"The sidebar couldn't be\nshown\". The error itself rarely says anything a reader can act on, so it stays behind\n\"Copy error message\".",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ErrorBoundary.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ErrorBoundary.tsx"
              }
            ]
          },
          "resetKeys": {
            "name": "resetKeys",
            "required": false,
            "type": {
              "name": "readonly unknown[]"
            },
            "description": "Clears the error when any entry changes, so a view that fails on one\nselection recovers by moving off it rather than sitting broken until the\nwindow reloads.\n\nKey these on the very thing being rendered — the child element itself,\nnot a URL or selection that merely correlates with it. The reset is\nsingle-shot: it happens after the commit, and if the subtree throws again\nbecause it read state the key had already moved past, that key will not\nchange a second time and the pane stays broken. Where no such key exists,\npass none and leave recovery to Retry.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ErrorBoundary.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ErrorBoundary.tsx"
              }
            ]
          },
          "onReset": {
            "name": "onReset",
            "required": false,
            "type": {
              "name": "() => void"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ErrorBoundary.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ErrorBoundary.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-errorboundary--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <ErrorBoundary title=\"This view couldn't be shown\">\n        <Broken broken />\n    </ErrorBoundary>\n);",
          "description": "What takes the place of a view that threw while rendering: what couldn't be shown, Retry, and the error to copy."
        },
        {
          "id": "components-errorboundary--retry",
          "name": "Retry",
          "snippet": "const Retry = () => <Recovering />;",
          "description": "Retry clears the error and renders the view again."
        }
      ],
      "import": "import { ErrorBoundary } from '@gitbutler/ui-react/ErrorBoundary.tsx';"
    },
    "components-field": {
      "id": "components-field",
      "name": "FieldRootStyles",
      "path": "../../packages/ui-react/src/Field.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { FieldRootStyles } from \"@gitbutler/ui-react/Field.tsx\";"
        ]
      },
      "reactComponentMeta": {
        "displayName": "FieldRootStyles",
        "exportName": "FieldRootStyles",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Field.tsx",
        "description": "",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { FieldRootStyles } from \"@gitbutler/ui-react/Field.tsx\";"
          ]
        },
        "props": {}
      },
      "stories": [
        {
          "id": "components-field--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <Field.Root render={<FieldRootStyles />} style={{ width: 320 }}>\n        <Field.Label render={<FieldLabelStyles />}>Label</Field.Label>\n        <Field.Control\n            render={<FieldControlStyles />}\n            className=\"text-13\"\n            placeholder=\"Placeholder\"\n        />\n    </Field.Root>\n);"
        },
        {
          "id": "components-field--with-value",
          "name": "With Value",
          "snippet": "const WithValue = () => (\n    <Field.Root render={<FieldRootStyles />} style={{ width: 320 }}>\n        <Field.Label render={<FieldLabelStyles />}>Branch name</Field.Label>\n        <Field.Control\n            render={<FieldControlStyles />}\n            className=\"text-13\"\n            defaultValue=\"feat/my-feature-branch\"\n        />\n    </Field.Root>\n);"
        },
        {
          "id": "components-field--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => (\n    <Field.Root render={<FieldRootStyles />} style={{ width: 320 }}>\n        <Field.Label render={<FieldLabelStyles />}>Read-only field</Field.Label>\n        <Field.Control\n            render={<FieldControlStyles />}\n            className=\"text-13\"\n            defaultValue=\"Cannot be edited\"\n            disabled\n        />\n    </Field.Root>\n);"
        },
        {
          "id": "components-field--textarea",
          "name": "Textarea",
          "snippet": "const Textarea = () => (\n    <Field.Root render={<FieldRootStyles />} style={{ width: 320 }}>\n        <Field.Label render={<FieldLabelStyles />}>Description</Field.Label>\n        <Field.Control\n            render={<FieldTextareaStyles />}\n            className=\"text-14 text-body\"\n            placeholder=\"Add a description…\"\n        />\n    </Field.Root>\n);"
        },
        {
          "id": "components-field--with-leading-icon",
          "name": "With Leading Icon",
          "snippet": "const WithLeadingIcon = () => (\n    <Field.Root render={<FieldRootStyles />} style={{ width: 320 }}>\n        <Field.Label render={<FieldLabelStyles />}>Search</Field.Label>\n        <FieldControlWithIcon\n            icon={<Icon name=\"search\" size={16} />}\n            iconPosition=\"leading\"\n            className=\"text-13\"\n            placeholder=\"Search…\"\n        />\n    </Field.Root>\n);"
        },
        {
          "id": "components-field--with-trailing-icon",
          "name": "With Trailing Icon",
          "snippet": "const WithTrailingIcon = () => (\n    <Field.Root render={<FieldRootStyles />} style={{ width: 320 }}>\n        <Field.Label render={<FieldLabelStyles />}>Repository URL</Field.Label>\n        <FieldControlWithIcon\n            icon={<Icon name=\"link\" size={16} />}\n            iconPosition=\"trailing\"\n            className=\"text-13\"\n            placeholder=\"https://github.com/org/repo\"\n        />\n    </Field.Root>\n);"
        },
        {
          "id": "components-field--all-variants",
          "name": "All Variants",
          "snippet": "const AllVariants = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16, width: 320 }}>\n        <Field.Root render={<FieldRootStyles />}>\n            <Field.Label render={<FieldLabelStyles />}>Default</Field.Label>\n            <Field.Control\n                render={<FieldControlStyles />}\n                className=\"text-13\"\n                placeholder=\"Placeholder\"\n            />\n        </Field.Root>\n\n        <Field.Root render={<FieldRootStyles />}>\n            <Field.Label render={<FieldLabelStyles />}>With value</Field.Label>\n            <Field.Control\n                render={<FieldControlStyles />}\n                className=\"text-13\"\n                defaultValue=\"Some input value\"\n            />\n        </Field.Root>\n\n        <Field.Root render={<FieldRootStyles />}>\n            <Field.Label render={<FieldLabelStyles />}>Disabled</Field.Label>\n            <Field.Control\n                render={<FieldControlStyles />}\n                className=\"text-13\"\n                defaultValue=\"Disabled value\"\n                disabled\n            />\n        </Field.Root>\n\n        <Field.Root render={<FieldRootStyles />}>\n            <Field.Label render={<FieldLabelStyles />}>Disabled with icon</Field.Label>\n            <FieldControlWithIcon\n                icon={<Icon name=\"search\" size={16} />}\n                iconPosition=\"leading\"\n                className=\"text-13\"\n                placeholder=\"Search…\"\n                disabled\n            />\n        </Field.Root>\n\n        <Field.Root render={<FieldRootStyles />}>\n            <Field.Label render={<FieldLabelStyles />}>Textarea</Field.Label>\n            <Field.Control\n                render={<FieldTextareaStyles />}\n                className=\"text-14 text-body\"\n                placeholder=\"Multi-line input…\"\n            />\n        </Field.Root>\n    </div>\n);"
        }
      ],
      "import": "import { Field } from '@base-ui/react';\nimport {\n  FieldControlStyles,\n  FieldControlWithIcon,\n  FieldLabelStyles,\n  FieldTextareaStyles,\n  Icon,\n} from '@gitbutler/ui-react';\nimport { FieldRootStyles } from '@gitbutler/ui-react/Field.tsx';"
    },
    "components-fileicon": {
      "id": "components-fileicon",
      "name": "FileIcon",
      "path": "../../packages/ui-react/src/FileIcon.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { FileIcon } from \"@gitbutler/ui-react/FileIcon.tsx\";"
        ]
      },
      "description": "A file's language or type glyph, picked from its name: the longest known suffix wins\n(`vite.config.ts` before `.ts`), and anything unknown is a plain document.",
      "reactComponentMeta": {
        "displayName": "FileIcon",
        "exportName": "FileIcon",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/FileIcon.tsx",
        "description": "A file's language or type glyph, picked from its name: the longest known suffix wins\n(`vite.config.ts` before `.ts`), and anything unknown is a plain document.",
        "jsDocTags": {
          "import": [
            "import { FileIcon } from \"@gitbutler/ui-react/FileIcon.tsx\";"
          ]
        },
        "props": {
          "fileName": {
            "name": "fileName",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/FileIcon.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileIcon.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-fileicon--default",
          "name": "Default",
          "snippet": "const Default = () => <FileIcon fileName=\"FileIcon.tsx\" />;",
          "description": "Type a file name; the icon follows its name or extension, and a type it doesn't know gets `document`."
        },
        {
          "id": "components-fileicon--all-icons",
          "name": "All Icons",
          "snippet": "const AllIcons = () => (\n    <div\n        className=\"text-11\"\n        style={{\n            display: \"grid\",\n            gridTemplateColumns: \"repeat(auto-fill, minmax(112px, 1fr))\",\n            gap: 12,\n            padding: 8,\n        }}\n    >\n        {[...samples]\n            .sort(([a], [b]) => a.localeCompare(b))\n            .map(([icon, fileName]) => (\n                <div\n                    key={icon}\n                    title={fileName}\n                    style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}\n                >\n                    <FileIcon fileName={fileName} />\n                    <span>{icon}</span>\n                </div>\n            ))}\n    </div>\n);",
          "description": "Every icon a file name can reach, under the icon's name in ⚛️ Core."
        }
      ],
      "import": "import { FileIcon } from '@gitbutler/ui-react/FileIcon.tsx';"
    },
    "components-filelist": {
      "id": "components-filelist",
      "name": "FileListItem",
      "path": "../../packages/ui-react/src/FileList.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { FileList, FileListItem } from \"@gitbutler/ui-react/FileList.tsx\";"
        ]
      },
      "description": "One changed file, or a directory of them, in a {@link FileList}: its icon, its name, and what\nhappened to it. The row is the host's to wire: `render` it as a tree item or an option, and\ngive it `onClick`, `inert` while it can't be acted on, and a `ref` and `style` when virtualised.\n\n- `directory` is the path to the file, shown faded after its name, or before it with\n  `directoryPosition=\"lead\"`; leave it out where a tree already says where the file is.\n- `depth` indents the row one step per directory it sits in, each step drawing the guide that\n  ties it to its directory, so a tree reads as one. A directory row sets `folded`, which gives\n  it a folder and a chevron in its own step; `onToggleFolded` answers the chevron, and\n  `toggleRender` wraps it, for a tooltip trigger.\n- `icon` defaults to the file's type glyph, or a folder for a directory.\n- `checkbox` shares the icon's cell and takes its place once the pointer is over it or it is\n  checked, so a row stays quiet while browsing.\n- The last cell says what happened: the conflict mark if it is `conflicted`, else a tick if it\n  is `reviewed`, which also fades the name (a reviewed file's news is that it is done with),\n  else the letter for its `status`, else a folded directory's `count` of files.\n- `actions` take the status's place while the row is hovered, holds focus or is selected, so a\n  keyboard user finds them where the pointer would; both sit centred in one fixed cell, so\n  nothing moves. `marks` always show, before it.\n- `added` and `removed` give the file's line counts, after its name; either side shows only\n  when it isn't zero.\n- `labelRender` and `statusRender` wrap the name and the status, for tooltip triggers.",
      "reactComponentMeta": {
        "displayName": "FileListItem",
        "exportName": "FileListItem",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/FileList.tsx",
        "description": "One changed file, or a directory of them, in a {@link FileList}: its icon, its name, and what\nhappened to it. The row is the host's to wire: `render` it as a tree item or an option, and\ngive it `onClick`, `inert` while it can't be acted on, and a `ref` and `style` when virtualised.\n\n- `directory` is the path to the file, shown faded after its name, or before it with\n  `directoryPosition=\"lead\"`; leave it out where a tree already says where the file is.\n- `depth` indents the row one step per directory it sits in, each step drawing the guide that\n  ties it to its directory, so a tree reads as one. A directory row sets `folded`, which gives\n  it a folder and a chevron in its own step; `onToggleFolded` answers the chevron, and\n  `toggleRender` wraps it, for a tooltip trigger.\n- `icon` defaults to the file's type glyph, or a folder for a directory.\n- `checkbox` shares the icon's cell and takes its place once the pointer is over it or it is\n  checked, so a row stays quiet while browsing.\n- The last cell says what happened: the conflict mark if it is `conflicted`, else a tick if it\n  is `reviewed`, which also fades the name (a reviewed file's news is that it is done with),\n  else the letter for its `status`, else a folded directory's `count` of files.\n- `actions` take the status's place while the row is hovered, holds focus or is selected, so a\n  keyboard user finds them where the pointer would; both sit centred in one fixed cell, so\n  nothing moves. `marks` always show, before it.\n- `added` and `removed` give the file's line counts, after its name; either side shows only\n  when it isn't zero.\n- `labelRender` and `statusRender` wrap the name and the status, for tooltip triggers.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { FileList, FileListItem } from \"@gitbutler/ui-react/FileList.tsx\";"
          ]
        },
        "props": {
          "name": {
            "name": "name",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "directory": {
            "name": "directory",
            "required": false,
            "type": {
              "name": "string | null | undefined"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "directoryPosition": {
            "name": "directoryPosition",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"trail\" | \"lead\"",
              "value": [
                {
                  "value": "\"trail\""
                },
                {
                  "value": "\"lead\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"trail\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "icon": {
            "name": "icon",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "checkbox": {
            "name": "checkbox",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "depth": {
            "name": "depth",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": {
              "value": "0"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "folded": {
            "name": "folded",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "onToggleFolded": {
            "name": "onToggleFolded",
            "required": false,
            "type": {
              "name": "() => void"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "toggleRender": {
            "name": "toggleRender",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>>"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "status": {
            "name": "status",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"Addition\" | \"Deletion\" | \"Modification\" | \"Rename\"",
              "value": [
                {
                  "value": "\"Addition\""
                },
                {
                  "value": "\"Deletion\""
                },
                {
                  "value": "\"Modification\""
                },
                {
                  "value": "\"Rename\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "count": {
            "name": "count",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "reviewed": {
            "name": "reviewed",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": {
              "value": "false"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "conflicted": {
            "name": "conflicted",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": {
              "value": "false"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "selected": {
            "name": "selected",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": {
              "value": "false"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "actions": {
            "name": "actions",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "marks": {
            "name": "marks",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "added": {
            "name": "added",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": {
              "value": "0"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "removed": {
            "name": "removed",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": {
              "value": "0"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "labelRender": {
            "name": "labelRender",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>>"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "statusRender": {
            "name": "statusRender",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>>"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileList.tsx"
              }
            ]
          },
          "render": {
            "name": "render",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}> | undefined"
            },
            "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
            "defaultValue": null,
            "parent": {
              "name": "UseRenderComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/use-render/useRender.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/use-render/useRender.d.mts"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-filelist--default",
          "name": "Default",
          "snippet": "const Default = () => <FileList title=\"Changes\" count={1} added={12} removed={3} focused>\n    <FileListItem\n        name=\"userSlice.ts\"\n        directory=\"src/store\"\n        status=\"Modification\"\n        added={12}\n        removed={3}\n        selected={false}\n        reviewed={false}\n        conflicted={false} />\n</FileList>;",
          "description": "One file in a panel: the header names the files with their count and line totals, and the row\ngives the file's type glyph, its name with the path after it, its line counts, and the letter\nfor its change."
        },
        {
          "id": "components-filelist--states",
          "name": "States",
          "snippet": "const States = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 24 }}>\n        <FileList title=\"Changes\" count={5} added={120} removed={48} focused>\n            <FileListItem name=\"useAuthHook.ts\" directory=\"src/hooks\" status=\"Addition\" added={64} />\n            <FileListItem\n                selected\n                name=\"Button.tsx\"\n                directory=\"src/components\"\n                status=\"Modification\"\n                added={18}\n                removed={9}\n                actions={kebab}\n            />\n            <FileListItem\n                name=\"apiService.ts\"\n                directory=\"src/services\"\n                status=\"Modification\"\n                added={4}\n                removed={2}\n                reviewed\n            />\n            <FileListItem\n                name=\"merge.rs\"\n                directory=\"crates/core\"\n                status=\"Modification\"\n                added={34}\n                removed={37}\n                conflicted\n            />\n            <FileListItem name=\"index.ts\" directory=\"src\" status=\"Deletion\" inert />\n        </FileList>\n        <FileList title=\"Changes\" count={2} added={30}>\n            <FileListItem name=\"styles.css\" directory=\"src/styles\" status=\"Addition\" />\n            <FileListItem selected name=\"theme.css\" directory=\"src/styles\" status=\"Modification\" />\n        </FileList>\n    </div>\n);",
          "description": "Every state a row can be in. The list holds the selection focus, so the selected row is solid;\nthe second list has lost it. A row that can't be acted on right now is `inert`."
        },
        {
          "id": "components-filelist--tree",
          "name": "Tree",
          "snippet": "const Tree = function Render() {\n    const [folded, setFolded] = useState<ReadonlySet<string>>(() => new Set([\"src/styles\"]));\n    const [checked, setChecked] = useState<ReadonlySet<string>>(() => new Set([\"Button.tsx\"]));\n    const toggle = (set: ReadonlySet<string>, key: string) => {\n        const next = new Set(set);\n        if (!next.delete(key)) next.add(key);\n        return next;\n    };\n    const rows = (nodes: Array<TreeNode>, depth: number, parent: string): Array<ReactNode> =>\n        nodes.flatMap((node) => {\n            const path = parent === \"\" ? node.name : `${parent}/${node.name}`;\n            if (node.kind === \"file\") {\n                return [\n                    <FileListItem\n                        key={path}\n                        role=\"treeitem\"\n                        aria-level={depth + 1}\n                        name={node.name}\n                        depth={depth}\n                        status={node.status}\n                        checkbox={\n                            <Checkbox\n                                aria-label={`Check ${path}`}\n                                checked={checked.has(node.name)}\n                                onCheckedChange={() => setChecked((set) => toggle(set, node.name))}\n                            />\n                        }\n                    />,\n                ];\n            }\n            const isFolded = folded.has(path);\n            return [\n                <FileListItem\n                    key={path}\n                    role=\"treeitem\"\n                    aria-level={depth + 1}\n                    aria-expanded={!isFolded}\n                    name={node.name}\n                    depth={depth}\n                    folded={isFolded}\n                    onToggleFolded={() => setFolded((set) => toggle(set, path))}\n                    count={isFolded ? countFiles(node) : undefined}\n                />,\n                ...(isFolded ? [] : rows(node.children, depth + 1, path)),\n            ];\n        });\n    return (\n        <FileList title=\"Changes\" count={6} added={214} removed={37} focused>\n            <div role=\"tree\" aria-label=\"Changes\" style={{ display: \"contents\" }}>\n                {rows(tree, 0, \"\")}\n            </div>\n        </FileList>\n    );\n};",
          "description": "A tree: each row steps in under its directory, with the guide that ties it there. A directory\nfolds on its chevron and says how many files it holds while folded; files under one leave out\ntheir path, since the tree says it."
        },
        {
          "id": "components-filelist--virtualised",
          "name": "Virtualised",
          "snippet": "const Virtualised = function Render() {\n    const scrollRef = useRef<HTMLDivElement>(null);\n    const [selected, setSelected] = useState(0);\n    const virtualizer = useVirtualizer({\n        count: many.length,\n        getScrollElement: () => scrollRef.current,\n        estimateSize: () => 28,\n        gap: 1,\n    });\n    return (\n        <div style={{ display: \"flex\", flexDirection: \"column\", height: 360 }}>\n            <FileList\n                title=\"Changes\"\n                count={many.length}\n                added={48210}\n                removed={9021}\n                focused\n                viewportRef={scrollRef}\n                style={{ flexGrow: 1 }}\n            >\n                <div style={{ position: \"relative\", height: virtualizer.getTotalSize() }}>\n                    {virtualizer.getVirtualItems().map((row) => {\n                        const file = many[row.index];\n                        if (file === undefined) return null;\n                        return (\n                            <FileListItem\n                                key={row.key}\n                                selected={row.index === selected}\n                                {...file}\n                                onClick={() => setSelected(row.index)}\n                                data-index={row.index}\n                                ref={virtualizer.measureElement}\n                                style={{\n                                    position: \"absolute\",\n                                    insetInline: 0,\n                                    transform: `translateY(${row.start}px)`,\n                                }}\n                            />\n                        );\n                    })}\n                </div>\n            </FileList>\n        </div>\n    );\n};",
          "description": "A long list, virtualised: the virtualizer positions each row and supplies the pixel between\nthem, since rows it places don't take the list's gap."
        },
        {
          "id": "components-filelist--filter",
          "name": "Filter",
          "snippet": "const Filter = function Render() {\n    const [query, setQuery] = useState<string | null>(\"comp\");\n    const shown = filterable.filter(\n        (file) => query === null || `${file.directory}/${file.name}`.includes(query),\n    );\n    return (\n        <FileList\n            title=\"Changes\"\n            count={filterable.length}\n            added={120}\n            removed={48}\n            focused\n            onOpenFilter={() => setQuery(\"\")}\n            filter={\n                query === null\n                    ? null\n                    : { value: query, onChange: setQuery, onClose: () => setQuery(null) }\n            }\n            actions={\n                <Button variant=\"ghost\" iconOnly aria-label=\"Changes menu\">\n                    <Icon name=\"kebab\" />\n                </Button>\n            }\n        >\n            {shown.map((file) => (\n                <FileListItem key={file.name} {...file} />\n            ))}\n        </FileList>\n    );\n};",
          "description": "The search button turns the header into the filter field in place, so narrowing the list costs\nno height; the cross or Escape brings the header back."
        }
      ],
      "import": "import { Button, Checkbox, FileList, Icon } from '@gitbutler/ui-react';\nimport { FileList as FileListItem } from '@gitbutler/ui-react/FileList.tsx';"
    },
    "components-filestatusbadge": {
      "id": "components-filestatusbadge",
      "name": "FileStatusBadge",
      "path": "../../packages/ui-react/src/FileStatusBadge.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { FileStatusBadge } from \"@gitbutler/ui-react/FileStatusBadge.tsx\";"
        ]
      },
      "reactComponentMeta": {
        "displayName": "FileStatusBadge",
        "exportName": "FileStatusBadge",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/FileStatusBadge.tsx",
        "description": "",
        "jsDocTags": {
          "import": [
            "import { FileStatusBadge } from \"@gitbutler/ui-react/FileStatusBadge.tsx\";"
          ]
        },
        "props": {
          "status": {
            "name": "status",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"Addition\" | \"Deletion\" | \"Modification\" | \"Rename\"",
              "value": [
                {
                  "value": "\"Addition\""
                },
                {
                  "value": "\"Deletion\""
                },
                {
                  "value": "\"Modification\""
                },
                {
                  "value": "\"Rename\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/FileStatusBadge.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/FileStatusBadge.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-filestatusbadge--default",
          "name": "Default",
          "snippet": "const Default = () => <FileStatusBadge status=\"Addition\" />;"
        },
        {
          "id": "components-filestatusbadge--all-statuses",
          "name": "All Statuses",
          "snippet": "const AllStatuses = (args) => (\n    <div style={{ display: \"flex\", gap: 16, alignItems: \"center\" }}>\n        {statuses.map((status) => (\n            <div\n                key={status}\n                style={{ display: \"flex\", flexDirection: \"column\", gap: 8, alignItems: \"center\" }}\n            >\n                <FileStatusBadge {...args} status={status} />\n                <span style={{ fontSize: 11, opacity: 0.5 }}>{status}</span>\n            </div>\n        ))}\n    </div>\n);"
        }
      ],
      "import": "import { FileStatusBadge } from '@gitbutler/ui-react/FileStatusBadge.tsx';"
    },
    "components-foldericon": {
      "id": "components-foldericon",
      "name": "FolderIcon",
      "path": "../../packages/ui-react/src/FolderIcon.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { FolderIcon } from \"@gitbutler/ui-react/FolderIcon.tsx\";"
        ]
      },
      "description": "The folder mark, wherever a folder is named: the workspace header and every\ndirectory row in the file tree. Callers size it with CSS; it keeps its\nproportions inside whatever box they give it.",
      "reactComponentMeta": {
        "displayName": "FolderIcon",
        "exportName": "FolderIcon",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/FolderIcon.tsx",
        "description": "The folder mark, wherever a folder is named: the workspace header and every\ndirectory row in the file tree. Callers size it with CSS; it keeps its\nproportions inside whatever box they give it.",
        "jsDocTags": {
          "import": [
            "import { FolderIcon } from \"@gitbutler/ui-react/FolderIcon.tsx\";"
          ]
        },
        "props": {}
      },
      "stories": [
        {
          "id": "components-foldericon--default",
          "name": "Default",
          "snippet": "const Default = () => <FolderIcon />;",
          "description": "The mark at the size it was drawn, 17×14."
        },
        {
          "id": "components-foldericon--sizes",
          "name": "Sizes",
          "snippet": "const Sizes = () => (\n    <div style={{ display: \"flex\", alignItems: \"end\", gap: 16 }}>\n        {[12, 14, 17, 24, 34].map((width) => (\n            <FolderIcon key={width} style={{ width, height: \"auto\" }} />\n        ))}\n    </div>\n);",
          "description": "Callers size it with CSS, and it keeps its proportions in whatever box it gets."
        }
      ],
      "import": "import { FolderIcon } from '@gitbutler/ui-react/FolderIcon.tsx';"
    },
    "components-icon": {
      "id": "components-icon",
      "name": "Icon",
      "path": "../../packages/ui-react/src/Icon.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Icon } from \"@gitbutler/ui-react/Icon.tsx\";"
        ]
      },
      "reactComponentMeta": {
        "displayName": "Icon",
        "exportName": "Icon",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Icon.tsx",
        "description": "",
        "jsDocTags": {
          "import": [
            "import { Icon } from \"@gitbutler/ui-react/Icon.tsx\";"
          ]
        },
        "props": {
          "name": {
            "name": "name",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"search\" | \"link\" | \"filter\" | \"contrast\" | \"docs\" | \"file\" | \"copy\" | \"danger\" | \"absorb\" | \"ai\" | \"ai-text\" | \"arrow-corner-down-left\" | \"arrow-corner-left-up\" | \"arrow-corner-right-down\" | \"arrow-corner-up-right\" | \"arrow-double-down\" | \"arrow-double-up\" | \"arrow-down\" | \"arrow-down-left\" | \"arrow-down-right\" | \"arrow-in-box\" | \"arrow-left\" | \"arrow-line-down\" | \"arrow-line-up\" | \"arrow-right\" | \"arrow-up\" | \"arrow-up-left\" | \"arrow-up-right\" | \"bell\" | \"bin\" | \"branch\" | \"branch-merge\" | \"bullet-disc\" | \"bullet-list\" | \"bullseye\" | \"camera\" | \"checklist\" | \"checklist-remove\" | \"chevron-down\" | \"chevron-left\" | \"chevron-right\" | \"chevron-up\" | \"clock\" | \"cloud\" | \"collapse-vertical\" | \"commit\" | \"commit-fill\" | \"cross\" | \"cross-circle\" | \"diff\" | \"discord\" | \"drag-horizontal\" | \"drag-square\" | \"drag-vertical\" | \"edit\" | \"expand-vertical\" | \"eye\" | \"eye-closed\" | \"file-diff\" | \"file-minus\" | \"file-plus\" | \"file-text\" | \"files-sidebar\" | \"finger-print\" | \"folder\" | \"folder-copy\" | \"folder-fork\" | \"folder-lock\" | \"folder-tree\" | \"fork\" | \"globe\" | \"hash\" | \"history\" | \"home\" | \"inbox\" | \"inbox-fill\" | \"info\" | \"kebab\" | \"kebab-vertical\" | \"lab\" | \"list\" | \"lock\" | \"lock-auth\" | \"lock-open\" | \"login\" | \"logout\" | \"minus\" | \"mixer\" | \"number-list\" | \"paperclip\" | \"plug\" | \"plus\" | \"pr\" | \"pr-close\" | \"pr-draft\" | \"question\" | \"question-circle\" | \"refresh\" | \"repo\" | \"resize-handle\" | \"robot\" | \"settings\" | \"sidebar\" | \"sidebar-narrow\" | \"smiley\" | \"spinner\" | \"stack\" | \"tag\" | \"text-block\" | \"text-bold\" | \"text-code\" | \"text-contain\" | \"text-h2\" | \"text-h3\" | \"text-italic\" | \"text-plain\" | \"text-quote\" | \"text-strikethrough\" | \"text-wrap\" | \"theme-dark\" | \"theme-light\" | \"theme-system\" | \"tick\" | \"tick-circle\" | \"tick-double\" | \"undo\" | \"user\" | \"warning\" | \"workbench\"",
              "value": [
                {
                  "value": "\"search\""
                },
                {
                  "value": "\"link\""
                },
                {
                  "value": "\"filter\""
                },
                {
                  "value": "\"contrast\""
                },
                {
                  "value": "\"docs\""
                },
                {
                  "value": "\"file\""
                },
                {
                  "value": "\"copy\""
                },
                {
                  "value": "\"danger\""
                },
                {
                  "value": "\"absorb\""
                },
                {
                  "value": "\"ai\""
                },
                {
                  "value": "\"ai-text\""
                },
                {
                  "value": "\"arrow-corner-down-left\""
                },
                {
                  "value": "\"arrow-corner-left-up\""
                },
                {
                  "value": "\"arrow-corner-right-down\""
                },
                {
                  "value": "\"arrow-corner-up-right\""
                },
                {
                  "value": "\"arrow-double-down\""
                },
                {
                  "value": "\"arrow-double-up\""
                },
                {
                  "value": "\"arrow-down\""
                },
                {
                  "value": "\"arrow-down-left\""
                },
                {
                  "value": "\"arrow-down-right\""
                },
                {
                  "value": "\"arrow-in-box\""
                },
                {
                  "value": "\"arrow-left\""
                },
                {
                  "value": "\"arrow-line-down\""
                },
                {
                  "value": "\"arrow-line-up\""
                },
                {
                  "value": "\"arrow-right\""
                },
                {
                  "value": "\"arrow-up\""
                },
                {
                  "value": "\"arrow-up-left\""
                },
                {
                  "value": "\"arrow-up-right\""
                },
                {
                  "value": "\"bell\""
                },
                {
                  "value": "\"bin\""
                },
                {
                  "value": "\"branch\""
                },
                {
                  "value": "\"branch-merge\""
                },
                {
                  "value": "\"bullet-disc\""
                },
                {
                  "value": "\"bullet-list\""
                },
                {
                  "value": "\"bullseye\""
                },
                {
                  "value": "\"camera\""
                },
                {
                  "value": "\"checklist\""
                },
                {
                  "value": "\"checklist-remove\""
                },
                {
                  "value": "\"chevron-down\""
                },
                {
                  "value": "\"chevron-left\""
                },
                {
                  "value": "\"chevron-right\""
                },
                {
                  "value": "\"chevron-up\""
                },
                {
                  "value": "\"clock\""
                },
                {
                  "value": "\"cloud\""
                },
                {
                  "value": "\"collapse-vertical\""
                },
                {
                  "value": "\"commit\""
                },
                {
                  "value": "\"commit-fill\""
                },
                {
                  "value": "\"cross\""
                },
                {
                  "value": "\"cross-circle\""
                },
                {
                  "value": "\"diff\""
                },
                {
                  "value": "\"discord\""
                },
                {
                  "value": "\"drag-horizontal\""
                },
                {
                  "value": "\"drag-square\""
                },
                {
                  "value": "\"drag-vertical\""
                },
                {
                  "value": "\"edit\""
                },
                {
                  "value": "\"expand-vertical\""
                },
                {
                  "value": "\"eye\""
                },
                {
                  "value": "\"eye-closed\""
                },
                {
                  "value": "\"file-diff\""
                },
                {
                  "value": "\"file-minus\""
                },
                {
                  "value": "\"file-plus\""
                },
                {
                  "value": "\"file-text\""
                },
                {
                  "value": "\"files-sidebar\""
                },
                {
                  "value": "\"finger-print\""
                },
                {
                  "value": "\"folder\""
                },
                {
                  "value": "\"folder-copy\""
                },
                {
                  "value": "\"folder-fork\""
                },
                {
                  "value": "\"folder-lock\""
                },
                {
                  "value": "\"folder-tree\""
                },
                {
                  "value": "\"fork\""
                },
                {
                  "value": "\"globe\""
                },
                {
                  "value": "\"hash\""
                },
                {
                  "value": "\"history\""
                },
                {
                  "value": "\"home\""
                },
                {
                  "value": "\"inbox\""
                },
                {
                  "value": "\"inbox-fill\""
                },
                {
                  "value": "\"info\""
                },
                {
                  "value": "\"kebab\""
                },
                {
                  "value": "\"kebab-vertical\""
                },
                {
                  "value": "\"lab\""
                },
                {
                  "value": "\"list\""
                },
                {
                  "value": "\"lock\""
                },
                {
                  "value": "\"lock-auth\""
                },
                {
                  "value": "\"lock-open\""
                },
                {
                  "value": "\"login\""
                },
                {
                  "value": "\"logout\""
                },
                {
                  "value": "\"minus\""
                },
                {
                  "value": "\"mixer\""
                },
                {
                  "value": "\"number-list\""
                },
                {
                  "value": "\"paperclip\""
                },
                {
                  "value": "\"plug\""
                },
                {
                  "value": "\"plus\""
                },
                {
                  "value": "\"pr\""
                },
                {
                  "value": "\"pr-close\""
                },
                {
                  "value": "\"pr-draft\""
                },
                {
                  "value": "\"question\""
                },
                {
                  "value": "\"question-circle\""
                },
                {
                  "value": "\"refresh\""
                },
                {
                  "value": "\"repo\""
                },
                {
                  "value": "\"resize-handle\""
                },
                {
                  "value": "\"robot\""
                },
                {
                  "value": "\"settings\""
                },
                {
                  "value": "\"sidebar\""
                },
                {
                  "value": "\"sidebar-narrow\""
                },
                {
                  "value": "\"smiley\""
                },
                {
                  "value": "\"spinner\""
                },
                {
                  "value": "\"stack\""
                },
                {
                  "value": "\"tag\""
                },
                {
                  "value": "\"text-block\""
                },
                {
                  "value": "\"text-bold\""
                },
                {
                  "value": "\"text-code\""
                },
                {
                  "value": "\"text-contain\""
                },
                {
                  "value": "\"text-h2\""
                },
                {
                  "value": "\"text-h3\""
                },
                {
                  "value": "\"text-italic\""
                },
                {
                  "value": "\"text-plain\""
                },
                {
                  "value": "\"text-quote\""
                },
                {
                  "value": "\"text-strikethrough\""
                },
                {
                  "value": "\"text-wrap\""
                },
                {
                  "value": "\"theme-dark\""
                },
                {
                  "value": "\"theme-light\""
                },
                {
                  "value": "\"theme-system\""
                },
                {
                  "value": "\"tick\""
                },
                {
                  "value": "\"tick-circle\""
                },
                {
                  "value": "\"tick-double\""
                },
                {
                  "value": "\"undo\""
                },
                {
                  "value": "\"user\""
                },
                {
                  "value": "\"warning\""
                },
                {
                  "value": "\"workbench\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/Icon.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Icon.tsx"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/Icon.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Icon.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-icon--default",
          "name": "Default",
          "snippet": "const Default = () => <Icon name=\"branch\" size={16} />;",
          "description": "One icon, at the size the controls set."
        },
        {
          "id": "components-icon--all-icons",
          "name": "All Icons",
          "snippet": "const AllIcons = (args) => (\n    <div\n        style={{\n            display: \"grid\",\n            gridTemplateColumns: \"repeat(auto-fill, minmax(100px, 1fr))\",\n            gap: 16,\n        }}\n    >\n        {iconNames.map((name) => (\n            <div\n                key={name}\n                style={{\n                    display: \"flex\",\n                    flexDirection: \"column\",\n                    gap: 12,\n                    padding: 16,\n                }}\n            >\n                <Icon name={name} size={args.size} />\n                <span style={{ fontSize: 11, lineHeight: 1.3, opacity: 0.5 }}>{name}</span>\n            </div>\n        ))}\n    </div>\n);"
        }
      ],
      "import": "import { Icon } from '@gitbutler/ui-react/Icon.tsx';"
    },
    "components-illustration": {
      "id": "components-illustration",
      "name": "Illustration",
      "path": "../../packages/ui-react/src/Illustration.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Illustration } from \"@gitbutler/ui-react/Illustration.tsx\";"
        ]
      },
      "description": "A drawing at the size it was drawn, never scaled. Pick it by meaning: `cactus` a list with\nnothing in it, `papers` a search or filter that found nothing or a state the app can't name, `sleep` nothing connected (no machine yet, or the one holding it is offline), `id-card` signing in, `terminal` the command line, `waving` all good with nothing to do —\nand `waving` only in a large view, never a sidebar or a popup. See\n`packages/ui-react/design/patterns/empty-states.md`.",
      "reactComponentMeta": {
        "displayName": "Illustration",
        "exportName": "Illustration",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Illustration.tsx",
        "description": "A drawing at the size it was drawn, never scaled. Pick it by meaning: `cactus` a list with\nnothing in it, `papers` a search or filter that found nothing or a state the app can't name, `sleep` nothing connected (no machine yet, or the one holding it is offline), `id-card` signing in, `terminal` the command line, `waving` all good with nothing to do —\nand `waving` only in a large view, never a sidebar or a popup. See\n`packages/ui-react/design/patterns/empty-states.md`.",
        "jsDocTags": {
          "import": [
            "import { Illustration } from \"@gitbutler/ui-react/Illustration.tsx\";"
          ]
        },
        "props": {
          "name": {
            "name": "name",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"terminal\" | \"cactus\" | \"id-card\" | \"papers\" | \"sleep\" | \"waving\"",
              "value": [
                {
                  "value": "\"terminal\""
                },
                {
                  "value": "\"cactus\""
                },
                {
                  "value": "\"id-card\""
                },
                {
                  "value": "\"papers\""
                },
                {
                  "value": "\"sleep\""
                },
                {
                  "value": "\"waving\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/Illustration.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Illustration.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-illustration--default",
          "name": "Default",
          "snippet": "const Default = () => <Illustration name=\"cactus\" />;",
          "description": "One drawing, at the size it was drawn."
        },
        {
          "id": "components-illustration--all-illustrations",
          "name": "All Illustrations",
          "snippet": "const AllIllustrations = () => (\n    <div\n        style={{\n            display: \"grid\",\n            // Wide enough for the largest drawing at its own size, plus the padding.\n            gridTemplateColumns: \"repeat(auto-fill, minmax(280px, 1fr))\",\n            gap: 16,\n        }}\n    >\n        {names.map((name) => (\n            <div\n                key={name}\n                style={{\n                    display: \"flex\",\n                    flexDirection: \"column\",\n                    alignItems: \"center\",\n                    gap: 12,\n                    padding: 16,\n                }}\n            >\n                {/* On the app's paper rather than the story's ground: an illustration's\n                    enclosed areas are --bg-1, so a swatch of anything else would hide\n                    where the fill ends and the page begins. */}\n                <div\n                    style={{\n                        display: \"grid\",\n                        placeItems: \"center\",\n                        width: \"100%\",\n                        padding: 24,\n                        borderRadius: 6,\n                        backgroundColor: \"var(--bg-2)\",\n                    }}\n                >\n                    <Illustration name={name} />\n                </div>\n                <span style={{ fontSize: 11, lineHeight: 1.3, opacity: 0.5 }}>{name}</span>\n            </div>\n        ))}\n    </div>\n);"
        }
      ],
      "import": "import { Illustration } from '@gitbutler/ui-react/Illustration.tsx';"
    },
    "components-kbd": {
      "id": "components-kbd",
      "name": "Kbd",
      "path": "../../packages/ui-react/src/Kbd.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Kbd } from \"@gitbutler/ui-react/Kbd.tsx\";"
        ]
      },
      "reactComponentMeta": {
        "displayName": "Kbd",
        "exportName": "Kbd",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Kbd.tsx",
        "description": "",
        "jsDocTags": {
          "import": [
            "import { Kbd } from \"@gitbutler/ui-react/Kbd.tsx\";"
          ]
        },
        "props": {
          "hotkey": {
            "name": "hotkey",
            "required": true,
            "type": {
              "name": "string | HotkeySequence"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/Kbd.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Kbd.tsx"
              }
            ]
          },
          "variant": {
            "name": "variant",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"button\"",
              "value": [
                {
                  "value": "\"button\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/Kbd.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Kbd.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/Kbd.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Kbd.tsx"
              }
            ]
          },
          "keyClassName": {
            "name": "keyClassName",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/Kbd.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Kbd.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-kbd--default",
          "name": "Default",
          "snippet": "const Default = () => <Kbd hotkey=\"A\" />;"
        },
        {
          "id": "components-kbd--modifier",
          "name": "Modifier",
          "snippet": "const Modifier = () => <Kbd hotkey=\"Mod+A\" />;"
        },
        {
          "id": "components-kbd--sequence",
          "name": "Sequence",
          "snippet": "const Sequence = () => <Kbd hotkey={[\"G\", \"F\"]} />;"
        }
      ],
      "import": "import { Kbd } from '@gitbutler/ui-react/Kbd.tsx';"
    },
    "components-list": {
      "id": "components-list",
      "name": "List",
      "path": "../../packages/ui-react/src/List.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { List, ListItem } from \"@gitbutler/ui-react/List.tsx\";"
        ]
      },
      "description": "A short, read-only list: the files a prompt acts on, the reasons a push was rejected, the checks\na merge waits on. Stacks its items with no indent beyond their markers. For rows that do\nsomething, use a row or {@link PopupItem }; authored lists in a description keep Markdown's own\nbullets.",
      "reactComponentMeta": {
        "displayName": "List",
        "exportName": "List",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/List.tsx",
        "description": "A short, read-only list: the files a prompt acts on, the reasons a push was rejected, the checks\na merge waits on. Stacks its items with no indent beyond their markers. For rows that do\nsomething, use a row or {@link PopupItem }; authored lists in a description keep Markdown's own\nbullets.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { List, ListItem } from \"@gitbutler/ui-react/List.tsx\";"
          ]
        },
        "props": {}
      },
      "stories": [
        {
          "id": "components-list--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <List>\n        <ListItem>Rejected by a pre-receive hook: 2 files</ListItem>\n        <ListItem>Too large for the remote: assets/video.mov</ListItem>\n        <ListItem>\n            A longer reason that wraps onto a second line stays aligned with its own text, not with the\n            dot\n        </ListItem>\n    </List>\n);",
          "description": "The default marker: a dot on each item's first line. A long item wraps under itself."
        },
        {
          "id": "components-list--files",
          "name": "Files",
          "snippet": "const Files = () => (\n    <List>\n        {[\"screenshot.png\", \"pasted-image.png\", \"src/components/App.tsx\"].map((name) => (\n            <ListItem key={name} marker={<FileIcon fileName={name} />}>\n                {name}\n            </ListItem>\n        ))}\n    </List>\n);",
          "description": "Files carry their own icon in place of the dot, so the list says what each one is."
        },
        {
          "id": "components-list--icons",
          "name": "Icons",
          "snippet": "const Icons = () => (\n    <List>\n        <ListItem marker={<Icon name=\"branch\" />}>feature/modal-parts</ListItem>\n        <ListItem marker={<Icon name=\"branch\" />}>fix/menu-above-dialogs</ListItem>\n    </List>\n);",
          "description": "Any glyph from the icon set can stand in, for branches, commits and the like."
        }
      ],
      "import": "import { FileIcon, Icon, ListItem } from '@gitbutler/ui-react';\nimport { List } from '@gitbutler/ui-react/List.tsx';"
    },
    "components-logo": {
      "id": "components-logo",
      "name": "Logo",
      "path": "../../packages/ui-react/src/Logo.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Logo } from \"@gitbutler/ui-react/Logo.tsx\";"
        ]
      },
      "description": "A forge's own mark — GitHub, GitLab, Bitbucket — in its brand colours, or `muted` for one the\nuser has not connected.",
      "reactComponentMeta": {
        "displayName": "Logo",
        "exportName": "Logo",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Logo.tsx",
        "description": "A forge's own mark — GitHub, GitLab, Bitbucket — in its brand colours, or `muted` for one the\nuser has not connected.",
        "jsDocTags": {
          "import": [
            "import { Logo } from \"@gitbutler/ui-react/Logo.tsx\";"
          ]
        },
        "props": {
          "name": {
            "name": "name",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"github\" | \"gitlab\" | \"bitbucket\"",
              "value": [
                {
                  "value": "\"github\""
                },
                {
                  "value": "\"gitlab\""
                },
                {
                  "value": "\"bitbucket\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/Logo.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Logo.tsx"
              }
            ]
          },
          "muted": {
            "name": "muted",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "The mark as a silhouette on the recessed ground: a forge the user has not connected.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/Logo.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Logo.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-logo--default",
          "name": "Default",
          "snippet": "const Default = () => <Logo name=\"github\" muted={false} />;"
        },
        {
          "id": "components-logo--all-logos",
          "name": "All Logos",
          "snippet": "const AllLogos = () => (\n    <div\n        style={{\n            display: \"grid\",\n            gridTemplateColumns: \"repeat(3, auto)\",\n            gap: 16,\n            width: \"fit-content\",\n        }}\n    >\n        {names.map((name) => (\n            <Logo key={name} name={name} />\n        ))}\n        {names.map((name) => (\n            <Logo key={name} name={name} muted />\n        ))}\n    </div>\n);",
          "description": "Each forge in its own colours, and muted: the silhouette for a forge the user hasn't connected."
        }
      ],
      "import": "import { Logo } from '@gitbutler/ui-react/Logo.tsx';"
    },
    "components-markdowntoolbar": {
      "id": "components-markdowntoolbar",
      "name": "MarkdownToolbar",
      "path": "../../packages/ui-react/src/MarkdownToolbar.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { MarkdownToolbar } from \"@gitbutler/ui-react/MarkdownToolbar.tsx\";"
        ]
      },
      "description": "Markdown formatting buttons for a plain textarea. The commands themselves\nlive in `markdown-editing.ts`; this only routes them at the live selection.\n\nToo narrow to show every group, the buttons scroll sideways a group at a\ntime, with a chevron pair at the end for anyone without a horizontal wheel.",
      "reactComponentMeta": {
        "displayName": "MarkdownToolbar",
        "exportName": "MarkdownToolbar",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/MarkdownToolbar.tsx",
        "description": "Markdown formatting buttons for a plain textarea. The commands themselves\nlive in `markdown-editing.ts`; this only routes them at the live selection.\n\nToo narrow to show every group, the buttons scroll sideways a group at a\ntime, with a chevron pair at the end for anyone without a horizontal wheel.",
        "jsDocTags": {
          "import": [
            "import { MarkdownToolbar } from \"@gitbutler/ui-react/MarkdownToolbar.tsx\";"
          ]
        },
        "props": {
          "targetRef": {
            "name": "targetRef",
            "required": true,
            "type": {
              "name": "RefObject<HTMLTextAreaElement | null>"
            },
            "description": "The textarea whose markdown source the buttons rewrite.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/MarkdownToolbar.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/MarkdownToolbar.tsx"
              }
            ]
          },
          "onInput": {
            "name": "onInput",
            "required": true,
            "type": {
              "name": "(value: string) => void"
            },
            "description": "Receives the rewritten source, for the owner's controlled state.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/MarkdownToolbar.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/MarkdownToolbar.tsx"
              }
            ]
          },
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/MarkdownToolbar.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/MarkdownToolbar.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/MarkdownToolbar.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/MarkdownToolbar.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-markdowntoolbar--default",
          "name": "Default",
          "snippet": "const Default = () => <Demo />;",
          "description": "Select some text in the field, or place the caret, and press a button."
        },
        {
          "id": "components-markdowntoolbar--narrow",
          "name": "Narrow",
          "snippet": "const Narrow = () => <Demo width={300} />;",
          "description": "Too narrow for every group, the buttons scroll a group at a time behind the\nchevrons; a horizontal wheel or a swipe snaps to the same stops."
        },
        {
          "id": "components-markdowntoolbar--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => <Demo disabled />;",
          "description": "Disabled while a submit is pending: the buttons stay put but do nothing."
        }
      ],
      "import": "import { FieldTextareaStyles } from '@gitbutler/ui-react';\nimport { MarkdownToolbar } from '@gitbutler/ui-react/MarkdownToolbar.tsx';\nimport { Tooltip } from '@base-ui/react';"
    },
    "components-menu": {
      "id": "components-menu",
      "name": "Menu",
      "path": "../../packages/ui-react/src/Menu.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Menu, MenuItem, MenuSection } from \"@gitbutler/ui-react/Menu.tsx\";"
        ]
      },
      "description": "A list of actions, opened by a button or from code: the ⋯ on a row, a header's options. Its rows\nare {@link MenuItem}s, grouped into {@link MenuSection}s, and a choice of one is a\n{@link MenuRadioGroup}. It wears the same container as every other overlay, anchored to what\nopened it, and is never narrower than that.\n\nFor a menu raised by a right-click on an area, use {@link ContextMenu}; the rows are the same.\nA row offers both: its ⋯ is a `Menu` in the row's `menu` slot, and the row itself is a\n`ContextMenu`'s `trigger`, with the same rows. Each keeps its own open state, so a right-click\nleaves the ⋯ as it was.\nFor an anchored panel that is not a list of actions (a filter, a notification list), use\n`Dropdown`.\n\nWithout a `trigger`, control `open` and pass `anchor`: an element to hang under, or a point.\nPressing an element anchor while the menu is open is left to that element's own click, which\ntoggles the menu, so the press doesn't close it only for the click to open it again.",
      "reactComponentMeta": {
        "displayName": "Menu",
        "exportName": "Menu",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Menu.tsx",
        "description": "A list of actions, opened by a button or from code: the ⋯ on a row, a header's options. Its rows\nare {@link MenuItem}s, grouped into {@link MenuSection}s, and a choice of one is a\n{@link MenuRadioGroup}. It wears the same container as every other overlay, anchored to what\nopened it, and is never narrower than that.\n\nFor a menu raised by a right-click on an area, use {@link ContextMenu}; the rows are the same.\nA row offers both: its ⋯ is a `Menu` in the row's `menu` slot, and the row itself is a\n`ContextMenu`'s `trigger`, with the same rows. Each keeps its own open state, so a right-click\nleaves the ⋯ as it was.\nFor an anchored panel that is not a list of actions (a filter, a notification list), use\n`Dropdown`.\n\nWithout a `trigger`, control `open` and pass `anchor`: an element to hang under, or a point.\nPressing an element anchor while the menu is open is left to that element's own click, which\ntoggles the menu, so the press doesn't close it only for the click to open it again.",
        "jsDocTags": {
          "import": [
            "import { Menu, MenuItem, MenuSection } from \"@gitbutler/ui-react/Menu.tsx\";"
          ]
        },
        "props": {
          "trigger": {
            "name": "trigger",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>>"
            },
            "description": "Opens the menu and anchors it. Leave it out to open the menu from code, at `anchor`.",
            "defaultValue": null,
            "parent": {
              "name": "MenuProps",
              "fileName": "../../packages/ui-react/src/Menu.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Menu.tsx"
              }
            ]
          },
          "anchor": {
            "name": "anchor",
            "required": false,
            "type": {
              "name": "MenuAnchor | null | undefined"
            },
            "description": "Where a menu without a trigger hangs: an element, or a point such as where a click landed.",
            "defaultValue": null,
            "parent": {
              "name": "MenuProps",
              "fileName": "../../packages/ui-react/src/Menu.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Menu.tsx"
              }
            ]
          },
          "open": {
            "name": "open",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Omit to leave the menu uncontrolled and drive it from `trigger` alone.",
            "defaultValue": null,
            "parent": {
              "name": "MenuProps",
              "fileName": "../../packages/ui-react/src/Menu.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Menu.tsx"
              }
            ]
          },
          "onOpenChange": {
            "name": "onOpenChange",
            "required": false,
            "type": {
              "name": "(open: boolean) => void"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "MenuProps",
              "fileName": "../../packages/ui-react/src/Menu.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Menu.tsx"
              }
            ]
          },
          "side": {
            "name": "side",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"top\" | \"bottom\" | \"left\" | \"right\"",
              "value": [
                {
                  "value": "\"top\""
                },
                {
                  "value": "\"bottom\""
                },
                {
                  "value": "\"left\""
                },
                {
                  "value": "\"right\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"bottom\""
            },
            "parent": {
              "name": "MenuProps",
              "fileName": "../../packages/ui-react/src/Menu.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Menu.tsx"
              }
            ]
          },
          "align": {
            "name": "align",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"center\" | \"end\" | \"start\"",
              "value": [
                {
                  "value": "\"center\""
                },
                {
                  "value": "\"end\""
                },
                {
                  "value": "\"start\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"start\""
            },
            "parent": {
              "name": "MenuProps",
              "fileName": "../../packages/ui-react/src/Menu.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Menu.tsx"
              }
            ]
          },
          "sideOffset": {
            "name": "sideOffset",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": {
              "value": "4"
            },
            "parent": {
              "name": "MenuProps",
              "fileName": "../../packages/ui-react/src/Menu.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Menu.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-menu--default",
          "name": "Default",
          "snippet": "const Default = () => <Menu\n    side=\"bottom\"\n    align=\"end\"\n    sideOffset={4}\n    aria-label=\"Branch actions\"\n    trigger={(<Button variant=\"ghost\" size=\"small\" iconOnly aria-label=\"More actions\">\n        <Icon name=\"kebab\" />\n    </Button>)}>(<>\n        <MenuSection>\n            <MenuItem>Send to…</MenuItem>\n            <MenuItem disabled hint=\"pavel--macbook-pro-2 is offline\">\n                Land…\n            </MenuItem>\n            <MenuItem>Rename…</MenuItem>\n        </MenuSection>\n        <MenuSection>\n            <MenuItem>Archive</MenuItem>\n            <MenuItem>Delete branch…</MenuItem>\n        </MenuSection>\n    </>)</Menu>;",
          "description": "A row's ⋯: its actions in sections, and one it can't run now held in place with the reason on\nhover."
        },
        {
          "id": "components-menu--view-options",
          "name": "View Options",
          "snippet": "const ViewOptions = () => <ViewOptionsMenu side=\"bottom\" align=\"end\" sideOffset={4} />;",
          "description": "A header's view options: three choices of one, each ticked where it stands."
        },
        {
          "id": "components-menu--on-right-click",
          "name": "On Right Click",
          "snippet": "const OnRightClick = () => (\n    <ContextMenu\n        aria-label=\"Commit actions\"\n        trigger={\n            <div\n                className=\"text-13\"\n                style={{\n                    padding: \"24px 32px\",\n                    border: \"1px dashed var(--border-2)\",\n                    borderRadius: \"var(--radius-card)\",\n                    color: \"var(--text-2)\",\n                }}\n            >\n                Right-click here\n            </div>\n        }\n    >\n        <MenuSection>\n            <MenuItem icon=\"copy\" kbd=\"Mod+C\">\n                Copy SHA\n            </MenuItem>\n            <MenuItem icon=\"edit\">Edit message…</MenuItem>\n        </MenuSection>\n        <MenuSection>\n            <MenuItem icon=\"undo\">Uncommit</MenuItem>\n        </MenuSection>\n    </ContextMenu>\n);",
          "description": "The same actions on a right-click, at the pointer."
        },
        {
          "id": "components-menu--on-a-row",
          "name": "On A Row",
          "snippet": "const OnARow = () => (\n    <div style={{ width: 334 }}>\n        <ContextMenu\n            aria-label=\"Branch actions\"\n            trigger={\n                <BranchItem\n                    title=\"resume-on-laptop\"\n                    folded\n                    meta={<MetaCount type=\"unpushed\">9</MetaCount>}\n                    menu={\n                        <Menu\n                            aria-label=\"Branch actions\"\n                            trigger={\n                                <Button variant=\"ghost\" size=\"small\" iconOnly aria-label=\"More actions\">\n                                    <Icon name=\"kebab\" />\n                                </Button>\n                            }\n                        >\n                            {branchActions}\n                        </Menu>\n                    }\n                />\n            }\n        >\n            {branchActions}\n        </ContextMenu>\n    </div>\n);",
          "description": "A row's actions, from its ⋯ and from a right-click anywhere on it: the ⋯ is a `Menu` in the\nrow's `menu` slot, and the row itself is a `ContextMenu`'s trigger, both with the same rows.\nEach menu keeps its own state, so a right-click leaves the ⋯ unpressed."
        }
      ],
      "import": "import {\n  BranchItem,\n  Button,\n  ContextMenu,\n  Icon,\n  MenuItem,\n  MenuRadioGroup,\n  MenuRadioItem,\n  MenuSection,\n  MetaCount,\n} from '@gitbutler/ui-react';\nimport { Menu } from '@gitbutler/ui-react/Menu.tsx';\nimport { Button } from './Button.tsx';\nimport { Icon } from './Icon.tsx';\nimport { MenuSection, MenuItem } from './Menu.tsx';"
    },
    "components-metacount": {
      "id": "components-metacount",
      "name": "MetaCount",
      "path": "../../packages/ui-react/src/MetaCount.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { MetaCount } from \"@gitbutler/ui-react/MetaCount.tsx\";"
        ]
      },
      "description": "A glyph and a short value in a row's meta: a count, an age, a branch's name. The type sets both.\nAmber is work waiting on you (`behind`, `uncommitted`, `agent-waiting`), blue is work to send\n(`unpushed`), green is an agent at work (`agent-working`); the rest are neutral. Quietest of all\nare `empty`, a branch with no commits yet, and `head`, what a worktree with nothing to list is on\n(`empty`, `detached`); a row shows either first, ahead of its counts.\n\nThe value is the children, so a host formats it (`12`, `3d`, `retry-transfers`). The glyph says\nnothing to a screen reader: wrap the count in a `Tooltip` saying what it counts, or give it an\n`aria-label`. A long value, such as a branch's name, ends in an ellipsis once its row runs out\nof room.",
      "reactComponentMeta": {
        "displayName": "MetaCount",
        "exportName": "MetaCount",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/MetaCount.tsx",
        "description": "A glyph and a short value in a row's meta: a count, an age, a branch's name. The type sets both.\nAmber is work waiting on you (`behind`, `uncommitted`, `agent-waiting`), blue is work to send\n(`unpushed`), green is an agent at work (`agent-working`); the rest are neutral. Quietest of all\nare `empty`, a branch with no commits yet, and `head`, what a worktree with nothing to list is on\n(`empty`, `detached`); a row shows either first, ahead of its counts.\n\nThe value is the children, so a host formats it (`12`, `3d`, `retry-transfers`). The glyph says\nnothing to a screen reader: wrap the count in a `Tooltip` saying what it counts, or give it an\n`aria-label`. A long value, such as a branch's name, ends in an ellipsis once its row runs out\nof room.",
        "jsDocTags": {
          "import": [
            "import { MetaCount } from \"@gitbutler/ui-react/MetaCount.tsx\";"
          ]
        },
        "props": {
          "type": {
            "name": "type",
            "required": true,
            "type": {
              "name": "enum",
              "raw": "\"head\" | \"branch\" | \"behind\" | \"unpushed\" | \"commits\" | \"empty\" | \"uncommitted\" | \"clean\" | \"age\" | \"worktrees\" | \"repos\" | \"agent-working\" | \"agent-waiting\"",
              "value": [
                {
                  "value": "\"head\""
                },
                {
                  "value": "\"branch\""
                },
                {
                  "value": "\"behind\""
                },
                {
                  "value": "\"unpushed\""
                },
                {
                  "value": "\"commits\""
                },
                {
                  "value": "\"empty\""
                },
                {
                  "value": "\"uncommitted\""
                },
                {
                  "value": "\"clean\""
                },
                {
                  "value": "\"age\""
                },
                {
                  "value": "\"worktrees\""
                },
                {
                  "value": "\"repos\""
                },
                {
                  "value": "\"agent-working\""
                },
                {
                  "value": "\"agent-waiting\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/MetaCount.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-metacount--default",
          "name": "Default",
          "snippet": "const Default = () => <MetaCount type=\"unpushed\">4</MetaCount>;",
          "description": "One count: its glyph, coloured by what it counts, and its value."
        },
        {
          "id": "components-metacount--kinds",
          "name": "Kinds",
          "snippet": "const Kinds = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n        <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 12 }}>\n            {types.map((type) => (\n                <MetaCount key={type} type={type}>\n                    {sample[type]}\n                </MetaCount>\n            ))}\n        </div>\n        <div style={{ display: \"flex\", gap: 12 }}>\n            <CiStatus status=\"working\" />\n            <CiStatus status=\"passed\" />\n            <CiStatus status=\"failed\" />\n        </div>\n    </div>\n);",
          "description": "Every kind of count, as rows show them, and the three states of a branch's checks."
        }
      ],
      "import": "import { CiStatus } from '@gitbutler/ui-react';\nimport { MetaCount } from '@gitbutler/ui-react/MetaCount.tsx';"
    },
    "components-modal": {
      "id": "components-modal",
      "name": "Modal",
      "path": "../../packages/ui-react/src/Modal.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Modal } from \"@gitbutler/ui-react/Popup.tsx\";"
        ]
      },
      "description": "A popup that opens over the whole window, dimming what it covers. The backdrop is the only thing\nseparating it from a {@link Dropdown} — the container beneath is the same.\n\nThe modal owns its chrome and placement. A prompt, a confirmation or a short form is built from\n{@link ModalHeader}, {@link ModalBody} and {@link ModalFooter}, and a pane as involved as settings\nlays itself out entirely. A list to search and pick from is not a modal's: it is a `PickerDialog`,\nor Popup's combobox when it hangs off the control that opened it.",
      "reactComponentMeta": {
        "displayName": "Modal",
        "exportName": "Modal",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Popup.tsx",
        "description": "A popup that opens over the whole window, dimming what it covers. The backdrop is the only thing\nseparating it from a {@link Dropdown} — the container beneath is the same.\n\nThe modal owns its chrome and placement. A prompt, a confirmation or a short form is built from\n{@link ModalHeader}, {@link ModalBody} and {@link ModalFooter}, and a pane as involved as settings\nlays itself out entirely. A list to search and pick from is not a modal's: it is a `PickerDialog`,\nor Popup's combobox when it hangs off the control that opened it.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Modal } from \"@gitbutler/ui-react/Popup.tsx\";"
          ]
        },
        "props": {
          "open": {
            "name": "open",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Omit to leave the modal uncontrolled and drive it from `trigger` alone.",
            "defaultValue": null,
            "parent": {
              "name": "ModalProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "onOpenChange": {
            "name": "onOpenChange",
            "required": false,
            "type": {
              "name": "(open: boolean) => void"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "ModalProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "trigger": {
            "name": "trigger",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>>"
            },
            "description": "Rendered as the modal's trigger. Omit for a modal opened from elsewhere in the app.",
            "defaultValue": null,
            "parent": {
              "name": "ModalProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "alert": {
            "name": "alert",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Takes the `alertdialog` role and refuses to close on Escape or a backdrop click: the question\nhas to be answered rather than dismissed. For credentials and destructive confirmations.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "ModalProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"small\" | \"large\" | \"xsmall\" | \"medium\"",
              "value": [
                {
                  "value": "\"small\""
                },
                {
                  "value": "\"large\""
                },
                {
                  "value": "\"xsmall\""
                },
                {
                  "value": "\"medium\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"small\""
            },
            "parent": {
              "name": "ModalProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "align": {
            "name": "align",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"center\" | \"top\"",
              "value": [
                {
                  "value": "\"center\""
                },
                {
                  "value": "\"top\""
                }
              ]
            },
            "description": "Where the modal sits in the window. A picker opens `top`, so its list grows downward the way a\ncommand palette does; everything else centres.",
            "defaultValue": {
              "value": "\"center\""
            },
            "parent": {
              "name": "ModalProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "recessed": {
            "name": "recessed",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Recesses the modal's own ground so the groups inside it read as cards sitting on it, rather\nthan as sections of one sheet. For a pane holding more than one group — settings, a resolver.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "ModalProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "initialFocus": {
            "name": "initialFocus",
            "required": false,
            "type": {
              "name": "boolean | RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | void | HTMLElement | null) | undefined"
            },
            "description": "What takes focus as the modal opens, when the first tabbable element is not the right one.",
            "defaultValue": null,
            "parent": {
              "name": "ModalProps",
              "fileName": "../../packages/ui-react/src/Popup.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-modal--default",
          "name": "Default",
          "snippet": "const Default = () => <Modal\n    size=\"small\"\n    align=\"center\"\n    alert={false}\n    trigger={<Button>Open modal</Button>}>(<>\n        <ModalHeader\n            title=\"Leave without saving?\"\n            description=\"Your edits to the description are lost.\"\n        />\n        <ModalFooter>\n            <Button variant=\"ghost\">Cancel</Button>\n            <Button variant=\"gray\">Leave</Button>\n        </ModalFooter>\n    </>)</Modal>;",
          "description": "The modal and its props, to try with the controls. The stories after it are modals as the app\nwrites them — a confirmation, a form, a destructive question — opened and whole, to copy from."
        },
        {
          "id": "components-modal--confirm",
          "name": "Confirm",
          "snippet": "const Confirm = function Confirm() {\n    const [open, setOpen] = useState(true);\n    return (\n        <Modal\n            size=\"small\"\n            open={open}\n            onOpenChange={setOpen}\n            trigger={<Button>Upload files</Button>}\n        >\n            <ModalHeader\n                title=\"Upload these 2 files?\"\n                description=\"They go to gitbutler.com, and anyone with the link can open them.\"\n            />\n            <ModalBody>\n                <List>\n                    <ListItem marker={<FileIcon fileName=\"screenshot.png\" />}>screenshot.png</ListItem>\n                    <ListItem marker={<FileIcon fileName=\"pasted-image.png\" />}>pasted-image.png</ListItem>\n                </List>\n            </ModalBody>\n            <ModalFooter>\n                <Button variant=\"ghost\" onClick={() => setOpen(false)}>\n                    Cancel\n                </Button>\n                <Button variant=\"gray\" onClick={() => setOpen(false)}>\n                    Upload\n                </Button>\n            </ModalFooter>\n        </Modal>\n    );\n};",
          "description": "A confirmation: the title asks, the description says what answering does, the body shows what\nit acts on, and the footer holds Cancel and the answer. The answer is `gray` and repeats the\ntitle's verb. Escape and the backdrop cancel it."
        },
        {
          "id": "components-modal--form",
          "name": "Form",
          "snippet": "const Form = function Form() {\n    const [open, setOpen] = useState(true);\n    return (\n        <Modal\n            alert\n            size=\"small\"\n            open={open}\n            onOpenChange={setOpen}\n            trigger={<Button>Sign in to git</Button>}\n        >\n            <form\n                onSubmit={(event) => {\n                    event.preventDefault();\n                    setOpen(false);\n                }}\n            >\n                <ModalHeader\n                    title=\"Git credentials required\"\n                    description=\"Enter your password for github.com to fetch.\"\n                />\n                <ModalBody>\n                    <Field.Root render={<FieldRootStyles />}>\n                        <Field.Control\n                            render={<FieldControlStyles />}\n                            type=\"password\"\n                            aria-label=\"Password\"\n                        />\n                    </Field.Root>\n                </ModalBody>\n                <ModalFooter>\n                    <Button variant=\"ghost\" onClick={() => setOpen(false)}>\n                        Cancel\n                    </Button>\n                    <Button type=\"submit\" variant=\"gray\">\n                        Continue\n                    </Button>\n                </ModalFooter>\n            </form>\n        </Modal>\n    );\n};",
          "description": "A short form. The `<form>` wraps all three parts so Enter submits, and the submit button is the\nanswer. The description names the one field, so it has no label above it, only an `aria-label`."
        },
        {
          "id": "components-modal--destructive",
          "name": "Destructive",
          "snippet": "const Destructive = function Destructive() {\n    const [open, setOpen] = useState(true);\n    return (\n        <Modal\n            alert\n            size=\"xsmall\"\n            open={open}\n            onOpenChange={setOpen}\n            trigger={<Button>Discard changes</Button>}\n        >\n            <ModalHeader\n                title=\"Discard 3 files?\"\n                description=\"Their changes are gone for good; nothing keeps a copy.\"\n            />\n            <ModalFooter>\n                <Button variant=\"ghost\" onClick={() => setOpen(false)}>\n                    Cancel\n                </Button>\n                <Button variant=\"danger\" onClick={() => setOpen(false)}>\n                    Discard\n                </Button>\n            </ModalFooter>\n        </Modal>\n    );\n};",
          "description": "Something that cannot be taken back: the answer is `danger`, chosen by consequence. A one-line\nquestion with nothing to list takes `xsmall` and no body."
        },
        {
          "id": "components-modal--with-back",
          "name": "With Back",
          "snippet": "const WithBack = function WithBack() {\n    const [open, setOpen] = useState(true);\n    const [place, setPlace] = useState<Place | null>(null);\n    const [from, setFrom] = useState<Place | null>(null);\n    const pick = (next: Place) => {\n        setFrom(next);\n        setPlace(next);\n    };\n\n    return (\n        <Modal\n            open={open}\n            onOpenChange={(next) => {\n                setOpen(next);\n                if (!next) {\n                    setPlace(null);\n                    setFrom(null);\n                }\n            }}\n            trigger={<Button>Add a machine</Button>}\n        >\n            {place === null && (\n                <>\n                    <ModalHeader\n                        title=\"Where does the code live?\"\n                        description=\"Each place joins your fleet as a machine.\"\n                    />\n                    <PopupSection>\n                        {places.map(({ id, label }) => (\n                            <PopupItem\n                                key={id}\n                                trailing=\"chevron-right\"\n                                onClick={() => pick(id)}\n                                // oxlint-disable-next-line jsx_a11y/no-autofocus -- Back unmounted with focus on it.\n                                autoFocus={id === from}\n                            >\n                                {label}\n                            </PopupItem>\n                        ))}\n                    </PopupSection>\n                </>\n            )}\n            {place === \"computer\" && (\n                <>\n                    <ModalHeader\n                        title=\"Connect a computer\"\n                        description=\"Run this in a terminal on the computer you want to connect, macOS or Linux. It prints a code to approve in any browser.\"\n                        onBack={() => setPlace(null)}\n                    />\n                    <ModalBody>\n                        <Field.Root render={<FieldRootStyles />}>\n                            <Field.Control\n                                render={<FieldControlStyles />}\n                                readOnly\n                                value=\"curl -fsSL https://but.dev/install | sh\"\n                                aria-label=\"Install command\"\n                            />\n                        </Field.Root>\n                    </ModalBody>\n                </>\n            )}\n            {place === \"cloud\" && (\n                <>\n                    <ModalHeader\n                        title=\"Claude Code cloud sessions\"\n                        description=\"Paste this setup script into the environment in Claude. Each session joins when it starts.\"\n                        onBack={() => setPlace(null)}\n                    />\n                    <ModalBody>\n                        <Field.Root render={<FieldRootStyles />}>\n                            <Field.Control\n                                render={<FieldControlStyles />}\n                                readOnly\n                                value=\"curl -fsSL https://but.dev/install | BUT_FLEET_NO_LOGIN=1 sh\"\n                                aria-label=\"Setup script\"\n                            />\n                        </Field.Root>\n                    </ModalBody>\n                </>\n            )}\n        </Modal>\n    );\n};",
          "description": "A modal that drills in: picking a choice opens its step in the same modal, and that step's\nheader takes `onBack` to return to the list. One level in, one task — adding a machine — not a\nsequence of steps. Escape and the backdrop still close the whole modal, so it starts over at the\nlist next time. Back returns focus to the choice it came from."
        },
        {
          "id": "components-modal--large",
          "name": "Large",
          "snippet": "const Large = () => <Modal\n    size=\"large\"\n    align=\"center\"\n    alert={false}\n    trigger={<Button>Resolve conflicts</Button>}\n    aria-label=\"Resolve conflicts\">(<div style={{ height: 400, padding: 16 }}>\n        <span className=\"text-13\">\n            A pane this size lays out its own header, body and sidebar. The modal only carries the\n            surface, the backdrop and the placement.\n        </span>\n    </div>)</Modal>;",
          "description": "The settings-sized pane: the modal supplies the chrome, the caller lays out everything inside."
        }
      ],
      "import": "import {\n  Button,\n  FieldControlStyles,\n  FieldRootStyles,\n  FileIcon,\n  List,\n  ListItem,\n  ModalBody,\n  ModalFooter,\n  ModalHeader,\n  PopupItem,\n  PopupSection,\n} from '@gitbutler/ui-react';\nimport { Field } from '@base-ui/react';\nimport { Modal } from '@gitbutler/ui-react/Popup.tsx';\nimport { Button } from './Button.tsx';\nimport { ModalHeader, ModalFooter } from './Popup.tsx';"
    },
    "components-numberfield": {
      "id": "components-numberfield",
      "name": "NumberField",
      "path": "../../packages/ui-react/src/NumberField.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { NumberField } from \"@gitbutler/ui-react/NumberField.tsx\";"
        ]
      },
      "description": "A field for one number the user is as likely to nudge as to type: a size, a count, a limit.\nThe input keeps the text field's chrome with the value centred, and a stepper closes each\nside; the arrow keys step too. Give it `min`, `max` and `step` so the steppers know where to\nstop, and `onValueCommitted` for a setting that should be written when the user is done.\n\nFor a number that is one of a few named choices — a preset — reach for {@link Select }.",
      "reactComponentMeta": {
        "displayName": "NumberField",
        "exportName": "NumberField",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/NumberField.tsx",
        "description": "A field for one number the user is as likely to nudge as to type: a size, a count, a limit.\nThe input keeps the text field's chrome with the value centred, and a stepper closes each\nside; the arrow keys step too. Give it `min`, `max` and `step` so the steppers know where to\nstop, and `onValueCommitted` for a setting that should be written when the user is done.\n\nFor a number that is one of a few named choices — a preset — reach for {@link Select }.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { NumberField } from \"@gitbutler/ui-react/NumberField.tsx\";"
          ]
        },
        "props": {
          "label": {
            "name": "label",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "The field's label, above the control. Omit for a field the surface labels some other way,\nand give it an `aria-label` instead.",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "placeholder": {
            "name": "placeholder",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "What the control reads while it holds no value.",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "value": {
            "name": "value",
            "required": false,
            "type": {
              "name": "number | null | undefined"
            },
            "description": "Omit to leave the field uncontrolled. `null` is an empty field.",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "defaultValue": {
            "name": "defaultValue",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "onValueChange": {
            "name": "onValueChange",
            "required": false,
            "type": {
              "name": "(value: number | null) => void"
            },
            "description": "Fires on every change: each keystroke, each press of a stepper.",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "onValueCommitted": {
            "name": "onValueCommitted",
            "required": false,
            "type": {
              "name": "(value: number | null) => void"
            },
            "description": "Fires once the user is done: on blur after typing, on release of a stepper, with each arrow\nkey. For a setting that should be written then rather than on every keystroke.",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "min": {
            "name": "min",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "max": {
            "name": "max",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "step": {
            "name": "step",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "What one press of a stepper or an arrow key adds. Shift steps by `largeStep`.",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "largeStep": {
            "name": "largeStep",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "name": {
            "name": "name",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Identifies the field when a form is submitted.",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "style": {
            "name": "style",
            "required": false,
            "type": {
              "name": "CSSProperties"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          },
          "aria-label": {
            "name": "aria-label",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "NumberFieldProps",
              "fileName": "../../packages/ui-react/src/NumberField.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/NumberField.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-numberfield--default",
          "name": "Default",
          "snippet": "const Default = () => <NumberField label=\"Label\" placeholder=\"0\" style={{ width: 100 }} />;",
          "description": "Empty: the input reads the placeholder, and the steppers count from zero."
        },
        {
          "id": "components-numberfield--with-value",
          "name": "With Value",
          "snippet": "const WithValue = () => <NumberField label=\"Label\" placeholder=\"0\" style={{ width: 100 }} defaultValue={99} />;"
        },
        {
          "id": "components-numberfield--with-range",
          "name": "With Range",
          "snippet": "const WithRange = () => <NumberField\n    label=\"Tab size\"\n    placeholder=\"0\"\n    style={{ width: 100 }}\n    defaultValue={8}\n    min={1}\n    max={8}\n    step={1} />;",
          "description": "A range: the stepper that would leave it is disabled, and a typed value is clamped on blur."
        },
        {
          "id": "components-numberfield--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => <NumberField\n    label=\"Label\"\n    placeholder=\"0\"\n    style={{ width: 100 }}\n    defaultValue={99}\n    disabled />;"
        }
      ],
      "import": "import { NumberField } from '@gitbutler/ui-react/NumberField.tsx';"
    },
    "components-pickerdialog": {
      "id": "components-pickerdialog",
      "name": "PickerDialog",
      "path": "../../packages/ui-react/src/PickerDialog.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { PickerDialog } from \"@gitbutler/ui-react/PickerDialog.tsx\";"
        ]
      },
      "description": "A searchable list of grouped items in a modal: type to filter, arrows to move, Enter to act on\nthe highlighted one. Lite's branch pickers, the operations log and the command palette are\nbuilt from it.",
      "reactComponentMeta": {
        "displayName": "PickerDialog",
        "exportName": "PickerDialog",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/PickerDialog.tsx",
        "description": "A searchable list of grouped items in a modal: type to filter, arrows to move, Enter to act on\nthe highlighted one. Lite's branch pickers, the operations log and the command palette are\nbuilt from it.",
        "jsDocTags": {
          "import": [
            "import { PickerDialog } from \"@gitbutler/ui-react/PickerDialog.tsx\";"
          ]
        },
        "props": {
          "ariaLabel": {
            "name": "ariaLabel",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "closeLabel": {
            "name": "closeLabel",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "nothingFoundLabel": {
            "name": "nothingFoundLabel",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "What the list says when a search matched nothing — \"No hotkeys found\".",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "nothingToListLabel": {
            "name": "nothingToListLabel",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "What the list says when it had nothing in it before anything was typed — \"Nothing to restore\nyet\". Nothing was searched for, so this is not a \"found\" line.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "footerAction": {
            "name": "footerAction",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "getItemKey": {
            "name": "getItemKey",
            "required": true,
            "type": {
              "name": "(item: Command) => string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "getItemLabel": {
            "name": "getItemLabel",
            "required": true,
            "type": {
              "name": "(item: Command) => string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "getItemType": {
            "name": "getItemType",
            "required": true,
            "type": {
              "name": "(item: Command, group: PickerDialogGroup<Command>) => ReactNode"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "itemToStringValue": {
            "name": "itemToStringValue",
            "required": false,
            "type": {
              "name": "(item: Command) => string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "items": {
            "name": "items",
            "required": true,
            "type": {
              "name": "PickerDialogGroup<Command>[]"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "onOpenChange": {
            "name": "onOpenChange",
            "required": true,
            "type": {
              "name": "(open: boolean) => void"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "onSelectItem": {
            "name": "onSelectItem",
            "required": true,
            "type": {
              "name": "(item: Command) => void"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "open": {
            "name": "open",
            "required": true,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "placeholder": {
            "name": "placeholder",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "selectLabel": {
            "name": "selectLabel",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "What pressing Enter does here — \"Restore\", \"Apply\", \"Run\". Named per picker rather than\ndefaulted, because \"Select\" tells the reader nothing they did not already assume.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          },
          "statusLabel": {
            "name": "statusLabel",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/PickerDialog.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-pickerdialog--default",
          "name": "Default",
          "snippet": "const Default = () => <PickerDialog\n    ariaLabel=\"Apply branch\"\n    closeLabel=\"Close apply branch picker\"\n    nothingFoundLabel=\"No available branches found\"\n    nothingToListLabel=\"Nothing left to apply\"\n    placeholder=\"Search for branches to apply…\"\n    selectLabel=\"Apply branch\"\n    getItemKey={(branch) => (branch as Branch).ref}\n    getItemLabel={(branch) => (branch as Branch).name}\n    getItemType={(branch) => (branch as Branch).updated}\n    items={[\n        {\n            value: \"Local\",\n            items: [\n                { ref: \"refs/heads/toolbox-gap\", name: \"toolbox-gap\", updated: \"2 hours ago\" },\n                { ref: \"refs/heads/design-pages\", name: \"design-pages\", updated: \"yesterday\" },\n                { ref: \"refs/heads/panel-behind\", name: \"panel-behind\", updated: \"3 days ago\" },\n            ],\n        },\n        {\n            value: \"origin\",\n            items: [\n                { ref: \"refs/remotes/origin/askpass-modal\", name: \"askpass-modal\", updated: \"last week\" },\n                {\n                    ref: \"refs/remotes/origin/hunk-separators\",\n                    name: \"hunk-separators\",\n                    updated: \"2 weeks ago\",\n                },\n            ],\n        },\n    ]}\n    open\n    onOpenChange={() => {}}\n    onSelectItem={() => {}} />;",
          "description": "Grouped items, filtered as you type; Enter runs the named action on the highlighted one."
        },
        {
          "id": "components-pickerdialog--command-palette",
          "name": "Command Palette",
          "snippet": "const CommandPalette = function CommandPalette() {\n    const [open, setOpen] = useState(true);\n\n    return (\n        <>\n            <Button onClick={() => setOpen(true)}>Open command palette</Button>\n            <PickerDialog<Command>\n                ariaLabel=\"Command palette\"\n                closeLabel=\"Close command palette\"\n                nothingFoundLabel=\"No hotkeys found\"\n                nothingToListLabel=\"No hotkeys to show\"\n                getItemKey={(command) => command.id}\n                getItemLabel={(command) => command.name}\n                getItemType={(command) => <Kbd hotkey={command.hotkey} />}\n                itemToStringValue={(command) => `${command.group}: ${command.name}`}\n                items={commands}\n                open={open}\n                onOpenChange={setOpen}\n                onSelectItem={() => setOpen(false)}\n                placeholder=\"Search hotkeys…\"\n                selectLabel=\"Run\"\n            />\n        </>\n    );\n};",
          "description": "The command palette: `PickerDialog`, opened from a hotkey rather than a trigger, over the whole\nwindow. Rows are grouped, each shows its hotkey where a picker shows an item's type, and Enter\nruns the highlighted one — `selectLabel` names that act in the footer."
        },
        {
          "id": "components-pickerdialog--nothing-to-list",
          "name": "Nothing To List",
          "snippet": "const NothingToList = () => <PickerDialog\n    ariaLabel=\"Apply branch\"\n    closeLabel=\"Close apply branch picker\"\n    nothingFoundLabel=\"No available branches found\"\n    nothingToListLabel=\"Nothing left to apply\"\n    placeholder=\"Search for branches to apply…\"\n    selectLabel=\"Apply branch\"\n    getItemKey={(branch) => (branch as Branch).ref}\n    getItemLabel={(branch) => (branch as Branch).name}\n    getItemType={(branch) => (branch as Branch).updated}\n    items={[]}\n    open\n    onOpenChange={() => {}}\n    onSelectItem={() => {}} />;",
          "description": "Nothing in the list before anything was typed."
        }
      ],
      "import": "import { Button, Kbd } from '@gitbutler/ui-react';\nimport { PickerDialog } from '@gitbutler/ui-react/PickerDialog.tsx';"
    },
    "components-popup": {
      "id": "components-popup",
      "name": "Popup",
      "path": "../../packages/ui-react/src/Popup.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Popup } from \"@gitbutler/ui-react/Popup.tsx\";"
        ]
      },
      "description": "The container every overlay in Lite is built from: modals, dropdowns and the toolbox all wear\nthis one surface. Use it directly only for something that floats without opening — a toolbox, a\nhover card. Anything that opens over the app wants {@link Modal} or {@link Dropdown}, which wrap\nthis in the Base UI primitive carrying the focus and dismissal behaviour.\n\nPass `render` where the popup has to be a list primitive's own part — a combobox owns its popup\nand cannot be handed one. `anchored` is what {@link Dropdown} adds over {@link Modal}: it grows\nout of the corner it is anchored to rather than fading in place.",
      "reactComponentMeta": {
        "displayName": "Popup",
        "exportName": "Popup",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Popup.tsx",
        "description": "The container every overlay in Lite is built from: modals, dropdowns and the toolbox all wear\nthis one surface. Use it directly only for something that floats without opening — a toolbox, a\nhover card. Anything that opens over the app wants {@link Modal} or {@link Dropdown}, which wrap\nthis in the Base UI primitive carrying the focus and dismissal behaviour.\n\nPass `render` where the popup has to be a list primitive's own part — a combobox owns its popup\nand cannot be handed one. `anchored` is what {@link Dropdown} adds over {@link Modal}: it grows\nout of the corner it is anchored to rather than fading in place.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Popup } from \"@gitbutler/ui-react/Popup.tsx\";"
          ]
        },
        "props": {
          "anchored": {
            "name": "anchored",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": {
              "value": "false"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Popup.tsx"
              }
            ]
          },
          "render": {
            "name": "render",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}> | undefined"
            },
            "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
            "defaultValue": null,
            "parent": {
              "name": "UseRenderComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/use-render/useRender.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/use-render/useRender.d.mts"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-popup--default",
          "name": "Default",
          "snippet": "const Default = () => <Popup style={{ width: 320, padding: 16 }} className=\"text-13\">All modals, dropdowns and the toolbox use this same container. A modal adds a backdrop.</Popup>;",
          "description": "The bare container — what a modal, a dropdown and the toolbox all sit in."
        },
        {
          "id": "components-popup--items",
          "name": "Items",
          "snippet": "const Items = () => <Popup style={{ width: 248 }}>\n    <PopupSection label=\"Item variants\">\n        <PopupItem>Bare label</PopupItem>\n        <PopupItem icon=\"plus\">Leading glyph</PopupItem>\n        <PopupItem trailing=\"plus\">Trailing glyph</PopupItem>\n        <PopupItem icon=\"folder-tree\" trailing=\"tick\">Both\n                            </PopupItem>\n        <PopupItem leading={<ProgramIcon program=\"vscode\" />} trailing=\"tick\">Leading image\n                            </PopupItem>\n    </PopupSection>\n    <PopupSection label=\"Shortcuts and submenus\">\n        <PopupItem kbd=\"Mod+B\">With a shortcut</PopupItem>\n        <PopupItem icon=\"branch\" trailing=\"chevron-right\">Steps further in\n                            </PopupItem>\n        <PopupItem icon=\"branch\" kbd=\"Mod+B\" trailing=\"chevron-right\">Both again\n                            </PopupItem>\n    </PopupSection>\n    <PopupSection label=\"States\">\n        <PopupItem data-highlighted>Highlighted</PopupItem>\n        <PopupItem disabled>Disabled</PopupItem>\n    </PopupSection>\n</Popup>;",
          "description": "Every combination of the row's slots, and the tint it takes from pointer or keyboard alike."
        },
        {
          "id": "components-popup--select-project",
          "name": "Select Project",
          "snippet": "const SelectProject = function SelectProject() {\n    const [open, setOpen] = useState(true);\n    const [current, setCurrent] = useState(projects[0] ?? null);\n    const [query, setQuery] = useState(\"\");\n    const deferredQuery = useDeferredValue(query);\n\n    return (\n        <Combobox.Root<Project>\n            items={projects}\n            open={open}\n            onOpenChange={setOpen}\n            value={current}\n            onValueChange={(project) => {\n                if (project === null) return;\n                setCurrent(project);\n                setOpen(false);\n            }}\n            inputValue={query}\n            onInputValueChange={setQuery}\n            itemToStringLabel={(project) => project.title}\n            itemToStringValue={(project) => project.id}\n            isItemEqualToValue={(a, b) => a.id === b.id}\n            autoHighlight\n        >\n            <Combobox.Trigger\n                aria-label={`Select project (current: ${current?.title ?? \"none\"})`}\n                render={<Button variant=\"ghost\" />}\n            >\n                <FolderIcon />\n                {current?.title}\n            </Combobox.Trigger>\n\n            <Combobox.Portal>\n                <Combobox.Positioner align=\"start\" sideOffset={4}>\n                    <Popup anchored style={{ width: 256 }} render={<Combobox.Popup />}>\n                        <PopupSearch\n                            placeholder=\"Search projects…\"\n                            aria-label=\"Search projects\"\n                            onClear={query === \"\" ? undefined : () => setQuery(\"\")}\n                            render={<Combobox.Input />}\n                        />\n                        <Combobox.Empty>\n                            <PopupEmpty\n                                query={deferredQuery}\n                                nothingFound=\"No projects found\"\n                                nothingToList=\"No projects yet\"\n                            />\n                        </Combobox.Empty>\n                        <Combobox.List>\n                            {(project: Project) => (\n                                <PopupItem\n                                    key={project.id}\n                                    icon={project.private ? \"lock\" : \"folder-tree\"}\n                                    trailing={project.id === current?.id ? \"tick\" : undefined}\n                                    render={<Combobox.Item value={project} />}\n                                >\n                                    {project.title}\n                                </PopupItem>\n                            )}\n                        </Combobox.List>\n                        <PopupSection>\n                            <PopupItem trailing=\"plus\" onClick={() => setOpen(false)}>\n                                Add local repository\n                            </PopupItem>\n                        </PopupSection>\n                    </Popup>\n                </Combobox.Positioner>\n            </Combobox.Portal>\n        </Combobox.Root>\n    );\n};",
          "description": "The project selector: a combobox anchored under the button that names the current project.\nBase UI's combobox owns its popup, input and rows, so `Popup`, `PopupSearch` and `PopupItem`\ndress those parts through `render` rather than wrapping them; `anchored` makes it open the way\nevery dropdown does. The tick marks the current project, and the action below the list is a row\nof its own section."
        },
        {
          "id": "components-popup--nothing-found",
          "name": "Nothing Found",
          "snippet": "const NothingFound = () => <Popup style={{ width: 420 }}>\n    <PopupSearch placeholder=\"Search hotkeys...\" aria-label=\"Search hotkeys\" />\n    <PopupEmpty\n        query=\"undo\"\n        nothingFound=\"No hotkeys found\"\n        nothingToList=\"No hotkeys to show\" />\n</Popup>;",
          "description": "A search that matched nothing: the block a picker's list shows in place of its rows."
        },
        {
          "id": "components-popup--nothing-to-list",
          "name": "Nothing To List",
          "snippet": "const NothingToList = () => <Popup style={{ width: 420 }}>\n    <PopupSearch\n        placeholder=\"Search for branches to apply...\"\n        aria-label=\"Search branches\" />\n    <PopupEmpty\n        query=\"\"\n        nothingFound=\"No available branches found\"\n        nothingToList=\"Nothing left to apply\" />\n</Popup>;",
          "description": "A list with nothing in it before anything was typed: the cactus and the other line, since\nnothing was searched for."
        }
      ],
      "import": "import {\n  Button,\n  FolderIcon,\n  PopupEmpty,\n  PopupItem,\n  PopupSearch,\n  PopupSection,\n  ProgramIcon,\n} from '@gitbutler/ui-react';\nimport { Combobox } from '@base-ui/react';\nimport { Popup } from '@gitbutler/ui-react/Popup.tsx';"
    },
    "components-profileimage": {
      "id": "components-profileimage",
      "name": "ProfileImage",
      "path": "../../packages/ui-react/src/ProfileImage.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { ProfileImage } from \"@gitbutler/ui-react/ProfileImage.tsx\";"
        ]
      },
      "description": "The account's own picture, and the control that changes it: clicking it picks an image\nfile, and with a picture set, hovering offers a remove button in its corner. It holds no\nstate and uploads nothing; the host gets the chosen file and decides what to do with it.\n\nWithout a picture it shows the account's Gravatar photo, else the account's glitch, the\none `Avatar` draws, which also shows while a picture loads. On the glitch alone the camera\nalways shows; over either, a dark wash comes on hover, the camera on it.",
      "reactComponentMeta": {
        "displayName": "ProfileImage",
        "exportName": "ProfileImage",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/ProfileImage.tsx",
        "description": "The account's own picture, and the control that changes it: clicking it picks an image\nfile, and with a picture set, hovering offers a remove button in its corner. It holds no\nstate and uploads nothing; the host gets the chosen file and decides what to do with it.\n\nWithout a picture it shows the account's Gravatar photo, else the account's glitch, the\none `Avatar` draws, which also shows while a picture loads. On the glitch alone the camera\nalways shows; over either, a dark wash comes on hover, the camera on it.",
        "jsDocTags": {
          "import": [
            "import { ProfileImage } from \"@gitbutler/ui-react/ProfileImage.tsx\";"
          ]
        },
        "props": {
          "src": {
            "name": "src",
            "required": true,
            "type": {
              "name": "string | null | undefined"
            },
            "description": "The picture to show; without one, the Gravatar photo or the colour.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ProfileImage.tsx"
              }
            ]
          },
          "seed": {
            "name": "seed",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "Who this is: an email finds their Gravatar, and either picks the colour.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ProfileImage.tsx"
              }
            ]
          },
          "onChoose": {
            "name": "onChoose",
            "required": true,
            "type": {
              "name": "(file: File) => void"
            },
            "description": "A file the person chose.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ProfileImage.tsx"
              }
            ]
          },
          "onRemove": {
            "name": "onRemove",
            "required": false,
            "type": {
              "name": "() => void"
            },
            "description": "Removes the picture. Without it, or without a picture, there is no remove button.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ProfileImage.tsx"
              }
            ]
          },
          "accept": {
            "name": "accept",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The image types the picker offers.",
            "defaultValue": {
              "value": "\"image/png,image/jpeg\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ProfileImage.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ProfileImage.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-profileimage--default",
          "name": "Default",
          "snippet": "const Default = () => <ProfileImage src={null} seed=\"PavelLaptev\" onChoose={() => {}} />;",
          "description": "No picture and no Gravatar: the account's glitch, with the camera on it."
        },
        {
          "id": "components-profileimage--accounts",
          "name": "Accounts",
          "snippet": "const Accounts = (args) => (\n    <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 16, maxWidth: 400 }}>\n        {[\n            \"krlvi\",\n            \"schacon\",\n            \"Caleb-T-Owens\",\n            \"mtsgrd\",\n            \"slarse\",\n            \"samhh\",\n            \"estib-vega\",\n            \"PavelLaptev\",\n        ].map((login) => (\n            <ProfileImage key={login} {...args} seed={login} />\n        ))}\n    </div>\n);",
          "description": "Each account gets its own colour and glitch, the same one every time."
        },
        {
          "id": "components-profileimage--picture",
          "name": "Picture",
          "snippet": "const Picture = () => <ProfileImage\n    src=\"https://avatars.githubusercontent.com/u/7453394?v=4\"\n    seed=\"PavelLaptev\"\n    onChoose={() => {}} />;",
          "description": "A picture, with the camera washed over it on hover."
        },
        {
          "id": "components-profileimage--removable",
          "name": "Removable",
          "snippet": "const Removable = () => <ProfileImage\n    src=\"https://avatars.githubusercontent.com/u/7453394?v=4\"\n    seed=\"PavelLaptev\"\n    onChoose={() => {}}\n    onRemove={() => {}} />;",
          "description": "A picture the host can remove: the corner button shows with the camera."
        },
        {
          "id": "components-profileimage--broken",
          "name": "Broken",
          "snippet": "const Broken = () => <ProfileImage\n    src=\"https://example.invalid/missing.png\"\n    seed=\"PavelLaptev\"\n    onChoose={() => {}} />;",
          "description": "A picture that fails to load: the glitch takes its place, not a broken image."
        }
      ],
      "import": "import { ProfileImage } from '@gitbutler/ui-react/ProfileImage.tsx';"
    },
    "components-programicon": {
      "id": "components-programicon",
      "name": "ProgramIcon",
      "path": "../../packages/ui-react/src/ProgramIcon.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { ProgramIcon } from \"@gitbutler/ui-react/ProgramIcon.tsx\";"
        ]
      },
      "description": "The mark of an editor or terminal, for a control that names one. Renders nothing for a\nprogram without a mark — a user-configured editor, a terminal the library has not drawn —\nso a caller can place it unconditionally and let the text carry the name alone.",
      "reactComponentMeta": {
        "displayName": "ProgramIcon",
        "exportName": "ProgramIcon",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/ProgramIcon.tsx",
        "description": "The mark of an editor or terminal, for a control that names one. Renders nothing for a\nprogram without a mark — a user-configured editor, a terminal the library has not drawn —\nso a caller can place it unconditionally and let the text carry the name alone.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { ProgramIcon } from \"@gitbutler/ui-react/ProgramIcon.tsx\";"
          ]
        },
        "props": {
          "program": {
            "name": "program",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "The identifier the backend lists the program under: `vscode`, `warp`, `iterm2`.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ProgramIcon.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ProgramIcon.tsx"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "Width and height in px.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ProgramIcon.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ProgramIcon.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-programicon--default",
          "name": "Default",
          "snippet": "const Default = () => <ProgramIcon program=\"vscode\" size={14} />;",
          "description": "One mark, at the size the controls set."
        },
        {
          "id": "components-programicon--all-programs",
          "name": "All Programs",
          "snippet": "const AllPrograms = (args) => (\n    <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 16, padding: 24 }}>\n        {programs.map((program) => (\n            <div\n                key={program}\n                className=\"text-11\"\n                style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"center\", gap: 6 }}\n            >\n                <ProgramIcon program={program} size={args.size} />\n                <span>{program}</span>\n            </div>\n        ))}\n    </div>\n);",
          "description": "Every mark the library has drawn, at the size a select's slot renders it."
        }
      ],
      "import": "import { ProgramIcon } from '@gitbutler/ui-react/ProgramIcon.tsx';"
    },
    "components-radio": {
      "id": "components-radio",
      "name": "Radio",
      "path": "../../packages/ui-react/src/Radio.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Radio } from \"@gitbutler/ui-react/Radio.tsx\";"
        ]
      },
      "description": "One choice among several that exclude each other. Radios go in Base UI's `RadioGroup`, which\nholds the value; each radio takes the `value` it stands for.\n\nReach for one rarely: two or three short options read better as a `ToggleGroup`, and a long\nlist as a popup with a tick on the current choice.",
      "reactComponentMeta": {
        "displayName": "Radio",
        "exportName": "Radio",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Radio.tsx",
        "description": "One choice among several that exclude each other. Radios go in Base UI's `RadioGroup`, which\nholds the value; each radio takes the `value` it stands for.\n\nReach for one rarely: two or three short options read better as a `ToggleGroup`, and a long\nlist as a popup with a tick on the current choice.",
        "jsDocTags": {
          "import": [
            "import { Radio } from \"@gitbutler/ui-react/Radio.tsx\";"
          ]
        },
        "props": {
          "style": {
            "name": "style",
            "required": false,
            "type": {
              "name": "CSSProperties | ((state: RadioRootState) => CSSProperties | undefined) | undefined"
            },
            "description": "Style applied to the element, or a function that\nreturns a style object based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "render": {
            "name": "render",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, RadioRootState> | undefined"
            },
            "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string | ((state: RadioRootState) => string | undefined) | undefined"
            },
            "description": "CSS class applied to the element, or a function that\nreturns a class based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the component should ignore user interaction.",
            "defaultValue": null,
            "parent": {
              "name": "RadioRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
            },
            "declarations": [
              {
                "name": "RadioRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
              }
            ]
          },
          "value": {
            "name": "value",
            "required": true,
            "type": {
              "name": "unknown"
            },
            "description": "The unique identifying value of the radio in a group.",
            "defaultValue": null,
            "parent": {
              "name": "RadioRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
            },
            "declarations": [
              {
                "name": "RadioRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
              }
            ]
          },
          "nativeButton": {
            "name": "nativeButton",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the component renders a native `<button>` element when replacing it\nvia the `render` prop.\nSet to `true` if the rendered element is a native button.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "NonNativeButtonProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "NonNativeButtonProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "readOnly": {
            "name": "readOnly",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the user should be unable to select the radio button.",
            "defaultValue": null,
            "parent": {
              "name": "RadioRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
            },
            "declarations": [
              {
                "name": "RadioRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
              }
            ]
          },
          "required": {
            "name": "required",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the user must choose a value before submitting a form.",
            "defaultValue": null,
            "parent": {
              "name": "RadioRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
            },
            "declarations": [
              {
                "name": "RadioRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
              }
            ]
          },
          "inputRef": {
            "name": "inputRef",
            "required": false,
            "type": {
              "name": "Ref<HTMLInputElement> | undefined"
            },
            "description": "A ref to access the hidden input element.",
            "defaultValue": null,
            "parent": {
              "name": "RadioRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
            },
            "declarations": [
              {
                "name": "RadioRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/radio/root/RadioRoot.d.mts"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-radio--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <RadioGroup\n        defaultValue=\"Merge\"\n        aria-label=\"Merge method\"\n        style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}\n    >\n        {options.map((option) => (\n            <label\n                key={option}\n                className=\"text-13\"\n                style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}\n            >\n                <Radio value={option} />\n                {option}\n            </label>\n        ))}\n    </RadioGroup>\n);",
          "description": "Radios in Base UI's `RadioGroup`, each with its label sharing the hit area."
        },
        {
          "id": "components-radio--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => (\n    <RadioGroup\n        defaultValue=\"on\"\n        disabled\n        aria-label=\"Disabled\"\n        style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}\n    >\n        <Radio value=\"on\" aria-label=\"Checked\" />\n        <Radio value=\"off\" aria-label=\"Unchecked\" />\n    </RadioGroup>\n);"
        }
      ],
      "import": "import { Radio } from '@gitbutler/ui-react/Radio.tsx';\nimport { RadioGroup } from '@base-ui/react';"
    },
    "components-range": {
      "id": "components-range",
      "name": "Range",
      "path": "../../packages/ui-react/src/Range.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Range } from \"@gitbutler/ui-react/Range.tsx\";"
        ]
      },
      "description": "A number the user finds by feel rather than by typing: an opacity, a scale, a limit on a\nbounded scale. The thumb rides a hairline track and the part below it fills in gray, so the\nvalue reads as a proportion before it reads as a number; the number itself sits in the header\nbeside the label. Give it a pair of values and it grows a second thumb, for a span rather than\na point, and give it `marks` for a scale under the track.\n\nThe thumb is inset so it sits inside the track at either end rather than hanging over it, the\nway ⚛️ Core draws it. Under the pointer it widens and grows a grip, and the drag cursor\ntakes over while it is held (see design/foundations/cursors.md).\n\nFor a number the user knows and would rather type or nudge — a font size, a tab width — reach\nfor {@link NumberField }.",
      "reactComponentMeta": {
        "displayName": "Range",
        "exportName": "Range",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Range.tsx",
        "description": "A number the user finds by feel rather than by typing: an opacity, a scale, a limit on a\nbounded scale. The thumb rides a hairline track and the part below it fills in gray, so the\nvalue reads as a proportion before it reads as a number; the number itself sits in the header\nbeside the label. Give it a pair of values and it grows a second thumb, for a span rather than\na point, and give it `marks` for a scale under the track.\n\nThe thumb is inset so it sits inside the track at either end rather than hanging over it, the\nway ⚛️ Core draws it. Under the pointer it widens and grows a grip, and the drag cursor\ntakes over while it is held (see design/foundations/cursors.md).\n\nFor a number the user knows and would rather type or nudge — a font size, a tab width — reach\nfor {@link NumberField }.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Range } from \"@gitbutler/ui-react/Range.tsx\";"
          ]
        },
        "props": {
          "label": {
            "name": "label",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "The field's label, above the control, with the current value reading at the other end of\nthe same line. Omit for a range the surface labels some other way, and give it an\n`aria-label` instead; the value then goes unshown.",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "value": {
            "name": "value",
            "required": false,
            "type": {
              "name": "Value"
            },
            "description": "One number, or a pair for a span with a thumb at each end. Omit to leave the range\nuncontrolled.",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "defaultValue": {
            "name": "defaultValue",
            "required": false,
            "type": {
              "name": "Value"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "onValueChange": {
            "name": "onValueChange",
            "required": false,
            "type": {
              "name": "(value: Value extends number ? number : Value) => void"
            },
            "description": "Fires on every change: each step of a drag, each arrow key.",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "onValueCommitted": {
            "name": "onValueCommitted",
            "required": false,
            "type": {
              "name": "(value: Value extends number ? number : Value) => void"
            },
            "description": "Fires once the user is done: on release of a drag, on a press of the track, with each arrow\nkey. For a setting that should be written then rather than on every step.",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "min": {
            "name": "min",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": {
              "value": "0"
            },
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "max": {
            "name": "max",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": {
              "value": "100"
            },
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "step": {
            "name": "step",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "What one arrow key adds, and where the thumb snaps to under a drag. Shift steps by `largeStep`.",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "largeStep": {
            "name": "largeStep",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "marks": {
            "name": "marks",
            "required": false,
            "type": {
              "name": "readonly RangeMark[]"
            },
            "description": "Values to write under the track as a scale, each centred on where the thumb sits at that\nvalue. For a range whose stops the user should be able to read off without dragging to\nthem. A mark with a `label` shows that in place of its number.",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "format": {
            "name": "format",
            "required": false,
            "type": {
              "name": "NumberFormatOptions"
            },
            "description": "How the value reads in the header and on the scale — a unit, a fraction.",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "name": {
            "name": "name",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Identifies the field when a form is submitted.",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "style": {
            "name": "style",
            "required": false,
            "type": {
              "name": "CSSProperties"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          },
          "aria-label": {
            "name": "aria-label",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "RangeProps",
              "fileName": "../../packages/ui-react/src/Range.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Range.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-range--default",
          "name": "Default",
          "snippet": "const Default = () => <Range label=\"Label\" defaultValue={50} style={{ width: 170 }} />;",
          "description": "The label at one end of the header and the value at the other; the fill reads the value as a\nproportion before the number does."
        },
        {
          "id": "components-range--span",
          "name": "Span",
          "snippet": "const Span = () => <Range label=\"Range\" defaultValue={[15, 55]} style={{ width: 170 }} />;",
          "description": "A pair of values grows a second thumb, and the fill runs between the two."
        },
        {
          "id": "components-range--with-marks",
          "name": "With Marks",
          "snippet": "const WithMarks = () => <Range\n    label=\"Label\"\n    defaultValue={80}\n    style={{ width: 170 }}\n    marks={[0, 20, 40, 60, 80, 100]} />;",
          "description": "A scale under the track, each mark centred on where the thumb sits at that value."
        },
        {
          "id": "components-range--labelled-marks",
          "name": "Labelled Marks",
          "snippet": "const LabelledMarks = () => <Range\n    label={undefined}\n    defaultValue={2}\n    style={{ width: 400 }}\n    aria-label=\"Auto-fetch frequency\"\n    min={0}\n    max={5}\n    step={1}\n    marks={[\n        { value: 0, label: \"Off\" },\n        { value: 1, label: \"5min\" },\n        { value: 2, label: \"15min\" },\n        { value: 3, label: \"30min\" },\n        { value: 4, label: \"1h\" },\n        { value: 5, label: \"2h\" },\n    ]} />;",
          "description": "Marks with labels, for stops whose numbers alone wouldn't say what they mean: here each step\nof the range stands for a duration, and the first for none at all."
        },
        {
          "id": "components-range--stepped",
          "name": "Stepped",
          "snippet": "const Stepped = () => <Range\n    label=\"Opacity\"\n    defaultValue={0.6}\n    style={{ width: 170 }}\n    min={0}\n    max={1}\n    step={0.1}\n    format={{ style: \"percent\" }} />;",
          "description": "Steps snap the thumb, and the format gives the value its unit."
        },
        {
          "id": "components-range--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => <Range label=\"Label\" defaultValue={50} style={{ width: 170 }} disabled />;"
        },
        {
          "id": "components-range--unlabelled",
          "name": "Unlabelled",
          "snippet": "const Unlabelled = () => <Range\n    label={undefined}\n    defaultValue={50}\n    style={{ width: 170 }}\n    aria-label=\"Label\" />;",
          "description": "Without a header, for a range the surface already names — a row in a settings table."
        }
      ],
      "import": "import { Range } from '@gitbutler/ui-react/Range.tsx';"
    },
    "components-relativetime": {
      "id": "components-relativetime",
      "name": "RelativeTime",
      "path": "../../packages/ui-react/src/RelativeTime.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { RelativeTime } from \"@gitbutler/ui-react/RelativeTime.tsx\";"
        ]
      },
      "description": "A relative timestamp whose hover tooltip carries the absolute time.",
      "reactComponentMeta": {
        "displayName": "RelativeTime",
        "exportName": "RelativeTime",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/RelativeTime.tsx",
        "description": "A relative timestamp whose hover tooltip carries the absolute time.",
        "jsDocTags": {
          "import": [
            "import { RelativeTime } from \"@gitbutler/ui-react/RelativeTime.tsx\";"
          ]
        },
        "props": {
          "timestamp": {
            "name": "timestamp",
            "required": true,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/RelativeTime.tsx"
              }
            ]
          },
          "now": {
            "name": "now",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "Pin \"now\" for stable output across re-renders, as the row lists do.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/RelativeTime.tsx"
              }
            ]
          },
          "compact": {
            "name": "compact",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "\"26m\" instead of \"26 minutes ago\", for dense rows.",
            "defaultValue": {
              "value": "false"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/RelativeTime.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/RelativeTime.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-relativetime--default",
          "name": "Default",
          "snippet": "const Default = () => <RelativeTime\n    timestamp={now - 26 * minute}\n    now={Date.parse(\"2026-08-29T12:00:00Z\")}\n    compact={false} />;",
          "description": "Hover it for the absolute time.",
          "warning": "Incomplete snippet: `now`, `minute` could not be resolved statically."
        },
        {
          "id": "components-relativetime--compact",
          "name": "Compact",
          "snippet": "const Compact = () => <RelativeTime\n    timestamp={now - 26 * minute}\n    now={Date.parse(\"2026-08-29T12:00:00Z\")}\n    compact />;",
          "description": "The tightest reading, for dense rows.",
          "warning": "Incomplete snippet: `now`, `minute` could not be resolved statically."
        },
        {
          "id": "components-relativetime--ages",
          "name": "Ages",
          "snippet": "const Ages = () => (\n    <div\n        className=\"text-13\"\n        style={{\n            display: \"grid\",\n            gridTemplateColumns: \"repeat(3, auto)\",\n            gap: \"8px 24px\",\n            width: \"fit-content\",\n        }}\n    >\n        {ages.map(([label, age]) => (\n            <div key={label} style={{ display: \"contents\" }}>\n                <span style={{ color: \"var(--text-2)\" }}>{label}</span>\n                <RelativeTime timestamp={now - age} now={now} />\n                <RelativeTime timestamp={now - age} now={now} compact />\n            </div>\n        ))}\n    </div>\n);",
          "description": "Every unit it steps through, in the full and the compact reading.",
          "warning": "Incomplete snippet: `now`, `minute` could not be resolved statically."
        }
      ],
      "import": "import { RelativeTime } from '@gitbutler/ui-react/RelativeTime.tsx';"
    },
    "components-resizehandle": {
      "id": "components-resizehandle",
      "name": "ResizeHandle",
      "path": "../../packages/ui-react/src/ResizeHandle.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { ResizeHandle } from \"@gitbutler/ui-react/ResizeHandle.tsx\";"
        ]
      },
      "description": "The hairline divider between resizable panels. It picks its own axis from\nthe separator's `aria-orientation`, so the same handle works in both\nhorizontal and vertical `Group`s. `grab=\"after\"` puts the whole grab area\npast the hairline, for a previous panel whose scrollbar meets it. `gap`\ndraws no hairline: the handle is the space between panels set apart as\ncards, and shows a short grip on hover that darkens and grows while\ndragged.",
      "reactComponentMeta": {
        "displayName": "ResizeHandle",
        "exportName": "ResizeHandle",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/ResizeHandle.tsx",
        "description": "The hairline divider between resizable panels. It picks its own axis from\nthe separator's `aria-orientation`, so the same handle works in both\nhorizontal and vertical `Group`s. `grab=\"after\"` puts the whole grab area\npast the hairline, for a previous panel whose scrollbar meets it. `gap`\ndraws no hairline: the handle is the space between panels set apart as\ncards, and shows a short grip on hover that darkens and grows while\ndragged.",
        "jsDocTags": {
          "import": [
            "import { ResizeHandle } from \"@gitbutler/ui-react/ResizeHandle.tsx\";"
          ]
        },
        "props": {
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "When disabled, the separator cannot be used to resize its neighboring panels.\r\n\r\nℹ️ The panels may still be resized indirectly (while other panels are being resized).\r\nTo prevent a panel from being resized at all, it needs to also be disabled.",
            "defaultValue": null,
            "parent": {
              "name": "SeparatorProps",
              "fileName": "../../node_modules/.pnpm/react-resizable-panels@4.11.2_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-resizable-panels/dist/react-resizable-panels.d.ts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/react-resizable-panels@4.11.2_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-resizable-panels/dist/react-resizable-panels.d.ts"
              }
            ]
          },
          "disableDoubleClick": {
            "name": "disableDoubleClick",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "When true, double-clicking this `Separator` will not reset its `Panel` to its default size.",
            "defaultValue": null,
            "parent": {
              "name": "SeparatorProps",
              "fileName": "../../node_modules/.pnpm/react-resizable-panels@4.11.2_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-resizable-panels/dist/react-resizable-panels.d.ts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/react-resizable-panels@4.11.2_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-resizable-panels/dist/react-resizable-panels.d.ts"
              }
            ]
          },
          "elementRef": {
            "name": "elementRef",
            "required": false,
            "type": {
              "name": "Ref<HTMLDivElement> | undefined"
            },
            "description": "Ref attached to the root `HTMLDivElement`.",
            "defaultValue": null,
            "parent": {
              "name": "SeparatorProps",
              "fileName": "../../node_modules/.pnpm/react-resizable-panels@4.11.2_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-resizable-panels/dist/react-resizable-panels.d.ts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/react-resizable-panels@4.11.2_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-resizable-panels/dist/react-resizable-panels.d.ts"
              }
            ]
          },
          "grab": {
            "name": "grab",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"after\"",
              "value": [
                {
                  "value": "\"after\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ResizeHandle.tsx"
              }
            ]
          },
          "gap": {
            "name": "gap",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ResizeHandle.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-resizehandle--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <Group orientation=\"horizontal\" style={{ height: 240, border: \"1px solid var(--border-2)\" }}>\n        <Panel minSize={80}>\n            <Pane label=\"Sidebar\" />\n        </Panel>\n        <ResizeHandle />\n        <Panel minSize={80}>\n            <Pane label=\"Details\" />\n        </Panel>\n    </Group>\n);",
          "description": "Between two side-by-side panels. Drag the hairline to resize them."
        },
        {
          "id": "components-resizehandle--vertical",
          "name": "Vertical",
          "snippet": "const Vertical = () => (\n    <Group orientation=\"vertical\" style={{ height: 320, border: \"1px solid var(--border-2)\" }}>\n        <Panel minSize={60}>\n            <Pane label=\"Diff\" />\n        </Panel>\n        <ResizeHandle />\n        <Panel minSize={60}>\n            <Pane label=\"Comments\" />\n        </Panel>\n    </Group>\n);",
          "description": "The same handle between stacked panels; it takes its axis from the group."
        },
        {
          "id": "components-resizehandle--grab-after",
          "name": "Grab After",
          "snippet": "const GrabAfter = () => (\n    <Group orientation=\"horizontal\" style={{ height: 240, border: \"1px solid var(--border-2)\" }}>\n        <Panel minSize={80}>\n            <Pane label=\"Sidebar\" />\n        </Panel>\n        <ResizeHandle grab=\"after\" />\n        <Panel minSize={80}>\n            <Pane label=\"Details\" />\n        </Panel>\n    </Group>\n);",
          "description": "`grab=\"after\"` puts the whole grab area past the hairline, so a scrollbar at the edge of the\npanel before it stays reachable."
        },
        {
          "id": "components-resizehandle--gap",
          "name": "Gap",
          "snippet": "const Gap = () => (\n    <Group\n        orientation=\"horizontal\"\n        resizeTargetMinimumSize={{ coarse: 1, fine: 1 }}\n        style={{ height: 240, padding: 6, background: \"var(--bg-2)\" }}\n    >\n        <Panel minSize={80} style={card}>\n            <Pane label=\"Sidebar\" />\n        </Panel>\n        <ResizeHandle gap />\n        <Panel minSize={80} style={card}>\n            <Pane label=\"Details\" />\n        </Panel>\n    </Group>\n);",
          "description": "`gap` separates panels drawn as cards: the space between them is the grab area, and a short\ngrip shows on hover, and darkens and grows while dragged."
        }
      ],
      "import": "import { Group, Panel } from 'react-resizable-panels';\nimport { ResizeHandle } from '@gitbutler/ui-react/ResizeHandle.tsx';"
    },
    "components-scrollarea": {
      "id": "components-scrollarea",
      "name": "ScrollArea",
      "path": "../../packages/ui-react/src/ScrollArea.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { ScrollArea } from \"@gitbutler/ui-react/ScrollArea.tsx\";"
        ]
      },
      "description": "A pane's scroll container, with a thin scrollbar drawn over the content rather than a gutter\nbeside it. The thumb shows while the area is scrolled or under the pointer, and fades away at\nrest.\n\nTwo elements, so their classes go to the right one: `className` places the area in the layout\nthat holds it (its growth, its height, a border), and `viewportClassName` lays out what scrolls\ninside it (a flex column, padding). The viewport is the element that scrolls: give a virtualizer,\nor anything that measures or restores scrolling, `viewportRef`.\n\n`separator` draws a hairline across the top while the content is scrolled down, so the rows\npassing under a sticky header read as passing under it.",
      "reactComponentMeta": {
        "displayName": "ScrollArea",
        "exportName": "ScrollArea",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/ScrollArea.tsx",
        "description": "A pane's scroll container, with a thin scrollbar drawn over the content rather than a gutter\nbeside it. The thumb shows while the area is scrolled or under the pointer, and fades away at\nrest.\n\nTwo elements, so their classes go to the right one: `className` places the area in the layout\nthat holds it (its growth, its height, a border), and `viewportClassName` lays out what scrolls\ninside it (a flex column, padding). The viewport is the element that scrolls: give a virtualizer,\nor anything that measures or restores scrolling, `viewportRef`.\n\n`separator` draws a hairline across the top while the content is scrolled down, so the rows\npassing under a sticky header read as passing under it.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { ScrollArea } from \"@gitbutler/ui-react/ScrollArea.tsx\";"
          ]
        },
        "props": {
          "viewportClassName": {
            "name": "viewportClassName",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ScrollArea.tsx"
              }
            ]
          },
          "viewportRef": {
            "name": "viewportRef",
            "required": false,
            "type": {
              "name": "Ref<HTMLDivElement> | undefined"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ScrollArea.tsx"
              }
            ]
          },
          "separator": {
            "name": "separator",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": {
              "value": "false"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ScrollArea.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-scrollarea--default",
          "name": "Default",
          "snippet": "const Default = () => <ScrollArea\n    separator={false}\n    style={{ height: 240, width: 280, border: \"1px solid var(--border-2)\" }}>\n    {rows.map((row) => (\n        <div key={row} className=\"text-13\" style={{ padding: \"6px 12px\" }}>\n            {row}\n        </div>\n    ))}\n</ScrollArea>;",
          "description": "A pane shorter than its content: the thumb shows while it scrolls or is pointed at."
        },
        {
          "id": "components-scrollarea--with-separator",
          "name": "With Separator",
          "snippet": "const WithSeparator = () => <div\n    style={{\n        display: \"flex\",\n        flexDirection: \"column\",\n        height: 280,\n        width: 280,\n        border: \"1px solid var(--border-2)\",\n    }}>\n    <div className=\"text-13 text-bold\" style={{ padding: \"10px 12px\" }}>Changes\n                    </div>\n    <ScrollArea separator style={{ flexGrow: 1 }}>\n        {rows.map((row) => (\n            <div key={row} className=\"text-13\" style={{ padding: \"6px 12px\" }}>\n                {row}\n            </div>\n        ))}\n    </ScrollArea>\n</div>;",
          "description": "With `separator`, a hairline crosses the top once the content is scrolled down, so the rows read\nas passing under the header above."
        },
        {
          "id": "components-scrollarea--on-another-scroller",
          "name": "On Another Scroller",
          "snippet": "const OnAnotherScroller = function OnAnotherScroller() {\n    const [scroller, setScroller] = useState<HTMLDivElement | null>(null);\n    return (\n        <div\n            style={{\n                display: \"grid\",\n                position: \"relative\",\n                height: 240,\n                width: 280,\n                border: \"1px solid var(--border-2)\",\n            }}\n        >\n            <div ref={setScroller} style={{ overflow: \"auto\", scrollbarWidth: \"none\" }}>\n                {rows.map((row) => (\n                    <div key={row} className=\"text-13\" style={{ padding: \"6px 12px\" }}>\n                        {row}\n                    </div>\n                ))}\n            </div>\n            <ScrollBars scrollElement={scroller} />\n        </div>\n    );\n};",
          "description": "`ScrollBars` over a scroller the app doesn't render itself, as the diff view's: the scroller\nhides its native scrollbar and hands its element over, and the bars sit beside it in a box it\nfills."
        }
      ],
      "import": "import { ScrollArea } from '@gitbutler/ui-react/ScrollArea.tsx';\nimport { ScrollBars } from '@gitbutler/ui-react';"
    },
    "components-select": {
      "id": "components-select",
      "name": "Select",
      "path": "../../packages/ui-react/src/Select.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Select } from \"@gitbutler/ui-react/Select.tsx\";"
        ]
      },
      "description": "One choice from a short, fixed list: a terminal, a theme, a default branch. The trigger is a\nfield-sized outline button reading the current choice, led by that choice's icon or image if\nit has one, and the list it opens is the same {@link Popup} every dropdown wears, with a tick\non the row that is chosen now.\n\nThe list opens over the trigger so the chosen row sits where the trigger's text was, the way\na native select does; Base UI drops that overlap when the window has no room for it. Each row's\ntext is wrapped in Base UI's ItemText part, which is what the overlap measures against — a row\nwithout it leaves the list to open plainly below the trigger.\n\nA list too long to scan takes `searchable`, which puts the {@link PopupSearch} row at its top\nand filters the rows as the query is typed. Underneath that is a combobox rather than a select,\ndressed the same way. For a list whose rows are not `{ value, label }` pairs — a branch, a\ncommit target — reach for the combobox directly instead.",
      "reactComponentMeta": {
        "displayName": "Select",
        "exportName": "Select",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Select.tsx",
        "description": "One choice from a short, fixed list: a terminal, a theme, a default branch. The trigger is a\nfield-sized outline button reading the current choice, led by that choice's icon or image if\nit has one, and the list it opens is the same {@link Popup} every dropdown wears, with a tick\non the row that is chosen now.\n\nThe list opens over the trigger so the chosen row sits where the trigger's text was, the way\na native select does; Base UI drops that overlap when the window has no room for it. Each row's\ntext is wrapped in Base UI's ItemText part, which is what the overlap measures against — a row\nwithout it leaves the list to open plainly below the trigger.\n\nA list too long to scan takes `searchable`, which puts the {@link PopupSearch} row at its top\nand filters the rows as the query is typed. Underneath that is a combobox rather than a select,\ndressed the same way. For a list whose rows are not `{ value, label }` pairs — a branch, a\ncommit target — reach for the combobox directly instead.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Select } from \"@gitbutler/ui-react/Select.tsx\";"
          ]
        },
        "props": {
          "items": {
            "name": "items",
            "required": true,
            "type": {
              "name": "readonly SelectItem<Value>[]"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "label": {
            "name": "label",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "The field's label, above the control. Omit for a select the surface labels some other way,\nand give it an `aria-label` instead.",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "placeholder": {
            "name": "placeholder",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "What the control reads while nothing is chosen. It is also the first row of the list, so the\nchoice can be cleared from the same place it was made — except in a searchable list, which\nhas no clearing row.",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "value": {
            "name": "value",
            "required": false,
            "type": {
              "name": "string | null | undefined"
            },
            "description": "Omit to leave the select uncontrolled.",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "defaultValue": {
            "name": "defaultValue",
            "required": false,
            "type": {
              "name": "string | null | undefined"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "onValueChange": {
            "name": "onValueChange",
            "required": false,
            "type": {
              "name": "(value: Value | null) => void"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "name": {
            "name": "name",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Identifies the field when a form is submitted.",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "searchable": {
            "name": "searchable",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Leads the list with the search row every other long list in Lite leads with — the branch\nand commit target pickers — and filters the rows as the query is typed. For a list too long\nto scan, such as the syntax themes. The list opens below the trigger rather than over it,\nsince the query row, not the chosen row, is what takes the trigger's place.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "searchPlaceholder": {
            "name": "searchPlaceholder",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "What the search row reads while empty.",
            "defaultValue": {
              "value": "\"Search...\""
            },
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "nothingFound": {
            "name": "nothingFound",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The line the list shows when the query matches nothing.",
            "defaultValue": {
              "value": "\"Nothing found\""
            },
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "style": {
            "name": "style",
            "required": false,
            "type": {
              "name": "CSSProperties"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          },
          "aria-label": {
            "name": "aria-label",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "SelectProps",
              "fileName": "../../packages/ui-react/src/Select.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Select.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-select--default",
          "name": "Default",
          "snippet": "const Default = () => <Select\n    items={[\n        { value: \"terminal\", label: \"Terminal\" },\n        { value: \"warp\", label: \"Warp\" },\n        { value: \"ghostty\", label: \"Ghostty\" },\n        { value: \"iterm2\", label: \"iTerm2\" },\n    ]}\n    label=\"Terminal\"\n    placeholder=\"Select terminal\"\n    style={{ width: 170 }} />;",
          "description": "Nothing chosen yet: the trigger reads the placeholder, and the list opens with it as its first row."
        },
        {
          "id": "components-select--with-value",
          "name": "With Value",
          "snippet": "const WithValue = () => <Select\n    items={[\n        { value: \"terminal\", label: \"Terminal\" },\n        { value: \"warp\", label: \"Warp\" },\n        { value: \"ghostty\", label: \"Ghostty\" },\n        { value: \"iterm2\", label: \"iTerm2\" },\n    ]}\n    label=\"Terminal\"\n    placeholder=\"Select terminal\"\n    style={{ width: 170 }}\n    defaultValue=\"terminal\" />;",
          "description": "The chosen row is ticked, and the list opens with that row over the trigger."
        },
        {
          "id": "components-select--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => <Select\n    items={[\n        { value: \"terminal\", label: \"Terminal\" },\n        { value: \"warp\", label: \"Warp\" },\n        { value: \"ghostty\", label: \"Ghostty\" },\n        { value: \"iterm2\", label: \"iTerm2\" },\n    ]}\n    label=\"Terminal\"\n    placeholder=\"Select terminal\"\n    style={{ width: 170 }}\n    defaultValue=\"terminal\"\n    disabled />;"
        },
        {
          "id": "components-select--with-icons",
          "name": "With Icons",
          "snippet": "const WithIcons = () => <Select\n    items={[\n        { value: \"vscode\", label: \"Visual Studio Code\", icon: \"edit\" },\n        { value: \"zed\", label: \"Zed\", icon: \"edit\" },\n        { value: \"finder\", label: \"Finder\", icon: \"folder\" },\n        { value: \"workbench\", label: \"Workbench\", icon: \"workbench\", disabled: true },\n    ]}\n    label=\"Open in\"\n    placeholder=\"Select editor\"\n    style={{ width: 220 }} />;",
          "description": "A glyph on each row, for a list whose choices are of different kinds."
        },
        {
          "id": "components-select--with-images",
          "name": "With Images",
          "snippet": "const WithImages = () => <Select\n    items={terminals.map((terminal) => ({\n        ...terminal,\n        leading: <ProgramIcon program={terminal.value} />,\n    }))}\n    label=\"Terminal\"\n    placeholder=\"Select terminal\"\n    style={{ width: 170 }}\n    defaultValue=\"warp\" />;",
          "description": "A program's own mark on each row and on the trigger, for a list of editors or terminals.",
          "warning": "Incomplete snippet: `terminals` could not be resolved statically."
        },
        {
          "id": "components-select--unlabelled",
          "name": "Unlabelled",
          "snippet": "const Unlabelled = () => <Select\n    items={[\n        { value: \"terminal\", label: \"Terminal\" },\n        { value: \"warp\", label: \"Warp\" },\n        { value: \"ghostty\", label: \"Ghostty\" },\n        { value: \"iterm2\", label: \"iTerm2\" },\n    ]}\n    label={undefined}\n    placeholder=\"Select terminal\"\n    style={{ width: 170 }}\n    aria-label=\"Terminal\"\n    defaultValue=\"warp\" />;",
          "description": "Without a label of its own, for a select the surface already names — a row in a settings table."
        },
        {
          "id": "components-select--searchable",
          "name": "Searchable",
          "snippet": "const Searchable = () => <Select\n    items={[\n        \"Ayu Light\",\n        \"Catppuccin Latte\",\n        \"Everforest Light\",\n        \"GitHub Light\",\n        \"GitHub Light Default\",\n        \"GitHub Light High Contrast\",\n        \"Gruvbox Light Hard\",\n        \"Gruvbox Light Medium\",\n        \"Gruvbox Light Soft\",\n        \"Horizon Bright\",\n        \"Kanagawa Lotus\",\n        \"Light+ (VS Code)\",\n        \"Material Lighter\",\n        \"Min Light\",\n        \"One Light\",\n        \"Rosé Pine Dawn\",\n        \"Slack Ochin\",\n        \"Snazzy Light\",\n        \"Solarized Light\",\n        \"Vitesse Light\",\n    ].map((label) => ({ value: label.toLowerCase().replace(/[^a-z0-9]+/g, \"-\"), label }))}\n    label=\"Syntax theme\"\n    placeholder={undefined}\n    style={{ width: 240 }}\n    aria-label={undefined}\n    defaultValue=\"github-light-default\"\n    searchable\n    searchPlaceholder=\"Search themes...\"\n    nothingFound=\"No themes found\" />;",
          "description": "A list too long to scan leads with the search row every other long list has, and filters as\nthe query is typed."
        }
      ],
      "import": "import { ProgramIcon } from '@gitbutler/ui-react';\nimport { Select } from '@gitbutler/ui-react/Select.tsx';\nimport { ProgramIcon } from './ProgramIcon.tsx';"
    },
    "components-sidebarrow": {
      "id": "components-sidebarrow",
      "name": "BranchItem",
      "path": "../../packages/ui-react/src/SidebarRow.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { BranchItem } from \"@gitbutler/ui-react/SidebarRow.tsx\";"
        ]
      },
      "description": "A branch in the sidebar. With a pull request (`pr`), the row is the request: its state in the\nglyph and the badge, its number, and its title as `title`; without one, `title` is the branch's\nname.\n\nIts `meta` reads in one order: `CiStatus`, then ↓ `behind`, ↑ `unpushed`, `uncommitted`, and\n`commits`. Show ↑ or ⟜, never both; on an expanded branch drop ⟜, since its commits are listed\nunder it. A branch with no commits yet leads with `empty` saying \"empty\", and takes\n`folded=\"empty\"`, so its row isn't bare and lines up with the branches that fold. `actions` hold the one next step (Resolve, Update, Push, Create PR or Merge),\nthen View PR on a branch with a request.\n\nIn `rich`, an open or draft request takes two lines: its title, which wraps once and then ends in\nan ellipsis, over the branch's name (`branch`), its state and its actions. A plain branch stays\none line, its state and actions right after its name, and the name gives way first. A merged or\nclosed request is done with: one muted line in either layout.",
      "reactComponentMeta": {
        "displayName": "BranchItem",
        "exportName": "BranchItem",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/SidebarRow.tsx",
        "description": "A branch in the sidebar. With a pull request (`pr`), the row is the request: its state in the\nglyph and the badge, its number, and its title as `title`; without one, `title` is the branch's\nname.\n\nIts `meta` reads in one order: `CiStatus`, then ↓ `behind`, ↑ `unpushed`, `uncommitted`, and\n`commits`. Show ↑ or ⟜, never both; on an expanded branch drop ⟜, since its commits are listed\nunder it. A branch with no commits yet leads with `empty` saying \"empty\", and takes\n`folded=\"empty\"`, so its row isn't bare and lines up with the branches that fold. `actions` hold the one next step (Resolve, Update, Push, Create PR or Merge),\nthen View PR on a branch with a request.\n\nIn `rich`, an open or draft request takes two lines: its title, which wraps once and then ends in\nan ellipsis, over the branch's name (`branch`), its state and its actions. A plain branch stays\none line, its state and actions right after its name, and the name gives way first. A merged or\nclosed request is done with: one muted line in either layout.",
        "jsDocTags": {
          "import": [
            "import { BranchItem } from \"@gitbutler/ui-react/SidebarRow.tsx\";"
          ]
        },
        "props": {
          "title": {
            "name": "title",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              },
              {
                "name": "HTMLAttributes",
                "fileName": "../../node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/index.d.ts"
              }
            ]
          },
          "pr": {
            "name": "pr",
            "required": false,
            "type": {
              "name": "{ number: number; state: PullRequestState; }"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "branch": {
            "name": "branch",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The branch's name, under a pull request's title in `rich`.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "layout": {
            "name": "layout",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"compact\" | \"rich\"",
              "value": [
                {
                  "value": "\"compact\""
                },
                {
                  "value": "\"rich\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"compact\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "depth": {
            "name": "depth",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "How many levels the row sits below the top of the card, one guide per level.",
            "defaultValue": null,
            "parent": {
              "name": "RowProps",
              "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "folded": {
            "name": "folded",
            "required": false,
            "type": {
              "name": "boolean | \"empty\" | undefined"
            },
            "description": "Gives the row a chevron: `true` while its children are hidden. Leave it out on a leaf.\n`\"empty\"` on a row that could hold children and has none yet, such as a branch without\ncommits: a dot in the chevron's place keeps it in line with the rows that fold.",
            "defaultValue": null,
            "parent": {
              "name": "RowProps",
              "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "onToggleFolded": {
            "name": "onToggleFolded",
            "required": false,
            "type": {
              "name": "() => void"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "RowProps",
              "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "selected": {
            "name": "selected",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Selected: the quiet fill, or the solid one while the list holds the selection focus.",
            "defaultValue": null,
            "parent": {
              "name": "RowProps",
              "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "meta": {
            "name": "meta",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "`MetaCount`s and a `CiStatus`, in the order the row should read them.",
            "defaultValue": null,
            "parent": {
              "name": "RowProps",
              "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "actions": {
            "name": "actions",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "The row's next step, as small outline `Button`s: Push, Update, Create PR, View PR. In\n`compact` they take the state's place under the pointer and on keyboard focus; leave them out\nwhen there is none, and the row keeps its state there.",
            "defaultValue": null,
            "parent": {
              "name": "RowProps",
              "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "menu": {
            "name": "menu",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "The row's menu button, a small ghost icon-only `Button`. It shows under the pointer, on\nkeyboard focus and on a selected row.",
            "defaultValue": null,
            "parent": {
              "name": "RowProps",
              "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "tooltip": {
            "name": "tooltip",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "What the name stands for in full (a path, a pull request's state, a commit's author), shown\nover the name alone, so the counts beside it keep their own.",
            "defaultValue": null,
            "parent": {
              "name": "RowProps",
              "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SidebarRow.tsx"
              }
            ]
          },
          "render": {
            "name": "render",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}> | undefined"
            },
            "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
            "defaultValue": null,
            "parent": {
              "name": "UseRenderComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/use-render/useRender.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/use-render/useRender.d.mts"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-sidebarrow--default",
          "name": "Default",
          "snippet": "const Default = () => <BranchItem\n    title=\"fix: retry stalled transfers\"\n    pr={{ number: 377, state: \"open\" }}\n    branch=\"retry-transfers\"\n    layout=\"rich\"\n    depth={1}\n    folded\n    selected={false}\n    meta={\n        <>\n            <CiStatus status=\"working\" />\n            <MetaCount type=\"unpushed\">4</MetaCount>\n        </>\n    }\n    actions={\n        <>\n            {push}\n            {viewPr}\n        </>\n    }\n    menu={menu(\"Branch\")} />;",
          "description": "A branch with an open pull request. In `rich` it takes two lines: the request's title over the\nbranch's name, the checks, what is still to push, and the next step; the menu shows under the\npointer. Switch `layout` to `compact` for one line, the state at the end."
        },
        {
          "id": "components-sidebarrow--compact",
          "name": "Compact",
          "snippet": "const Compact = () => (\n    <Card label=\"pavel--macbook-pro-2\" header={machine}>\n        <Tree layout=\"compact\" />\n    </Card>\n);",
          "description": "`compact`: one line a row, its state at the end. Under the pointer, on focus and on a selected\nrow, the actions and the menu take the state's place."
        },
        {
          "id": "components-sidebarrow--rich",
          "name": "Rich",
          "snippet": "const Rich = () => (\n    <Card label=\"pavel--macbook-pro-2\" header={machine}>\n        <Tree layout=\"rich\" />\n    </Card>\n);",
          "description": "`rich`: the state and the next step stay in view. A pull request takes two lines, its title\nwrapping once under its glyph; every other row stays one line, its state and actions right after\nits name. A merged request stays one muted line."
        },
        {
          "id": "components-sidebarrow--selection",
          "name": "Selection",
          "snippet": "const Selection = () => (\n    <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 24, alignItems: \"flex-start\" }}>\n        <Card label=\"pavel--macbook-pro-2\" header={machine} focused>\n            <Tree layout=\"rich\" selected=\"commit\" />\n        </Card>\n        <Card label=\"pavel--macbook-pro-2\" header={machine}>\n            <Tree layout=\"rich\" selected=\"ios-push-handoff\" />\n        </Card>\n    </div>\n);",
          "description": "A selected row: the solid fill while the list holds the selection focus, inverting what it\nshows, and the quiet one in a list that has lost it. A selected row shows its menu, as the\npointer would."
        },
        {
          "id": "components-sidebarrow--offline-machine",
          "name": "Offline Machine",
          "snippet": "const OfflineMachine = () => (\n    <MachineItem\n        name=\"studio-desktop\"\n        online={false}\n        folded\n        icon={<img src={machinePictures[0].src} alt=\"\" width={14} height={14} />}\n        meta={\n            <>\n                <MetaCount type=\"repos\">4</MetaCount>\n                <MetaCount type=\"age\">2d</MetaCount>\n            </>\n        }\n    />\n);",
          "description": "A machine that is offline: its light goes grey and its picture dims."
        },
        {
          "id": "components-sidebarrow--uncommitted-changes",
          "name": "Uncommitted Changes",
          "snippet": "const UncommittedChanges = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 1 }}>\n        <RepoItem\n            name=\"berlin-brutalism\"\n            folded={false}\n            meta={\n                <>\n                    <MetaCount type=\"behind\">1</MetaCount>\n                    <MetaCount type=\"age\">2h</MetaCount>\n                </>\n            }\n            menu={menu(\"Repository\")}\n        />\n        <UncommittedItem count={12} depth={1} menu={menu(\"Uncommitted changes\")} />\n        <BranchItem\n            title=\"cursor-unique-names\"\n            depth={1}\n            folded\n            meta={\n                <>\n                    <MetaCount type=\"commits\">23</MetaCount>\n                    <MetaCount type=\"age\">2h</MetaCount>\n                </>\n            }\n            menu={menu(\"Branch\")}\n        />\n        <WorktreeDivider depth={0} />\n        <RepoItem name=\"but-dev\" folded={false} menu={menu(\"Repository\")} />\n        <WorktreeItem\n            name=\"review-ios\"\n            depth={1}\n            folded={false}\n            meta={\n                <>\n                    <MetaCount type=\"behind\">8</MetaCount>\n                    <MetaCount type=\"age\">40m</MetaCount>\n                </>\n            }\n            menu={menu(\"Worktree\")}\n        />\n        <UncommittedItem count={17} depth={2} selected menu={menu(\"Uncommitted changes\")} />\n        <BranchItem\n            title=\"ios-push-handoff\"\n            depth={2}\n            folded\n            meta={<MetaCount type=\"unpushed\">4</MetaCount>}\n            menu={menu(\"Branch\")}\n        />\n    </div>\n);",
          "description": "A worktree's uncommitted changes as a row of their own, first among its branches: straight under\na repository with one worktree, and under each worktree of one with several. The repository and\nthe worktree no longer carry the ± count while open; this row does, and opens the changes."
        },
        {
          "id": "components-sidebarrow--empty",
          "name": "Empty",
          "snippet": "const Empty = () => (\n    <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 24, alignItems: \"flex-start\" }}>\n        <Card label=\"pavel--macbook-pro-2\" header={machine}>\n            <Repository last>\n                <RepoItem name=\"but-dev\" folded={false} menu={menu(\"Repository\")} />\n                <UncommittedItem count={10} depth={1} menu={menu(\"Uncommitted changes\")} />\n                <BranchItem\n                    title=\"redact-remote-creds\"\n                    depth={1}\n                    folded\n                    meta={\n                        <>\n                            <MetaCount type=\"commits\">11</MetaCount>\n                            <MetaCount type=\"age\">1d</MetaCount>\n                        </>\n                    }\n                    menu={menu(\"Branch\")}\n                />\n                <BranchItem\n                    title=\"offline-cache\"\n                    depth={1}\n                    folded=\"empty\"\n                    meta={<MetaCount type=\"empty\">empty</MetaCount>}\n                    menu={menu(\"Branch\")}\n                />\n            </Repository>\n        </Card>\n        <Card label=\"pavel--macbook-pro-2\" header={machine}>\n            <Repository last>\n                <RepoItem name=\"but-dev\" folded={false} menu={menu(\"Repository\")} />\n                <WorktreeItem\n                    main\n                    name=\"Main worktree\"\n                    depth={1}\n                    folded={false}\n                    meta={<MetaCount type=\"behind\">2</MetaCount>}\n                    menu={menu(\"Worktree\")}\n                />\n                <UncommittedItem count={9} depth={2} menu={menu(\"Uncommitted changes\")} />\n                <BranchItem\n                    title=\"ios-push-handoff\"\n                    depth={2}\n                    folded\n                    meta={<MetaCount type=\"unpushed\">9</MetaCount>}\n                    menu={menu(\"Branch\")}\n                />\n                <WorktreeDivider depth={1} />\n                <WorktreeItem\n                    name=\"scratch\"\n                    depth={1}\n                    folded=\"empty\"\n                    meta={\n                        <>\n                            <MetaCount type=\"head\">detached</MetaCount>\n                            <MetaCount type=\"age\">3d</MetaCount>\n                        </>\n                    }\n                    menu={menu(\"Worktree\")}\n                />\n            </Repository>\n        </Card>\n        <Card label=\"pavel--macbook-pro-2\" header={machine}>\n            <Repository>\n                <RepoItem name=\"but-dev\" folded={false} menu={menu(\"Repository\")} />\n                <UncommittedItem count={12} depth={1} menu={menu(\"Uncommitted changes\")} />\n                <BranchItem\n                    title=\"ios-push-handoff\"\n                    depth={1}\n                    folded\n                    meta={<MetaCount type=\"unpushed\">4</MetaCount>}\n                    menu={menu(\"Branch\")}\n                />\n            </Repository>\n            <Repository last>\n                <RepoItem\n                    name=\"skill-soup\"\n                    folded=\"empty\"\n                    meta={\n                        <>\n                            <MetaCount type=\"head\">empty</MetaCount>\n                            <MetaCount type=\"behind\">2</MetaCount>\n                            <MetaCount type=\"age\">3d</MetaCount>\n                        </>\n                    }\n                    menu={menu(\"Repository\")}\n                />\n            </Repository>\n        </Card>\n    </div>\n);",
          "description": "Rows that could hold something and hold nothing yet: a branch with no commits, a worktree with\nno branches and no changes, and a repository whose only worktree is such a one. Each keeps a dot\nwhere its chevron would be, so it lines up with the rows that fold and nothing offers to open,\nand says why first in its state: `empty` for a branch without commits, and for a worktree what it\nis on, `empty` with nothing applied or `detached`."
        },
        {
          "id": "components-sidebarrow--by-repository",
          "name": "By Repository",
          "snippet": "const ByRepository = () => (\n    <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 24, alignItems: \"flex-start\" }}>\n        <Card label=\"but-dev\" header={repository}>\n            <ByRepositoryTree layout=\"compact\" open={false} />\n        </Card>\n        <Card label=\"but-dev\" header={repository}>\n            <ByRepositoryTree layout=\"compact\" open />\n        </Card>\n        <Card label=\"but-dev\" header={repository}>\n            <ByRepositoryTree layout=\"rich\" open />\n        </Card>\n    </div>\n);",
          "description": "Grouped by repository: the repository heads the card and its machines are rows inside it, each\nover its own worktrees, or straight over the branches of its only one. Folded, a machine sums up\nits worktrees and its age, and a cloud machine shows its agents' time. Open, a row over several\nworktrees shows no age, as each says its own. The same card in `compact` and in `rich`."
        }
      ],
      "import": "import { BranchItem } from '@gitbutler/ui-react/SidebarRow.tsx';\nimport {\n  Button,\n  CiStatus,\n  CommitItem,\n  Icon,\n  MachineItem,\n  MetaCount,\n  MoreItem,\n  RepoItem,\n  StackCaption,\n  UncommittedItem,\n  WorktreeDivider,\n  WorktreeItem,\n} from '@gitbutler/ui-react';"
    },
    "components-snackbar": {
      "id": "components-snackbar",
      "name": "Snackbar",
      "path": "../../packages/ui-react/src/Snackbar.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Snackbar } from \"@gitbutler/ui-react/Snackbar.tsx\";"
        ]
      },
      "description": "One line of consequence, floated over the surface that caused it: a glyph, a sentence, and — when\nit needs dismissing by hand — a way out fenced off behind a divider. A whole {@link Toasts } card\nwould state a title and a description; a snackbar has only the sentence, so it can sit close to\nthe thing it is about rather than in the corner of the window.\n\nEvery variant wears the same surface: the verdict is carried by the glyph alone, so a run of\nsnackbars reads as one row of statements rather than a traffic light.",
      "reactComponentMeta": {
        "displayName": "Snackbar",
        "exportName": "Snackbar",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Snackbar.tsx",
        "description": "One line of consequence, floated over the surface that caused it: a glyph, a sentence, and — when\nit needs dismissing by hand — a way out fenced off behind a divider. A whole {@link Toasts } card\nwould state a title and a description; a snackbar has only the sentence, so it can sit close to\nthe thing it is about rather than in the corner of the window.\n\nEvery variant wears the same surface: the verdict is carried by the glyph alone, so a run of\nsnackbars reads as one row of statements rather than a traffic light.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Snackbar } from \"@gitbutler/ui-react/Snackbar.tsx\";"
          ]
        },
        "props": {
          "variant": {
            "name": "variant",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"safe\" | \"danger\" | \"info\" | \"warning\"",
              "value": [
                {
                  "value": "\"safe\""
                },
                {
                  "value": "\"danger\""
                },
                {
                  "value": "\"info\""
                },
                {
                  "value": "\"warning\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"info\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Snackbar.tsx"
              }
            ]
          },
          "icon": {
            "name": "icon",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"search\" | \"link\" | \"filter\" | \"contrast\" | \"docs\" | \"file\" | \"copy\" | \"danger\" | \"absorb\" | \"ai\" | \"ai-text\" | \"arrow-corner-down-left\" | \"arrow-corner-left-up\" | \"arrow-corner-right-down\" | \"arrow-corner-up-right\" | \"arrow-double-down\" | \"arrow-double-up\" | \"arrow-down\" | \"arrow-down-left\" | \"arrow-down-right\" | \"arrow-in-box\" | \"arrow-left\" | \"arrow-line-down\" | \"arrow-line-up\" | \"arrow-right\" | \"arrow-up\" | \"arrow-up-left\" | \"arrow-up-right\" | \"bell\" | \"bin\" | \"branch\" | \"branch-merge\" | \"bullet-disc\" | \"bullet-list\" | \"bullseye\" | \"camera\" | \"checklist\" | \"checklist-remove\" | \"chevron-down\" | \"chevron-left\" | \"chevron-right\" | \"chevron-up\" | \"clock\" | \"cloud\" | \"collapse-vertical\" | \"commit\" | \"commit-fill\" | \"cross\" | \"cross-circle\" | \"diff\" | \"discord\" | \"drag-horizontal\" | \"drag-square\" | \"drag-vertical\" | \"edit\" | \"expand-vertical\" | \"eye\" | \"eye-closed\" | \"file-diff\" | \"file-minus\" | \"file-plus\" | \"file-text\" | \"files-sidebar\" | \"finger-print\" | \"folder\" | \"folder-copy\" | \"folder-fork\" | \"folder-lock\" | \"folder-tree\" | \"fork\" | \"globe\" | \"hash\" | \"history\" | \"home\" | \"inbox\" | \"inbox-fill\" | \"info\" | \"kebab\" | \"kebab-vertical\" | \"lab\" | \"list\" | \"lock\" | \"lock-auth\" | \"lock-open\" | \"login\" | \"logout\" | \"minus\" | \"mixer\" | \"number-list\" | \"paperclip\" | \"plug\" | \"plus\" | \"pr\" | \"pr-close\" | \"pr-draft\" | \"question\" | \"question-circle\" | \"refresh\" | \"repo\" | \"resize-handle\" | \"robot\" | \"settings\" | \"sidebar\" | \"sidebar-narrow\" | \"smiley\" | \"spinner\" | \"stack\" | \"tag\" | \"text-block\" | \"text-bold\" | \"text-code\" | \"text-contain\" | \"text-h2\" | \"text-h3\" | \"text-italic\" | \"text-plain\" | \"text-quote\" | \"text-strikethrough\" | \"text-wrap\" | \"theme-dark\" | \"theme-light\" | \"theme-system\" | \"tick\" | \"tick-circle\" | \"tick-double\" | \"undo\" | \"user\" | \"warning\" | \"workbench\"",
              "value": [
                {
                  "value": "\"search\""
                },
                {
                  "value": "\"link\""
                },
                {
                  "value": "\"filter\""
                },
                {
                  "value": "\"contrast\""
                },
                {
                  "value": "\"docs\""
                },
                {
                  "value": "\"file\""
                },
                {
                  "value": "\"copy\""
                },
                {
                  "value": "\"danger\""
                },
                {
                  "value": "\"absorb\""
                },
                {
                  "value": "\"ai\""
                },
                {
                  "value": "\"ai-text\""
                },
                {
                  "value": "\"arrow-corner-down-left\""
                },
                {
                  "value": "\"arrow-corner-left-up\""
                },
                {
                  "value": "\"arrow-corner-right-down\""
                },
                {
                  "value": "\"arrow-corner-up-right\""
                },
                {
                  "value": "\"arrow-double-down\""
                },
                {
                  "value": "\"arrow-double-up\""
                },
                {
                  "value": "\"arrow-down\""
                },
                {
                  "value": "\"arrow-down-left\""
                },
                {
                  "value": "\"arrow-down-right\""
                },
                {
                  "value": "\"arrow-in-box\""
                },
                {
                  "value": "\"arrow-left\""
                },
                {
                  "value": "\"arrow-line-down\""
                },
                {
                  "value": "\"arrow-line-up\""
                },
                {
                  "value": "\"arrow-right\""
                },
                {
                  "value": "\"arrow-up\""
                },
                {
                  "value": "\"arrow-up-left\""
                },
                {
                  "value": "\"arrow-up-right\""
                },
                {
                  "value": "\"bell\""
                },
                {
                  "value": "\"bin\""
                },
                {
                  "value": "\"branch\""
                },
                {
                  "value": "\"branch-merge\""
                },
                {
                  "value": "\"bullet-disc\""
                },
                {
                  "value": "\"bullet-list\""
                },
                {
                  "value": "\"bullseye\""
                },
                {
                  "value": "\"camera\""
                },
                {
                  "value": "\"checklist\""
                },
                {
                  "value": "\"checklist-remove\""
                },
                {
                  "value": "\"chevron-down\""
                },
                {
                  "value": "\"chevron-left\""
                },
                {
                  "value": "\"chevron-right\""
                },
                {
                  "value": "\"chevron-up\""
                },
                {
                  "value": "\"clock\""
                },
                {
                  "value": "\"cloud\""
                },
                {
                  "value": "\"collapse-vertical\""
                },
                {
                  "value": "\"commit\""
                },
                {
                  "value": "\"commit-fill\""
                },
                {
                  "value": "\"cross\""
                },
                {
                  "value": "\"cross-circle\""
                },
                {
                  "value": "\"diff\""
                },
                {
                  "value": "\"discord\""
                },
                {
                  "value": "\"drag-horizontal\""
                },
                {
                  "value": "\"drag-square\""
                },
                {
                  "value": "\"drag-vertical\""
                },
                {
                  "value": "\"edit\""
                },
                {
                  "value": "\"expand-vertical\""
                },
                {
                  "value": "\"eye\""
                },
                {
                  "value": "\"eye-closed\""
                },
                {
                  "value": "\"file-diff\""
                },
                {
                  "value": "\"file-minus\""
                },
                {
                  "value": "\"file-plus\""
                },
                {
                  "value": "\"file-text\""
                },
                {
                  "value": "\"files-sidebar\""
                },
                {
                  "value": "\"finger-print\""
                },
                {
                  "value": "\"folder\""
                },
                {
                  "value": "\"folder-copy\""
                },
                {
                  "value": "\"folder-fork\""
                },
                {
                  "value": "\"folder-lock\""
                },
                {
                  "value": "\"folder-tree\""
                },
                {
                  "value": "\"fork\""
                },
                {
                  "value": "\"globe\""
                },
                {
                  "value": "\"hash\""
                },
                {
                  "value": "\"history\""
                },
                {
                  "value": "\"home\""
                },
                {
                  "value": "\"inbox\""
                },
                {
                  "value": "\"inbox-fill\""
                },
                {
                  "value": "\"info\""
                },
                {
                  "value": "\"kebab\""
                },
                {
                  "value": "\"kebab-vertical\""
                },
                {
                  "value": "\"lab\""
                },
                {
                  "value": "\"list\""
                },
                {
                  "value": "\"lock\""
                },
                {
                  "value": "\"lock-auth\""
                },
                {
                  "value": "\"lock-open\""
                },
                {
                  "value": "\"login\""
                },
                {
                  "value": "\"logout\""
                },
                {
                  "value": "\"minus\""
                },
                {
                  "value": "\"mixer\""
                },
                {
                  "value": "\"number-list\""
                },
                {
                  "value": "\"paperclip\""
                },
                {
                  "value": "\"plug\""
                },
                {
                  "value": "\"plus\""
                },
                {
                  "value": "\"pr\""
                },
                {
                  "value": "\"pr-close\""
                },
                {
                  "value": "\"pr-draft\""
                },
                {
                  "value": "\"question\""
                },
                {
                  "value": "\"question-circle\""
                },
                {
                  "value": "\"refresh\""
                },
                {
                  "value": "\"repo\""
                },
                {
                  "value": "\"resize-handle\""
                },
                {
                  "value": "\"robot\""
                },
                {
                  "value": "\"settings\""
                },
                {
                  "value": "\"sidebar\""
                },
                {
                  "value": "\"sidebar-narrow\""
                },
                {
                  "value": "\"smiley\""
                },
                {
                  "value": "\"spinner\""
                },
                {
                  "value": "\"stack\""
                },
                {
                  "value": "\"tag\""
                },
                {
                  "value": "\"text-block\""
                },
                {
                  "value": "\"text-bold\""
                },
                {
                  "value": "\"text-code\""
                },
                {
                  "value": "\"text-contain\""
                },
                {
                  "value": "\"text-h2\""
                },
                {
                  "value": "\"text-h3\""
                },
                {
                  "value": "\"text-italic\""
                },
                {
                  "value": "\"text-plain\""
                },
                {
                  "value": "\"text-quote\""
                },
                {
                  "value": "\"text-strikethrough\""
                },
                {
                  "value": "\"text-wrap\""
                },
                {
                  "value": "\"theme-dark\""
                },
                {
                  "value": "\"theme-light\""
                },
                {
                  "value": "\"theme-system\""
                },
                {
                  "value": "\"tick\""
                },
                {
                  "value": "\"tick-circle\""
                },
                {
                  "value": "\"tick-double\""
                },
                {
                  "value": "\"undo\""
                },
                {
                  "value": "\"user\""
                },
                {
                  "value": "\"warning\""
                },
                {
                  "value": "\"workbench\""
                }
              ]
            },
            "description": "Overrides the variant's own glyph.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Snackbar.tsx"
              }
            ]
          },
          "onDismiss": {
            "name": "onDismiss",
            "required": false,
            "type": {
              "name": "() => void"
            },
            "description": "Given, the snackbar carries a close button; otherwise it says its piece and nothing more.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Snackbar.tsx"
              }
            ]
          },
          "dismissLabel": {
            "name": "dismissLabel",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": {
              "value": "\"Dismiss\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Snackbar.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-snackbar--default",
          "name": "Default",
          "snippet": "const Default = () => <Snackbar variant=\"info\" onDismiss={() => {}}>Info. Snackbar message</Snackbar>;",
          "description": "The snackbar as the design states it: a glyph, a sentence, and a way out."
        },
        {
          "id": "components-snackbar--all-variants",
          "name": "All Variants",
          "snippet": "const AllVariants = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"start\", gap: 12 }}>\n        <Snackbar>Info. Snackbar message</Snackbar>\n        <Snackbar variant=\"warning\">Warning. Snackbar message</Snackbar>\n        <Snackbar variant=\"danger\">Danger. Snackbar message</Snackbar>\n        <Snackbar variant=\"safe\">Success. Snackbar message</Snackbar>\n    </div>\n);",
          "description": "One surface, four glyphs: only the leading icon says how the news landed."
        },
        {
          "id": "components-snackbar--with-dismiss",
          "name": "With Dismiss",
          "snippet": "const WithDismiss = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"start\", gap: 12 }}>\n        <Snackbar onDismiss={() => {}}>Info. Snackbar message</Snackbar>\n        <Snackbar variant=\"warning\" onDismiss={() => {}}>\n            Warning. Snackbar message\n        </Snackbar>\n        <Snackbar variant=\"danger\" onDismiss={() => {}}>\n            Danger. Snackbar message\n        </Snackbar>\n        <Snackbar variant=\"safe\" onDismiss={() => {}}>\n            Success. Snackbar message\n        </Snackbar>\n    </div>\n);",
          "description": "With `onDismiss` the snackbar grows a divider and a close button, and the row with it."
        },
        {
          "id": "components-snackbar--custom-icon",
          "name": "Custom Icon",
          "snippet": "const CustomIcon = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"start\", gap: 12 }}>\n        <Snackbar icon=\"spinner\">Absorbing…</Snackbar>\n        <Snackbar icon=\"absorb\" onDismiss={() => {}}>\n            Couldn’t work out where to absorb\n        </Snackbar>\n        <Snackbar variant=\"safe\" icon=\"commit\">\n            Changes absorbed into 3 commits\n        </Snackbar>\n    </div>\n);",
          "description": "`icon` overrides the variant's own glyph without changing what the snackbar means."
        },
        {
          "id": "components-snackbar--long-message",
          "name": "Long Message",
          "snippet": "const LongMessage = () => (\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12, width: 320 }}>\n        <Snackbar icon=\"absorb\" onDismiss={() => {}}>\n            Couldn’t work out where to absorb these changes, so nothing was moved anywhere at all\n        </Snackbar>\n        <Snackbar variant=\"danger\" onDismiss={() => {}}>\n            The commit could not be created because the workspace has conflicts left in it\n        </Snackbar>\n    </div>\n);",
          "description": "A sentence wider than the space it has ellipsises rather than widening the snackbar."
        }
      ],
      "import": "import { Snackbar } from '@gitbutler/ui-react/Snackbar.tsx';"
    },
    "components-snackbars": {
      "id": "components-snackbars",
      "name": "Snackbars",
      "path": "../../packages/ui-react/src/Snackbars.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Snackbars } from \"@gitbutler/ui-react/Snackbars.tsx\";"
        ]
      },
      "description": "Where snackbars appear: a stack at the bottom centre of the window. Render it once with a manager\nof its own, separate from the toasts', from Base UI's `Toast.createToastManager<SnackbarData>()`.\nRaise one with `manager.add({ title, type })`; `update(id, …)` turns a `loading` one into its\nresult, and `close(id)` lets it go.\n\nThey stack one below another, 8px apart, the newest at the bottom. Each rises in as it arrives and\nsinks out as it goes while the rest close the gap, and a click anywhere on one lets it go early.\nSnackbars on a timer pause while the stack is hovered.",
      "reactComponentMeta": {
        "displayName": "Snackbars",
        "exportName": "Snackbars",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Snackbars.tsx",
        "description": "Where snackbars appear: a stack at the bottom centre of the window. Render it once with a manager\nof its own, separate from the toasts', from Base UI's `Toast.createToastManager<SnackbarData>()`.\nRaise one with `manager.add({ title, type })`; `update(id, …)` turns a `loading` one into its\nresult, and `close(id)` lets it go.\n\nThey stack one below another, 8px apart, the newest at the bottom. Each rises in as it arrives and\nsinks out as it goes while the rest close the gap, and a click anywhere on one lets it go early.\nSnackbars on a timer pause while the stack is hovered.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Snackbars } from \"@gitbutler/ui-react/Snackbars.tsx\";"
          ]
        },
        "props": {
          "manager": {
            "name": "manager",
            "required": true,
            "type": {
              "name": "ToastManager<SnackbarData>"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Snackbars.tsx"
              }
            ]
          },
          "timeout": {
            "name": "timeout",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "How long one on a timer stays, in milliseconds.",
            "defaultValue": {
              "value": "5000"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Snackbars.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "On the stack, for a host that lifts it with `--snackbars-bottom`.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Snackbars.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-snackbars--default",
          "name": "Default",
          "snippet": "const Default = () => <Playground />;",
          "description": "The stack at the bottom centre, one below another with the newest at the bottom. Each press raises\na random snackbar: a busy one turns into its result, one on a timer sinks out after a few seconds,\nand a click on any lets it go early.",
          "warning": "Incomplete snippet: `SnackbarData` could not be resolved statically."
        }
      ],
      "import": "import { Button } from '@gitbutler/ui-react';\nimport { Snackbars } from '@gitbutler/ui-react/Snackbars.tsx';\nimport { Toast } from '@base-ui/react';"
    },
    "components-switch": {
      "id": "components-switch",
      "name": "Switch",
      "path": "../../packages/ui-react/src/Switch.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Switch } from \"@gitbutler/ui-react/Switch.tsx\";"
        ]
      },
      "description": "An on/off switch for a setting that takes effect immediately. Use it where there is no Save\nto press; for a choice confirmed later, use a Checkbox. Pairing a switch with its own label is\n{@link SwitchButton }'s job, not this one's.",
      "reactComponentMeta": {
        "displayName": "Switch",
        "exportName": "Switch",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Switch.tsx",
        "description": "An on/off switch for a setting that takes effect immediately. Use it where there is no Save\nto press; for a choice confirmed later, use a Checkbox. Pairing a switch with its own label is\n{@link SwitchButton }'s job, not this one's.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Switch } from \"@gitbutler/ui-react/Switch.tsx\";"
          ]
        },
        "props": {
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"large\" | \"default\"",
              "value": [
                {
                  "value": "\"large\""
                },
                {
                  "value": "\"default\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"default\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Switch.tsx"
              }
            ]
          },
          "style": {
            "name": "style",
            "required": false,
            "type": {
              "name": "CSSProperties | ((state: SwitchRootState) => CSSProperties | undefined) | undefined"
            },
            "description": "Style applied to the element, or a function that\nreturns a style object based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "render": {
            "name": "render",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SwitchRootState> | undefined"
            },
            "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "id": {
            "name": "id",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The id of the hidden input element.\n\nWhen `nativeButton` is `true`, the id is applied to the root element.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string | ((state: SwitchRootState) => string | undefined) | undefined"
            },
            "description": "CSS class applied to the element, or a function that\nreturns a class based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "name": {
            "name": "name",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Identifies the field when a form is submitted.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "form": {
            "name": "form",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Identifies the form that owns the hidden input.\nUseful when the switch is rendered outside the form.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "defaultChecked": {
            "name": "defaultChecked",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the switch is initially active.\n\nTo render a controlled switch, use the `checked` prop instead.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the component should ignore user interaction.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "value": {
            "name": "value",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The value submitted with the form when the switch is on.\nBy default, switch submits the \"on\" value, matching native checkbox behavior.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "nativeButton": {
            "name": "nativeButton",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the component renders a native `<button>` element when replacing it\nvia the `render` prop.\nSet to `true` if the rendered element is a native button.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "NonNativeButtonProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "NonNativeButtonProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "checked": {
            "name": "checked",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the switch is currently active.\n\nTo render an uncontrolled switch, use the `defaultChecked` prop instead.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "onCheckedChange": {
            "name": "onCheckedChange",
            "required": false,
            "type": {
              "name": "(checked: boolean, eventDetails: { reason: \"none\"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void"
            },
            "description": "Event handler called when the switch is activated or deactivated.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "readOnly": {
            "name": "readOnly",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the user should be unable to activate or deactivate the switch.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "required": {
            "name": "required",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the user must activate the switch before submitting a form.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "inputRef": {
            "name": "inputRef",
            "required": false,
            "type": {
              "name": "Ref<HTMLInputElement> | undefined"
            },
            "description": "A ref to access the hidden `<input>` element.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "uncheckedValue": {
            "name": "uncheckedValue",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The value submitted with the form when the switch is off.\nBy default, unchecked switches do not submit any value, matching native checkbox behavior.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-switch--default",
          "name": "Default",
          "snippet": "const Default = () => <Toggleable />;"
        },
        {
          "id": "components-switch--large",
          "name": "Large",
          "snippet": "const Large = () => (\n    <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n        <Toggleable size=\"large\" />\n        <Switch checked disabled size=\"large\" />\n        <Switch checked={false} disabled size=\"large\" />\n    </div>\n);",
          "description": "The size a settings row's switch wears, beside the row's 15px title."
        },
        {
          "id": "components-switch--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => (\n    <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n        <Switch checked disabled />\n        <Switch checked={false} disabled />\n    </div>\n);"
        }
      ],
      "import": "import { Switch } from '@gitbutler/ui-react/Switch.tsx';"
    },
    "components-switchbutton": {
      "id": "components-switchbutton",
      "name": "SwitchButton",
      "path": "../../packages/ui-react/src/SwitchButton.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { SwitchButton } from \"@gitbutler/ui-react/SwitchButton.tsx\";"
        ]
      },
      "description": "A switch and its label wearing button chrome, so the pair reads and behaves\nas one control rather than a toggle with text next to it.\n\nThe chrome lives on a `<label>` rather than around the switch, so the text\nshares the switch's hit area: base-ui points the label at the hidden\ncheckbox it renders alongside the `<span role=\"switch\">`.",
      "reactComponentMeta": {
        "displayName": "SwitchButton",
        "exportName": "SwitchButton",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/SwitchButton.tsx",
        "description": "A switch and its label wearing button chrome, so the pair reads and behaves\nas one control rather than a toggle with text next to it.\n\nThe chrome lives on a `<label>` rather than around the switch, so the text\nshares the switch's hit area: base-ui points the label at the hidden\ncheckbox it renders alongside the `<span role=\"switch\">`.",
        "jsDocTags": {
          "import": [
            "import { SwitchButton } from \"@gitbutler/ui-react/SwitchButton.tsx\";"
          ]
        },
        "props": {
          "style": {
            "name": "style",
            "required": false,
            "type": {
              "name": "CSSProperties | ((state: SwitchRootState) => CSSProperties | undefined) | undefined"
            },
            "description": "Style applied to the element, or a function that\nreturns a style object based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "render": {
            "name": "render",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SwitchRootState> | undefined"
            },
            "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"large\" | \"default\"",
              "value": [
                {
                  "value": "\"large\""
                },
                {
                  "value": "\"default\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Switch.tsx"
              }
            ]
          },
          "name": {
            "name": "name",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Identifies the field when a form is submitted.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "form": {
            "name": "form",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Identifies the form that owns the hidden input.\nUseful when the switch is rendered outside the form.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "defaultChecked": {
            "name": "defaultChecked",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the switch is initially active.\n\nTo render a controlled switch, use the `checked` prop instead.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the component should ignore user interaction.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "value": {
            "name": "value",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The value submitted with the form when the switch is on.\nBy default, switch submits the \"on\" value, matching native checkbox behavior.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "nativeButton": {
            "name": "nativeButton",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the component renders a native `<button>` element when replacing it\nvia the `render` prop.\nSet to `true` if the rendered element is a native button.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "NonNativeButtonProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "NonNativeButtonProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "checked": {
            "name": "checked",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the switch is currently active.\n\nTo render an uncontrolled switch, use the `defaultChecked` prop instead.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "onCheckedChange": {
            "name": "onCheckedChange",
            "required": false,
            "type": {
              "name": "(checked: boolean, eventDetails: { reason: \"none\"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void"
            },
            "description": "Event handler called when the switch is activated or deactivated.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "readOnly": {
            "name": "readOnly",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the user should be unable to activate or deactivate the switch.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "required": {
            "name": "required",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the user must activate the switch before submitting a form.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "inputRef": {
            "name": "inputRef",
            "required": false,
            "type": {
              "name": "Ref<HTMLInputElement> | undefined"
            },
            "description": "A ref to access the hidden `<input>` element.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "uncheckedValue": {
            "name": "uncheckedValue",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The value submitted with the form when the switch is off.\nBy default, unchecked switches do not submit any value, matching native checkbox behavior.",
            "defaultValue": null,
            "parent": {
              "name": "SwitchRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
            },
            "declarations": [
              {
                "name": "SwitchRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/switch/root/SwitchRoot.d.mts"
              }
            ]
          },
          "label": {
            "name": "label",
            "required": true,
            "type": {
              "name": "ReactNode"
            },
            "description": "Sits beside the switch and shares its hit area.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/SwitchButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SwitchButton.tsx"
              }
            ]
          },
          "variant": {
            "name": "variant",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"outline\" | \"ghost\"",
              "value": [
                {
                  "value": "\"outline\""
                },
                {
                  "value": "\"ghost\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"ghost\""
            },
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/SwitchButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SwitchButton.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/SwitchButton.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/SwitchButton.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-switchbutton--default",
          "name": "Default",
          "snippet": "const Default = ({ label, variant, disabled }) => (\n    <SwitchButton label={label} variant={variant} disabled={disabled} defaultChecked />\n);"
        },
        {
          "id": "components-switchbutton--variants",
          "name": "Variants",
          "snippet": "const Variants = () => (\n    <div style={{ display: \"flex\", gap: 12, alignItems: \"center\" }}>\n        <Toggleable label=\"Draft\" variant=\"ghost\" />\n        <Toggleable label=\"Auto-merge\" variant=\"outline\" initial />\n    </div>\n);",
          "description": "Ghost sits inside a surface that already has chrome; outline stands alone."
        },
        {
          "id": "components-switchbutton--disabled",
          "name": "Disabled",
          "snippet": "const Disabled = () => (\n    <div style={{ display: \"flex\", gap: 12, alignItems: \"center\" }}>\n        <SwitchButton label=\"Draft\" disabled />\n        <SwitchButton label=\"Draft\" disabled defaultChecked />\n        <SwitchButton label=\"Auto-merge\" variant=\"outline\" disabled defaultChecked />\n    </div>\n);",
          "description": "The pill fades as a whole rather than compounding the switch's own fade."
        },
        {
          "id": "components-switchbutton--long-label",
          "name": "Long Label",
          "snippet": "const LongLabel = () => <Toggleable label=\"Delete the branch after merging\" variant=\"outline\" />;",
          "description": "The label shares the switch's hit area, so a click anywhere in the pill —\nincluding on the switch itself — toggles exactly once."
        }
      ],
      "import": "import { SwitchButton } from '@gitbutler/ui-react/SwitchButton.tsx';"
    },
    "components-tabs": {
      "id": "components-tabs",
      "name": "Tabs",
      "path": "../../packages/ui-react/src/Tabs.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Tabs, Tab } from \"@gitbutler/ui-react/Tabs.tsx\";"
        ]
      },
      "description": "A row of {@link Tab}s that switch what a pane shows, one at a time, with an underline under the\nselected one that slides to the next as the selection moves.\n\n- Controlled with `value` and `onValueChange`, or left to itself with `defaultValue`.\n- The arrow keys move between the tabs, as a tab list does.\n- The underline runs under the selected tab's content and hangs outside the row, 8px below it\n  and 4px thick, so the header holding the tabs leaves 12px below them: the underline then\n  sits on the header's divider.",
      "reactComponentMeta": {
        "displayName": "Tabs",
        "exportName": "Tabs",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Tabs.tsx",
        "description": "A row of {@link Tab}s that switch what a pane shows, one at a time, with an underline under the\nselected one that slides to the next as the selection moves.\n\n- Controlled with `value` and `onValueChange`, or left to itself with `defaultValue`.\n- The arrow keys move between the tabs, as a tab list does.\n- The underline runs under the selected tab's content and hangs outside the row, 8px below it\n  and 4px thick, so the header holding the tabs leaves 12px below them: the underline then\n  sits on the header's divider.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Tabs, Tab } from \"@gitbutler/ui-react/Tabs.tsx\";"
          ]
        },
        "props": {
          "style": {
            "name": "style",
            "required": false,
            "type": {
              "name": "CSSProperties | ((state: TabsRootState) => CSSProperties | undefined) | undefined"
            },
            "description": "Style applied to the element, or a function that\nreturns a style object based on the component's state.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "render": {
            "name": "render",
            "required": false,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, TabsRootState> | undefined"
            },
            "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
            "defaultValue": null,
            "parent": {
              "name": "BaseUIComponentProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/internals/types.d.mts"
              }
            ]
          },
          "defaultValue": {
            "name": "defaultValue",
            "required": false,
            "type": {
              "name": "any"
            },
            "description": "The default value. Use when the component is not controlled.\nWhen the value is `null`, no Tab will be active.",
            "defaultValue": {
              "value": "0"
            },
            "parent": {
              "name": "TabsRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tabs/root/TabsRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TabsRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tabs/root/TabsRoot.d.mts"
              }
            ]
          },
          "aria-label": {
            "name": "aria-label",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "Defines a string value that labels the current element.",
            "defaultValue": null,
            "parent": {
              "name": "AriaAttributes",
              "fileName": "../../node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/index.d.ts"
            },
            "declarations": [
              {
                "name": "AriaAttributes",
                "fileName": "../../node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/index.d.ts"
              },
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tabs.tsx"
              }
            ]
          },
          "value": {
            "name": "value",
            "required": false,
            "type": {
              "name": "any"
            },
            "description": "The value of the currently active `Tab`. Use when the component is controlled.\nWhen the value is `null`, no Tab will be active.",
            "defaultValue": null,
            "parent": {
              "name": "TabsRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tabs/root/TabsRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TabsRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tabs/root/TabsRoot.d.mts"
              }
            ]
          },
          "orientation": {
            "name": "orientation",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"horizontal\" | \"vertical\"",
              "value": [
                {
                  "value": "\"horizontal\""
                },
                {
                  "value": "\"vertical\""
                }
              ]
            },
            "description": "The component orientation (layout flow direction).",
            "defaultValue": {
              "value": "'horizontal'"
            },
            "parent": {
              "name": "TabsRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tabs/root/TabsRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TabsRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tabs/root/TabsRoot.d.mts"
              }
            ]
          },
          "onValueChange": {
            "name": "onValueChange",
            "required": false,
            "type": {
              "name": "(value: any, eventDetails: TabsRootChangeEventDetails) => void"
            },
            "description": "Callback invoked when new value is being set.\n\nThe event `reason` is `'none'` for user-initiated changes, such as a click\nor keyboard navigation; `'initial'` for the first automatic selection or\nfallback in uncontrolled roots when `defaultValue` is omitted or\n`undefined`, including when the implicit initial value is disabled or\nmissing; `'disabled'` for automatic fallback when the selected tab becomes\ndisabled in uncontrolled roots; or `'missing'` for automatic fallback when\nthe selected tab is removed, or when an explicit `defaultValue` never\nmatches a mounted tab in uncontrolled roots.\n\nFor automatic changes, the selected value can be `null` when no enabled Tab\nis available as a fallback.\n\nAutomatic changes cannot be canceled; calling `eventDetails.cancel()` for\n`'initial'`, `'disabled'`, or `'missing'` has no effect.",
            "defaultValue": null,
            "parent": {
              "name": "TabsRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tabs/root/TabsRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TabsRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tabs/root/TabsRoot.d.mts"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tabs.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-tabs--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <Tabs defaultValue=\"diff\" aria-label=\"Branch\">\n        <Tab value=\"diff\">Diff</Tab>\n        <Tab value=\"pr\">Pull Request</Tab>\n        <Tab value=\"sessions\">Sessions</Tab>\n        <Tab value=\"activity\">Activity</Tab>\n    </Tabs>\n);",
          "description": "Tabs that switch a pane's contents; the underline follows the selected one."
        },
        {
          "id": "components-tabs--icons-and-counts",
          "name": "Icons And Counts",
          "snippet": "const IconsAndCounts = () => (\n    <Tabs defaultValue=\"changes\" aria-label=\"Worktree\">\n        <Tab value=\"changes\" icon={<Icon name=\"diff\" />} count={3}>\n            Changes\n        </Tab>\n        <Tab value=\"pr\" icon={<Icon name=\"pr\" />}>\n            Pull Request\n        </Tab>\n        <Tab value=\"sessions\" icon={<Icon name=\"ai\" />} count={2}>\n            Sessions\n        </Tab>\n        <Tab value=\"activity\" icon={<Icon name=\"history\" />}>\n            Activity\n        </Tab>\n    </Tabs>\n);",
          "description": "With an `icon` before each label and a `count` after the ones that hold things."
        },
        {
          "id": "components-tabs--shortcuts",
          "name": "Shortcuts",
          "snippet": "const Shortcuts = () => (\n    <Tabs defaultValue=\"diff\" aria-label=\"Branch\">\n        <Tab value=\"diff\" kbd=\"Mod+1\">\n            Diff\n        </Tab>\n        <Tab value=\"pr\" kbd=\"Mod+2\" count={4}>\n            Pull Request\n        </Tab>\n        <Tab value=\"activity\" kbd=\"Mod+3\">\n            Activity\n        </Tab>\n    </Tabs>\n);",
          "description": "With `kbd`, the shortcut that selects each tab, faint after its label."
        },
        {
          "id": "components-tabs--in-a-header",
          "name": "In A Header",
          "snippet": "const InAHeader = function Render() {\n    const [tab, setTab] = useState(\"changes\");\n    return (\n        <div style={{ width: 480, border: \"1px solid var(--border-2)\" }}>\n            <div\n                style={{\n                    paddingInline: 12,\n                    paddingBlock: \"6px 12px\",\n                    borderBlockEnd: \"1px solid var(--border-2)\",\n                }}\n            >\n                <Tabs value={tab} onValueChange={setTab} aria-label=\"Worktree\">\n                    <Tab value=\"changes\" count={3}>\n                        Changes\n                    </Tab>\n                    <Tab value=\"activity\">Activity</Tab>\n                </Tabs>\n            </div>\n            <p className=\"text-13\" style={{ padding: 12, margin: 0 }}>\n                {tab === \"changes\" ? \"Three changed files.\" : \"Nothing happened yet.\"}\n            </p>\n        </div>\n    );\n};",
          "description": "In a pane's header, controlled by the pane. The header leaves 12px below the row, the underline's\n8px gap and its 4px, so the underline sits on the divider rather than across it."
        }
      ],
      "import": "import { Icon, Tab } from '@gitbutler/ui-react';\nimport { Tabs } from '@gitbutler/ui-react/Tabs.tsx';"
    },
    "components-tag": {
      "id": "components-tag",
      "name": "Tag",
      "path": "../../packages/ui-react/src/Tag.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Tag } from \"@gitbutler/ui-react/Tag.tsx\";"
        ]
      },
      "description": "A named, coloured category: a label on a pull request, an issue's label, a topic.\nAn outlined pill with the name in the text colour and the colour as a dot, so any\ncolour reads on any ground and a row of them stays calm. Without a colour, no dot.",
      "reactComponentMeta": {
        "displayName": "Tag",
        "exportName": "Tag",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Tag.tsx",
        "description": "A named, coloured category: a label on a pull request, an issue's label, a topic.\nAn outlined pill with the name in the text colour and the colour as a dot, so any\ncolour reads on any ground and a row of them stays calm. Without a colour, no dot.",
        "jsDocTags": {
          "import": [
            "import { Tag } from \"@gitbutler/ui-react/Tag.tsx\";"
          ]
        },
        "props": {
          "name": {
            "name": "name",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tag.tsx"
              }
            ]
          },
          "color": {
            "name": "color",
            "required": false,
            "type": {
              "name": "string | null | undefined"
            },
            "description": "The category's colour, as hex with or without the `#` (forges send both).",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tag.tsx"
              }
            ]
          },
          "description": {
            "name": "description",
            "required": false,
            "type": {
              "name": "string | null | undefined"
            },
            "description": "Shown on hover after the name, as a forge's label description is.",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tag.tsx"
              }
            ]
          },
          "size": {
            "name": "size",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"regular\" | \"large\"",
              "value": [
                {
                  "value": "\"regular\""
                },
                {
                  "value": "\"large\""
                }
              ]
            },
            "description": "",
            "defaultValue": {
              "value": "\"large\""
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tag.tsx"
              }
            ]
          },
          "className": {
            "name": "className",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tag.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-tag--default",
          "name": "Default",
          "snippet": "const Default = () => <Tag name=\"ui\" color=\"F2C230\" />;"
        },
        {
          "id": "components-tag--regular",
          "name": "Regular",
          "snippet": "const Regular = () => <Tag name=\"ui\" color=\"F2C230\" size=\"regular\" />;"
        },
        {
          "id": "components-tag--colorless",
          "name": "Colorless",
          "snippet": "const Colorless = () => <Tag name=\"needs review\" color={null} />;",
          "description": "No colour: the name alone, no dot."
        },
        {
          "id": "components-tag--edge-colours",
          "name": "Edge Colours",
          "snippet": "const EdgeColours = () => <div style={{ display: \"flex\", gap: 6 }}>\n    <Tag name=\"@gitbutler/lite\" color=\"#ffffff\" />\n    <Tag name=\"wontfix\" color=\"000000\" />\n</div>;",
          "description": "A colour as light as the ground keeps its dot's shape; so does black in the dark theme."
        },
        {
          "id": "components-tag--row",
          "name": "Row",
          "snippet": "const Row = (args) => (\n    <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 6, maxWidth: 480 }}>\n        {(\n            [\n                [\"ui\", \"F2C230\"],\n                [\"UX\", \"4FB3D1\"],\n                [\"dependencies\", \"0366d6\"],\n                [\"@gitbutler/desktop\", \"76AF01\"],\n                [\"@gitbutler/lite\", \"ededed\"],\n                [\"@gitbutler/ui-react\", \"f79614\"],\n                [\"javascript\", \"168700\"],\n                [\"@gitbutler/butler-bot\", \"5319e7\"],\n            ] as const\n        ).map(([name, color]) => (\n            <Tag key={name} {...args} name={name} color={color} />\n        ))}\n    </div>\n);",
          "description": "This repository's labels and a Linear pair, to hold against the row they came from."
        },
        {
          "id": "components-tag--long-name",
          "name": "Long Name",
          "snippet": "const LongName = () => <div style={{ width: 160 }}>\n    <Tag name=\"A long label that needs to fit in a narrow row\" color=\"dea584\" />\n</div>;"
        }
      ],
      "import": "import { Tag } from '@gitbutler/ui-react/Tag.tsx';"
    },
    "components-textlink": {
      "id": "components-textlink",
      "name": "TextLink",
      "path": "../../packages/ui-react/src/TextLink.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { TextLink } from \"@gitbutler/ui-react/TextLink.tsx\";"
        ]
      },
      "description": "A link that reads as a link: underlined text with an arrow hung off the\nend, since every link leaves the app. The arrow is drawn here rather than\ntyped, because the text fonts don't carry ↗ at every weight. How a link\nleaves is the host's to say, through `onClick`: a web page can let the\nanchor navigate, while Electron has to hand the URL to the system browser.",
      "reactComponentMeta": {
        "displayName": "TextLink",
        "exportName": "TextLink",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/TextLink.tsx",
        "description": "A link that reads as a link: underlined text with an arrow hung off the\nend, since every link leaves the app. The arrow is drawn here rather than\ntyped, because the text fonts don't carry ↗ at every weight. How a link\nleaves is the host's to say, through `onClick`: a web page can let the\nanchor navigate, while Electron has to hand the URL to the system browser.",
        "jsDocTags": {
          "import": [
            "import { TextLink } from \"@gitbutler/ui-react/TextLink.tsx\";"
          ]
        },
        "props": {
          "href": {
            "name": "href",
            "required": true,
            "type": {
              "name": "string"
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/TextLink.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/TextLink.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-textlink--default",
          "name": "Default",
          "snippet": "const Default = () => <TextLink\n    href=\"https://github.com/gitbutlerapp/gitbutler/pull/15941\"\n    onClick={(evt) => evt.preventDefault()}>#15941</TextLink>;"
        },
        {
          "id": "components-textlink--in-text",
          "name": "In Text",
          "snippet": "const InText = () => <p className=\"text-12\" style={{ color: \"var(--text-2)\" }}>We’d love to hear what you think. <TextLink\n        href=\"https://discord.gg/MmFkmaJ42D\"\n        onClick={(evt) => evt.preventDefault()}>Share feedback on Discord</TextLink>\n</p>;"
        }
      ],
      "import": "import { TextLink } from '@gitbutler/ui-react/TextLink.tsx';"
    },
    "components-toasts": {
      "id": "components-toasts",
      "name": "Toasts",
      "path": "../../packages/ui-react/src/Toasts.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Toasts } from \"@gitbutler/ui-react/Toasts.tsx\";"
        ]
      },
      "description": "Where toasts appear. Render it once inside Base UI's `Toast.Provider`; anything under the\nprovider raises one through `Toast.useToastManager().add({ type, title, description, actionProps })`.\n\nEach toast is a card in the window's bottom-right corner: a glyph, a title naming what happened, a\ndescription that can hold real content, at most one action under it, and a close button. Every\ntype wears the same surface; the glyph alone carries the verdict.",
      "reactComponentMeta": {
        "displayName": "Toasts",
        "exportName": "Toasts",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Toasts.tsx",
        "description": "Where toasts appear. Render it once inside Base UI's `Toast.Provider`; anything under the\nprovider raises one through `Toast.useToastManager().add({ type, title, description, actionProps })`.\n\nEach toast is a card in the window's bottom-right corner: a glyph, a title naming what happened, a\ndescription that can hold real content, at most one action under it, and a close button. Every\ntype wears the same surface; the glyph alone carries the verdict.",
        "jsDocTags": {
          "import": [
            "import { Toasts } from \"@gitbutler/ui-react/Toasts.tsx\";"
          ]
        },
        "props": {}
      },
      "stories": [
        {
          "id": "components-toasts--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <Raise\n        toasts={[\n            {\n                type: \"error\",\n                title: \"Failed to create comment\",\n                actionProps: { children: \"Copy error message\" },\n                priority: \"high\",\n            },\n        ]}\n    />\n);",
          "description": "A failure in the window's bottom-right corner: the title says what failed, and the raw error waits\nbehind \"Copy error message\" for a bug report instead of showing under it."
        },
        {
          "id": "components-toasts--apply-conflict",
          "name": "Apply Conflict",
          "snippet": "const ApplyConflict = () => (\n    <Raise\n        toasts={[\n            {\n                type: \"error\",\n                title: \"Failed to apply branch\",\n                description:\n                    \"'feature/login' conflicts with existing stack in the workspace: auth-refactor\",\n                priority: \"high\",\n                actionProps: { children: \"Switch to branch instead\" },\n            },\n        ]}\n    />\n);",
          "description": "A failure with a way round it: the action sits under the description, however long its label."
        },
        {
          "id": "components-toasts--rejected-changes",
          "name": "Rejected Changes",
          "snippet": "const RejectedChanges = () => (\n    <Raise\n        toasts={[\n            {\n                type: \"warning\",\n                title: \"Some changes were not committed\",\n                description: (\n                    <ul>\n                        <li>\n                            <strong>Workspace merge conflict:</strong> src/app.ts and src/lib/api.ts\n                        </li>\n                        <li>\n                            <strong>File too large or binary:</strong> assets/logo.psd\n                        </li>\n                    </ul>\n                ),\n                priority: \"high\",\n            },\n        ]}\n    />\n);",
          "description": "A commit that came off in part: the description breaks down what was left behind, and why."
        },
        {
          "id": "components-toasts--update-ready",
          "name": "Update Ready",
          "snippet": "const UpdateReady = () => (\n    <Raise\n        toasts={[\n            {\n                type: \"info\",\n                title: \"Check for updates\",\n                description: \"Update downloaded. Restart now or install on quit.\",\n                actionProps: { children: \"Install 0.18.2 now\" },\n                data: { icon: \"arrow-in-box\" },\n            },\n        ]}\n    />\n);",
          "description": "News with no verdict, and the next step it offers; `data.icon` gives it the updater's own glyph."
        },
        {
          "id": "components-toasts--conflicts-resolved",
          "name": "Conflicts Resolved",
          "snippet": "const ConflictsResolved = () => (\n    <Raise\n        toasts={[\n            {\n                type: \"success\",\n                title: \"3 conflicts resolved\",\n                description: \"2 conflicts remaining in this commit.\",\n                priority: \"low\",\n            },\n        ]}\n    />\n);",
          "description": "A success the screen doesn't otherwise show."
        },
        {
          "id": "components-toasts--stack",
          "name": "Stack",
          "snippet": "const Stack = () => <Raise toasts={stack} />;",
          "description": "Several at once fold behind the newest: the ones further back show only their top edge."
        },
        {
          "id": "components-toasts--stack-expanded",
          "name": "Stack Expanded",
          "snippet": "const StackExpanded = () => <Raise toasts={stack} />;",
          "description": "Under the pointer or keyboard focus the stack unfolds into a column, 8px apart."
        }
      ],
      "import": "import { Button } from '@gitbutler/ui-react';\nimport { Toast } from '@base-ui/react';\nimport { Toasts } from '@gitbutler/ui-react/Toasts.tsx';"
    },
    "components-togglegroup": {
      "id": "components-togglegroup",
      "name": "ToggleGroupStyles",
      "path": "../../packages/ui-react/src/ToggleGroup.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { ToggleGroupStyles } from \"@gitbutler/ui-react/ToggleGroup.tsx\";"
        ]
      },
      "reactComponentMeta": {
        "displayName": "ToggleGroupStyles",
        "exportName": "ToggleGroupStyles",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/ToggleGroup.tsx",
        "description": "",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { ToggleGroupStyles } from \"@gitbutler/ui-react/ToggleGroup.tsx\";"
          ]
        },
        "props": {}
      },
      "stories": [
        {
          "id": "components-togglegroup--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <ToggleGroup render={<ToggleGroupStyles />} defaultValue={[\"list\"]} aria-label=\"View mode\">\n        <Toggle render={<ToggleStyles />} value=\"list\">\n            List\n        </Toggle>\n        <Toggle render={<ToggleStyles />} value=\"tree\">\n            Tree\n        </Toggle>\n    </ToggleGroup>\n);"
        },
        {
          "id": "components-togglegroup--small",
          "name": "Small",
          "snippet": "const Small = () => (\n    <ToggleGroup\n        render={<ToggleGroupStyles />}\n        defaultValue={[\"humans\"]}\n        aria-label=\"Notification type\"\n    >\n        <Toggle render={<ToggleStyles size=\"small\" />} value=\"humans\">\n            Humans\n        </Toggle>\n        <Toggle render={<ToggleStyles size=\"small\" />} value=\"agents\">\n            Agents\n        </Toggle>\n    </ToggleGroup>\n);"
        },
        {
          "id": "components-togglegroup--with-icons",
          "name": "With Icons",
          "snippet": "const WithIcons = () => (\n    <ToggleGroup render={<ToggleGroupStyles />} defaultValue={[\"list\"]} aria-label=\"View mode\">\n        <Toggle render={<ToggleStyles />} value=\"list\">\n            <Icon name=\"list\" size={14} />\n            List\n        </Toggle>\n        <Toggle render={<ToggleStyles />} value=\"tree\">\n            <Icon name=\"folder-tree\" size={14} />\n            Tree\n        </Toggle>\n    </ToggleGroup>\n);"
        },
        {
          "id": "components-togglegroup--with-badge",
          "name": "With Badge",
          "snippet": "const WithBadge = () => (\n    <ToggleGroup render={<ToggleGroupStyles />} defaultValue={[\"selection\"]} aria-label=\"Diff view\">\n        <Toggle render={<ToggleStyles />} value=\"selection\">\n            <Icon name=\"checklist\" size={14} />\n            Selection\n            <Badge variant=\"lightGray\">12</Badge>\n        </Toggle>\n        <Toggle render={<ToggleStyles />} value=\"plain\">\n            <Icon name=\"text-plain\" size={14} />\n            Plain\n        </Toggle>\n        <Toggle render={<ToggleStyles />} value=\"wrap\">\n            <Icon name=\"text-wrap\" size={14} />\n            Wrap\n        </Toggle>\n    </ToggleGroup>\n);"
        },
        {
          "id": "components-togglegroup--icon-only",
          "name": "Icon Only",
          "snippet": "const IconOnly = () => (\n    <ToggleGroup render={<ToggleGroupStyles />} defaultValue={[\"list\"]} aria-label=\"View mode\">\n        <Toggle render={<ToggleStyles iconOnly />} value=\"list\" aria-label=\"List view\">\n            <Icon name=\"list\" size={14} />\n        </Toggle>\n        <Toggle render={<ToggleStyles iconOnly />} value=\"tree\" aria-label=\"Tree view\">\n            <Icon name=\"folder-tree\" size={14} />\n        </Toggle>\n    </ToggleGroup>\n);"
        },
        {
          "id": "components-togglegroup--three-items",
          "name": "Three Items",
          "snippet": "const ThreeItems = () => (\n    <ToggleGroup render={<ToggleGroupStyles />} defaultValue={[\"list\"]} aria-label=\"View mode\">\n        <Toggle render={<ToggleStyles iconOnly />} value=\"list\">\n            <Icon name=\"list\" size={14} />\n        </Toggle>\n        <Toggle render={<ToggleStyles iconOnly />} value=\"tree\">\n            <Icon name=\"folder-tree\" size={14} />\n        </Toggle>\n        <Toggle render={<ToggleStyles iconOnly />} value=\"grid\">\n            <Icon name=\"text-block\" size={14} />\n        </Toggle>\n    </ToggleGroup>\n);"
        },
        {
          "id": "components-togglegroup--multiple-selection",
          "name": "Multiple Selection",
          "snippet": "const MultipleSelection = () => (\n    <ToggleGroup\n        multiple\n        render={<ToggleGroupStyles />}\n        defaultValue={[\"bold\", \"italic\"]}\n        aria-label=\"Text formatting\"\n    >\n        <Toggle render={<ToggleStyles />} value=\"bold\">\n            Bold\n        </Toggle>\n        <Toggle render={<ToggleStyles />} value=\"italic\">\n            Italic\n        </Toggle>\n        <Toggle render={<ToggleStyles />} value=\"underline\">\n            Underline\n        </Toggle>\n    </ToggleGroup>\n);"
        },
        {
          "id": "components-togglegroup--multiple-selection-with-icons-and-labels",
          "name": "Multiple Selection With Icons And Labels",
          "snippet": "const MultipleSelectionWithIconsAndLabels = () => (\n    <ToggleGroup\n        multiple\n        render={<ToggleGroupStyles />}\n        defaultValue={[\"wrap\", \"contain\"]}\n        aria-label=\"Text options\"\n    >\n        <Toggle render={<ToggleStyles />} value=\"wrap\">\n            <Icon name=\"text-wrap\" size={14} />\n            Wrap\n        </Toggle>\n        <Toggle render={<ToggleStyles />} value=\"contain\">\n            <Icon name=\"text-contain\" size={14} />\n            Contain\n        </Toggle>\n        <Toggle render={<ToggleStyles />} value=\"block\">\n            <Icon name=\"text-block\" size={14} />\n            Block\n        </Toggle>\n    </ToggleGroup>\n);"
        },
        {
          "id": "components-togglegroup--multiple-selection-icon-only",
          "name": "Multiple Selection Icon Only",
          "snippet": "const MultipleSelectionIconOnly = () => (\n    <ToggleGroup\n        multiple\n        render={<ToggleGroupStyles />}\n        defaultValue={[\"wrap\", \"contain\"]}\n        aria-label=\"Text options\"\n    >\n        <Toggle render={<ToggleStyles iconOnly />} value=\"wrap\" aria-label=\"Text wrap\">\n            <Icon name=\"text-wrap\" size={14} />\n        </Toggle>\n        <Toggle render={<ToggleStyles iconOnly />} value=\"contain\" aria-label=\"Text contain\">\n            <Icon name=\"text-contain\" size={14} />\n        </Toggle>\n        <Toggle render={<ToggleStyles iconOnly />} value=\"block\" aria-label=\"Text block\">\n            <Icon name=\"text-block\" size={14} />\n        </Toggle>\n    </ToggleGroup>\n);"
        }
      ],
      "import": "import { Badge, Icon, ToggleStyles } from '@gitbutler/ui-react';\nimport { Toggle, ToggleGroup } from '@base-ui/react';\nimport { ToggleGroupStyles } from '@gitbutler/ui-react/ToggleGroup.tsx';"
    },
    "components-toolbox": {
      "id": "components-toolbox",
      "name": "Toolbox",
      "path": "../../packages/ui-react/src/Toolbox.stories.tsx",
      "jsDocTags": {
        "public": [
          ""
        ],
        "import": [
          "import { Toolbox } from \"@gitbutler/ui-react/Toolbox.tsx\";"
        ]
      },
      "description": "A floating card of things to do with what is currently in hand — a checked set, a transfer\nbeing aimed, an absorb waiting on its plan. It states its subject in a {@link ToolboxMeta}\nstrip and stacks one {@link ToolboxSection} per decision the subject still needs.",
      "reactComponentMeta": {
        "displayName": "Toolbox",
        "exportName": "Toolbox",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Toolbox.tsx",
        "description": "A floating card of things to do with what is currently in hand — a checked set, a transfer\nbeing aimed, an absorb waiting on its plan. It states its subject in a {@link ToolboxMeta}\nstrip and stacks one {@link ToolboxSection} per decision the subject still needs.",
        "jsDocTags": {
          "public": [
            ""
          ],
          "import": [
            "import { Toolbox } from \"@gitbutler/ui-react/Toolbox.tsx\";"
          ]
        },
        "props": {}
      },
      "stories": [
        {
          "id": "components-toolbox--default",
          "name": "Default",
          "snippet": "const Default = () => (\n    <Toolbox>\n        <ToolboxMeta icon=\"commit\">\n            <span>3 commits selected</span>\n            <ToolboxMetaHint>Esc to close</ToolboxMetaHint>\n        </ToolboxMeta>\n        <ToolboxSection>\n            <Action label=\"Absorb\" hotkey=\"A\" />\n            <Action label=\"Cut\" hotkey=\"Mod+X\" />\n            <Action label=\"Discard\" hotkey=\"Mod+Backspace\" variant=\"danger\" />\n            <ToolboxSeparator />\n            <Button aria-label=\"Cancel\" variant=\"ghost\" iconOnly>\n                <Icon name=\"cross\" />\n            </Button>\n        </ToolboxSection>\n    </Toolbox>\n);",
          "description": "The acts on a checked set run without confirming, so each one is its own button. With nothing\npending to abandon, the way out is a close affordance and its chord is stated in the strip."
        },
        {
          "id": "components-toolbox--with-confirmation",
          "name": "With Confirmation",
          "snippet": "const WithConfirmation = () => (\n    <Toolbox style={{ width: 270 }}>\n        <ToolboxMeta icon=\"file-diff\">\n            <span>3 files selected</span>\n        </ToolboxMeta>\n        <ToolboxSection variant=\"stretch\">\n            <ToggleGroup render={<ToggleGroupStyles />} defaultValue={[\"above\"]} aria-label=\"Placement\">\n                <Toggle render={<ToggleStyles />} value=\"above\">\n                    Above <Kbd hotkey=\"A\" variant=\"button\" />\n                </Toggle>\n                <Toggle render={<ToggleStyles />} value=\"below\">\n                    Below <Kbd hotkey=\"B\" variant=\"button\" />\n                </Toggle>\n                <Toggle render={<ToggleStyles />} value=\"into\">\n                    Into <Kbd hotkey=\"I\" variant=\"button\" />\n                </Toggle>\n            </ToggleGroup>\n        </ToolboxSection>\n        <ToolboxSection variant=\"confirm\">\n            <Action label=\"Move commit\" hotkey=\"Mod+Enter\" variant=\"gray\" small />\n            <Action label=\"Cancel\" hotkey=\"Escape\" small />\n        </ToolboxSection>\n    </Toolbox>\n);",
          "description": "An operation still being aimed asks for a placement, then for confirmation."
        },
        {
          "id": "components-toolbox--with-type-selector",
          "name": "With Type Selector",
          "snippet": "const WithTypeSelector = () => (\n    <ToolboxStack style={{ width: 322 }}>\n        <Toolbox>\n            <ToolboxSection variant=\"stretch\">\n                <ToggleGroup render={<ToggleGroupStyles />} defaultValue={[\"move\"]} aria-label=\"Kind\">\n                    <Toggle render={<ToggleStyles />} value=\"move\">\n                        Move <Kbd hotkey=\"M\" variant=\"button\" />\n                    </Toggle>\n                    <Toggle render={<ToggleStyles />} value=\"copy\">\n                        Copy <Kbd hotkey=\"C\" variant=\"button\" />\n                    </Toggle>\n                </ToggleGroup>\n            </ToolboxSection>\n        </Toolbox>\n        <Toolbox>\n            <ToolboxMeta icon=\"commit\">\n                <strong>Move</strong>\n                <ToolboxMetaText>docs: update endpoint documentation</ToolboxMetaText>\n                <strong>below</strong>\n                <ToolboxMetaText>migrate BaseButton to TypeScript</ToolboxMetaText>\n            </ToolboxMeta>\n            <ToolboxSection variant=\"stretch\">\n                <ToggleGroup\n                    render={<ToggleGroupStyles />}\n                    defaultValue={[\"above\"]}\n                    aria-label=\"Placement\"\n                >\n                    <Toggle render={<ToggleStyles />} value=\"above\">\n                        Above <Kbd hotkey=\"A\" variant=\"button\" />\n                    </Toggle>\n                    <Toggle render={<ToggleStyles />} value=\"below\">\n                        Below <Kbd hotkey=\"B\" variant=\"button\" />\n                    </Toggle>\n                    <Toggle render={<ToggleStyles />} value=\"into\">\n                        Into <Kbd hotkey=\"I\" variant=\"button\" />\n                    </Toggle>\n                </ToggleGroup>\n            </ToolboxSection>\n            <ToolboxSection variant=\"confirm\">\n                <Action label=\"Cherry-pick\" hotkey=\"Mod+Enter\" variant=\"gray\" small />\n                <Action label=\"Cancel\" hotkey=\"Escape\" small />\n            </ToolboxSection>\n        </Toolbox>\n    </ToolboxStack>\n);",
          "description": "A transfer that can be copied picks its kind in an addon above, and states its subject as a\nsentence."
        },
        {
          "id": "components-toolbox--type-addon",
          "name": "Type Addon",
          "snippet": "const TypeAddon = () => (\n    <Toolbox style={{ width: 322 }}>\n        <ToolboxSection variant=\"stretch\">\n            <ToggleGroup render={<ToggleGroupStyles />} defaultValue={[\"move\"]} aria-label=\"Kind\">\n                <Toggle render={<ToggleStyles />} value=\"move\">\n                    Move <Kbd hotkey=\"M\" variant=\"button\" />\n                </Toggle>\n                <Toggle render={<ToggleStyles />} value=\"copy\">\n                    Copy <Kbd hotkey=\"C\" variant=\"button\" />\n                </Toggle>\n            </ToggleGroup>\n        </ToolboxSection>\n    </Toolbox>\n);",
          "description": "Nothing but the choice, for a toolbox that has already stated its subject elsewhere."
        }
      ],
      "import": "import {\n  Button,\n  Icon,\n  Kbd,\n  ToggleGroupStyles,\n  ToggleStyles,\n  ToolboxMeta,\n  ToolboxMetaHint,\n  ToolboxMetaText,\n  ToolboxSection,\n  ToolboxSeparator,\n  ToolboxStack,\n} from '@gitbutler/ui-react';\nimport { Toggle, ToggleGroup } from '@base-ui/react';\nimport { Toolbox } from '@gitbutler/ui-react/Toolbox.tsx';"
    },
    "components-tooltip": {
      "id": "components-tooltip",
      "name": "Tooltip",
      "path": "../../packages/ui-react/src/Tooltip.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { Tooltip } from \"@gitbutler/ui-react/Tooltip.tsx\";"
        ]
      },
      "description": "A tooltip on the element it wraps. An icon-only button still needs its own `aria-label`: a\ntooltip shows on hover and focus, and a screen reader doesn't read it as the button's name.\n\nA disabled button swallows hover, so give one under a tooltip `focusableWhenDisabled`, which\nkeeps it hoverable and focusable while it can't be pressed.",
      "reactComponentMeta": {
        "displayName": "Tooltip",
        "exportName": "Tooltip",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/Tooltip.tsx",
        "description": "A tooltip on the element it wraps. An icon-only button still needs its own `aria-label`: a\ntooltip shows on hover and focus, and a screen reader doesn't read it as the button's name.\n\nA disabled button swallows hover, so give one under a tooltip `focusableWhenDisabled`, which\nkeeps it hoverable and focusable while it can't be pressed.",
        "jsDocTags": {
          "import": [
            "import { Tooltip } from \"@gitbutler/ui-react/Tooltip.tsx\";"
          ]
        },
        "props": {
          "disabled": {
            "name": "disabled",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the tooltip is disabled.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "open": {
            "name": "open",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the tooltip is currently open.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "onOpenChange": {
            "name": "onOpenChange",
            "required": false,
            "type": {
              "name": "(open: boolean, eventDetails: TooltipRootChangeEventDetails) => void"
            },
            "description": "Event handler called when the tooltip is opened or closed.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "defaultOpen": {
            "name": "defaultOpen",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the tooltip is initially open.\n\nTo render a controlled tooltip, use the `open` prop instead.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "onOpenChangeComplete": {
            "name": "onOpenChangeComplete",
            "required": false,
            "type": {
              "name": "(open: boolean) => void"
            },
            "description": "Event handler called after any animations complete when the tooltip is opened or closed.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "disableHoverablePopup": {
            "name": "disableHoverablePopup",
            "required": false,
            "type": {
              "name": "boolean"
            },
            "description": "Whether the tooltip contents can be hovered without closing the tooltip.",
            "defaultValue": {
              "value": "false"
            },
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "trackCursorAxis": {
            "name": "trackCursorAxis",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"none\" | \"x\" | \"y\" | \"both\"",
              "value": [
                {
                  "value": "\"none\""
                },
                {
                  "value": "\"x\""
                },
                {
                  "value": "\"y\""
                },
                {
                  "value": "\"both\""
                }
              ]
            },
            "description": "Determines which axis the tooltip should track the cursor on.",
            "defaultValue": {
              "value": "'none'"
            },
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "actionsRef": {
            "name": "actionsRef",
            "required": false,
            "type": {
              "name": "RefObject<TooltipRootActions | null>"
            },
            "description": "A ref to imperative actions.\n- `unmount`: Unmounts the tooltip popup.\n- `close`: Closes the tooltip imperatively when called.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "handle": {
            "name": "handle",
            "required": false,
            "type": {
              "name": "TooltipHandle<unknown>"
            },
            "description": "A handle to associate the tooltip with a trigger.\nIf specified, allows external triggers to control the tooltip's open state.\nCan be created with the Tooltip.createHandle() method.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "triggerId": {
            "name": "triggerId",
            "required": false,
            "type": {
              "name": "string | null | undefined"
            },
            "description": "ID of the trigger that the tooltip is associated with.\nThis is useful in conjunction with the `open` prop to create a controlled tooltip.\nThere's no need to specify this prop when the tooltip is uncontrolled (that is, when the `open` prop is not set).",
            "defaultValue": null,
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "defaultTriggerId": {
            "name": "defaultTriggerId",
            "required": false,
            "type": {
              "name": "string | null | undefined"
            },
            "description": "ID of the trigger that the tooltip is associated with.\nThis is useful in conjunction with the `defaultOpen` prop to create an initially open tooltip.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipRootProps",
              "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
            },
            "declarations": [
              {
                "name": "TooltipRootProps",
                "fileName": "../../node_modules/.pnpm/@base-ui+react@1.6.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/tooltip/root/TooltipRoot.d.mts"
              }
            ]
          },
          "content": {
            "name": "content",
            "required": true,
            "type": {
              "name": "ReactNode"
            },
            "description": "What the tooltip says.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipProps",
              "fileName": "../../packages/ui-react/src/Tooltip.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tooltip.tsx"
              }
            ]
          },
          "children": {
            "name": "children",
            "required": true,
            "type": {
              "name": "ReactElement<unknown, string | JSXElementConstructor<any>>"
            },
            "description": "The element it describes, usually a `Button`. It becomes the trigger, so it must take a ref and spread props.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipProps",
              "fileName": "../../packages/ui-react/src/Tooltip.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tooltip.tsx"
              }
            ]
          },
          "kbd": {
            "name": "kbd",
            "required": false,
            "type": {
              "name": "string | HotkeySequence | undefined"
            },
            "description": "A keyboard shortcut shown after the content.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipProps",
              "fileName": "../../packages/ui-react/src/Tooltip.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tooltip.tsx"
              }
            ]
          },
          "kbdScope": {
            "name": "kbdScope",
            "required": false,
            "type": {
              "name": "string"
            },
            "description": "The focus scope the shortcut acts in; see `TooltipPopup`.",
            "defaultValue": null,
            "parent": {
              "name": "TooltipProps",
              "fileName": "../../packages/ui-react/src/Tooltip.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tooltip.tsx"
              }
            ]
          },
          "side": {
            "name": "side",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"top\" | \"bottom\" | \"left\" | \"right\" | \"inline-end\" | \"inline-start\"",
              "value": [
                {
                  "value": "\"top\""
                },
                {
                  "value": "\"bottom\""
                },
                {
                  "value": "\"left\""
                },
                {
                  "value": "\"right\""
                },
                {
                  "value": "\"inline-end\""
                },
                {
                  "value": "\"inline-start\""
                }
              ]
            },
            "description": "",
            "defaultValue": null,
            "parent": {
              "name": "TooltipProps",
              "fileName": "../../packages/ui-react/src/Tooltip.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tooltip.tsx"
              }
            ]
          },
          "sideOffset": {
            "name": "sideOffset",
            "required": false,
            "type": {
              "name": "number"
            },
            "description": "",
            "defaultValue": {
              "value": "4"
            },
            "parent": {
              "name": "TooltipProps",
              "fileName": "../../packages/ui-react/src/Tooltip.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/Tooltip.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-tooltip--default",
          "name": "Default",
          "snippet": "const Default = () => <Tooltip content=\"This is a tooltip\" kbd=\"Mod+A\" side=\"top\"><Button>Hover me</Button></Tooltip>;"
        },
        {
          "id": "components-tooltip--icon-only",
          "name": "Icon Only",
          "snippet": "const IconOnly = () => (\n    <Tooltip content=\"New branch\" kbd=\"Mod+B\">\n        <Button variant=\"ghost\" iconOnly aria-label=\"New branch\">\n            <Icon name=\"plus\" />\n        </Button>\n    </Tooltip>\n);"
        },
        {
          "id": "components-tooltip--on-disabled-button",
          "name": "On Disabled Button",
          "snippet": "const OnDisabledButton = () => (\n    <Tooltip content=\"Nothing to commit\">\n        <Button variant=\"pop\" focusableWhenDisabled disabled>\n            Commit\n        </Button>\n    </Tooltip>\n);"
        }
      ],
      "import": "import { Tooltip as BaseTooltip } from '@base-ui/react';\nimport { Button, Icon } from '@gitbutler/ui-react';\nimport { Tooltip } from '@gitbutler/ui-react/Tooltip.tsx';\nimport { Button } from './Button.tsx';"
    },
    "components-viewheader": {
      "id": "components-viewheader",
      "name": "ViewHeader",
      "path": "../../packages/ui-react/src/ViewHeader.stories.tsx",
      "jsDocTags": {
        "import": [
          "import { ViewHeader } from \"@gitbutler/ui-react/ViewHeader.tsx\";"
        ]
      },
      "description": "The header of a details view: what is shown, a line about it, and the controls for it. Layout\nonly; what goes in each slot is the app's. One component for every view, rather than one per\nview, so the rules that keep the views alike live here: the actions always end the last line,\nand the meta line never wraps.",
      "reactComponentMeta": {
        "displayName": "ViewHeader",
        "exportName": "ViewHeader",
        "filePath": "/home/runner/work/gitbutler/gitbutler/packages/ui-react/src/ViewHeader.tsx",
        "description": "The header of a details view: what is shown, a line about it, and the controls for it. Layout\nonly; what goes in each slot is the app's. One component for every view, rather than one per\nview, so the rules that keep the views alike live here: the actions always end the last line,\nand the meta line never wraps.",
        "jsDocTags": {
          "import": [
            "import { ViewHeader } from \"@gitbutler/ui-react/ViewHeader.tsx\";"
          ]
        },
        "props": {
          "title": {
            "name": "title",
            "required": true,
            "type": {
              "name": "ReactNode"
            },
            "description": "What the view shows. Its first part ellipsizes rather than pushing the actions off the edge;\nanything after it, as a badge, keeps its size.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
              }
            ]
          },
          "icon": {
            "name": "icon",
            "required": false,
            "type": {
              "name": "enum",
              "raw": "\"search\" | \"link\" | \"filter\" | \"contrast\" | \"docs\" | \"file\" | \"copy\" | \"danger\" | \"absorb\" | \"ai\" | \"ai-text\" | \"arrow-corner-down-left\" | \"arrow-corner-left-up\" | \"arrow-corner-right-down\" | \"arrow-corner-up-right\" | \"arrow-double-down\" | \"arrow-double-up\" | \"arrow-down\" | \"arrow-down-left\" | \"arrow-down-right\" | \"arrow-in-box\" | \"arrow-left\" | \"arrow-line-down\" | \"arrow-line-up\" | \"arrow-right\" | \"arrow-up\" | \"arrow-up-left\" | \"arrow-up-right\" | \"bell\" | \"bin\" | \"branch\" | \"branch-merge\" | \"bullet-disc\" | \"bullet-list\" | \"bullseye\" | \"camera\" | \"checklist\" | \"checklist-remove\" | \"chevron-down\" | \"chevron-left\" | \"chevron-right\" | \"chevron-up\" | \"clock\" | \"cloud\" | \"collapse-vertical\" | \"commit\" | \"commit-fill\" | \"cross\" | \"cross-circle\" | \"diff\" | \"discord\" | \"drag-horizontal\" | \"drag-square\" | \"drag-vertical\" | \"edit\" | \"expand-vertical\" | \"eye\" | \"eye-closed\" | \"file-diff\" | \"file-minus\" | \"file-plus\" | \"file-text\" | \"files-sidebar\" | \"finger-print\" | \"folder\" | \"folder-copy\" | \"folder-fork\" | \"folder-lock\" | \"folder-tree\" | \"fork\" | \"globe\" | \"hash\" | \"history\" | \"home\" | \"inbox\" | \"inbox-fill\" | \"info\" | \"kebab\" | \"kebab-vertical\" | \"lab\" | \"list\" | \"lock\" | \"lock-auth\" | \"lock-open\" | \"login\" | \"logout\" | \"minus\" | \"mixer\" | \"number-list\" | \"paperclip\" | \"plug\" | \"plus\" | \"pr\" | \"pr-close\" | \"pr-draft\" | \"question\" | \"question-circle\" | \"refresh\" | \"repo\" | \"resize-handle\" | \"robot\" | \"settings\" | \"sidebar\" | \"sidebar-narrow\" | \"smiley\" | \"spinner\" | \"stack\" | \"tag\" | \"text-block\" | \"text-bold\" | \"text-code\" | \"text-contain\" | \"text-h2\" | \"text-h3\" | \"text-italic\" | \"text-plain\" | \"text-quote\" | \"text-strikethrough\" | \"text-wrap\" | \"theme-dark\" | \"theme-light\" | \"theme-system\" | \"tick\" | \"tick-circle\" | \"tick-double\" | \"undo\" | \"user\" | \"warning\" | \"workbench\"",
              "value": [
                {
                  "value": "\"search\""
                },
                {
                  "value": "\"link\""
                },
                {
                  "value": "\"filter\""
                },
                {
                  "value": "\"contrast\""
                },
                {
                  "value": "\"docs\""
                },
                {
                  "value": "\"file\""
                },
                {
                  "value": "\"copy\""
                },
                {
                  "value": "\"danger\""
                },
                {
                  "value": "\"absorb\""
                },
                {
                  "value": "\"ai\""
                },
                {
                  "value": "\"ai-text\""
                },
                {
                  "value": "\"arrow-corner-down-left\""
                },
                {
                  "value": "\"arrow-corner-left-up\""
                },
                {
                  "value": "\"arrow-corner-right-down\""
                },
                {
                  "value": "\"arrow-corner-up-right\""
                },
                {
                  "value": "\"arrow-double-down\""
                },
                {
                  "value": "\"arrow-double-up\""
                },
                {
                  "value": "\"arrow-down\""
                },
                {
                  "value": "\"arrow-down-left\""
                },
                {
                  "value": "\"arrow-down-right\""
                },
                {
                  "value": "\"arrow-in-box\""
                },
                {
                  "value": "\"arrow-left\""
                },
                {
                  "value": "\"arrow-line-down\""
                },
                {
                  "value": "\"arrow-line-up\""
                },
                {
                  "value": "\"arrow-right\""
                },
                {
                  "value": "\"arrow-up\""
                },
                {
                  "value": "\"arrow-up-left\""
                },
                {
                  "value": "\"arrow-up-right\""
                },
                {
                  "value": "\"bell\""
                },
                {
                  "value": "\"bin\""
                },
                {
                  "value": "\"branch\""
                },
                {
                  "value": "\"branch-merge\""
                },
                {
                  "value": "\"bullet-disc\""
                },
                {
                  "value": "\"bullet-list\""
                },
                {
                  "value": "\"bullseye\""
                },
                {
                  "value": "\"camera\""
                },
                {
                  "value": "\"checklist\""
                },
                {
                  "value": "\"checklist-remove\""
                },
                {
                  "value": "\"chevron-down\""
                },
                {
                  "value": "\"chevron-left\""
                },
                {
                  "value": "\"chevron-right\""
                },
                {
                  "value": "\"chevron-up\""
                },
                {
                  "value": "\"clock\""
                },
                {
                  "value": "\"cloud\""
                },
                {
                  "value": "\"collapse-vertical\""
                },
                {
                  "value": "\"commit\""
                },
                {
                  "value": "\"commit-fill\""
                },
                {
                  "value": "\"cross\""
                },
                {
                  "value": "\"cross-circle\""
                },
                {
                  "value": "\"diff\""
                },
                {
                  "value": "\"discord\""
                },
                {
                  "value": "\"drag-horizontal\""
                },
                {
                  "value": "\"drag-square\""
                },
                {
                  "value": "\"drag-vertical\""
                },
                {
                  "value": "\"edit\""
                },
                {
                  "value": "\"expand-vertical\""
                },
                {
                  "value": "\"eye\""
                },
                {
                  "value": "\"eye-closed\""
                },
                {
                  "value": "\"file-diff\""
                },
                {
                  "value": "\"file-minus\""
                },
                {
                  "value": "\"file-plus\""
                },
                {
                  "value": "\"file-text\""
                },
                {
                  "value": "\"files-sidebar\""
                },
                {
                  "value": "\"finger-print\""
                },
                {
                  "value": "\"folder\""
                },
                {
                  "value": "\"folder-copy\""
                },
                {
                  "value": "\"folder-fork\""
                },
                {
                  "value": "\"folder-lock\""
                },
                {
                  "value": "\"folder-tree\""
                },
                {
                  "value": "\"fork\""
                },
                {
                  "value": "\"globe\""
                },
                {
                  "value": "\"hash\""
                },
                {
                  "value": "\"history\""
                },
                {
                  "value": "\"home\""
                },
                {
                  "value": "\"inbox\""
                },
                {
                  "value": "\"inbox-fill\""
                },
                {
                  "value": "\"info\""
                },
                {
                  "value": "\"kebab\""
                },
                {
                  "value": "\"kebab-vertical\""
                },
                {
                  "value": "\"lab\""
                },
                {
                  "value": "\"list\""
                },
                {
                  "value": "\"lock\""
                },
                {
                  "value": "\"lock-auth\""
                },
                {
                  "value": "\"lock-open\""
                },
                {
                  "value": "\"login\""
                },
                {
                  "value": "\"logout\""
                },
                {
                  "value": "\"minus\""
                },
                {
                  "value": "\"mixer\""
                },
                {
                  "value": "\"number-list\""
                },
                {
                  "value": "\"paperclip\""
                },
                {
                  "value": "\"plug\""
                },
                {
                  "value": "\"plus\""
                },
                {
                  "value": "\"pr\""
                },
                {
                  "value": "\"pr-close\""
                },
                {
                  "value": "\"pr-draft\""
                },
                {
                  "value": "\"question\""
                },
                {
                  "value": "\"question-circle\""
                },
                {
                  "value": "\"refresh\""
                },
                {
                  "value": "\"repo\""
                },
                {
                  "value": "\"resize-handle\""
                },
                {
                  "value": "\"robot\""
                },
                {
                  "value": "\"settings\""
                },
                {
                  "value": "\"sidebar\""
                },
                {
                  "value": "\"sidebar-narrow\""
                },
                {
                  "value": "\"smiley\""
                },
                {
                  "value": "\"spinner\""
                },
                {
                  "value": "\"stack\""
                },
                {
                  "value": "\"tag\""
                },
                {
                  "value": "\"text-block\""
                },
                {
                  "value": "\"text-bold\""
                },
                {
                  "value": "\"text-code\""
                },
                {
                  "value": "\"text-contain\""
                },
                {
                  "value": "\"text-h2\""
                },
                {
                  "value": "\"text-h3\""
                },
                {
                  "value": "\"text-italic\""
                },
                {
                  "value": "\"text-plain\""
                },
                {
                  "value": "\"text-quote\""
                },
                {
                  "value": "\"text-strikethrough\""
                },
                {
                  "value": "\"text-wrap\""
                },
                {
                  "value": "\"theme-dark\""
                },
                {
                  "value": "\"theme-light\""
                },
                {
                  "value": "\"theme-system\""
                },
                {
                  "value": "\"tick\""
                },
                {
                  "value": "\"tick-circle\""
                },
                {
                  "value": "\"tick-double\""
                },
                {
                  "value": "\"undo\""
                },
                {
                  "value": "\"user\""
                },
                {
                  "value": "\"warning\""
                },
                {
                  "value": "\"workbench\""
                }
              ]
            },
            "description": "The glyph for what it is: `branch`, `commit`, `folder`.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
              }
            ]
          },
          "avatar": {
            "name": "avatar",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "An `EntityAvatar` (or its picker) ahead of the title and meta, for an entity rather than a view\nof code: a machine, a cloud session. A branch or a commit takes an `icon` instead.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
              }
            ]
          },
          "leading": {
            "name": "leading",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "Ahead of the title on its line, for the app's own window controls: Lite's sidebar toggle\nand the room it leaves for the traffic lights in full-window mode. Only the title's line\nmakes room for it; the meta line under it starts at the header's edge.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
              }
            ]
          },
          "meta": {
            "name": "meta",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "One line under the title, cut short with an ellipsis rather than wrapped. Parts are joined\nwith \" · \"; the last part is the one that gives way.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
              }
            ]
          },
          "metaTabs": {
            "name": "metaTabs",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "Tabs that lead the meta line rather than take a toolbar of their own: a landed review's\nDiff / Pull Request, on a commit whose header has no other row for them.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
              }
            ]
          },
          "children": {
            "name": "children",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "The rest of what the title begins, as a commit's message body. It stays folded behind a\ntoggle after the title, and opens under it, above the meta line.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
              }
            ]
          },
          "toolbar": {
            "name": "toolbar",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "The row under the title block: the view's tabs, a divider, the commit filter. Omit it when\nthe view has no tabs, and the header is the title block alone.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
              }
            ]
          },
          "actions": {
            "name": "actions",
            "required": false,
            "type": {
              "name": "ReactNode"
            },
            "description": "Every button the view has: Send, Apply to workspace, previous and next, a menu, and on a\npull request tab its toolbar. They sit at the end of the header's last line, wherever that\nis: the toolbar's end when there is a toolbar, otherwise level with the meta line, otherwise\nbeside the title. Never the diff's own controls; those sit in the bar over the diff.",
            "defaultValue": null,
            "parent": {
              "name": "Props",
              "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
            },
            "declarations": [
              {
                "name": "TypeLiteral",
                "fileName": "../../packages/ui-react/src/ViewHeader.tsx"
              }
            ]
          }
        }
      },
      "stories": [
        {
          "id": "components-viewheader--default",
          "name": "Default",
          "snippet": "const Default = () => <ViewHeader\n    icon=\"branch\"\n    title=\"feature/JIRA-404-search-filters\"\n    meta=\"4 commits ahead of origin/master · 36 behind · draft #15941 · 2 of 32 checks failing\" />;"
        },
        {
          "id": "components-viewheader--branch",
          "name": "Branch",
          "snippet": "const Branch = () => <ViewHeader\n    icon=\"branch\"\n    title=\"feature/JIRA-404-search-filters\"\n    meta=\"4 commits ahead of origin/master · 36 behind · draft #15941 · 2 of 32 checks failing\"\n    toolbar={(<>\n        <BranchTabs />\n        <ViewHeaderDivider />\n        <CommitFilter />\n    </>)} />;",
          "description": "An applied branch on the Diff tab: its tabs, a divider and the commit filter. No buttons.",
          "warning": "Incomplete snippet: `BranchTabs`, `CommitFilter` could not be resolved statically."
        },
        {
          "id": "components-viewheader--branch-full-window",
          "name": "Branch Full Window",
          "snippet": "const BranchFullWindow = () => <ViewHeader\n    leading={(<div style={{ display: \"flex\", columnGap: 12, alignItems: \"center\" }}>\n        <div style={{ width: 64 }} />\n        <Button iconOnly variant=\"ghost\" aria-label=\"Show the sidebar\">\n            <Icon name=\"sidebar-narrow\" />\n        </Button>\n        <ViewHeaderDivider />\n    </div>)}\n    icon=\"branch\"\n    title=\"feature/JIRA-404-search-filters\"\n    meta=\"4 commits ahead of origin/master · 36 behind · draft #15941 · 2 of 32 checks failing\"\n    toolbar={(<>\n        <BranchTabs />\n        <ViewHeaderDivider />\n        <CommitFilter />\n    </>)} />;",
          "description": "Lite in full-window mode: the window's controls lead the title's line, after the room the\ntraffic lights take. The meta line and the toolbar still start at the header's edge.",
          "warning": "Incomplete snippet: `BranchTabs`, `CommitFilter` could not be resolved statically."
        },
        {
          "id": "components-viewheader--branch-pull-request-tab",
          "name": "Branch Pull Request Tab",
          "snippet": "const BranchPullRequestTab = () => <ViewHeader\n    icon=\"branch\"\n    title=\"feature/JIRA-404-search-filters\"\n    meta=\"4 commits ahead of origin/master · 36 behind · draft #15941 · 2 of 32 checks failing\"\n    toolbar={<BranchTabs tab=\"pr\" />}\n    actions={(<>\n        <Button variant=\"ghost\">\n            Edit\n            <Icon name=\"edit\" />\n        </Button>\n        <SwitchButton label=\"Auto-merge\" variant=\"outline\" />\n        <DropdownButton variant=\"pop\" menuLabel=\"Merge options\" onMenuTrigger={() => {}}>\n            Merge\n        </DropdownButton>\n        <Button variant=\"ghost\" iconOnly aria-label=\"Pull request menu\">\n            <Icon name=\"kebab\" />\n        </Button>\n    </>)} />;",
          "description": "The Pull Request tab: the commit filter leaves with the diff, and the pull request's own\ntoolbar takes the end. Ghosts for Edit and the menu, an outline switch for Auto-merge since it\nholds state, and Merge as the surface's one pop.",
          "warning": "Incomplete snippet: `BranchTabs` could not be resolved statically."
        },
        {
          "id": "components-viewheader--branch-not-applied",
          "name": "Branch Not Applied",
          "snippet": "const BranchNotApplied = () => <ViewHeader\n    icon=\"branch\"\n    title=\"debug-this-nightmare\"\n    meta=\"3 commits ahead of origin/master\"\n    toolbar={<BranchTabs prDisabled />}\n    actions={<Button variant=\"gray\">Apply to workspace</Button>} />;",
          "description": "A branch outside the workspace: no review, so the tab says why, and Apply is its action.",
          "warning": "Incomplete snippet: `BranchTabs` could not be resolved statically."
        },
        {
          "id": "components-viewheader--commit",
          "name": "Commit",
          "snippet": "const Commit = () => <ViewHeader\n    icon=\"commit\"\n    title=\"fix: sanitize user input in search query\"\n    meta={<CommitAuthorLine />}><CommitBody /></ViewHeader>;",
          "description": "No tabs, so no toolbar: the author line ends the header.",
          "warning": "Incomplete snippet: `CommitAuthorLine`, `CommitBody` could not be resolved statically."
        },
        {
          "id": "components-viewheader--commit-landed-review",
          "name": "Commit Landed Review",
          "snippet": "const CommitLandedReview = () => <ViewHeader\n    icon=\"commit\"\n    title=\"Add test file 18 to collection\"\n    metaTabs={<BranchTabs tab=\"pr\" />}\n    meta={<CommitAuthorLine />}><CommitBody /></ViewHeader>;",
          "description": "A commit whose review has landed: its tabs lead the author line rather than take a row.",
          "warning": "Incomplete snippet: `BranchTabs`, `CommitAuthorLine`, `CommitBody` could not be resolved statically."
        },
        {
          "id": "components-viewheader--commit-conflicted",
          "name": "Commit Conflicted",
          "snippet": "const CommitConflicted = () => <ViewHeader\n    icon=\"commit\"\n    title={(<>\n        <span>fix: sanitize user input in search query before it reaches the index</span>\n        <Badge variant=\"danger\">Conflicted</Badge>\n    </>)}\n    meta={<CommitAuthorLine />}><CommitBody /></ViewHeader>;",
          "description": "A conflicted commit: the badge keeps its size while the subject gives way.",
          "warning": "Incomplete snippet: `CommitAuthorLine`, `CommitBody` could not be resolved statically."
        },
        {
          "id": "components-viewheader--commit-with-picker",
          "name": "Commit With Picker",
          "snippet": "const CommitWithPicker = () => <ViewHeader\n    icon=\"commit\"\n    title=\"fix: sanitize user input in search query\"\n    meta={<CommitAuthorLine />}\n    actions={(<>\n        <Button iconOnly aria-label=\"Previous commit\">\n            <Icon name=\"arrow-left\" />\n        </Button>\n        <Button>1 of 4</Button>\n        <Button iconOnly aria-label=\"Next commit\">\n            <Icon name=\"arrow-right\" />\n        </Button>\n    </>)}><CommitBody /></ViewHeader>;",
          "description": "but.dev's commit, stepping through a branch's commits. No toolbar, so the buttons sit level\nwith the author line.",
          "warning": "Incomplete snippet: `CommitAuthorLine`, `CommitBody` could not be resolved statically."
        },
        {
          "id": "components-viewheader--uncommitted",
          "name": "Uncommitted",
          "snippet": "const Uncommitted = () => <ViewHeader icon=\"file-diff\" title=\"Uncommitted\" />;",
          "description": "A clean worktree: the title alone."
        },
        {
          "id": "components-viewheader--worktree",
          "name": "Worktree",
          "snippet": "const Worktree = () => <ViewHeader\n    icon=\"folder\"\n    title=\"gitbutler\"\n    meta=\"Workspace · 2 branches · 4 unpushed · 3 uncommitted files\"\n    actions={<SendAndMenu />} />;",
          "description": "but.dev's repository checkout: what it holds besides commits, and where to send it.",
          "warning": "Incomplete snippet: `SendAndMenu` could not be resolved statically."
        },
        {
          "id": "components-viewheader--machine",
          "name": "Machine",
          "snippet": "const Machine = () => <ViewHeader\n    avatar={<EntityAvatar value={{ _tag: \"Picture\", src: machinePictures[0].src }} />}\n    title=\"pave--macbook-pro\"\n    meta=\"macOS · but 0.19 · connected since 3 Sep\"\n    actions={<SendAndMenu />} />;",
          "description": "but.dev's machine: an entity, so it wears the picture of its kind as its avatar.",
          "warning": "Incomplete snippet: `SendAndMenu` could not be resolved statically."
        },
        {
          "id": "components-viewheader--cloud-session",
          "name": "Cloud Session",
          "snippet": "const CloudSession = () => <ViewHeader\n    avatar={<EntityAvatar value={{ _tag: \"Emoji\", emoji: \"☁️\" }} />}\n    title=\"Panel incoming commits count\"\n    meta=\"Claude Code · started from your phone · works on feature/JIRA-404-search-filters · 4 commits · 3 uncommitted\"\n    toolbar={(<>\n        <BranchTabs />\n        <ViewHeaderDivider />\n        <CommitFilter />\n    </>)}\n    actions={(<Button variant=\"pop\">\n        <Icon name=\"arrow-right\" />Send to…\n                    </Button>)} />;",
          "description": "but.dev's cloud session: an avatar, the branch's tabs, and Send to… as the surface's pop.",
          "warning": "Incomplete snippet: `BranchTabs`, `CommitFilter` could not be resolved statically."
        }
      ],
      "import": "import {\n  Avatar,\n  Badge,\n  Button,\n  CopyableId,\n  DropdownButton,\n  EntityAvatar,\n  Icon,\n  SwitchButton,\n  ToggleGroupStyles,\n  ToggleStyles,\n  ViewHeaderDivider,\n} from '@gitbutler/ui-react';\nimport { Toggle, ToggleGroup } from '@base-ui/react';\nimport { ViewHeader } from '@gitbutler/ui-react/ViewHeader.tsx';\nimport { ViewHeaderDivider } from './ViewHeader.tsx';\nimport { Button } from './Button.tsx';\nimport { Icon } from './Icon.tsx';\nimport { SwitchButton } from './SwitchButton.tsx';\nimport { DropdownButton } from './DropdownButton.tsx';\nimport { Badge } from './Badge.tsx';\nimport { EntityAvatar } from './EntityAvatar.tsx';\nimport { machinePictures } from './story-assets/machines.ts';"
    }
  },
  "meta": {
    "docgen": "react-component-meta",
    "durationMs": 6051
  }
}