# Drawer

> A panel that slides in from the right for details and settings people look at for a while, and on a phone a bottom sheet for picking a place to go or reading a short explanation.

Source: https://raft-design.botiverse.build/components/drawer. Generated from the current release; where it differs from what you remember, this page is right.

A drawer slides in from the right with details and settings that people look at for a while, scroll and edit, such as the details and members of #launch-week. The page stays in place behind it, under a scrim. On a phone the same component rises from the bottom as a bottom sheet: to pick a place to go, or to read a short explanation with one button.

```tsx
import {
  Button,
  Drawer,
  DrawerActions,
  DrawerBody,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
  Field,
  FieldDescription,
  FieldLabel,
  Input,
  Textarea,
} from "@botiverse/raft-ui";
import { useMediaQuery } from "foxact/use-media-query";

const PLACEHOLDER_NOTES = [
  "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
  "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
  "Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris.",
  "Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis. Morbi in sem quis dui placerat ornare.",
] as const;

export function DrawerResponsivePlacementComposition() {
  const isMobile = useMediaQuery("(max-width: 767px)", false);
  const swipeDirection = isMobile ? "down" : "right";

  return (
    <Drawer swipeDirection={swipeDirection}>
      <DrawerTrigger render={<Button variant="primary" />}>Open details</DrawerTrigger>
      <DrawerContent>
        <DrawerHeader>
          <DrawerTitle>Edit profile</DrawerTitle>
          {swipeDirection === "right" ? <DrawerClose /> : null}
        </DrawerHeader>
        <DrawerBody className="min-h-0 w-full items-stretch overflow-y-auto overscroll-contain text-left">
          <DrawerDescription className="text-left">
            Desktop opens from the right. Below md it switches to a bottom sheet. Scroll the body to
            verify longer form content.
          </DrawerDescription>
          <div className="mt-6 grid w-full gap-4">
            <Field>
              <FieldLabel htmlFor="drawer-responsive-name" required>
                Display name
              </FieldLabel>
              <Input id="drawer-responsive-name" defaultValue="Alex Rivera" />
            </Field>
            <Field>
              <FieldLabel htmlFor="drawer-responsive-email" required>
                Email
              </FieldLabel>
              <Input id="drawer-responsive-email" type="email" defaultValue="alex@example.com" />
            </Field>
            <Field>
              <FieldLabel htmlFor="drawer-responsive-title" optional>
                Title
              </FieldLabel>
              <Input id="drawer-responsive-title" defaultValue="Design engineer" />
              <FieldDescription>Shown on your profile and in mentions.</FieldDescription>
            </Field>
            <Field>
              <FieldLabel htmlFor="drawer-responsive-location" optional>
                Location
              </FieldLabel>
              <Input id="drawer-responsive-location" defaultValue="San Francisco, CA" />
            </Field>
            <Field>
              <FieldLabel htmlFor="drawer-responsive-website" optional>
                Website
              </FieldLabel>
              <Input id="drawer-responsive-website" defaultValue="https://example.com" />
            </Field>
            <Field>
              <FieldLabel htmlFor="drawer-responsive-bio" optional>
                Bio
              </FieldLabel>
              <Textarea
                id="drawer-responsive-bio"
                className="min-h-28"
                defaultValue="Open Raft as a fullscreen app — faster, more focused. Prefer short updates and clear handoffs."
              />
            </Field>
            <div className="stack-y-3 text-sm leading-6 text-foreground/70">
              {PLACEHOLDER_NOTES.map((paragraph) => (
                <p key={paragraph.slice(0, 24)}>{paragraph}</p>
              ))}
            </div>
          </div>
        </DrawerBody>
        <DrawerFooter>
          <DrawerActions>
            <DrawerClose render={<Button variant="primary" />}>Save</DrawerClose>
            <DrawerClose render={<Button variant="outline" />}>Cancel</DrawerClose>
          </DrawerActions>
        </DrawerFooter>
      </DrawerContent>
    </Drawer>
  );
}
```

## When to use

| Situation                                                      | Use                                                                                                                                                      |
| -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Details or settings people read, scroll and edit               | Drawer, from the right                                                                                                                                   |
| A large form filled in one pass: registering or editing an app | The wide [Dialog](https://raft-design.botiverse.build/components/dialog.md), not a wide drawer ([Forms](https://raft-design.botiverse.build/patterns/forms.md#the-large-form-dialog))                       |
| Switching server, on a phone                                   | Not a drawer: a popover under the top bar ([Navigation](https://raft-design.botiverse.build/patterns/navigation.md#servers)). Working now is a popover, on a phone too |
| A sentence or two and one button, on a phone                   | A bottom sheet                                                                                                                                           |
| Acting on one thing                                            | A menu ([DropdownMenu](https://raft-design.botiverse.build/components/dropdown-menu.md), [ContextMenu](https://raft-design.botiverse.build/components/context-menu.md)), never a bottom sheet                         |
| Picking a value, such as sort order or status                  | The list of a [Select](https://raft-design.botiverse.build/components/select.md), or radio items in a menu                                                                                    |
| Confirming                                                     | [AlertDialog](https://raft-design.botiverse.build/components/alert-dialog.md)                                                                                                           |
| A glance on hover                                              | [PreviewCard](https://raft-design.botiverse.build/components/preview-card.md)                                                                                                           |
| A thread or a profile kept open beside the conversation        | A side panel ([ThreadPanel](https://raft-design.botiverse.build/components/thread-panel.md), [Panel](https://raft-design.botiverse.build/components/panel.md)), which is not a drawer and has no scrim                        |

## Anatomy

- `Drawer`: the root. Its `swipeDirection` sets the edge it comes from. Required.
- `DrawerTrigger`: the button that opens it.
- `DrawerContent`: the surface, portaled, with the scrim (`DrawerOverlay`) behind it when the drawer is modal. Required. It is `layer-popover` with a `line-seam` edge and `shadow-float`, like every other popup, not an ink border and a hard shadow: every floating surface uses the same shadow ([Elevation](https://raft-design.botiverse.build/foundations/elevation.md)).
- `DrawerHeader`: the title row. In a drawer from the right it is 56px tall, with a `line-seam` under it and `DrawerClose` at its end.
- `DrawerTitle`: the title. Required, unless the content has an `aria-label`.
- `DrawerDescription`: a sentence under the title.
- `DrawerBody`: the content. It scrolls.
- `DrawerFooter`: the bottom bar. In a drawer from the right it has a `line-seam` over it.
- `DrawerActions`: the buttons in the footer, in a row at the end in a drawer and stacked full width in a bottom sheet.
- `DrawerClose`: closes the drawer. Without children it is the × icon button; with `render` it turns another button into a close button.
- `DrawerPortal` and `DrawerOverlay`: lower-level parts.

## Variants

| Variant                           | Use for                                                                                         |
| --------------------------------- | ----------------------------------------------------------------------------------------------- |
| `swipeDirection="right"`          | The drawer: details and settings on desktop, at most 420px wide and the full window height      |
| `swipeDirection="down"` (default) | The bottom sheet, on a phone                                                                    |
| `snapPoints`                      | A bottom sheet that opens to a summary and expands to its full height. It shows the grab handle |

```tsx
import type { CSSProperties } from "react";
import {
  Button,
  Drawer,
  DrawerActions,
  DrawerBody,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
} from "@botiverse/raft-ui";
import type { DrawerProps } from "@botiverse/raft-ui";

const EXPANDED_HEIGHT = "24rem";
const SNAP_POINTS = ["8rem", EXPANDED_HEIGHT] satisfies NonNullable<DrawerProps["snapPoints"]>;
const SNAP_CONTENT_STYLE = {
  "--drawer-content-height": EXPANDED_HEIGHT,
} as CSSProperties;

export function DrawerSnapPointsComposition() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-2">
      <Drawer swipeDirection="down" snapPoints={SNAP_POINTS} defaultSnapPoint={SNAP_POINTS[0]}>
        <DrawerTrigger render={<Button variant="primary" />}>
          Open bottom notification
        </DrawerTrigger>
        <DrawerContent style={SNAP_CONTENT_STYLE}>
          <DrawerHeader className="py-3">
            <DrawerTitle>Release ready</DrawerTitle>
            <DrawerDescription>raft-ui 0.0.21 passed all release checks.</DrawerDescription>
          </DrawerHeader>
          <DrawerBody>
            <dl className="mt-6 grid w-full grid-cols-[auto_minmax(0,1fr)] gap-x-6 gap-y-3 text-left text-sm leading-6">
              <dt className="text-foreground-muted">Owner</dt>
              <dd className="text-foreground">Maya Chen</dd>
              <dt className="text-foreground-muted">Due</dt>
              <dd className="text-foreground">July 16, 2026</dd>
              <dt className="text-foreground-muted">Checklist</dt>
              <dd className="text-foreground">3 of 5 complete</dd>
            </dl>
            <DrawerActions className="mt-6">
              <DrawerClose render={<Button variant="primary" />}>Dismiss Notification</DrawerClose>
            </DrawerActions>
          </DrawerBody>
        </DrawerContent>
      </Drawer>
      <Drawer swipeDirection="up" snapPoints={SNAP_POINTS} defaultSnapPoint={SNAP_POINTS[0]}>
        <DrawerTrigger render={<Button variant="primary" />}>Open top notification</DrawerTrigger>
        <DrawerContent style={SNAP_CONTENT_STYLE}>
          <DrawerBody>
            <dl className="grid w-full grid-cols-[auto_minmax(0,1fr)] gap-x-6 gap-y-3 text-left text-sm leading-6">
              <dt className="text-foreground-muted">Owner</dt>
              <dd className="text-foreground">Maya Chen</dd>
              <dt className="text-foreground-muted">Due</dt>
              <dd className="text-foreground">July 16, 2026</dd>
              <dt className="text-foreground-muted">Checklist</dt>
              <dd className="text-foreground">3 of 5 complete</dd>
            </dl>
            <DrawerActions className="mt-6">
              <DrawerClose render={<Button variant="primary" />}>Dismiss Notification</DrawerClose>
            </DrawerActions>
          </DrawerBody>
          <DrawerHeader className="py-3">
            <DrawerTitle>Release ready</DrawerTitle>
            <DrawerDescription>raft-ui 0.0.21 passed all release checks.</DrawerDescription>
          </DrawerHeader>
        </DrawerContent>
      </Drawer>
    </div>
  );
}
```

## Behavior

- A drawer slides in from its edge with `ease-slide`. It is the only overlay that moves, because the slide shows where it came from ([Motion](https://raft-design.botiverse.build/foundations/motion.md#usage)).
- A modal drawer puts the same scrim as a dialog over the rest of the page: the page can't be used while the drawer is open, and the scrim says so. A click on the scrim closes it. A bottom sheet has the scrim too.
- Swiping toward its edge dismisses a drawer.
- A drawer opened from a drawer stacks on top of it, and the one below steps back.
- On a phone, a drawer from the right fills the screen and works as a page: no ×, and Back at the top left.
- A bottom sheet rises to at most 82% of the window height, with `radius-dialog` on its top corners, and keeps clear of the home indicator.

```tsx
import { useCallback, useState } from "react";
import { createToastManager, ToastProvider } from "@botiverse/raft-ui";

import { MemberDetailsDrawer } from "./workspace-settings/member-details-drawer.tsx";
import { RemoveMemberDrawer } from "./workspace-settings/remove-member-drawer.tsx";
import { WorkspaceSettingsDrawer } from "./workspace-settings/workspace-settings-drawer.tsx";

export function DrawerNestedCloseCallbackComposition() {
  const [toastManager] = useState(() => createToastManager());
  const [memberDetailsOpen, setMemberDetailsOpen] = useState(false);
  const [removeMemberOpen, setRemoveMemberOpen] = useState(false);

  const notifyClosed = useCallback(
    (title: string) => {
      toastManager.add({ title, type: "info" });
    },
    [toastManager],
  );

  const handleWorkspaceSettingsOpenChangeComplete = useCallback(
    (open: boolean) => {
      if (!open) notifyClosed("Workspace settings closed");
    },
    [notifyClosed],
  );

  const handleMemberDetailsOpenChangeComplete = useCallback(
    (open: boolean) => {
      if (!open) notifyClosed("Member details closed");
    },
    [notifyClosed],
  );

  const handleRemoveMemberOpenChangeComplete = useCallback(
    (open: boolean) => {
      if (!open) notifyClosed("Remove member closed");
    },
    [notifyClosed],
  );

  const handleRemove = useCallback(() => {
    setRemoveMemberOpen(false);
    setMemberDetailsOpen(false);
  }, []);

  return (
    <ToastProvider
      toastManager={toastManager}
      timeout={2400}
      limit={3}
      viewportPlacement="top-center"
    >
      <WorkspaceSettingsDrawer onOpenChangeComplete={handleWorkspaceSettingsOpenChangeComplete}>
        <MemberDetailsDrawer
          open={memberDetailsOpen}
          onOpenChange={setMemberDetailsOpen}
          onOpenChangeComplete={handleMemberDetailsOpenChangeComplete}
        >
          <RemoveMemberDrawer
            open={removeMemberOpen}
            onOpenChange={setRemoveMemberOpen}
            onOpenChangeComplete={handleRemoveMemberOpenChangeComplete}
            onRemove={handleRemove}
          />
        </MemberDetailsDrawer>
      </WorkspaceSettingsDrawer>
    </ToastProvider>
  );
}
```

## Content

- Title it with the words of the button that opened it ([Writing](https://raft-design.botiverse.build/content/writing.md#actions-and-their-dialogs)).
- In a bottom sheet, write the explanation in one or two sentences, in `foreground-muted`, and its button as one action in Title Case: Got It.

## Accessibility

- Drawer wraps the Base UI Drawer. It provides the `dialog` semantics, the focus trap of a modal drawer, Esc, swipe to dismiss, and focus return to the trigger.
- Give every drawer and bottom sheet a title: a visible `DrawerTitle`, or at least an `aria-label` on `DrawerContent`.
- The × of `DrawerClose` is labeled "Close". On a phone, give the Back button that replaces it an `aria-label` ("Back").
- The grab handle is hidden from assistive technology. Never make swiping the only way to close: keep ×, Back or a button in the sheet.

## Rules

- Keep a drawer to 420px at most. A form that needs more room is the wide [Dialog](https://raft-design.botiverse.build/components/dialog.md).
- Make the × the same icon button as in a panel header, with the same icon size, and put it last in `DrawerHeader`: its icon box ends on the margin, and a Back that replaces it on a phone starts on it ([Alignment](https://raft-design.botiverse.build/foundations/alignment.md#the-ends-of-a-header)).
- Put the buttons in the footer, never in the header. They are `size="lg"` (44px on a phone, 32px on a desktop): Cancel first, Save last ([Forms](https://raft-design.botiverse.build/patterns/forms.md#forms-in-a-dialog)).
- Split a long form in a drawer into [FormSection](https://raft-design.botiverse.build/components/form-section.md) parts, the same sections as in the wide dialog, and save them all together with the footer's Save.
- Under each yes-or-no checkbox in a drawer form, add a line that says what happens when it is unchecked. It is a checkbox, not a switch, because the form is saved ([Forms](https://raft-design.botiverse.build/patterns/forms.md#forms-in-a-dialog)).
- Give every bottom sheet a grab handle at its top edge.
- In a bottom sheet list, make each row 52px tall, with a 20px icon and the label in `text-body`, medium. Mark the current row with a check mark and bold text.

## API

### Drawer

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `actionsRef` | `RefObject<DrawerRootActions \| null>` |  | A ref to imperative actions. - `unmount`: Manually unmounts the drawer. Call this after any externally controlled closing animation finishes. - `close`: Closes the drawer imperatively when called. |
| `children` | `ReactNode \| PayloadChildRenderFunction<unknown>` |  | The content of the drawer. |
| `defaultOpen` | `boolean` | `false` | Whether the drawer is initially open. |
| `defaultSnapPoint` | `DrawerSnapPoint` |  | The initial snap point value when uncontrolled. |
| `defaultTriggerId` | `string` |  | ID of the trigger that the drawer is associated with. This is useful in conjunction with the `defaultOpen` prop to create an initially open drawer. |
| `disablePointerDismissal` | `boolean` | `false` | Whether to prevent the drawer from closing on outside presses. For non-modal drawers, this also prevents the drawer from closing when focus moves outside of it. |
| `handle` | `DrawerPrimitive.Handle<unknown>` |  | A handle to associate the drawer with a trigger. If specified, allows detached triggers to control the drawer's open state. Can be created with the Drawer.createHandle() method. |
| `modal` | `boolean \| "trap-focus"` | `true` | Determines if the drawer enters a modal state when open. - `true`: user interaction is limited to just the drawer: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled. - `false`: user interaction with the rest of the document is allowed. - `'trap-focus'`: focus is trapped inside the drawer, but document page scroll is not locked and pointer interactions outside of it remain enabled. |
| `onOpenChange` | `(open: boolean, eventDetails: DrawerPrimitive.Root.ChangeEventDetails) => void` |  | Event handler called when the drawer is opened or closed. |
| `onOpenChangeComplete` | `(open: boolean) => void` |  | Event handler called after any animations complete when the drawer is opened or closed. |
| `onSnapPointChange` | `(snapPoint: DrawerSnapPoint \| null, eventDetails: DrawerPrimitive.Root.SnapPointChangeEventDetails) => void` |  | Callback fired when the snap point changes. |
| `open` | `boolean` |  | Whether the drawer is currently open. |
| `snapPoint` | `DrawerSnapPoint` |  | The currently active snap point. Use with `onSnapPointChange` to control the snap point. |
| `snapPoints` | `DrawerSnapPoint[]` |  | Snap points used to position the drawer. Use numbers between 0 and 1 to represent fractions of the viewport height, numbers greater than 1 as pixel values, or strings in `px`/`rem` units (for example, `'148px'` or `'30rem'`). |
| `snapToSequentialPoints` | `boolean` | `false` | Disables velocity-based snap skipping so drag distance determines the next snap point. |
| `swipeDirection` | `SwipeDirection` | `"down"` | The swipe direction used to dismiss the drawer. |
| `triggerId` | `string` |  | ID of the trigger that the drawer is associated with. This is useful in conjunction with the `open` prop to create a controlled drawer. There's no need to specify this prop when the drawer is uncontrolled (that is, when the `open` prop is not set). |

### DrawerActions

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerBody

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerClose

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` | `"md" \| "lg" \| "xl" \| "icon-md" \| "icon-lg" \| DeprecatedButtonSize` |  | `md` (32px) and `icon-md` for rows, cards, banners, toolbars and panel headers; `lg` and `icon-lg` (the control height) for dialog footers, forms and beside a field; `xl` for a full-width call to action. The size follows the place: see Button › Size by place. |
| `variant` | `"primary" \| "accent" \| "warning" \| "danger" \| "default" \| "outline" \| "information" \| "muted" \| "success" \| "danger-secondary" \| "danger-outline" \| "ghost" \| "on-frame"` |  |  |
| `nativeButton` | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerContent

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `portalProps` | `DrawerPortalProps` |  |  |
| `finalFocus` | `boolean \| RefObject<HTMLElement \| null> \| ((closeType: InteractionType) => boolean \| HTMLElement \| null \| void)` |  | Determines the element to focus when the drawer is closed. |
| `initialFocus` | `boolean \| RefObject<HTMLElement \| null> \| ((openType: InteractionType) => boolean \| HTMLElement \| null \| void)` |  | Determines the element to focus when the drawer is opened. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerDescription

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerFooter

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerHeader

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerOverlay

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `forceRender` | `boolean` | `false` | Whether the backdrop is forced to render even when nested. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerPortal

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `container` | `HTMLElement \| ShadowRoot \| RefObject<HTMLElement \| ShadowRoot \| null>` |  | A parent element to render the portal element into. |
| `keepMounted` | `boolean` | `false` | Whether to keep the portal mounted in the DOM while the popup is hidden. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerTitle

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### DrawerTrigger

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `handle` | `DrawerPrimitive.Handle<unknown>` |  | A handle to associate the trigger with a drawer. Can be created with the Drawer.createHandle() method. |
| `id` | `string` |  | ID of the trigger. In addition to being forwarded to the rendered element, it is also used to specify the active trigger for drawers in controlled mode (with the Drawer.Root `triggerId` prop). |
| `nativeButton` | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |
| `payload` | `{}` |  | A payload to pass to the drawer when it is opened. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

## Changes

- 0.6.0 (Breaking Changes): **Props that no longer change anything are removed:** `Badge` `uppercase`; `Checkbox` `size`, `variant`, `color`; `Status` `pulse`, `attention` (status never animates); `Switch` / `SwitchThumb` `size`; `SidebarItem` `variant`; `SidebarItemCount` / `SidebarItemIndicator` `variant` and `appearance` (the count is always the pink sticker, the indicator the yellow @); `NotificationCenterActionButton` `variant`; `DrawerContent` `width` (one-go forms use the wide `Dialog`); `AppRailItemIndicator` `attention`; `AppRailItemAttention` `children`; `Steps` `size`, `track`, `renderIndicator`, `renderTraveler`; `FilePreviewBadge` `type`, `color`. Remove them at call sites.
