diff --git a/assets/js/app.js b/assets/js/app.js index 560d0a824..7ce36c1fb 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -22,7 +22,8 @@ import {Socket} from "phoenix" import {LiveSocket} from "phoenix_live_view" import topbar from "../vendor/topbar" import live_select from "live_select" -import { QrScanner, Wheel, Confetti, Countdown, Sorting } from "./hooks"; +import { QrScanner, Wheel, Confetti, Sorting } from "./hooks"; +import darkModeHook from "../vendor/dark_mode" let Hooks = { QrScanner: QrScanner, @@ -32,6 +33,7 @@ let Hooks = { Sorting: Sorting, ...live_select }; +Hooks.DarkThemeToggle = darkModeHook let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") let liveSocket = new LiveSocket("/live", Socket, { @@ -40,6 +42,12 @@ let liveSocket = new LiveSocket("/live", Socket, { hooks: Hooks }) +if (localStorage.getItem('theme') === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { + document.documentElement.classList.add('dark'); +} else { + document.documentElement.classList.remove('dark') +} + // Show progress bar on live navigation and form submits topbar.config({barColors: {0: "#ffdb0d"}, shadowColor: "rgba(0, 0, 0, .3)"}) window.addEventListener("phx:page-loading-start", _info => topbar.show(300)) diff --git a/assets/vendor/dark_mode.js b/assets/vendor/dark_mode.js new file mode 100644 index 000000000..6561a9ffa --- /dev/null +++ b/assets/vendor/dark_mode.js @@ -0,0 +1,40 @@ + +const localStorageKey = 'theme'; + +const isDark = () => { + if (localStorage.getItem(localStorageKey) === 'dark') return true; + if (localStorage.getItem(localStorageKey) === 'light') return false; + return window.matchMedia('(prefers-color-scheme: dark)').matches; +} + +const setupThemeToggle = () => { + toggleVisibility = (dark) => { + const themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon'); + const themeToggleLightIcon = document.getElementById('theme-toggle-light-icon'); + if (themeToggleDarkIcon == null || themeToggleLightIcon == null) return; + const show = dark ? themeToggleDarkIcon : themeToggleLightIcon + const hide = dark ? themeToggleLightIcon : themeToggleDarkIcon + show.classList.remove('hidden', 'text-transparent'); + hide.classList.add('hidden', 'text-transparent'); + if (dark) { + document.documentElement.classList.add('dark') + } else { + document.documentElement.classList.remove('dark') + } + try { localStorage.setItem(localStorageKey, dark ? 'dark' : 'light') } catch (_err) { } + } + toggleVisibility(isDark()) + document.getElementById('theme-toggle').addEventListener('click', function () { + toggleVisibility(!isDark()) + }); +} + +const darkModeHook = { + mounted() { + setupThemeToggle(); + }, + updated() { + }, +} + +export default darkModeHook; diff --git a/lib/safira_web/components/dark_mode.ex b/lib/safira_web/components/dark_mode.ex new file mode 100644 index 000000000..12dfa096f --- /dev/null +++ b/lib/safira_web/components/dark_mode.ex @@ -0,0 +1,54 @@ +defmodule DarkMode do + @moduledoc false + use Phoenix.Component + + def button(assigns) do + ~H""" + + + + """ + end +end diff --git a/lib/safira_web/components/layouts/root.html.heex b/lib/safira_web/components/layouts/root.html.heex index 2fb7f709d..d993f04ea 100644 --- a/lib/safira_web/components/layouts/root.html.heex +++ b/lib/safira_web/components/layouts/root.html.heex @@ -1,5 +1,5 @@ - +
diff --git a/lib/safira_web/components/page.ex b/lib/safira_web/components/page.ex index 86582aecf..7e508e6fc 100644 --- a/lib/safira_web/components/page.ex +++ b/lib/safira_web/components/page.ex @@ -23,7 +23,7 @@ defmodule SafiraWeb.Components.Page do <.header title_class={"#{size_class(@size)} #{@title_class}"}> <%= @title %> <:subtitle> - <%= @subtitle %> + <%= @subtitle %> <%= if @back_to_link do %> <.link patch={@back_to_link}> diff --git a/lib/safira_web/components/sidebar.ex b/lib/safira_web/components/sidebar.ex index da7dc3a08..9ce046c14 100644 --- a/lib/safira_web/components/sidebar.ex +++ b/lib/safira_web/components/sidebar.ex @@ -148,7 +148,7 @@ defmodule SafiraWeb.Components.Sidebar do <:img src={"https://github.com/identicons/#{@user.handle |> String.slice(0..2)}.png"} /> <:title color={@title_color}><%= @user.name %> <:subtitle color={@subtitle_color}>@<%= @user.handle %> - <:link navigate="/profile/settings">Settings + <:link navigate="/app/profile/settings">Settings <:link href="/users/log_out" method={:delete}>Sign out """ diff --git a/lib/safira_web/live/app/profile_live/form_component.ex b/lib/safira_web/live/app/profile_live/form_component.ex new file mode 100644 index 000000000..5cebf33ae --- /dev/null +++ b/lib/safira_web/live/app/profile_live/form_component.ex @@ -0,0 +1,27 @@ +defmodule SafiraWeb.App.ProfileLive.FormComponent do + use SafiraWeb, :live_component + + @impl true + def render(assigns) do + ~H""" +