meme_editor_dark_mode.rs 4.0 KB

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