Skip to main content

dioxus_flow/
controls.rs

1//! Built-in zoom / fit-view control buttons.
2
3use dioxus::prelude::*;
4
5use crate::state::{use_overlay_inset, FlowCore};
6use crate::types::Side;
7
8/// Zoom-in, zoom-out and fit-view buttons. Render as a child of
9/// [`crate::Flow`]; add extra buttons as children.
10#[component]
11pub fn Controls(class: Option<String>, children: Element) -> Element {
12    let core = use_context::<FlowCore>();
13    // Panel footprint (3 × 28px buttons + borders + 14px offset) plus
14    // breathing room, so fit-view keeps nodes clear of the controls.
15    use_overlay_inset(Side::Bottom, 112.0);
16    let class = format!(
17        "df-controls{}",
18        class
19            .as_deref()
20            .map(|c| format!(" {c}"))
21            .unwrap_or_default()
22    );
23    rsx! {
24        div {
25            class,
26            // Keep pane gestures from starting on the controls.
27            onpointerdown: move |evt| evt.stop_propagation(),
28            button {
29                class: "df-control-btn",
30                r#type: "button",
31                title: "Zoom in",
32                aria_label: "Zoom in",
33                onclick: move |_| core.zoom_in(200),
34                svg {
35                    view_box: "0 0 16 16",
36                    path { d: "M8 3.5v9M3.5 8h9", stroke: "currentColor", stroke_width: "1.6", stroke_linecap: "round", fill: "none" }
37                }
38            }
39            button {
40                class: "df-control-btn",
41                r#type: "button",
42                title: "Zoom out",
43                aria_label: "Zoom out",
44                onclick: move |_| core.zoom_out(200),
45                svg {
46                    view_box: "0 0 16 16",
47                    path { d: "M3.5 8h9", stroke: "currentColor", stroke_width: "1.6", stroke_linecap: "round", fill: "none" }
48                }
49            }
50            button {
51                class: "df-control-btn",
52                r#type: "button",
53                title: "Fit view",
54                aria_label: "Fit view",
55                onclick: move |_| core.fit_view(400),
56                svg {
57                    view_box: "0 0 16 16",
58                    path {
59                        d: "M2.5 6V2.5H6M10 2.5h3.5V6M13.5 10v3.5H10M6 13.5H2.5V10",
60                        stroke: "currentColor",
61                        stroke_width: "1.6",
62                        stroke_linecap: "round",
63                        stroke_linejoin: "round",
64                        fill: "none",
65                    }
66                }
67            }
68            {children}
69        }
70    }
71}