IndiaCN UI

Close Button

Dismiss control for modals, toasts and panels, with a guaranteed accessible name.

Introduction

UX4G specifies the dismiss control as a component in its own right — three sizes, three variants, five states — not as a bare glyph each surface draws for itself.

That distinction is the point of shipping it. Before this existed, Modal, Offcanvas and Toast each drew their own close: three different corner radii, an opacity value that appears nowhere in the spec, and no fixed hit area. All three now use this component.

Installation

npx shadcn@latest add https://indiacn.in/r/close-button.json
import { CloseButton } from '@/components/ui/close-button';

Usage

<CloseButton label="Close dialog" onClick={dismiss} />

Examples

Default

CloseButtonDefault
import { CloseButton } from '@/components/ui/close-button';

export default function Component() {
  return <CloseButton label='Close dialog' />;
}

Variants

text
outlined
tonal
CloseButtonVariants
import { CloseButton } from '@/components/ui/close-button';
import { Label3 } from '@/components/ui/typography';

export default function Component() {
  return (
    <div className='flex items-center gap-6'>
      {(['text', 'outlined', 'tonal'] as const).map(variant => (
        <div key={variant} className='flex flex-col items-center gap-2'>
          <CloseButton variant={variant} label={`Close (${variant})`} />
          <Label3 className='text-neutral-600'>{variant}</Label3>
        </div>
      ))}
    </div>
  );
}

Sizes

sm
md
lg
CloseButtonSizes
import { CloseButton } from '@/components/ui/close-button';
import { Label3 } from '@/components/ui/typography';

export default function Component() {
  return (
    <div className='flex items-center gap-6'>
      {(['sm', 'md', 'lg'] as const).map(size => (
        <div key={size} className='flex flex-col items-center gap-2'>
          <CloseButton size={size} variant='outlined' label={`Close (${size})`} />
          <Label3 className='text-neutral-600'>{size}</Label3>
        </div>
      ))}
    </div>
  );
}

Disabled

CloseButtonDisabled
import { CloseButton } from '@/components/ui/close-button';

export default function Component() {
  return (
    <div className='flex items-center gap-6'>
      <CloseButton disabled label='Close' />
      <CloseButton variant='outlined' disabled label='Close' />
      <CloseButton variant='tonal' disabled label='Close' />
    </div>
  );
}

Composing with Radix

Modal and Offcanvas close through Radix's Dialog.Close. Pass asChild so the primitive uses this button rather than wrapping one:

<DialogPrimitive.Close asChild>
<CloseButton />
</DialogPrimitive.Close>

The label is not optional

label defaults to "Close" and is always rendered as aria-label, so a dismiss control cannot ship as an unlabelled glyph. Where a page has more than one, say what closes:

<CloseButton label="Close filters" />
<CloseButton label="Dismiss notification" />

Measurements

Read off the Figma symbols on the Close button page:

boxicon
sm32px20px
md40px24px
lg48px32px

Interaction matches the rest of the library, which is not a coincidence — the measured values are the same ones Button already uses: primary at 8% on hover, 16% on press, a 4px focus ring at 48%, and 50% opacity when disabled.

The glyph is neutral in all three variants, and outlined draws a neutral-100 border. Neither takes the primary colour, which is where this differs from an icon Button.

API Reference

CloseButton

PropTypeDefaultDescription
varianttext | outlined | tonaltextSurface treatment
sizesm | md | lgmd32, 40 or 48px
labelstring'Close'Accessible name

Any other button prop is forwarded.

On this page