# Invoker Modal

> Not every interaction needs React state. The browser can open and close a dialog with plain HTML attributes via the Invoker Commands API — no useState, no event handlers, no JavaScript.

- Difficulty: beginner
- Tags: dialog, native apis
- Estimated time: 30 minutes
- Tests: 5
- Requires subscription: yes

## Overview

Not every interaction needs React state. The browser can open and close a `<dialog>` with plain HTML attributes via the Invoker Commands API — no `useState`, no event handlers, no JavaScript.


## Requirements

- Use the Invoker Commands API to wire the **"Contact Us"** button (`data-testid="open-dialog"`) so it opens the dialog when clicked — without `useState`, refs, or manual DOM calls.
- Wire the **"Close"** button (`data-testid="close-dialog"`) so it closes the dialog when clicked.
- The dialog must be closed initially.
- The dialog already contains a form with name, email, message fields, and a submit button. Do not remove or rename any of these elements or their `data-testid` attributes.
- The `declare module "react"` block at the top of `App.tsx` must not be removed or modified — it already provides the TypeScript types you need.


## Notes

- Check the [Invoker Commands API on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API). The idea: a `<button>` uses `command` and `commandfor` attributes to tell the browser to call `showModal()` or `close()` on a target element — no JavaScript event handlers.
- To link a button to the dialog: give the dialog an `id`, then set `commandfor` on the button to that same id. Use `command="show-modal"` to open and `command="close"` to close.
- `useId()` from React is the idiomatic way to generate a unique id, but any unique string works.
- The `declare module "react"` block is a TypeScript module augmentation. It adds `command` and `commandfor` to `ButtonHTMLAttributes` so you can use them in JSX without type errors.
- The `data-testid` attributes on the button, dialog, and form fields are required by the tests — do not rename or remove them.


## Tests

01. renders the app title
02. renders the open button with command attributes
03. matches the button commandfor with the dialog id
04. dialog does not have the open attribute initially
05. close button has command close with matching commandfor


