<!-- Protocore Design System — CloseButton -->
# CloseButton

- **Category:** Utilities (`utilities`)
- **Slug:** `utilities/close-button`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { CloseButton } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/utilities/close-button

> A square, icon-only × dismiss control with a required aria-label — the shared close affordance for overlays.

## When to use it

**CloseButton** is the one standardized × used across the library's dismissible surfaces — [Dialog](/overlay/dialog), [Sheet](/overlay/sheet), [Notification](/feedback/notification), and [Banner](/feedback/banner) all reach for the same crossed-stroke glyph and interaction model, so "close" looks and behaves identically everywhere.

Reach for it whenever you need a bare dismiss affordance. If your control carries a *different* icon or a text label, use an [IconButton](/utilities/icon-button) or [Button](/inputs/button) instead — CloseButton is deliberately locked to the × glyph.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `aria-label` | `string` | no | `Close` | Accessible name for the control — required, since the × glyph carries no text. |
| `className` | `string` | no | — | — |
| `size` | `enum` | no | `md` | Square control size: `sm` 24px · `md` 28px. |
| `style` | `CSSProperties` | no | — | — |
| `variant` | `enum` | no | `subtle` | Visual weight: `subtle` is a transparent ghost; `filled` sits on a faint fill. |

## Examples

### Basics

A sharp, square × button. It ships with a default `aria-label` of "Close" — override it whenever the surface it dismisses has a more specific name.

```tsx
import { CloseButton } from "@protocore/pds";

export default function Basics() {
  return <CloseButton aria-label="Close panel" />;
}
```

### Variants and sizes

`subtle` (default) is a transparent ghost that fills on hover; `filled` sits on a faint fill at rest. Two sizes — `sm` 24px and `md` 28px — to match the density of the chrome around it.

```tsx
import { CloseButton, HStack } from "@protocore/pds";

export default function Variants() {
  return (
    <HStack gap={4} align="center">
      <CloseButton variant="subtle" size="sm" aria-label="Close, subtle small" />
      <CloseButton variant="subtle" size="md" aria-label="Close, subtle medium" />
      <CloseButton variant="filled" size="sm" aria-label="Close, filled small" />
      <CloseButton variant="filled" size="md" aria-label="Close, filled medium" />
    </HStack>
  );
}
```

## Do & don't

**Do**

- Give it an `aria-label` describing what it closes when "Close" is ambiguous.
- Use `sm` inside dense chrome (chips, list rows) and `md` on cards and dialogs.
- Pair it with the surface it dismisses, aligned to the top-inline-end corner.
- Let its own hover feedback signal interactivity — don't wrap it in another button.

**Don't**

- Don't use it for a non-dismiss action — its × glyph promises "close".
- Don't remove or blank the `aria-label`; the glyph carries no text.
- Don't scale it up as a primary action — that's a Button.
- Don't stack several close buttons on one surface.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Moves focus to the button. |
| `Enter / Space` | Activates it (native button semantics). |

**Notes**

- Renders a real `<button type="button">`, so it is keyboard- and screen-reader-operable for free.
- Requires an accessible name via `aria-label` (default "Close") since the × glyph is `aria-hidden`.
- The glyph is an inline SVG (crossed strokes), not a text × codepoint, so it never renders as an emoji and always inherits `currentColor`.
- Server-safe: it carries no client state, only CSS `:hover`/`:focus-visible` states.

## Related

`icon-button`, `notification`, `dialog`, `banner`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
