# Triggers and Controls

Components for opening and closing dialogs with proper accessibility, keyboard navigation, and focus management.

## Capabilities

### DialogTrigger

Button component that opens the dialog when activated, with automatic accessibility attributes.

```typescript { .api }
/**
 * Button component that opens the dialog when activated
 * Extends all standard button props and automatically adds accessibility attributes
 */
type DialogTriggerElement = React.ComponentRef<typeof Primitive.button>;
interface DialogTriggerProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {}

const DialogTrigger: React.ForwardRefExoticComponent<
  DialogTriggerProps & React.RefAttributes<DialogTriggerElement>
>;
```

**Usage Examples:**

```typescript
import { Dialog, DialogTrigger, DialogContent } from "@radix-ui/react-dialog";

// Basic trigger
function BasicTrigger() {
  return (
    <Dialog>
      <DialogTrigger>Open Dialog</DialogTrigger>
      <DialogContent>Content here</DialogContent>
    </Dialog>
  );
}

// Custom styled trigger
function StyledTrigger() {
  return (
    <Dialog>
      <DialogTrigger className="custom-button" disabled={false}>
        <span className="icon">📋</span>
        Open Settings
      </DialogTrigger>
      <DialogContent>Settings content</DialogContent>
    </Dialog>
  );
}

// Trigger with custom click handler
function TriggerWithHandler() {
  const handleClick = (event: React.MouseEvent) => {
    console.log('Trigger clicked');
    // Dialog will still open automatically
  };

  return (
    <Dialog>
      <DialogTrigger onClick={handleClick}>
        Open with Custom Handler
      </DialogTrigger>
      <DialogContent>Content here</DialogContent>
    </Dialog>
  );
}

// Using asChild pattern with existing element
function AsChildTrigger() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <button className="existing-button-class">
          Open Dialog
        </button>
      </DialogTrigger>
      <DialogContent>Content here</DialogContent>
    </Dialog>
  );
}
```

### DialogClose

Button component that closes the dialog when activated, can be placed anywhere within the dialog content.

```typescript { .api }
/**
 * Button component that closes the dialog when activated
 * Can be placed anywhere within dialog content
 * Extends all standard button props
 */
type DialogCloseElement = React.ComponentRef<typeof Primitive.button>;
interface DialogCloseProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {}

const DialogClose: React.ForwardRefExoticComponent<
  DialogCloseProps & React.RefAttributes<DialogCloseElement>
>;
```

**Usage Examples:**

```typescript
import { Dialog, DialogTrigger, DialogContent, DialogClose } from "@radix-ui/react-dialog";

// Basic close button
function BasicClose() {
  return (
    <Dialog>
      <DialogTrigger>Open</DialogTrigger>
      <DialogContent>
        <p>Dialog content</p>
        <DialogClose>Close</DialogClose>
      </DialogContent>
    </Dialog>
  );
}

// Multiple close buttons
function MultipleCloseButtons() {
  return (
    <Dialog>
      <DialogTrigger>Open</DialogTrigger>
      <DialogContent>
        <div className="dialog-header">
          <h2>Confirm Action</h2>
          <DialogClose className="close-icon">×</DialogClose>
        </div>
        <p>Are you sure you want to continue?</p>
        <div className="dialog-actions">
          <DialogClose className="cancel-btn">Cancel</DialogClose>
          <DialogClose className="confirm-btn">Confirm</DialogClose>
        </div>
      </DialogContent>
    </Dialog>
  );
}

// Close button with custom handler
function CloseWithHandler() {
  const handleClose = (event: React.MouseEvent) => {
    console.log('Dialog closing');
    // Dialog will still close automatically
  };

  return (
    <Dialog>
      <DialogTrigger>Open</DialogTrigger>
      <DialogContent>
        <p>Content here</p>
        <DialogClose onClick={handleClose}>
          Close with Handler
        </DialogClose>
      </DialogContent>
    </Dialog>
  );
}

// Using asChild pattern
function AsChildClose() {
  return (
    <Dialog>
      <DialogTrigger>Open</DialogTrigger>
      <DialogContent>
        <p>Content here</p>
        <DialogClose asChild>
          <button className="existing-close-class">
            Close Dialog
          </button>
        </DialogClose>
      </DialogContent>
    </Dialog>
  );
}
```

## Accessibility Features

### DialogTrigger Accessibility

The DialogTrigger component automatically provides:

- `type="button"` for proper button semantics
- `aria-haspopup="dialog"` to indicate it opens a dialog
- `aria-expanded` that reflects the current dialog state
- `aria-controls` that references the dialog content ID
- `data-state` attribute with "open" or "closed" values

### DialogClose Accessibility

The DialogClose component automatically provides:

- `type="button"` for proper button semantics
- Proper event handling for keyboard activation (Enter, Space)
- Focus restoration to the trigger when dialog closes

## Event Handling

Both components compose event handlers, meaning you can add your own click handlers and they will be called alongside the built-in dialog control logic:

```typescript
// Your handler is called first, then the built-in logic
<DialogTrigger onClick={(e) => {
  console.log('Custom logic before opening');
  // Dialog opens automatically after this
}}>
  Open
</DialogTrigger>

<DialogClose onClick={(e) => {
  console.log('Custom logic before closing');
  // Dialog closes automatically after this
}}>
  Close
</DialogClose>
```

## Styling and Customization

Both components render as buttons by default but can be customized:

### CSS Classes and Styling

```typescript
<DialogTrigger className="btn btn-primary" style={{ fontSize: '16px' }}>
  Styled Trigger
</DialogTrigger>

<DialogClose className="btn btn-secondary" data-testid="close-btn">
  Styled Close
</DialogClose>
```

### AsChild Pattern

Use the `asChild` prop to render the functionality on your own element:

```typescript
<DialogTrigger asChild>
  <YourCustomButton>Open</YourCustomButton>
</DialogTrigger>

<DialogClose asChild>
  <YourCustomCloseIcon />
</DialogClose>
```