add 3 toggle botons
This commit is contained in:
@@ -1,48 +1,63 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["sunIcon", "moonIcon"]
|
||||
static targets = ["lightBtn", "darkBtn", "autoBtn"]
|
||||
|
||||
connect() {
|
||||
this.applyStoredTheme()
|
||||
this.updateIcon()
|
||||
this.updateButtons()
|
||||
}
|
||||
|
||||
toggle() {
|
||||
const currentTheme = document.documentElement.getAttribute("data-theme")
|
||||
// If no theme is set, check system preference or default to light
|
||||
let newTheme
|
||||
if (!currentTheme) {
|
||||
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
newTheme = prefersDark ? "light" : "dark"
|
||||
} else {
|
||||
newTheme = currentTheme === "dark" ? "light" : "dark"
|
||||
}
|
||||
this.setTheme(newTheme)
|
||||
this.updateIcon()
|
||||
setLight() {
|
||||
this.setTheme("light")
|
||||
document.documentElement.setAttribute("data-theme", "light")
|
||||
this.updateButtons()
|
||||
}
|
||||
|
||||
setDark() {
|
||||
this.setTheme("dark")
|
||||
document.documentElement.setAttribute("data-theme", "dark")
|
||||
this.updateButtons()
|
||||
}
|
||||
|
||||
setAuto() {
|
||||
this.setTheme("auto")
|
||||
document.documentElement.removeAttribute("data-theme")
|
||||
this.updateButtons()
|
||||
}
|
||||
|
||||
setTheme(theme) {
|
||||
document.documentElement.setAttribute("data-theme", theme)
|
||||
localStorage.setItem("theme", theme)
|
||||
}
|
||||
|
||||
applyStoredTheme() {
|
||||
const storedTheme = localStorage.getItem("theme")
|
||||
if (storedTheme) {
|
||||
document.documentElement.setAttribute("data-theme", storedTheme)
|
||||
const storedTheme = localStorage.getItem("theme") || "auto"
|
||||
|
||||
if (storedTheme === "light") {
|
||||
document.documentElement.setAttribute("data-theme", "light")
|
||||
} else if (storedTheme === "dark") {
|
||||
document.documentElement.setAttribute("data-theme", "dark")
|
||||
} else {
|
||||
// auto - don't set data-theme, let CSS media query handle it
|
||||
document.documentElement.removeAttribute("data-theme")
|
||||
}
|
||||
}
|
||||
|
||||
updateIcon() {
|
||||
const currentTheme = document.documentElement.getAttribute("data-theme")
|
||||
const isDark = currentTheme === "dark" ||
|
||||
(!currentTheme && window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
updateButtons() {
|
||||
const storedTheme = localStorage.getItem("theme") || "auto"
|
||||
|
||||
// Show moon icon in light mode, sun icon in dark mode
|
||||
if (this.hasSunIconTarget && this.hasMoonIconTarget) {
|
||||
this.sunIconTarget.style.display = isDark ? "block" : "none"
|
||||
this.moonIconTarget.style.display = isDark ? "none" : "block"
|
||||
// Reset all buttons
|
||||
if (this.hasLightBtnTarget) this.lightBtnTarget.removeAttribute("aria-selected")
|
||||
if (this.hasDarkBtnTarget) this.darkBtnTarget.removeAttribute("aria-selected")
|
||||
if (this.hasAutoBtnTarget) this.autoBtnTarget.removeAttribute("aria-selected")
|
||||
|
||||
// Highlight active button
|
||||
if (storedTheme === "light" && this.hasLightBtnTarget) {
|
||||
this.lightBtnTarget.setAttribute("aria-selected", "true")
|
||||
} else if (storedTheme === "dark" && this.hasDarkBtnTarget) {
|
||||
this.darkBtnTarget.setAttribute("aria-selected", "true")
|
||||
} else if (this.hasAutoBtnTarget) {
|
||||
this.autoBtnTarget.setAttribute("aria-selected", "true")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,36 @@
|
||||
<button type="button" class="btn btn--icon" data-action="click->theme#toggle" title="Toggle theme" style="position: absolute; right: 3rem; top: 5px; z-index: 100;">
|
||||
<svg data-theme-target="sunIcon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
|
||||
<circle cx="12" cy="12" r="5"/>
|
||||
<line x1="12" y1="1" x2="12" y2="3"/>
|
||||
<line x1="12" y1="21" x2="12" y2="23"/>
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
|
||||
<line x1="1" y1="12" x2="3" y2="12"/>
|
||||
<line x1="21" y1="12" x2="23" y2="12"/>
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
|
||||
</svg>
|
||||
<svg data-theme-target="moonIcon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="flex flex-column align-center gap txt-medium--responsive txt-medium margin-block-start-double">
|
||||
<strong class="txt-medium">Appearance</strong>
|
||||
|
||||
<div class="nav__hotkeys" role="list" style="margin: 1rem auto;">
|
||||
<button type="button" class="popup__item btn borderless" data-action="click->theme#setLight" data-theme-target="lightBtn" role="listitem">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="width: 2em; height: 2em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="5"/>
|
||||
<line x1="12" y1="1" x2="12" y2="3"/>
|
||||
<line x1="12" y1="21" x2="12" y2="23"/>
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
|
||||
<line x1="1" y1="12" x2="3" y2="12"/>
|
||||
<line x1="21" y1="12" x2="23" y2="12"/>
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
|
||||
</svg>
|
||||
<span>Always light</span>
|
||||
</button>
|
||||
|
||||
<button type="button" class="popup__item btn borderless" data-action="click->theme#setDark" data-theme-target="darkBtn" role="listitem">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="width: 2em; height: 2em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
||||
</svg>
|
||||
<span>Always dark</span>
|
||||
</button>
|
||||
|
||||
<button type="button" class="popup__item btn borderless" data-action="click->theme#setAuto" data-theme-target="autoBtn" role="listitem">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="width: 2em; height: 2em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/>
|
||||
<line x1="8" y1="21" x2="16" y2="21"/>
|
||||
<line x1="12" y1="17" x2="12" y2="21"/>
|
||||
</svg>
|
||||
<span>Same as OS</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
<% @page_title = @user.name %>
|
||||
<% me_or_you = Current.user == @user ? "me" : @user.first_name %>
|
||||
|
||||
<% if Current.user == @user %>
|
||||
<%= render "users/theme" %>
|
||||
<% end %>
|
||||
|
||||
<div class="profile-layout">
|
||||
<section class="panel shadow txt-align-center" style="--panel-size: 45ch;">
|
||||
<div class="flex flex-column gap position-relative">
|
||||
@@ -43,6 +39,8 @@
|
||||
<section class="panel shadow" style="--panel-size: 45ch;">
|
||||
<%= render "users/transfer", user: @user %>
|
||||
|
||||
<%= render "users/theme" %>
|
||||
|
||||
<div class="center margin-block-start-double">
|
||||
<%= button_to session_url(script_name: nil), method: :delete, class: "btn btn--plain txt-link txt-small", data: { turbo: false } do %>
|
||||
<span>Sign out</span>
|
||||
|
||||
Reference in New Issue
Block a user