# `MishkaCmsCore.Builder.Actions.OpenVerb`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/builder/actions/open_verb.ex#L5)

Show, hide or toggle — and the component being aimed at decides what those mean.

## Why the component decides

"Open it" is not one thing. A dialog is `display:none` on the root AND `display:none` again on the
panel inside it, so revealing the root paints the backdrop over a page and shows no dialog. A
drawer is fully displayed and held off-screen by `-translate-x-full`. A dropdown is opened by a
JavaScript hook. A navbar wants one class toggled on the very element being clicked. One generic
`JS.show` is right for exactly one of those shapes and silently does nothing for the rest — which
is what it did, and what a full-page grey overlay with no dialog under it looked like.

So the verb stays the author's and the command becomes the component's:

    <div id={@id} data-pb-open={show_modal(@id)} data-pb-close={hide_modal(@id)}>

A click aimed at that compiles to `JS.exec("data-pb-open", to: ".pb-xxxxxxxx")`, so what runs is
the component's own sequence — every transition, the body scroll lock, the focus trap. See
`MishkaCmsCore.Builder.PaletteEntry.opens/1`; a package's component joins in by writing one
attribute, with nothing registered anywhere.

A component that declares nothing keeps the plain verb it always had.

# `descriptors`

```elixir
@spec descriptors() :: [map()]
```

The three descriptors this module answers for.

# `openers`

```elixir
@spec openers() :: %{required(String.t()) =&gt; String.t()}
```

The attribute each verb looks for on a component that declares its own open command.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
