Some checks failed
CI/CD Pipeline / Build Docker Image (push) Has been cancelled
CI/CD Pipeline / Test (push) Has been cancelled
CI/CD Pipeline / Build (arm64, windows, linkbeam-windows-arm64.exe) (push) Has been cancelled
CI/CD Pipeline / Build (386, linux, linkbeam-linux-386) (push) Has been cancelled
CI/CD Pipeline / Lint (push) Has been cancelled
CI/CD Pipeline / Build (amd64, linux, linkbeam-linux-amd64) (push) Has been cancelled
CI/CD Pipeline / Build (arm, 7, linux, linkbeam-linux-armv7) (push) Has been cancelled
CI/CD Pipeline / Build (386, windows, linkbeam-windows-386.exe) (push) Has been cancelled
CI/CD Pipeline / Build (amd64, windows, linkbeam-windows-amd64.exe) (push) Has been cancelled
CI/CD Pipeline / Build (arm64, darwin, linkbeam-darwin-arm64) (push) Has been cancelled
CI/CD Pipeline / Build (arm64, linux, linkbeam-linux-arm64) (push) Has been cancelled
CI/CD Pipeline / Build (amd64, darwin, linkbeam-darwin-amd64) (push) Has been cancelled
CI/CD Pipeline / Create Release (push) Has been cancelled
190 lines
6.0 KiB
HTML
190 lines
6.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<meta name="generator" content="LinkBeam - https://github.com/5mdt/linkbeam" />
|
|
<title>{{ .Name }} - LinkBeam</title>
|
|
<link rel="icon" type="image/x-icon" href="/static/favicon.png">
|
|
<link rel="stylesheet" href="/themes/{{ .Theme }}.css" />
|
|
{{- if .FontAwesomeCDN }}
|
|
<link rel="stylesheet" href="{{ .FontAwesomeCDN }}" />
|
|
{{- else }}
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
|
{{- end }}
|
|
<style>
|
|
.theme-toggle {
|
|
position: fixed;
|
|
top: 1rem;
|
|
right: 1rem;
|
|
background: none;
|
|
border: none;
|
|
font-size: 1.5rem;
|
|
cursor: pointer;
|
|
padding: 0.5rem;
|
|
border-radius: 50%;
|
|
transition: transform 0.2s ease;
|
|
z-index: 1000;
|
|
}
|
|
.theme-toggle:hover {
|
|
transform: scale(1.1);
|
|
}
|
|
.theme-toggle:active {
|
|
transform: scale(0.95);
|
|
}
|
|
.theme-label {
|
|
display: none;
|
|
}
|
|
@media (min-width: 768px) {
|
|
.theme-toggle {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
border-radius: 2rem;
|
|
padding: 0.5rem 1rem;
|
|
background-color: var(--link-bg);
|
|
border: 1px solid var(--border-color);
|
|
}
|
|
.theme-label {
|
|
display: inline;
|
|
font-size: 0.9rem;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
.socials {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
max-width: 600px;
|
|
margin: 2rem auto;
|
|
padding: 1rem;
|
|
}
|
|
.socials a {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 3rem;
|
|
height: 3rem;
|
|
background-color: var(--link-bg);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 50%;
|
|
color: var(--text-color);
|
|
text-decoration: none;
|
|
font-size: 1.5rem;
|
|
transition: all 0.2s ease;
|
|
}
|
|
.socials a:hover {
|
|
background-color: var(--link-hover);
|
|
transform: scale(1.1);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<button class="theme-toggle" id="themeToggle" aria-label="Toggle theme">
|
|
<span id="themeIcon">💡</span>
|
|
<span class="theme-label" id="themeLabel">System</span>
|
|
</button>
|
|
<header>
|
|
{{- if .Avatar }}
|
|
<img src="{{ .Avatar }}" alt="{{ .Name }}" width="100" height="100" />
|
|
{{- end }}
|
|
<h1>{{ .Name }}</h1>
|
|
<p>{{ .Bio }}</p>
|
|
</header>
|
|
<main>
|
|
<ul>
|
|
{{- range .Links }}
|
|
<li>
|
|
<a href="{{ .URL }}" target="_blank" rel="noopener noreferrer">
|
|
{{- if .Icon }}<i class="{{ .Icon }}"></i> {{- end }}{{ .Title }}
|
|
</a>
|
|
</li>
|
|
{{- end }}
|
|
</ul>
|
|
</main>
|
|
{{- if .Socials }}
|
|
<div class="socials">
|
|
{{- range .Socials }}
|
|
<a href="{{ .URL }}" target="_blank" rel="noopener noreferrer" aria-label="{{ .Platform }}" title="{{ .Platform }}">
|
|
{{- if .Icon }}<i class="{{ .Icon }}"></i>{{- end }}
|
|
</a>
|
|
{{- end }}
|
|
</div>
|
|
{{- end }}
|
|
{{- if .Footer }}
|
|
<footer>
|
|
{{- range .Footer }}
|
|
<p>{{ .Text }}</p>
|
|
{{- end }}
|
|
</footer>
|
|
{{- end }}
|
|
<script>
|
|
const THEME_OPTIONS = ['system', 'light', 'dark'];
|
|
const THEME_ICONS = { system: '💡', light: '☀️', dark: '🌙' };
|
|
const THEME_LABELS = { system: 'System', light: 'Light', dark: 'Dark' };
|
|
|
|
// Storage with fallback
|
|
function getStorage() {
|
|
try {
|
|
localStorage.setItem('__test__', '1');
|
|
localStorage.removeItem('__test__');
|
|
return localStorage;
|
|
} catch {
|
|
return sessionStorage;
|
|
}
|
|
}
|
|
|
|
function getFromStorage(key, defaultValue) {
|
|
try {
|
|
return getStorage().getItem(key) || defaultValue;
|
|
} catch {
|
|
return defaultValue;
|
|
}
|
|
}
|
|
|
|
function saveToStorage(key, value) {
|
|
try {
|
|
getStorage().setItem(key, value);
|
|
} catch {
|
|
// Silent fail in private browsing
|
|
}
|
|
}
|
|
|
|
function applyTheme(theme) {
|
|
// Update HTML attribute
|
|
if (theme === 'system') {
|
|
document.documentElement.removeAttribute('data-theme');
|
|
} else {
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
}
|
|
|
|
// Update UI
|
|
document.getElementById('themeIcon').textContent = THEME_ICONS[theme];
|
|
document.getElementById('themeLabel').textContent = THEME_LABELS[theme];
|
|
|
|
// Save preference
|
|
saveToStorage('themePreference', theme);
|
|
}
|
|
|
|
function toggleTheme() {
|
|
const current = getFromStorage('themePreference', 'system');
|
|
const nextIndex = (THEME_OPTIONS.indexOf(current) + 1) % 3;
|
|
const next = THEME_OPTIONS[nextIndex];
|
|
applyTheme(next);
|
|
}
|
|
|
|
function initTheme() {
|
|
const saved = getFromStorage('themePreference', 'system');
|
|
applyTheme(saved);
|
|
}
|
|
|
|
// Initialize on load
|
|
initTheme();
|
|
|
|
// Attach event listener
|
|
document.getElementById('themeToggle').addEventListener('click', toggleTheme);
|
|
</script>
|
|
</body>
|
|
</html>
|