# Dialog (React Native)

> Alert, confirm and prompt dialogs, awaited from code with dialog.confirm().

GramproKit for React Native · Overlays · Beta · Source: https://kit.gramproindia.com/native/docs/dialog

> **Beta:** React Native support is in beta. APIs may change or break between prereleases (npm tag `native`).

_Interactive demo:_ [open the live example](https://kit.gramproindia.com/native/docs/dialog). The example's source:

```tsx
import { useState } from "react";
import { Text } from "react-native";
import { Button } from "@/component-lib/button";
import { Dialog, DialogHost, dialog } from "@/component-lib/dialog";
import { useKitTheme } from "@/component-lib/shared/native";
import { Row, Section } from "./layout"; // Section and Row: page layout for the demo

const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

export function DialogDemo() {
  const { tokens } = useKitTheme();
  const [answer, setAnswer] = useState("—");
  const [open, setOpen] = useState(false);

  return (
    <>
      {/* Normally mounted once at the app root; here so the demo stands alone. */}
      <DialogHost />

      <Section title="dialog · promise API">
        <Row>
          <Button
            variant="danger"
            onPress={async () => {
              const ok = await dialog.confirm({
                title: "Delete 3 invoices?",
                description: "They move to the bin for 30 days.",
                intent: "danger",
                confirmLabel: "Delete",
                onConfirm: async () => {
                  await wait(900);
                },
              });
              setAnswer(`confirm → ${ok}`);
            }}
          >
            Confirm (danger)
          </Button>
          <Button
            variant="outline"
            onPress={async () => {
              const name = await dialog.prompt({
                title: "Rename report",
                inputLabel: "Report name",
                defaultValue: "Q3 collections",
                required: true,
                validate: (v) => (v.length > 40 ? "Keep it under 40 characters." : null),
              });
              setAnswer(`prompt → ${JSON.stringify(name)}`);
            }}
          >
            Prompt
          </Button>
        </Row>
        <Row>
          <Button
            variant="secondary"
            onPress={async () => {
              await dialog.alert({ title: "Export ready", description: "invoices-q3.xlsx was saved.", intent: "success" });
              setAnswer("alert → closed");
            }}
          >
            Alert (success)
          </Button>
          <Button
            variant="secondary"
            onPress={async () => {
              const ok = await dialog.confirm({
                title: "Retry the upload?",
                intent: "warning",
                onConfirm: async () => {
                  await wait(700);
                  throw new Error("The server is still unreachable.");
                },
              });
              setAnswer(`confirm → ${ok}`);
            }}
          >
            Confirm that fails
          </Button>
        </Row>
        <Text style={{ color: tokens.muted }}>Last answer: {answer}</Text>
      </Section>

      <Section title="Dialog · controlled">
        <Button variant="outline" onPress={() => setOpen(true)}>
          Open info dialog
        </Button>
        <Dialog
          open={open}
          kind="alert"
          intent="info"
          title="Statements are generated nightly"
          description="Changes you make today appear in tomorrow's statement."
          onClose={() => setOpen(false)}
        />
      </Section>
    </>
  );
}
```

## Install

```bash
npx @grampro/kit@native add DialogHost
```

## Usage

```tsx
import { DialogHost, dialog } from "@/component-lib/dialog";

// Once, inside KitProvider:
<DialogHost />

const ok = await dialog.confirm({ title: "Delete invoice?", intent: "danger" });
```

## Props

### DialogProps

| Prop | Type | Description |
|---|---|---|
| `open` (required) | `boolean` | Whether the dialog is on screen. Always controlled: set it to false in `onClose`. |
| `kind` | `DialogKind` | `alert` has one button, `confirm` two, `prompt` adds a text field. Default `confirm`. |
| `onConfirm` | `(value: string) => void \| Promise<void>` | Runs on Confirm, with the prompt's value. While its promise is pending the buttons show progress; if it throws, the error is shown and the dialog stays open. |
| `onClose` | `(action: DialogAction, value: string) => void` | The user answered. Set `open` to false here. |
| `onExited` | `() => void` | The exit animation finished. |
| `id` | `string` |   |
| `style` | `StyleProp<ViewStyle>` |   |
| `styles` | `Partial<{ root: StyleProp<ViewStyle>; body: StyleProp<ViewStyle>; icon: StyleProp<ViewS…` |   |
| `localeText` | `Partial<DialogLocaleText>` |   |

Also accepts the props of `Omit<PromptOptions, "onConfirm">`.

### DialogHostProps

| Prop | Type | Description |
|---|---|---|
| `store` | `DialogStore` | A store from `createDialogStore()`. Defaults to the one behind `dialog`. |
| `style` | `DialogProps["style"]` | Applied to every dialog this host shows. |
| `styles` | `DialogProps["styles"]` |   |
| `localeText` | `Partial<DialogLocaleText>` |   |

## Native and web

- Android back cancels. The prompt picks its keyboard from `inputType` and moves above it.
- Web version: [Dialog on the web](https://kit.gramproindia.com/dialog).
