# Close button

> The small × affordance for dismissing panels, toasts, and modals. Defaults to `aria-label='Close'` so every dismiss target stays labelled.

- Category: primitive
- Status: stable (since 0.1.0)
- A11y pattern: https://www.w3.org/WAI/ARIA/apg/patterns/button/
- Tokens: --foreground-primary, --foreground-muted, --background-secondary
- Playground: https://design.freecodecamp.org/playground#close-button
- npm dependencies: `react@>=18 <20`
- Registry dependencies: [theme](https://design.freecodecamp.org/registry/theme.md)
- Files:
  - `CloseButton.tsx` → `src/ui/close-button/CloseButton.tsx` (raw: https://design.freecodecamp.org/registry/close-button/CloseButton.tsx)
  - `close-button.css` → `src/ui/close-button/close-button.css` (raw: https://design.freecodecamp.org/registry/close-button/close-button.css)

## Install (copy source)

1. Ensure the theme is installed once per project - tokens.css + base.css imported globally, fonts available. See https://design.freecodecamp.org/registry/theme.md and https://design.freecodecamp.org/registry/starter.md.
2. Copy the files below into `src/ui/close-button/` (adjust to your project layout) and import the CSS once from your global stylesheet, e.g. `@import './ui/close-button/close-button.css';`.
3. Colors, spacing and type come from tokens - tailor the component by editing the copied source; recolour by editing tokens.css, not the component CSS.

## Usage

`<CloseButton>` wraps a native `<button>` with the shared dismiss
visual and a default `aria-label`. It's the right primitive for toast
close affordances, modal close-×, and dismissible banners - a single
component keeps every dismiss target looking the same.

## Keyboard

| Key           | Action                                            |
| ------------- | ------------------------------------------------- |
| Space / Enter | Fires `onClick`.                                  |
| Escape        | If parent is `<Modal>`, dismisses the dialog too. |

## Accessibility

Native `<button>` labelled `"Close"` by default. Always pair with a
discoverable keyboard path - Escape on `<Modal>` mirrors the click.
Override `aria-label` when the surface context matters
("Close filter drawer").

## Example

```tsx
import { CloseButton } from './ui/close-button/CloseButton';

<CloseButton onClick={onDismiss} aria-label="Dismiss" />
```

## Props

No component-specific props - accepts standard HTML attributes. See the TypeScript source below.

## Source: CloseButton.tsx

```tsx
import React, { forwardRef } from 'react';

export interface CloseButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}

export const CloseButton = forwardRef<HTMLButtonElement, CloseButtonProps>(
  (
    { className = '', children, 'aria-label': ariaLabel = 'Close', ...rest },
    ref
  ) => {
    const classes = ['close-btn', className].filter(Boolean).join(' ');
    return (
      <button
        ref={ref}
        type='button'
        className={classes}
        aria-label={ariaLabel}
        {...rest}
      >
        {children ?? '×'}
      </button>
    );
  }
);
CloseButton.displayName = 'CloseButton';
```

## Source: close-button.css

```css
.close-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: transparent;
  border: 0;
  color: var(--foreground-primary);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 120ms;
}
.close-btn:hover,
.close-btn:focus-visible {
  opacity: 1;
}
```

## HTML / vanilla variant

```html
<button class="close-btn" aria-label="Dismiss">×</button>
```

Interactive behaviours for plain HTML come from the vanilla runtime (data-uikit-* attributes): https://design.freecodecamp.org/registry/vanilla.md - or download https://design.freecodecamp.org/cdn/uikit.global.js once and self-host it (do not hotlink).

## For coding agents

This library is distributed as copyable source, not an npm package. Start at https://design.freecodecamp.org/registry/starter.md, discover components via https://design.freecodecamp.org/llms.txt, and copy files into the consuming project. Keep token names intact; recolour by editing the copied tokens.css.
