meme_editor_dark_mode.rs 4.0 KB

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