# Alert

> Display important messages to users with both visual inline alerts and native system alerts.

**BNA UI** — a React Native / Expo component library.
These components render through `react-native`, not the DOM: there are no HTML
elements, no Tailwind classes and no Radix primitives. Source is copied into your
project and imported through `@/components/ui/*`, `@/components/charts/*`,
`@/hooks/*` and `@/theme/*`. Colours come from the `useColor` hook rather than
hardcoded hex; sizing tokens (`HEIGHT`, `FONT_SIZE`, `BORDER_RADIUS`, `CORNERS`)
come from `@/theme/globals`.

- Docs: https://ui.ahmedbna.com/docs/components/alert
- Markdown: https://ui.ahmedbna.com/docs/components/alert.md
- Structured JSON (props, usage, source, examples): https://ui.ahmedbna.com/r/ai/alert.json
- Install payload (source plus every file it imports): https://ui.ahmedbna.com/r/alert.json
- Install: `npx bna-ui add alert`
- Registry dependencies: `mode-provider`, `useColorScheme`, `colors`, `useColor`, `globals`, `text`, `view`
- Preview recording: https://demo.ahmedbna.com/0016-alert-demo.mov

---

**Example:** A basic native alert with two buttons

```tsx
// components/demo/alert/alert-demo.tsx
import { createTwoButtonAlert } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import React from 'react';

export function AlertDemo() {
  const handleTwoButtonAlert = () => {
    createTwoButtonAlert({
      title: 'Two Button Alert',
      message: 'This is a two-button alert example',
      buttons: [
        {
          text: 'Cancel',
          onPress: () => console.log('Cancel Pressed'),
          style: 'cancel',
        },
        {
          text: 'OK',
          onPress: () => console.log('OK Pressed'),
        },
      ],
    });
  };

  return <Button onPress={handleTwoButtonAlert}>Show Two Button Alert</Button>;
}
```

## Installation

### CLI

```bash
npx bna-ui add alert
```

### Manual

**1.** Copy and paste the following code into your project.

```tsx
// components/ui/alert.tsx
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import { useColor } from '@/hooks/useColor';
import { BORDER_RADIUS } from '@/theme/globals';
import React from 'react';
import { Alert as RNAlert, TextStyle, ViewStyle } from 'react-native';

type AlertVariant = 'default' | 'destructive';

interface AlertProps {
  children: React.ReactNode;
  variant?: AlertVariant;
  style?: ViewStyle;
}

// Visual Alert Component (existing functionality)
export function Alert({ children, variant = 'default', style }: AlertProps) {
  const borderColor = useColor('border');
  const destructiveColor = useColor('destructive');
  const backgroundColor = useColor('card');

  return (
    <View
      accessibilityRole='alert'
      accessibilityLiveRegion={
        variant === 'destructive' ? 'assertive' : 'polite'
      }
      style={[
        {
          padding: BORDER_RADIUS,
          borderRadius: BORDER_RADIUS,
          backgroundColor: backgroundColor,
          borderWidth: 1,
          borderColor:
            variant === 'destructive' ? destructiveColor : borderColor,
        },
        style,
      ]}
    >
      {children}
    </View>
  );
}

interface AlertTitleProps {
  children: React.ReactNode;
  style?: TextStyle;
}

export function AlertTitle({ children, style }: AlertTitleProps) {
  return (
    <Text variant='title' style={[style]}>
      {children}
    </Text>
  );
}

interface AlertDescriptionProps {
  children: React.ReactNode;
  style?: TextStyle;
}

export function AlertDescription({ children, style }: AlertDescriptionProps) {
  return (
    <Text
      variant='caption'
      style={[
        {
          marginTop: 8,
        },
        style,
      ]}
    >
      {children}
    </Text>
  );
}

// Native Alert Functions
interface AlertButton {
  text: string;
  onPress?: () => void;
  style?: 'default' | 'cancel' | 'destructive';
}

interface NativeAlertOptions {
  title: string;
  message?: string;
  buttons?: AlertButton[];
  cancelable?: boolean;
}

// Two-button native alert
export const createTwoButtonAlert = (options: NativeAlertOptions) => {
  const { title, message, buttons } = options;

  const defaultButtons: AlertButton[] = [
    {
      text: 'Cancel',
      onPress: () => console.log('Cancel Pressed'),
      style: 'cancel',
    },
    {
      text: 'OK',
      onPress: () => console.log('OK Pressed'),
    },
  ];

  RNAlert.alert(title, message, buttons || defaultButtons);
};

// Three-button native alert
export const createThreeButtonAlert = (options: NativeAlertOptions) => {
  const { title, message, buttons } = options;

  const defaultButtons: AlertButton[] = [
    {
      text: 'Ask me later',
      onPress: () => console.log('Ask me later pressed'),
    },
    {
      text: 'Cancel',
      onPress: () => console.log('Cancel Pressed'),
      style: 'cancel',
    },
    {
      text: 'OK',
      onPress: () => console.log('OK Pressed'),
    },
  ];

  RNAlert.alert(title, message, buttons || defaultButtons);
};

// Generic native alert function
export const showNativeAlert = (options: NativeAlertOptions) => {
  const { title, message, buttons, cancelable = true } = options;

  if (!buttons || buttons.length === 0) {
    // Simple alert with just OK button
    RNAlert.alert(title, message, [
      {
        text: 'OK',
        onPress: () => console.log('OK Pressed'),
      },
    ]);
  } else {
    RNAlert.alert(title, message, buttons, { cancelable });
  }
};

// Convenience functions for common alert types
export const showSuccessAlert = (
  title: string,
  message?: string,
  onOk?: () => void
) => {
  showNativeAlert({
    title,
    message,
    buttons: [
      {
        text: 'OK',
        onPress: onOk || (() => console.log('Success acknowledged')),
      },
    ],
  });
};

export const showErrorAlert = (
  title: string,
  message?: string,
  onOk?: () => void
) => {
  showNativeAlert({
    title,
    message,
    buttons: [
      {
        text: 'OK',
        onPress: onOk || (() => console.log('Error acknowledged')),
        style: 'destructive',
      },
    ],
  });
};

export const showConfirmAlert = (
  title: string,
  message?: string,
  onConfirm?: () => void,
  onCancel?: () => void
) => {
  showNativeAlert({
    title,
    message,
    buttons: [
      {
        text: 'Cancel',
        onPress: onCancel || (() => console.log('Cancelled')),
        style: 'cancel',
      },
      {
        text: 'Confirm',
        onPress: onConfirm || (() => console.log('Confirmed')),
      },
    ],
  });
};

// Export the React Native Alert for direct use
export { RNAlert as NativeAlert };
```

**2.** Update the import paths to match your project setup.

## Usage

```tsx
import {
  Alert,
  AlertTitle,
  AlertDescription,
  showSuccessAlert,
  showErrorAlert,
  showConfirmAlert,
  showNativeAlert,
} from '@/components/ui/alert';
```

### Visual Alert (Inline)

```tsx
function MyComponent() {
  return (
    <Alert>
      <AlertTitle>Attention</AlertTitle>
      <AlertDescription>
        This is an important message that appears inline with your content.
      </AlertDescription>
    </Alert>
  );
}
```

### Native Alerts (System Dialogs)

```tsx
function MyComponent() {
  const handleSuccess = () => {
    showSuccessAlert(
      'Success!',
      'Your action was completed successfully.',
      () => console.log('Success acknowledged')
    );
  };

  const handleConfirm = () => {
    showConfirmAlert(
      'Confirm Action',
      'Are you sure you want to proceed?',
      () => console.log('Confirmed'),
      () => console.log('Cancelled')
    );
  };

  return (
    <>
      <Button onPress={handleSuccess}>Show Success</Button>
      <Button onPress={handleConfirm}>Show Confirmation</Button>
    </>
  );
}
```

#### Visual Alerts

#### Default

**Example:** Inline visual alerts that appear within your content

```tsx
// components/demo/alert/alert-visual-demo.tsx
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import React from 'react';

export function AlertVisualDemo() {
  return (
    <View>
      <Alert>
        <AlertTitle>Visual Alert</AlertTitle>
        <AlertDescription>
          This is a default visual alert that appears inline with your content.
        </AlertDescription>
      </Alert>

      <Text variant='caption' style={{ marginTop: 16 }}>
        Visual alerts appear inline with your content, while native alerts
        appear as system dialogs on top of your app.
      </Text>
    </View>
  );
}
```

#### Destructive

**Example:** Destructive visual alerts for error messages

```tsx
// components/demo/alert/alert-visual-destructive-demo.tsx
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import React from 'react';

export function AlertVisualDestructiveDemo() {
  return (
    <View>
      <Alert variant='destructive' style={{ marginBottom: 24 }}>
        <AlertTitle>Destructive Alert</AlertTitle>
        <AlertDescription>
          This is a destructive visual alert for error messages.
        </AlertDescription>
      </Alert>

      <Text variant='caption' style={{ marginTop: 16 }}>
        Visual alerts appear inline with your content, while native alerts
        appear as system dialogs on top of your app.
      </Text>
    </View>
  );
}
```

### Native Alerts

#### Default

**Example:** Basic two-button native alert

```tsx
// components/demo/alert/alert-demo.tsx
import { createTwoButtonAlert } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import React from 'react';

export function AlertDemo() {
  const handleTwoButtonAlert = () => {
    createTwoButtonAlert({
      title: 'Two Button Alert',
      message: 'This is a two-button alert example',
      buttons: [
        {
          text: 'Cancel',
          onPress: () => console.log('Cancel Pressed'),
          style: 'cancel',
        },
        {
          text: 'OK',
          onPress: () => console.log('OK Pressed'),
        },
      ],
    });
  };

  return <Button onPress={handleTwoButtonAlert}>Show Two Button Alert</Button>;
}
```

#### Three Button

**Example:** Native alert with three button options

```tsx
// components/demo/alert/alert-three-button-demo.tsx
import { createThreeButtonAlert } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import React from 'react';

export function AlertThreeButtonDemo() {
  const handleThreeButtonAlert = () => {
    createThreeButtonAlert({
      title: 'Three Button Alert',
      message: 'This is a three-button alert example',
      buttons: [
        {
          text: 'Ask me later',
          onPress: () => console.log('Ask me later pressed'),
        },
        {
          text: 'Cancel',
          onPress: () => console.log('Cancel Pressed'),
          style: 'cancel',
        },
        {
          text: 'OK',
          onPress: () => console.log('OK Pressed'),
        },
      ],
    });
  };

  return (
    <Button onPress={handleThreeButtonAlert} variant='outline'>
      Show Three Button Alert
    </Button>
  );
}
```

#### Success

**Example:** Success alert with positive messaging

```tsx
// components/demo/alert/alert-success-demo.tsx
import { showSuccessAlert } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import React from 'react';

export function AlertSuccessDemo() {
  const handleSuccessAlert = () => {
    showSuccessAlert(
      'Success!',
      'Your action was completed successfully.',
      () => console.log('Success acknowledged')
    );
  };

  return (
    <Button onPress={handleSuccessAlert} variant='secondary'>
      Show Success Alert
    </Button>
  );
}
```

#### Error

**Example:** Error alert with destructive styling

```tsx
// components/demo/alert/alert-error-demo.tsx
import { showErrorAlert } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import React from 'react';

export function AlertErrorDemo() {
  const handleErrorAlert = () => {
    showErrorAlert('Error', 'Something went wrong. Please try again.', () =>
      console.log('Error acknowledged')
    );
  };

  return (
    <Button onPress={handleErrorAlert} variant='destructive'>
      Show Error Alert
    </Button>
  );
}
```

#### Confirm

**Example:** Confirmation alert for destructive actions

```tsx
// components/demo/alert/alert-confirm-demo.tsx
import { showConfirmAlert } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import React from 'react';

export function AlertConfirmDemo() {
  const handleConfirmAlert = () => {
    showConfirmAlert(
      'Confirm Action',
      'Are you sure you want to proceed with this action?',
      () => console.log('Action confirmed'),
      () => console.log('Action cancelled')
    );
  };

  return (
    <Button onPress={handleConfirmAlert} variant='success'>
      Show Confirm Alert
    </Button>
  );
}
```

#### Custom

**Example:** Custom native alert with multiple options

```tsx
// components/demo/alert/alert-custom-demo.tsx
import { showNativeAlert } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import React from 'react';

export function AlertCustomDemo() {
  const handleCustomAlert = () => {
    showNativeAlert({
      title: 'Custom Alert',
      message: 'This is a custom native alert with multiple options',
      buttons: [
        {
          text: 'Option 1',
          onPress: () => console.log('Option 1 selected'),
        },
        {
          text: 'Option 2',
          onPress: () => console.log('Option 2 selected'),
        },
        {
          text: 'Cancel',
          onPress: () => console.log('Cancelled'),
          style: 'cancel',
        },
      ],
    });
  };

  return <Button onPress={handleCustomAlert}>Show Custom Alert</Button>;
}
```

## API Reference

### Visual Alert Components

#### Alert

The main visual alert container component.

| Prop       | Type                         | Default     | Description                                |
| ---------- | ---------------------------- | ----------- | ------------------------------------------ |
| `children` | `React.ReactNode`            | -           | The content to display inside the alert.   |
| `variant`  | `'default' \| 'destructive'` | `'default'` | The visual style variant of the alert.     |
| `style`    | `ViewStyle`                  | -           | Additional styles for the alert container. |

#### AlertTitle

Component for displaying the alert title.

| Prop       | Type              | Default | Description                           |
| ---------- | ----------------- | ------- | ------------------------------------- |
| `children` | `React.ReactNode` | -       | The title text to display.            |
| `style`    | `TextStyle`       | -       | Additional styles for the title text. |

#### AlertDescription

Component for displaying the alert description.

| Prop       | Type              | Default | Description                                 |
| ---------- | ----------------- | ------- | ------------------------------------------- |
| `children` | `React.ReactNode` | -       | The description text to display.            |
| `style`    | `TextStyle`       | -       | Additional styles for the description text. |

### Native Alert Functions

#### showSuccessAlert

Display a success alert with positive messaging.

```tsx
showSuccessAlert(
  title: string,
  message?: string,
  onOk?: () => void
)
```

#### showErrorAlert

Display an error alert with destructive styling.

```tsx
showErrorAlert(
  title: string,
  message?: string,
  onOk?: () => void
)
```

#### showConfirmAlert

Display a confirmation alert for important actions.

```tsx
showConfirmAlert(
  title: string,
  message?: string,
  onConfirm?: () => void,
  onCancel?: () => void
)
```

#### showNativeAlert

Generic native alert function with full customization.

```tsx
showNativeAlert({
  title: string;
  message?: string;
  buttons?: AlertButton[];
  cancelable?: boolean;
})
```

#### createTwoButtonAlert / createThreeButtonAlert

Predefined alert functions for common use cases.

```tsx
createTwoButtonAlert(options: NativeAlertOptions)
createThreeButtonAlert(options: NativeAlertOptions)
```

### AlertButton

Configuration for individual alert buttons.

| Prop      | Type                                     | Default     | Description                                |
| --------- | ---------------------------------------- | ----------- | ------------------------------------------ |
| `text`    | `string`                                 | -           | The text to display on the button.         |
| `onPress` | `() => void`                             | -           | Callback fired when the button is pressed. |
| `style`   | `'default' \| 'cancel' \| 'destructive'` | `'default'` | The visual style of the button.            |

## Platform Behavior

### Visual Alerts

Visual alerts work consistently across all platforms and appear inline with your content. They're perfect for:

- Form validation messages
- Status updates
- Non-critical notifications
- Persistent information display

### Native Alerts

Native alerts use the platform's built-in alert system:

#### iOS

- Uses `Alert.alert()` from React Native
- Follows iOS Human Interface Guidelines
- Integrates with system UI and accessibility features

#### Android

- Uses `Alert.alert()` from React Native
- Follows Material Design principles
- Adapts to device theme and user preferences

## Accessibility

Both visual and native alerts follow accessibility best practices:

### Visual Alerts

- Proper color contrast ratios
- Semantic markup with appropriate roles
- Screen reader friendly content structure
- Respects system font size preferences

### Native Alerts

- Automatic focus management
- Screen reader announcements
- Keyboard navigation support
- System accessibility integration

## Best Practices

### When to Use Visual vs Native Alerts

**Use Visual Alerts for:**

- Form validation feedback
- Status messages that don't require immediate action
- Information that should remain visible while user continues working
- Non-critical notifications

**Use Native Alerts for:**

- Critical actions that require user confirmation
- Error messages that prevent continued use
- Success confirmations for important actions
- When you need to interrupt the user's workflow

### Button Configuration

- **Cancel buttons**: Use `style: 'cancel'` - typically appears on the left (iOS) or as the negative action
- **Destructive buttons**: Use `style: 'destructive'` - appears in red to indicate dangerous actions
- **Default buttons**: Use `style: 'default'` or omit - for primary positive actions

### Message Guidelines

- Keep titles short and descriptive
- Use clear, actionable language
- Provide enough context in the message
- Make button text specific to the action ("Delete Photo" vs "OK")

## Theming

The Alert components automatically adapt to your app's theme:

### Visual Alerts

- Background colors from theme's card color
- Border colors from theme's border color
- Text colors from theme's text colors
- Destructive variant uses theme's destructive color

### Native Alerts

- Follow system theme automatically
- Button colors adapt to platform conventions
- Text rendering follows system preferences
