{
  "name": "AgentStop",
  "source": "src/components/AgentStop.tsx",
  "propsType": "AgentStopProps",
  "description": "AgentStop — the always-visible way to end a run.\n\nNOT OPTIONAL, AND NOT BEHIND A MENU. A user who cannot stop an agent is\nwatching it, not supervising it. Human oversight of an automated process is\na compliance surface in regulated contexts, not a UX preference, and the\ncontrol that provides it has to be present and reachable at the moment it is\nwanted — not two clicks into an overflow menu.\n\nWHY IT IS NOT JUST `<Button variant=\"destructive\">`\n\nThree things it owns that a Button does not:\n\n  It keeps its place while stopping. A control that vanishes the instant it\n  is pressed leaves the user unsure whether the press registered, and the\n  run is usually still going. It stays, relabels, and disables — the layout\n  does not move.\n\n  It announces. The label change is only announced to a screen reader if the\n  button happens to hold focus, which it usually does not when a run was\n  started elsewhere. A polite live region says \"Stopping\" once.\n\n  It is not destructive-red. Stopping is a normal, expected, reversible-in-\n  spirit action — you can run it again. Colouring it like `delete` teaches\n  hesitation about the one control that must never be hesitated over.\n\nWHAT IT DOES NOT DO. It does not stop anything. It reports intent; the\ncaller aborts the request, closes the stream and settles the state. A stop\nbutton that resolves optimistically while tokens keep arriving is worse than\nnone, because it lies about a guarantee the user is relying on.",
  "import": "import { AgentStop } from 'ionbase-ui';",
  "status": "stable",
  "summary": "The always-visible way to end a running agent. Not optional, and not behind a menu.",
  "useWhen": [
    "anything runs long enough that a person might want it to stop — a generation, a tool chain, a batch job",
    "the run was started by the user and is still going"
  ],
  "useInstead": [
    {
      "when": "the action is instant and there is nothing to interrupt",
      "use": "Button"
    },
    {
      "when": "you are asking permission before something happens rather than ending something already happening",
      "use": "ApprovalGate"
    },
    {
      "when": "the thing to undo has already finished",
      "use": "Toast",
      "why": "an undo affordance belongs with the confirmation of what was done"
    }
  ],
  "variants": {
    "size": {
      "sm": {
        "use": "inside a toolbar or beside an inline activity row"
      },
      "md": {
        "use": "the default"
      },
      "lg": {
        "use": "a full-width run surface where stopping is the primary available action"
      }
    }
  },
  "a11y": {
    "role": "button",
    "guarantees": [
      "the control keeps its place while stopping — it relabels and disables rather than disappearing, so the layout does not move under the pointer",
      "the transition to stopping is announced once through a polite live region, because the label change alone is only heard if the button happens to hold focus",
      "`stopOnEscape` ignores Escape raised inside a dialog, so closing a modal never cancels a background run"
    ],
    "requires": [
      "keeping it rendered and visible for the whole run — a stop control that scrolls away or hides in an overflow menu is the failure this component exists to prevent"
    ],
    "notes": [
      "It does not stop anything. It reports intent; aborting the request and settling the state is the caller's. A stop that resolves optimistically while output keeps arriving lies about the one guarantee the user is relying on."
    ]
  },
  "antiPatterns": [
    {
      "dont": "putting the stop control in an overflow menu",
      "why": "a user who cannot reach it is watching the agent, not supervising it"
    },
    {
      "dont": "disabling it while the run is going",
      "why": "the only correct disabled state is `isStopping` — after the request, never before"
    },
    {
      "dont": "unmounting it the moment it is pressed",
      "do": "pass `isStopping`",
      "why": "the run is usually still going, and a control that vanishes leaves the user unsure the press registered"
    },
    {
      "dont": "styling it as destructive",
      "why": "stopping is normal and repeatable; red teaches hesitation about the one control that must never be hesitated over"
    },
    {
      "dont": "`stopOnEscape` on a page with modals over the run",
      "why": "Escape already means dismiss to every overlay in this system"
    }
  ],
  "stylesheet": "src/styles/agent-stop.css",
  "tokens": [
    "--border-default",
    "--border-error",
    "--border-focus",
    "--border-strong",
    "--border-width-default",
    "--border-width-thick",
    "--font-family-sans",
    "--font-weight-medium",
    "--icon-size-md",
    "--icon-size-sm",
    "--icon-size-xs",
    "--ion-duration-base",
    "--ion-ease-out",
    "--radius-md",
    "--spacing-12",
    "--spacing-16",
    "--spacing-20",
    "--spacing-32",
    "--spacing-40",
    "--spacing-48",
    "--spacing-8",
    "--surface-default",
    "--surface-error-subtle",
    "--surface-error-subtle-hover",
    "--surface-muted",
    "--text-default",
    "--text-error",
    "--text-secondary",
    "--type-body",
    "--type-body-line-height",
    "--type-body-md",
    "--type-body-md-line-height",
    "--type-body-sm",
    "--type-body-sm-line-height"
  ],
  "props": {
    "onStop": {
      "type": "() => void",
      "required": true,
      "origin": "own",
      "description": "Called when the user asks the run to stop."
    },
    "isStopping": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own",
      "description": "The request is in flight. The control stays visible and keeps its place;\nit does not disappear while the thing it cancels is still running."
    },
    "label": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Visible label."
    },
    "stoppingLabel": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Visible label once `isStopping` is set."
    },
    "size": {
      "type": "AgentStopSize | undefined",
      "required": false,
      "origin": "own",
      "values": [
        "sm",
        "md",
        "lg"
      ]
    },
    "stopOnEscape": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own",
      "description": "Bind Escape, at the document, to stop the run.\n\nOff by default and deliberately so: Escape already means \"dismiss the\nthing in front of me\" to every modal, popover and menu in this system, and\na document-level handler would cancel a background run when the user meant\nto close a dialog. Turn it on only where the run IS the foreground task."
    }
  },
  "propCounts": {
    "own": 6,
    "aria": 0,
    "dom": 286,
    "other": 0
  }
}
