Unstyled, headless-ish function components for the two surfaces of the
flow: the desktop QR panel/1 and the phone confirm_screen/1.
They ship minimal structural markup and Tailwind/daisyUI-friendly
classes but assume nothing about your design system — override via the
class slots or wrap them. All copy is passed in (or defaulted in
English) so the host owns i18n.
Summary
Functions
The phone confirm screen. Shows the requesting device (from the
request's meta) and Approve / Deny buttons.
The desktop QR panel. Render the SVG produced by Keyfob.QR.svg/2 and
reflect the waiting state.
Functions
The phone confirm screen. Shows the requesting device (from the
request's meta) and Approve / Deny buttons.
Never auto-approve — the whole point of this screen is the human check against QR-jacking.
Attributes:
:meta— the request meta map (:browser,:os,:ip, etc.; all optional). Whatever keys you put increate_request/1.:state—:pending | :approved | :denied | :expired:approve_event/:deny_event—phx-clicknames.:labels— copy overrides.
Attributes
meta(:map) - Defaults to%{}.state(:atom) (required)approve_event(:string) - Defaults to"keyfob_approve".deny_event(:string) - Defaults to"keyfob_deny".class(:string) - Defaults tonil.labels(:map) - Defaults to%{}.
The desktop QR panel. Render the SVG produced by Keyfob.QR.svg/2 and
reflect the waiting state.
Attributes:
:qr_svg— the inline SVG string (required unlessstate != :waiting):state—:waiting | :approved | :denied | :expired(required):refresh_event—phx-clickevent name for the "New code" button shown on:expired. Default"keyfob_refresh".:labels— map overriding the default copy.
Attributes
qr_svg(:string) - Defaults tonil.state(:atom) (required)refresh_event(:string) - Defaults to"keyfob_refresh".class(:string) - Defaults tonil.labels(:map) - Defaults to%{}.