# `Mob.Keyboard`
[🔗](https://github.com/genericjam/mob/blob/master/lib/mob/keyboard.ex#L1)

The on-screen keyboard. No permission required.

A `:text_field` brings the keyboard up when tapped. It goes down again on
the field's return key, when another field takes focus, when the field
leaves the render tree, and on iOS via the "Done" button `MobTextField`
adds to the keyboard toolbar. What none of those cover is the app's own
idea of done — a Save button of its own, a tap on blank space, a value it
has just committed. This is the call for that handler:

    def handle_info({:tap, :save}, socket) do
      {:noreply, socket |> Mob.Keyboard.dismiss() |> save()}
    end

It matters most for `keyboard: "decimal"` and `"number"`: those iOS
keyboards have no return key, so `on_submit` never fires for them and the
toolbar button is the only built-in exit on the field itself.

A `value:` assigned in the same handler reaches the field, and the field's
`on_blur` arrives, including when that handler re-renders.

iOS resigns the first responder found in any visible window of a connected
scene — the view the keyboard is up for — and returns once the main thread
has done it, so the handler's re-render applies to a field that is no
longer focused (a focused field keeps what the user typed rather than take
a new `value:`). Android calls `MobBridge.dismissKeyboard()`, which hides
the soft keyboard and clears focus, in apps generated by a mob_new that has
it. An older generated bridge lacks the method: the NIF returns
`{:error, :not_loaded}` and `dismiss/1` is a no-op — the field keeps its
keyboard and nothing else changes. Copy the method from a freshly generated
app to add it.

# `dismiss`

```elixir
@spec dismiss(Mob.Socket.t()) :: Mob.Socket.t()
```

Take the keyboard down. Returns the socket unchanged so it chains inside a
`handle_info` / `handle_event` return. Nothing focused is not an error.

---

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