add(web): basic layout and ui
This commit is contained in:
parent
fd14d22fed
commit
80df48284c
17 changed files with 9288 additions and 4 deletions
34
web/templates/modules/navbar.templ
Normal file
34
web/templates/modules/navbar.templ
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
package modules
|
||||
|
||||
import "maot-shortner/web/templates/components/icon"
|
||||
import "maot-shortner/web/templates/components/button"
|
||||
|
||||
templ Github() {
|
||||
@button.Button(button.Props{
|
||||
Variant: button.VariantGhost,
|
||||
Href: "https://git.maot.dev/maot/maot-shortner",
|
||||
}) {
|
||||
<span class="font-bold">
|
||||
repo
|
||||
</span>
|
||||
@icon.GitMerge(icon.Props{Class: "w-6 h-6"})
|
||||
}
|
||||
}
|
||||
|
||||
templ Navbar() {
|
||||
<nav class="py-1">
|
||||
<div class="px-6 flex justify-between items-center relative">
|
||||
<div class="flex items-center">
|
||||
<a href="/" class="flex items-center gap-1.5">
|
||||
@icon.Link(icon.Props{Class: "w-6 h-6"})
|
||||
<span class="text-xl font-bold">s.maot.dev</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex gap-1 items-center justify-center">
|
||||
@ThemeSwitcher()
|
||||
@Github()
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
}
|
||||
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