> ## Documentation Index
> Fetch the complete documentation index at: https://neo.tvk.company/llms.txt
> Use this file to discover all available pages before exploring further.

# Modal

> A modal overlay for creating dialogs, confirmations, and custom popups with flexible content and actions.

<Note>
  **Different from other Neo widgets**: Modal is used as a method call (`NeoModal.show()`) rather than a widget you place in your build tree. Use it for important interactions that require user attention—confirmations, forms, or critical information that must be acknowledged.
</Note>

## Examples

<Tabs>
  <Tab title="Basic Modal">
    <Frame caption="Simple modal with title, content, and action buttons.">
      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/overlays/modal/modal_basic_light.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=3bac4f8e1cd82659aa61dced72f9fa1b" noZoom className="block dark:hidden" width="1536" height="768" data-path="images/widgets/overlays/modal/modal_basic_light.png" />

      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/overlays/modal/modal_basic_dark.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=b714dfbc6af57e7ea6402aa0e113b608" noZoom className="hidden dark:block" width="1536" height="768" data-path="images/widgets/overlays/modal/modal_basic_dark.png" />
    </Frame>

    <CodeGroup>
      ```dart Basic Modal lines theme={null}
      NeoModal.show(
        ref,
        title: "Are You Sure?",
        contentBuilder: (context) => Text(
          "Take a moment to review the details provided to ensure you understand the implications.",
          style: theme.textStyles.body2.copyWith(
            color: theme.colors.fgSecondary,
          ),
        ),
        actionsBuilder: (context) => [
          NeoButton(
            variant: .ghost,
            label: "Cancel",
            onPressed: () => NeoModal.dismissAll(ref),
          ),
          NeoButton(
            variant: .filled,
            label: "Okay",
            onPressed: () {
              // Handle action
              NeoModal.dismissAll(ref);
            },
          ),
        ],
      );
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Form Modal">
    <Frame caption="Modal containing form fields for user input.">
      <img src="https://mintcdn.com/tvk/M1ZGdn8TY0ukkJe8/images/widgets/overlays/modal/modal_form_light.png?fit=max&auto=format&n=M1ZGdn8TY0ukkJe8&q=85&s=cbb3d3b5294cc95e1c026c25e88d15ba" noZoom className="block dark:hidden" width="1536" height="1024" data-path="images/widgets/overlays/modal/modal_form_light.png" />

      <img src="https://mintcdn.com/tvk/M1ZGdn8TY0ukkJe8/images/widgets/overlays/modal/modal_form_dark.png?fit=max&auto=format&n=M1ZGdn8TY0ukkJe8&q=85&s=08e24b484c3a4d1e99b12b5a54b47ba2" noZoom className="hidden dark:block" width="1536" height="1024" data-path="images/widgets/overlays/modal/modal_form_dark.png" />
    </Frame>

    <CodeGroup>
      ```dart Form Modal lines theme={null}
      NeoModal.show(
        ref,
        isDismissable: false,
        title: "Edit Profile",
        contentBuilder: (context) => ValueListenableBuilder<bool>(
          valueListenable: isChecked, // Using hooks
          builder: (_, value, __) => Column(
            crossAxisAlignment: .start,
            mainAxisSize: .min,
            children: [
              Text(
                "Make changes to your profile here. Click save when you're done.",
                style: theme.textStyles.body2.copyWith(
                  color: theme.colors.fgSecondary,
                ),
              ),
              Gap(theme.spacings.medium),
              NeoTextField(
                controller: nameController,
                label: "Name",
              ),
              Gap(theme.spacings.medium),
              NeoTextField(
                controller: emailController,
                label: "Email",
              ),
              Gap(theme.spacings.medium),
              NeoCheckbox(
                isChecked: value,
                label: "I agree to the terms and conditions",
                onChanged: (value) {
                  isChecked.value = value;
                },
              ),
            ],
          ),
        ),
        actionsBuilder: (context) => [
          NeoButton(
            variant: .ghost,
            label: "Cancel",
            onPressed: () => NeoModal.dismissAll(ref),
          ),
          ValueListenableBuilder<bool>(
            valueListenable: isChecked, // Using hooks
            builder: (_, value, __) => NeoButton(
              variant: .filled,
              label: "Save Changes",
              isEnabled: value,
              onPressed: () {
                // Handle save
                NeoModal.dismissAll(ref);
              },
            ),
          ),
        ],
      );
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Non-Dismissable Modal">
    <Frame caption="Modal that must be explicitly dismissed by the user.">
      <img src="https://mintcdn.com/tvk/M1ZGdn8TY0ukkJe8/images/widgets/overlays/modal/modal_non_dismissable_light.png?fit=max&auto=format&n=M1ZGdn8TY0ukkJe8&q=85&s=57649e9d6696261961e2b5925f4020dc" noZoom className="block dark:hidden" width="1536" height="768" data-path="images/widgets/overlays/modal/modal_non_dismissable_light.png" />

      <img src="https://mintcdn.com/tvk/M1ZGdn8TY0ukkJe8/images/widgets/overlays/modal/modal_non_dismissable_dark.png?fit=max&auto=format&n=M1ZGdn8TY0ukkJe8&q=85&s=b15f51da5b354d03852977fb54340fa1" noZoom className="hidden dark:block" width="1536" height="768" data-path="images/widgets/overlays/modal/modal_non_dismissable_dark.png" />
    </Frame>

    <CodeGroup>
      ```dart Non-Dismissable Modal lines theme={null}
      NeoModal.show(
        ref,
        title: "Delete Product?",
        isDismissable: false,
        contentBuilder: (context) => Text(
          "You're about to delete this product. This action cannot be reversed.",
          style: theme.textStyles.body2.copyWith(
            color: theme.colors.fgSecondary,
          ),
        ),
        actionsBuilder: (context) => [
          ValueListenableBuilder<bool>(
              valueListenable: isDeleteProductLoading, // Using hooks
              builder: (_, value, __) {
                return NeoButton(
                  variant: .ghost,
                  isEnabled: !value,
                  label: "Cancel",
                  onPressed: () => NeoModal.dismissAll(ref),
                );
              }),
          ValueListenableBuilder<bool>(
            valueListenable: isDeleteProductLoading, // Using hooks
            builder: (_, value, __) => NeoButton(
              variant: .filled,
              label: "Delete Product",
              icon: PhosphorIconsRegular.trash,
              isDanger: true,
              isLoading: value,
              onPressed: () async {
                isDeleteProductLoading.value = true;
                // Handle delete
                NeoModal.dismissAll(ref);
                isDeleteProductLoading.value = false;
              },
            ),
          ),
        ],
      );
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Methods

### NeoModal.show()

Displays a modal overlay with customizable content and actions.

#### Required Parameters

<ParamField path="ref" type="WidgetRef" required>
  The widget reference from a `ConsumerWidget` or `HookConsumerWidget`, used to access the modal provider.
</ParamField>

<ParamField path="title" type="String" required>
  The title text displayed at the top of the modal.
</ParamField>

<ParamField path="contentBuilder" type="Widget Function(BuildContext)" required>
  A builder function that returns the main content of the modal. Use this to create forms, display information, or any custom content.
</ParamField>

<ParamField path="actionsBuilder" type="List<Widget> Function(BuildContext)" required>
  A builder function that returns a list of action buttons displayed at the bottom of the modal. Typically contains confirm/cancel buttons.
</ParamField>

#### Optional Parameters

<ParamField path="isDismissable" type="bool" default="true">
  Whether users can dismiss the modal by clicking the background or close button. Set to `false` for critical modals that require explicit user action.
</ParamField>

<ParamField path="size" type="NeoModalSize" default=".small">
  The size of the modal. Controls the maximum width.
</ParamField>

### NeoModal.dismissAll()

Dismisses all currently visible modals.

<ParamField path="ref" type="WidgetRef" required>
  The widget reference to access the modal provider.
</ParamField>

### NeoModal.dismissCount()

Dismisses a specific number of modals from the top of the stack.

<ParamField path="ref" type="WidgetRef" required>
  The widget reference to access the modal provider.
</ParamField>

<ParamField path="count" type="int" required>
  The number of modals to dismiss from the stack.
</ParamField>

## Enums

### NeoModalSize

Controls the maximum width of the modal.

* `small` (400px): Best for most use cases, simple confirmations and brief messages.
* `medium` (640px): Ideal for forms and moderate content.
* `large` (896px): Perfect for extensive content, detailed forms, or comprehensive information.
* `extraLarge` (1536px): For wide content like tables, dashboards, or side-by-side comparisons.

All sizes have a minimum width of 320px and automatically adapt to smaller screen sizes.

## Best Practices

* **Dangerous Actions**: Use `isDanger: true` on buttons for destructive actions like deletion

## Integration Notes

* **Backdrop Blur**: Modals automatically blur the background content to focus user attention
* **Responsive Design**: Modals automatically adapt to different screen sizes with appropriate padding and constraints
* **Stack Management**: Multiple modals stack on top of each other; use `dismissCount()` to dismiss specific numbers of modals
