diff --git a/smart-house-web/frontend/src/main.rs b/smart-house-web/frontend/src/main.rs
index d7c5702..57c11e5 100644
--- a/smart-house-web/frontend/src/main.rs
+++ b/smart-house-web/frontend/src/main.rs
@@ -1,49 +1,114 @@
#![allow(non_snake_case)]
-use leptos::prelude::*;
+
+use leptos::{ev::MouseEvent, prelude::*};
+
+// This highlights four different ways that child components can communicate
+// with their parent:
+// 1) : passing a WriteSignal as one of the child component props,
+// for the child component to write into and the parent to read
+// 2) : passing a closure as one of the child component props, for
+// the child component to call
+// 3) : adding an `on:` event listener to a component
+// 4) : providing a context that is used in the component (rather than prop drilling)
+
+#[derive(Copy, Clone)]
+struct SmallcapsContext(WriteSignal);
#[component]
-fn App() -> impl IntoView {
- let (value, set_value) = signal(Ok(0));
+pub fn App() -> impl IntoView {
+ // just some signals to toggle four classes on our
+ let (red, set_red) = signal(false);
+ let (right, set_right) = signal(false);
+ let (italics, set_italics) = signal(false);
+ let (smallcaps, set_smallcaps) = signal(false);
+
+ // the newtype pattern isn't *necessary* here but is a good practice
+ // it avoids confusion with other possible future `WriteSignal` contexts
+ // and makes it easier to refer to it in ButtonD
+ provide_context(SmallcapsContext(set_smallcaps));
view! {
-
"Error Handling"
-
+ "Lorem ipsum sit dolor amet."
+
+
+ // Button A: pass the signal setter
+
+
+ // Button B: pass a closure
+
+
+ // Button C: use a regular event listener
+ // setting an event listener on a component like this applies it
+ // to each of the top-level elements the component returns
+
+
+ // Button D gets its setter from context rather than props
+
+
+ }
+}
+
+/// Button A receives a signal setter and updates the signal itself
+#[component]
+pub fn ButtonA(
+ /// Signal that will be toggled when the button is clicked.
+ setter: WriteSignal,
+) -> impl IntoView {
+ view! {
+
+ }
+}
+
+/// Button B receives a closure
+#[component]
+pub fn ButtonB(
+ /// Callback that will be invoked when the button is clicked.
+ on_click: impl FnMut(MouseEvent) + 'static,
+) -> impl IntoView {
+ view! {
+
+ }
+}
+
+/// Button C is a dummy: it renders a button but doesn't handle
+/// its click. Instead, the parent component adds an event listener.
+#[component]
+pub fn ButtonC() -> impl IntoView {
+ view! {
+
+ }
+}
+
+/// Button D is very similar to Button A, but instead of passing the setter as a prop
+/// we get it from the context
+#[component]
+pub fn ButtonD() -> impl IntoView {
+ let setter = use_context::().unwrap().0;
+
+ view! {
+
}
}