meme_editor_dark_mode.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // ANCHOR: all
  2. #![allow(non_snake_case)]
  3. use dioxus::prelude::*;
  4. fn main() {
  5. dioxus_desktop::launch(App);
  6. }
  7. // ANCHOR: DarkMode_struct
  8. struct DarkMode(bool);
  9. // ANCHOR_END: DarkMode_struct
  10. pub fn App(cx: Scope) -> Element {
  11. // ANCHOR: context_provider
  12. use_shared_state_provider(cx, || DarkMode(false));
  13. // ANCHOR_END: context_provider
  14. let is_dark_mode = use_is_dark_mode(cx);
  15. let wrapper_style = if is_dark_mode {
  16. r"
  17. background: #222;
  18. min-height: 100vh;
  19. "
  20. } else {
  21. r""
  22. };
  23. cx.render(rsx!(div {
  24. style: "{wrapper_style}",
  25. DarkModeToggle {},
  26. MemeEditor {},
  27. }))
  28. }
  29. pub fn use_is_dark_mode(cx: &ScopeState) -> bool {
  30. // ANCHOR: use_context
  31. let dark_mode_context = use_shared_state::<DarkMode>(cx);
  32. // ANCHOR_END: use_context
  33. dark_mode_context
  34. .map(|context| context.read().0)
  35. .unwrap_or(false)
  36. }
  37. // ANCHOR: toggle
  38. pub fn DarkModeToggle(cx: Scope) -> Element {
  39. let dark_mode = use_shared_state::<DarkMode>(cx).unwrap();
  40. let style = if dark_mode.read().0 {
  41. "color:white"
  42. } else {
  43. ""
  44. };
  45. cx.render(rsx!(label {
  46. style: "{style}",
  47. "Dark Mode",
  48. input {
  49. r#type: "checkbox",
  50. oninput: move |event| {
  51. let is_enabled = event.value == "true";
  52. dark_mode.write().0 = is_enabled;
  53. },
  54. },
  55. }))
  56. }
  57. // ANCHOR_END: toggle
  58. // ANCHOR: meme_editor
  59. fn MemeEditor(cx: Scope) -> Element {
  60. let is_dark_mode = use_is_dark_mode(cx);
  61. let heading_style = if is_dark_mode { "color: white" } else { "" };
  62. let container_style = r"
  63. display: flex;
  64. flex-direction: column;
  65. gap: 16px;
  66. margin: 0 auto;
  67. width: fit-content;
  68. ";
  69. let caption = use_state(cx, || "me waiting for my rust code to compile".to_string());
  70. cx.render(rsx! {
  71. div {
  72. style: "{container_style}",
  73. h1 {
  74. style: "{heading_style}",
  75. "Meme Editor"
  76. },
  77. Meme {
  78. caption: caption,
  79. },
  80. CaptionEditor {
  81. caption: caption,
  82. on_input: move |event: FormEvent| {caption.set(event.value.clone());},
  83. },
  84. }
  85. })
  86. }
  87. // ANCHOR_END: meme_editor
  88. // ANCHOR: meme_component
  89. #[inline_props]
  90. fn Meme<'a>(cx: Scope<'a>, caption: &'a str) -> Element<'a> {
  91. let container_style = r"
  92. position: relative;
  93. width: fit-content;
  94. ";
  95. let caption_container_style = r"
  96. position: absolute;
  97. bottom: 0;
  98. left: 0;
  99. right: 0;
  100. padding: 16px 8px;
  101. ";
  102. let caption_style = r"
  103. font-size: 32px;
  104. margin: 0;
  105. color: white;
  106. text-align: center;
  107. ";
  108. cx.render(rsx!(
  109. div {
  110. style: "{container_style}",
  111. img {
  112. src: "https://i.imgflip.com/2zh47r.jpg",
  113. height: "500px",
  114. },
  115. div {
  116. style: "{caption_container_style}",
  117. p {
  118. style: "{caption_style}",
  119. "{caption}"
  120. }
  121. }
  122. }
  123. ))
  124. }
  125. // ANCHOR_END: meme_component
  126. // ANCHOR: caption_editor
  127. #[inline_props]
  128. fn CaptionEditor<'a>(
  129. cx: Scope<'a>,
  130. caption: &'a str,
  131. on_input: EventHandler<'a, FormEvent>,
  132. ) -> Element<'a> {
  133. let is_dark_mode = use_is_dark_mode(cx);
  134. let colors = if is_dark_mode {
  135. r"
  136. background: cornflowerblue;
  137. color: white;
  138. "
  139. } else {
  140. r"
  141. background: #def;
  142. color: black;
  143. "
  144. };
  145. let input_style = r"
  146. border: none;
  147. padding: 8px 16px;
  148. margin: 0;
  149. border-radius: 4px;
  150. ";
  151. cx.render(rsx!(input {
  152. style: "{input_style}{colors}",
  153. value: "{caption}",
  154. oninput: move |event| on_input.call(event),
  155. }))
  156. }
  157. // ANCHOR_END: caption_editor
  158. // ANCHOR_END: all