add(web): basic layout and ui
This commit is contained in:
parent
fd14d22fed
commit
80df48284c
17 changed files with 9288 additions and 4 deletions
91
web/templates/modules/themeswitcher.templ
Normal file
91
web/templates/modules/themeswitcher.templ
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
package modules
|
||||
|
||||
import (
|
||||
"maot-shortner/web/templates/components/button"
|
||||
"maot-shortner/web/templates/components/icon"
|
||||
)
|
||||
|
||||
type ThemeSwitcherProps struct {
|
||||
Class string
|
||||
}
|
||||
|
||||
templ ThemeSwitcher(props ...ThemeSwitcherProps) {
|
||||
{{ var p ThemeSwitcherProps }}
|
||||
if len(props) > 0 {
|
||||
{{ p = props[0] }}
|
||||
}
|
||||
<script nonce={ templ.GetNonce(ctx) }>
|
||||
(function() {
|
||||
// Get current theme preference (system, light, or dark)
|
||||
function getThemePreference() {
|
||||
return localStorage.getItem('themePreference') || 'system';
|
||||
}
|
||||
|
||||
// Apply theme based on preference
|
||||
function applyTheme() {
|
||||
const preference = getThemePreference();
|
||||
let isDark = false;
|
||||
|
||||
if (preference === 'system') {
|
||||
// Use system preference
|
||||
isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
} else {
|
||||
// Use explicit preference
|
||||
isDark = preference === 'dark';
|
||||
}
|
||||
|
||||
document.documentElement.classList.toggle('dark', isDark);
|
||||
|
||||
// Dispatch event for compatibility
|
||||
document.dispatchEvent(new CustomEvent('theme-changed'));
|
||||
}
|
||||
|
||||
// Toggle between light and dark (system only on initial state)
|
||||
function cycleTheme() {
|
||||
const current = getThemePreference();
|
||||
let next;
|
||||
|
||||
if (current === 'system') {
|
||||
// First click from system state - determine based on current appearance
|
||||
const isDarkNow = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
next = isDarkNow ? 'light' : 'dark';
|
||||
} else {
|
||||
// Toggle between light and dark
|
||||
next = current === 'light' ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
localStorage.setItem('themePreference', next);
|
||||
applyTheme();
|
||||
}
|
||||
|
||||
// Initialize theme
|
||||
applyTheme();
|
||||
|
||||
// Listen for system theme changes
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
||||
if (getThemePreference() === 'system') {
|
||||
applyTheme();
|
||||
}
|
||||
});
|
||||
|
||||
// Use event delegation for click handling
|
||||
document.addEventListener('click', (e) => {
|
||||
const themeSwitcher = e.target.closest('[data-theme-switcher]');
|
||||
if (themeSwitcher) {
|
||||
e.preventDefault();
|
||||
cycleTheme();
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@button.Button(button.Props{
|
||||
Size: button.SizeIcon,
|
||||
Variant: button.VariantGhost,
|
||||
Class: p.Class,
|
||||
Attributes: templ.Attributes{
|
||||
"data-theme-switcher": "true",
|
||||
},
|
||||
}) {
|
||||
@icon.Eclipse(icon.Props{Size: 20})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue