Close button

v0.0.10

v0.0.10StableMobStatelessApache-2.0
Installation mix mishka.ui.gen.mob close_button
Source View Source

Mob Close Button is the ✕ that dismisses a dialog, drawer, toast or card on iOS and Android. It comes from Mishka Chelekom and runs on Mob, which renders native Jetpack Compose and SwiftUI views from Elixir. It is the native port of the headless Close Button.

Overview of the Mob Close Button component for iOS and Android

Close Button is a thin wrapper over Action Icon. It sets the icon to ✕ and the shape to :circle, then passes every other prop through. It keeps the finger-sized 40 dp default that Action Icon enforces.

Both defaults are applied with Map.put_new/3, so you can still override icon and shape. Child nodes replace the ✕, as they do in Action Icon.

The screen owns the state. A tap sends {:tap, tag} to the screen's handle_info/2, and the screen decides what to close, for example by setting an :open flag to false.

Generate the close button component

Run this from your Mob app's root to add the component to lib/<app>/components/:

bash
mix mishka.ui.gen.mob close_button

The generator registers the component's tag, so you can use it in ~MOB markup. Close Button calls Action Icon, so the generator generates that component too, without asking. The examples on this page use the mishka_ prefix of the showcase app (--module-prefix mishka_), so the tag is <MishkaCloseButton>. Without a prefix the tag is <CloseButton>.

Plain, filled and disabled close buttons

The first button is plain, the second sits on a raised surface with variant: :filled, and the third is disabled. All three keep the ✕ and the circular shape. The two live buttons share the :dismiss tag. The disabled button has no on_tap, so it sends nothing.

Plain, filled and disabled close buttons

Card titled Close button, with three close X icon buttons in a row: one plain, one on a white circle and one in muted gray
elixir
# icon and shape are applied with Map.put_new/3, so every Action Icon
# prop still works and both defaults can still be overridden.
<MishkaCloseButton on_tap={:dismiss} />
<MishkaCloseButton variant={:filled} on_tap={:dismiss} />
<MishkaCloseButton disabled={true} />

def handle_info({:tap, :dismiss}, socket) do
  {:noreply, assign(socket, :open, false)}
end

Props

Close Button accepts every Action Icon prop. Two defaults differ: icon is "✕" and shape is :circle.

PropTypeDefaultDescription
iconstring"✕"The glyph. Children override it.
on_tapevent tagnoneSent as {:tap, tag}.
disabledbooleanfalseWires no handler, mutes the glyph and drops a :filled fill to :surface.
sizenumber40Tap-target edge, not the glyph size.
variant:plain or :filled:plainTransparent, or on a raised surface.
shape:rounded or :circle:circleAction Icon defaults to :rounded. :circle uses an exact size / 2 radius.
colorcolor token or ARGB integer:on_surfaceGlyph color.
backgroundcolor token or ARGB integer:surface_raisedFill when variant is :filled.
shadowstringnilDrop shadow on the tap target, as dx dy blur spread #AARRGGBB.
border_colorcolor token or ARGB integernilHairline color. Nothing draws unless you set it.
border_widthnumber (dp)1Read only when border_color is set.

Events

Your screen receives {:tap, tag} in handle_info/2 when the user taps the button:

elixir
def handle_info({:tap, :dismiss}, socket) do
  {:noreply, assign(socket, :open, false)}
end

Differences from the web component

  • label is not ported. On the web it becomes an aria-label, and Mob exposes no accessible name on a box.