Modal#

Create modals to ask critical questions or notify the user about an upcoming event which must be acknowledged in some way.

let (show_simple_modal, set_show_simple_modal) = create_signal(false); view! { <P><Button on_press=move |_| set_show_simple_modal.set(true)>"Show simple modal"</Button></P> <Modal show_when=show_simple_modal> <ModalHeader><ModalTitle>"Hello"</ModalTitle></ModalHeader> <ModalBody>"This ia a simple modal."</ModalBody> <ModalFooter> <ButtonWrapper> <Button on_press=move |_| set_show_simple_modal.set(false) color=ButtonColor::Secondary>"Cancel"</Button> </ButtonWrapper> </ModalFooter> </Modal> }

Stages#

You can connect multiple modals by setting their visibility props appropriately.

let (show_staged_modal1, set_show_staged_modal1) = create_signal(false); let (show_staged_modal2, set_show_staged_modal2) = create_signal(false); view! { <P><Button on_press=move |_| set_show_staged_modal1.set(true)>"Show staged modal"</Button></P> <Modal show_when=show_staged_modal1> <ModalHeader><ModalTitle>"Sure?"</ModalTitle></ModalHeader> <ModalBody>"This ia a test modal."</ModalBody> <ModalFooter> <ButtonWrapper> <Button on_press=move |_| set_show_staged_modal2.set(true) color=ButtonColor::Info>"Next"</Button> <Button on_press=move |_| set_show_staged_modal1.set(false) color=ButtonColor::Secondary>"Cancel"</Button> </ButtonWrapper> </ModalFooter> </Modal> <Modal show_when=show_staged_modal2> <ModalHeader><ModalTitle>"Next one"</ModalTitle></ModalHeader> <ModalBody>"This overlays..."</ModalBody> <ModalFooter> <ButtonWrapper> <Button on_press=move |_| set_show_staged_modal2.set(false) color=ButtonColor::Secondary>"Back"</Button> </ButtonWrapper> </ModalFooter> </Modal> }

React to user input#

You can include arbitrary (reactive) children inside a modal. The next modal can only be accepted after entering "ok" in the presented input field.

let (show_confirm_modal, set_show_confirm_modal) = create_signal(false); view! { <P><Button on_press=move |_| set_show_confirm_modal.set(true)>"Show confirmation modal"</Button></P> <ConfirmModal show_when=show_confirm_modal requires_confirmation_of="ok".to_owned() on_accept=move || set_show_confirm_modal.set(false) on_cancel=move || set_show_confirm_modal.set(false) /> }

Using:

#[component] pub fn ConfirmModal<A, C>( #[prop(into)] show_when: Signal<bool>, requires_confirmation_of: String, on_accept: A, on_cancel: C, ) -> impl IntoView where A: Fn() + Copy + 'static, C: Fn() + Copy + 'static, { let required = store_value(requires_confirmation_of); let (input, set_input) = create_signal(String::new()); let confirmed = move || required.with_value(|r| input.with(|i| r == i)); let disabled = Signal::derive(move || !confirmed()); let on_accept = move || { set_input.update(|it| it.clear()); (on_accept)(); }; let on_cancel = move || { set_input.update(|it| it.clear()); (on_cancel)(); }; view! { <Modal show_when=show_when on_escape=move || (on_cancel)()> <ModalHeader><ModalTitle>"Delete repository?"</ModalTitle></ModalHeader> <ModalBody> "Please enter \""{required.get_value()}"\" to confirm." <TextInput get=input set=set_input/> </ModalBody> <ModalFooter> <ButtonWrapper> <Button on_press=move |_| (on_accept)() disabled=disabled color=ButtonColor::Danger>"Confirm"</Button> <Button on_press=move |_| (on_cancel)() color=ButtonColor::Secondary>"Cancel"</Button> </ButtonWrapper> </ModalFooter> </Modal> } }

Handling escape and backdrop interactions #

Closing a modal through a press on Esc or closing it through a click outside its rendered content can be considered "commonly expected behavior" of modals.

Modals may be used as critical gate-keepers. The API of them should minimize error-potential as much as possible. The author of a modal should therefore have full control, preferably at a centralized point, over all ways a modals display state may change.As the modal component does neither owns it's display state nor knows what to do when the modal is shown or hidden (modals only know whether they should be rendered or not, reading their show_when prop) fully automated handling of escape keys is not possible.

Leptonic'sModal component will however automatically listen for an 'Escape' key press when the on_escape callback property is provided. This gives you explicit control over the effect this should have.

The Modal's on_backdrop_interaction callback property allows you to handle user interactions with the backdrop. In the current implementation, pressing the backdrop triggers the callback. This gives you explicit control over the effect this should have.

We snuck this in for all example modals (even the staged one). For our first example, it simply looks like this.

<Modal show_when=show_simple_modal on_escape=move || set_show_simple_modal.set(false) on_backdrop_interaction=move || set_show_simple_modal.set(false) > <ModalHeader><ModalTitle>"Hello"</ModalTitle></ModalHeader> <ModalBody>"This ia a simple modal."</ModalBody> <ModalFooter> <ButtonWrapper> <Button on_press=move |_| set_show_simple_modal.set(false) color=ButtonColor::Secondary>"Cancel"</Button> </ButtonWrapper> </ModalFooter> </Modal>

Styling#

You may overwrite any of the following CSS variables to meet your styling needs.

--modal-color --modal-background-color --modal-padding --modal-font-size --modal-header-padding --modal-body-padding --modal-footer-padding --modal-border-radius --modal-box-shadow