From e65f9ce940f6b5f92be74dafb840f8f1d263596d Mon Sep 17 00:00:00 2001
From: StarArawn <toasterthegamer@gmail.com>
Date: Sat, 18 Dec 2021 20:44:59 -0500
Subject: [PATCH] Fully working todo..

---
 Cargo.toml                              |   4 +
 bevy_kayak_ui/src/render/unified/mod.rs |   2 +
 examples/text_box.rs                    |   4 +-
 examples/todo/add_button.rs             |  46 +++++++++
 examples/todo/card.rs                   |  40 ++++++++
 examples/todo/cards.rs                  |  22 +++++
 examples/todo/delete_button.rs          |  45 +++++++++
 examples/todo/todo.rs                   | 126 ++++++++++++++++++++++++
 kayak_core/src/lib.rs                   |  30 +++++-
 kayak_core/src/node.rs                  |  22 ++++-
 kayak_core/src/styles.rs                |   4 +
 kayak_core/src/vec.rs                   |   2 +-
 kayak_core/src/widget_manager.rs        |  32 +++++-
 kayak_render_macros/src/lib.rs          |   3 +-
 kayak_widgets/src/element.rs            |  12 ++-
 kayak_widgets/src/text_box.rs           |  11 ++-
 kayak_widgets/src/window.rs             |   8 +-
 17 files changed, 393 insertions(+), 20 deletions(-)
 create mode 100644 examples/todo/add_button.rs
 create mode 100644 examples/todo/card.rs
 create mode 100644 examples/todo/cards.rs
 create mode 100644 examples/todo/delete_button.rs
 create mode 100644 examples/todo/todo.rs

diff --git a/Cargo.toml b/Cargo.toml
index e76dc57..4357ec4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,3 +27,7 @@ kayak_render_macros = { path = "kayak_render_macros" }
 [dev-dependencies]
 bevy = { git = "https://github.com/bevyengine/bevy", rev = "9a16a4d01830297987db40b45f03382ed3acad62" }
 kayak_widgets = { path = "kayak_widgets", features = ["bevy_renderer"] }
+
+[[example]]
+name = "todo"
+path = "examples/todo/todo.rs"
diff --git a/bevy_kayak_ui/src/render/unified/mod.rs b/bevy_kayak_ui/src/render/unified/mod.rs
index 6fff2f9..ee0390d 100644
--- a/bevy_kayak_ui/src/render/unified/mod.rs
+++ b/bevy_kayak_ui/src/render/unified/mod.rs
@@ -78,6 +78,8 @@ pub fn extract(
         vec![]
     };
 
+    // dbg!(&render_primitives);
+
     let dpi = if let Some(window) = windows.get_primary() {
         window.scale_factor() as f32
     } else {
diff --git a/examples/text_box.rs b/examples/text_box.rs
index bbf01ec..5a91981 100644
--- a/examples/text_box.rs
+++ b/examples/text_box.rs
@@ -38,8 +38,8 @@ fn TextBoxExample(context: &mut KayakContext) {
     rsx! {
         <>
             <Window position={(50.0, 50.0)} size={(300.0, 300.0)} title={"TextBox Example".to_string()}>
-                <TextBox styles={Some(input_styles)} value={current_value} on_change={Some(on_change)} />
-                <TextBox styles={Some(input_styles)} value={current_value2} on_change={Some(on_change2)} />
+                <TextBox styles={Some(input_styles)} value={current_value} on_change={Some(on_change)} placeholder={None as Option<String>} />
+                <TextBox styles={Some(input_styles)} value={current_value2} on_change={Some(on_change2)} placeholder={None as Option<String>} />
             </Window>
         </>
     }
diff --git a/examples/todo/add_button.rs b/examples/todo/add_button.rs
new file mode 100644
index 0000000..febec97
--- /dev/null
+++ b/examples/todo/add_button.rs
@@ -0,0 +1,46 @@
+use kayak_ui::core::{
+    color::Color,
+    render_command::RenderCommand,
+    rsx,
+    styles::{Style, StyleProp, Units},
+    use_state, widget, Bound, Children, EventType, MutableBound, OnEvent,
+};
+
+use kayak_widgets::{Background, Text};
+
+#[widget]
+pub fn AddButton(children: Children, styles: Option<Style>) {
+    let (color, set_color) = use_state!(Color::new(0.0781, 0.0898, 0.101, 1.0));
+
+    let base_styles = styles.clone().unwrap_or_default();
+    *styles = Some(Style {
+        render_command: StyleProp::Value(RenderCommand::Layout),
+        height: StyleProp::Value(Units::Pixels(32.0)),
+        width: StyleProp::Value(Units::Pixels(30.0)),
+        ..base_styles
+    });
+
+    let background_styles = Some(Style {
+        border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
+        background_color: StyleProp::Value(color),
+        padding_left: StyleProp::Value(Units::Pixels(9.0)),
+        padding_bottom: StyleProp::Value(Units::Pixels(6.0)),
+        ..Style::default()
+    });
+
+    let on_event = OnEvent::new(move |_, event| match event.event_type {
+        EventType::MouseIn => {
+            set_color(Color::new(0.0791, 0.0998, 0.201, 1.0));
+        }
+        EventType::MouseOut => {
+            set_color(Color::new(0.0781, 0.0898, 0.101, 1.0));
+        }
+        _ => {}
+    });
+
+    rsx! {
+        <Background styles={background_styles} on_event={Some(on_event)}>
+            <Text content={"+".to_string()} size={20.0} />
+        </Background>
+    }
+}
diff --git a/examples/todo/card.rs b/examples/todo/card.rs
new file mode 100644
index 0000000..7bb615c
--- /dev/null
+++ b/examples/todo/card.rs
@@ -0,0 +1,40 @@
+use kayak_core::{
+    rsx,
+    styles::{LayoutType, Style, StyleProp, Units},
+    widget, Color, EventType, Handler, OnEvent,
+};
+use kayak_widgets::{Background, Text};
+
+use super::delete_button::DeleteButton;
+
+#[widget]
+pub fn Card(card_id: usize, name: String, on_delete: Handler<usize>) {
+    let name = name.clone();
+    let background_styles = Style {
+        layout_type: StyleProp::Value(LayoutType::Row),
+        background_color: StyleProp::Value(Color::new(0.176, 0.196, 0.215, 1.0)),
+        height: StyleProp::Value(Units::Pixels(26.0)),
+        top: StyleProp::Value(Units::Pixels(10.0)),
+        padding_left: StyleProp::Value(Units::Pixels(5.0)),
+        padding_right: StyleProp::Value(Units::Pixels(5.0)),
+        padding_top: StyleProp::Value(Units::Pixels(5.0)),
+        padding_bottom: StyleProp::Value(Units::Pixels(5.0)),
+        ..Style::default()
+    };
+
+    let on_delete = on_delete.clone();
+    let card_id = *card_id;
+    let on_event = OnEvent::new(move |_, event| match event.event_type {
+        EventType::Click => {
+            on_delete.call(card_id);
+        }
+        _ => (),
+    });
+
+    rsx! {
+        <Background styles={Some(background_styles)}>
+            <Text size={14.0} content={name} />
+            <DeleteButton on_event={Some(on_event)} />
+        </Background>
+    }
+}
diff --git a/examples/todo/cards.rs b/examples/todo/cards.rs
new file mode 100644
index 0000000..04e059b
--- /dev/null
+++ b/examples/todo/cards.rs
@@ -0,0 +1,22 @@
+use kayak_core::{constructor, rsx, widget, Handler, VecTracker};
+use kayak_widgets::Element;
+
+use super::{card::Card, Todo};
+
+#[widget]
+pub fn Cards(cards: Vec<Todo>, on_delete: Handler<usize>) {
+    let cards = cards.clone();
+
+    let on_delete = on_delete.clone();
+    rsx! {
+        <Element>
+            {VecTracker::from(
+                cards
+                    .clone()
+                    .into_iter()
+                    .enumerate()
+                    .map(|(index, todo)| constructor! { <Card card_id={index} name={todo.name.clone()} on_delete={on_delete.clone()} /> }),
+            )}
+        </Element>
+    }
+}
diff --git a/examples/todo/delete_button.rs b/examples/todo/delete_button.rs
new file mode 100644
index 0000000..e7a5971
--- /dev/null
+++ b/examples/todo/delete_button.rs
@@ -0,0 +1,45 @@
+use kayak_ui::core::{
+    color::Color,
+    render_command::RenderCommand,
+    rsx,
+    styles::{Style, StyleProp, Units},
+    use_state, widget, Bound, Children, EventType, MutableBound, OnEvent,
+};
+
+use kayak_widgets::{Background, Text};
+
+#[widget]
+pub fn DeleteButton(children: Children, styles: Option<Style>) {
+    let (color, set_color) = use_state!(Color::new(0.0781, 0.0898, 0.101, 1.0));
+
+    let base_styles = styles.clone().unwrap_or_default();
+    *styles = Some(Style {
+        render_command: StyleProp::Value(RenderCommand::Layout),
+        height: StyleProp::Value(Units::Pixels(32.0)),
+        width: StyleProp::Value(Units::Pixels(30.0)),
+        ..base_styles
+    });
+
+    let background_styles = Some(Style {
+        border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
+        background_color: StyleProp::Value(color),
+        padding_left: StyleProp::Value(Units::Pixels(8.0)),
+        ..Style::default()
+    });
+
+    let on_event = OnEvent::new(move |_, event| match event.event_type {
+        EventType::MouseIn => {
+            set_color(Color::new(0.0791, 0.0998, 0.201, 1.0));
+        }
+        EventType::MouseOut => {
+            set_color(Color::new(0.0781, 0.0898, 0.101, 1.0));
+        }
+        _ => {}
+    });
+
+    rsx! {
+        <Background styles={background_styles} on_event={Some(on_event)}>
+            <Text content={"X".to_string()} size={20.0} />
+        </Background>
+    }
+}
diff --git a/examples/todo/todo.rs b/examples/todo/todo.rs
new file mode 100644
index 0000000..6685015
--- /dev/null
+++ b/examples/todo/todo.rs
@@ -0,0 +1,126 @@
+use bevy::{
+    prelude::{App as BevyApp, AssetServer, Commands, Res, ResMut},
+    window::WindowDescriptor,
+    DefaultPlugins,
+};
+use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle};
+use kayak_ui::core::{
+    render, rsx,
+    styles::{LayoutType, Style, StyleProp, Units},
+    use_state, widget, Bound, EventType, Handler, Index, MutableBound, OnEvent,
+};
+use kayak_widgets::{App, Element, OnChange, TextBox, Window};
+
+mod add_button;
+mod card;
+mod cards;
+mod delete_button;
+use add_button::AddButton;
+use cards::Cards;
+
+#[derive(Debug, Clone, PartialEq)]
+pub struct Todo {
+    name: String,
+}
+
+#[widget]
+fn TodoApp() {
+    let (todos, set_todos) = use_state!(vec![
+        Todo {
+            name: "Use bevy to make a game!".to_string(),
+        },
+        Todo {
+            name: "Help contribute to bevy!".to_string(),
+        },
+        Todo {
+            name: "Join the bevy discord!".to_string(),
+        },
+    ]);
+
+    let (new_todo_value, set_new_todo_value) = use_state!("".to_string());
+
+    let text_box_styles = Style {
+        right: StyleProp::Value(Units::Pixels(10.0)),
+        ..Style::default()
+    };
+
+    let top_area_styles = Style {
+        layout_type: StyleProp::Value(LayoutType::Row),
+        bottom: StyleProp::Value(Units::Pixels(10.0)),
+        height: StyleProp::Value(Units::Pixels(30.0)),
+        padding_top: StyleProp::Value(Units::Stretch(1.0)),
+        padding_bottom: StyleProp::Value(Units::Stretch(1.0)),
+        ..Style::default()
+    };
+
+    let on_change = OnChange::new(move |event| {
+        set_new_todo_value(event.value);
+    });
+
+    let new_todo_value_cloned = new_todo_value.clone();
+    let mut todos_cloned = todos.clone();
+    let cloned_set_todos = set_todos.clone();
+    let add_events = OnEvent::new(move |_, event| match event.event_type {
+        EventType::Click => {
+            if !new_todo_value_cloned.is_empty() {
+                todos_cloned.push(Todo {
+                    name: new_todo_value_cloned.clone(),
+                });
+                cloned_set_todos(todos_cloned.clone());
+            }
+        }
+        _ => {}
+    });
+
+    let mut todos_cloned = todos.clone();
+    let cloned_set_todos = set_todos.clone();
+    let handle_delete = Handler::new(move |card_id: usize| {
+        todos_cloned.remove(card_id);
+        cloned_set_todos(todos_cloned.clone());
+    });
+
+    let placeholder = Some("Type here to add a new todo!".to_string());
+    rsx! {
+        <Window position={(415.0, 50.0)} size={(450.0, 600.0)} title={"Todo!".to_string()}>
+            <Element styles={Some(top_area_styles)}>
+                <TextBox styles={Some(text_box_styles)} value={new_todo_value} placeholder={placeholder} on_change={Some(on_change)} />
+                <AddButton on_event={Some(add_events)} />
+            </Element>
+            <Cards cards={todos} on_delete={handle_delete} />
+        </Window>
+    }
+}
+
+fn startup(
+    mut commands: Commands,
+    mut font_mapping: ResMut<FontMapping>,
+    asset_server: Res<AssetServer>,
+) {
+    commands.spawn_bundle(UICameraBundle::new());
+
+    font_mapping.add(asset_server.load("roboto.kayak_font"));
+
+    let context = BevyContext::new(|context| {
+        render! {
+            <App>
+                <TodoApp />
+            </App>
+        }
+    });
+
+    commands.insert_resource(context);
+}
+
+fn main() {
+    BevyApp::new()
+        .insert_resource(WindowDescriptor {
+            width: 1270.0,
+            height: 720.0,
+            title: String::from("UI Example"),
+            ..Default::default()
+        })
+        .add_plugins(DefaultPlugins)
+        .add_plugin(BevyKayakUIPlugin)
+        .add_startup_system(startup)
+        .run();
+}
diff --git a/kayak_core/src/lib.rs b/kayak_core/src/lib.rs
index 9fa9138..0a12999 100644
--- a/kayak_core/src/lib.rs
+++ b/kayak_core/src/lib.rs
@@ -32,6 +32,9 @@ pub use resources::Resources;
 pub use tree::{Tree, WidgetTree};
 pub use vec::VecTracker;
 pub use widget::Widget;
+pub mod derivative {
+    pub use derivative::*;
+}
 
 pub type Children = Option<
     Arc<dyn Fn(WidgetTree, Option<crate::Index>, &mut crate::context::KayakContext) + Send + Sync>,
@@ -52,6 +55,29 @@ impl OnEvent {
     }
 }
 
-pub mod derivative {
-    pub use derivative::*;
+#[derive(Clone)]
+pub struct Handler<T>(pub Arc<RwLock<dyn FnMut(T) + Send + Sync + 'static>>);
+
+impl<T> Handler<T> {
+    pub fn new<F: FnMut(T) + Send + Sync + 'static>(f: F) -> Handler<T> {
+        Handler(Arc::new(RwLock::new(f)))
+    }
+
+    pub fn call(&self, data: T) {
+        if let Ok(mut handler) = self.0.write() {
+            handler(data);
+        }
+    }
+}
+
+impl<T> PartialEq for Handler<T> {
+    fn eq(&self, _other: &Self) -> bool {
+        true
+    }
+}
+
+impl<T> std::fmt::Debug for Handler<T> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_tuple("Handler").finish()
+    }
 }
diff --git a/kayak_core/src/node.rs b/kayak_core/src/node.rs
index 9bd99bd..91023eb 100644
--- a/kayak_core/src/node.rs
+++ b/kayak_core/src/node.rs
@@ -116,11 +116,29 @@ impl<'a> morphorm::Node<'a> for Index {
         return Some(morphorm::Units::Stretch(1.0));
     }
 
-    fn min_width(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
+    fn min_width(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
+        if let Some(node) = store.get(*self) {
+            if let Some(node) = node {
+                return match node.styles.min_width {
+                    StyleProp::Default => Some(morphorm::Units::Stretch(1.0)),
+                    StyleProp::Value(prop) => Some(prop),
+                    _ => Some(morphorm::Units::Auto),
+                };
+            }
+        }
         Some(morphorm::Units::Auto)
     }
 
-    fn min_height(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
+    fn min_height(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
+        if let Some(node) = store.get(*self) {
+            if let Some(node) = node {
+                return match node.styles.min_height {
+                    StyleProp::Default => Some(morphorm::Units::Stretch(1.0)),
+                    StyleProp::Value(prop) => Some(prop),
+                    _ => Some(morphorm::Units::Auto),
+                };
+            }
+        }
         Some(morphorm::Units::Auto)
     }
 
diff --git a/kayak_core/src/styles.rs b/kayak_core/src/styles.rs
index a1671dc..850f17b 100644
--- a/kayak_core/src/styles.rs
+++ b/kayak_core/src/styles.rs
@@ -53,6 +53,8 @@ pub struct Style {
     pub margin_right: StyleProp<Units>,
     pub margin_top: StyleProp<Units>,
     pub margin_bottom: StyleProp<Units>,
+    pub min_width: StyleProp<Units>,
+    pub min_height: StyleProp<Units>,
 }
 
 impl Default for Style {
@@ -78,6 +80,8 @@ impl Default for Style {
             margin_right: StyleProp::Default,
             margin_top: StyleProp::Default,
             margin_bottom: StyleProp::Default,
+            min_width: StyleProp::Default,
+            min_height: StyleProp::Default,
         }
     }
 }
diff --git a/kayak_core/src/vec.rs b/kayak_core/src/vec.rs
index ff8ff99..5bc2776 100644
--- a/kayak_core/src/vec.rs
+++ b/kayak_core/src/vec.rs
@@ -3,7 +3,7 @@ use derivative::*;
 use crate::{context::KayakContext, styles::Style, Index, Widget};
 
 #[derive(Derivative)]
-#[derivative(Debug, PartialEq)]
+#[derivative(Debug, PartialEq, Clone)]
 pub struct VecTracker<T> {
     pub id: Index,
     pub styles: Option<Style>,
diff --git a/kayak_core/src/widget_manager.rs b/kayak_core/src/widget_manager.rs
index c10c225..e8a54ff 100644
--- a/kayak_core/src/widget_manager.rs
+++ b/kayak_core/src/widget_manager.rs
@@ -256,6 +256,7 @@ impl WidgetManager {
         nodes: &Arena<Option<Node>>,
         current_node: Index,
         mut main_z_index: f32,
+        mut prev_clip: RenderPrimitive,
     ) -> Vec<RenderPrimitive> {
         let mut render_primitives = Vec::new();
 
@@ -272,6 +273,14 @@ impl WidgetManager {
                 render_primitive.set_layout(layout);
                 render_primitives.push(render_primitive.clone());
 
+                let new_prev_clip = if matches!(render_primitive, RenderPrimitive::Clip { .. }) {
+                    render_primitive.clone()
+                } else {
+                    prev_clip
+                };
+
+                prev_clip = new_prev_clip.clone();
+
                 if node_tree.children.contains_key(&current_node) {
                     for child in node_tree.children.get(&current_node).unwrap() {
                         main_z_index += 1.0;
@@ -281,22 +290,36 @@ impl WidgetManager {
                             nodes,
                             *child,
                             main_z_index,
+                            new_prev_clip.clone(),
                         ));
 
                         main_z_index = layout.z_index;
                         // Between each child node we need to reset the clip.
-                        if matches!(render_primitive, RenderPrimitive::Clip { .. }) {
-                            main_z_index = new_z_index;
-                            match &mut render_primitive {
+                        if matches!(prev_clip, RenderPrimitive::Clip { .. }) {
+                            // main_z_index = new_z_index;
+                            match &mut prev_clip {
                                 RenderPrimitive::Clip { layout } => {
                                     layout.z_index = main_z_index + 0.1;
                                 }
                                 _ => {}
                             };
-                            render_primitives.push(render_primitive.clone());
+                            render_primitives.push(prev_clip.clone());
                         }
                     }
                 }
+
+                // if matches!(render_primitive, RenderPrimitive::Clip { .. })
+                //     && matches!(prev_clip, RenderPrimitive::Clip { .. })
+                // {
+                //     // main_z_index = new_z_index;
+                //     match &mut prev_clip {
+                //         RenderPrimitive::Clip { layout } => {
+                //             layout.z_index = main_z_index + 0.1;
+                //         }
+                //         _ => {}
+                //     };
+                //     render_primitives.push(render_primitive.clone());
+                // }
             }
         }
 
@@ -310,6 +333,7 @@ impl WidgetManager {
             &self.nodes,
             self.node_tree.root_node.unwrap(),
             0.0,
+            RenderPrimitive::Empty,
         )
     }
 
diff --git a/kayak_render_macros/src/lib.rs b/kayak_render_macros/src/lib.rs
index 916372f..0d66f43 100644
--- a/kayak_render_macros/src/lib.rs
+++ b/kayak_render_macros/src/lib.rs
@@ -104,7 +104,6 @@ pub fn dyn_partial_eq(_: TokenStream, input: TokenStream) -> TokenStream {
     .into()
 }
 
-
 /// Create a state and its setter
 ///
 /// # Arguments
@@ -151,4 +150,4 @@ pub fn use_state(initial_state: TokenStream) -> TokenStream {
         (state.get(), set_state)
     }};
     TokenStream::from(result)
-}
\ No newline at end of file
+}
diff --git a/kayak_widgets/src/element.rs b/kayak_widgets/src/element.rs
index be6c883..3c14e83 100644
--- a/kayak_widgets/src/element.rs
+++ b/kayak_widgets/src/element.rs
@@ -1,7 +1,17 @@
-use kayak_ui::core::{rsx, widget, Children};
+use kayak_ui::core::{
+    render_command::RenderCommand,
+    rsx,
+    styles::{Style, StyleProp},
+    widget, Children,
+};
 
 #[widget]
 pub fn Element(children: Children) {
+    *styles = Some(Style {
+        render_command: StyleProp::Value(RenderCommand::Layout),
+        ..styles.clone().unwrap_or_default()
+    });
+
     rsx! {
         <>
             {children}
diff --git a/kayak_widgets/src/text_box.rs b/kayak_widgets/src/text_box.rs
index 0da96fe..3ba7dc4 100644
--- a/kayak_widgets/src/text_box.rs
+++ b/kayak_widgets/src/text_box.rs
@@ -38,9 +38,12 @@ impl std::fmt::Debug for OnChange {
 pub struct Focus(pub bool);
 
 #[widget(focusable)]
-pub fn TextBox(value: String, on_change: Option<OnChange>) {
+pub fn TextBox(value: String, on_change: Option<OnChange>, placeholder: Option<String>) {
     *styles = Some(Style {
         render_command: StyleProp::Value(RenderCommand::Layout),
+        height: StyleProp::Value(Units::Pixels(26.0)),
+        top: StyleProp::Value(Units::Pixels(0.0)),
+        bottom: StyleProp::Value(Units::Pixels(0.0)),
         ..styles.clone().unwrap_or_default()
     });
 
@@ -83,7 +86,11 @@ pub fn TextBox(value: String, on_change: Option<OnChange>) {
         _ => {}
     }));
 
-    let value = value.clone();
+    let value = if value.is_empty() {
+        placeholder.clone().unwrap_or(value.clone())
+    } else {
+        value.clone()
+    };
     rsx! {
         <Background styles={Some(background_styles)}>
             <Clip>
diff --git a/kayak_widgets/src/window.rs b/kayak_widgets/src/window.rs
index 186bec3..c2cdee3 100644
--- a/kayak_widgets/src/window.rs
+++ b/kayak_widgets/src/window.rs
@@ -56,10 +56,10 @@ pub fn Window(
     };
 
     let content_styles = Style {
-        padding_left: StyleProp::Value(Units::Stretch(1.0)),
-        padding_right: StyleProp::Value(Units::Stretch(1.0)),
-        padding_top: StyleProp::Value(Units::Stretch(1.0)),
-        padding_bottom: StyleProp::Value(Units::Stretch(1.0)),
+        padding_left: StyleProp::Value(Units::Pixels(10.0)),
+        padding_right: StyleProp::Value(Units::Pixels(10.0)),
+        padding_top: StyleProp::Value(Units::Pixels(10.0)),
+        padding_bottom: StyleProp::Value(Units::Pixels(10.0)),
         ..Style::default()
     };
 
-- 
GitLab