Files
personal-website/src/components/TuiToggle.astro
syntaxbullet bfefaa0055 Initial commit
2026-02-09 12:54:10 +01:00

110 lines
2.9 KiB
Plaintext

---
interface Props {
id: string;
label: string;
checked?: boolean;
title?: string;
}
const { id, label, checked = false, title = "" } = Astro.props;
---
<button
type="button"
class:list={["tui-toggle", { active: checked }]}
id={id}
data-checked={checked ? "true" : "false"}
title={title}
>
<span class="tui-toggle-label">{label}</span>
</button>
<style>
.tui-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
background: none;
border: 1px solid rgba(255, 103, 0, 0.3);
color: var(--text-color);
font-family: inherit;
font-size: 11px;
padding: 2px 8px;
cursor: pointer;
opacity: 0.5;
transition: all 0.15s;
user-select: none;
min-width: 3ch;
text-align: center;
}
.tui-toggle:hover {
opacity: 0.8;
background: rgba(255, 103, 0, 0.1);
}
.tui-toggle.active {
background: var(--text-color);
color: #000;
opacity: 1;
font-weight: bold;
border-color: var(--text-color);
}
.tui-toggle-label {
font-weight: bold;
}
</style>
<script>
// Use a WeakSet to track initialized toggles (prevents duplicate listeners)
const initializedToggles = new WeakSet<Element>();
function initToggles() {
document.querySelectorAll(".tui-toggle").forEach((toggle) => {
// Skip if already initialized
if (initializedToggles.has(toggle)) return;
initializedToggles.add(toggle);
const btn = toggle as HTMLButtonElement;
btn.addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
const isChecked = this.dataset.checked === "true";
const newState = !isChecked;
// Update visual state
this.dataset.checked = String(newState);
this.classList.toggle("active", newState);
// Dispatch custom event that bubbles
this.dispatchEvent(
new CustomEvent("toggle-change", {
detail: { checked: newState },
bubbles: true,
composed: true,
}),
);
});
});
}
// Initialize immediately and on DOMContentLoaded
initToggles();
document.addEventListener("DOMContentLoaded", initToggles);
// Expose update function globally
(window as any).updateToggleState = function (
toggleId: string,
newState: boolean,
) {
const btn = document.getElementById(toggleId) as HTMLButtonElement;
if (btn) {
btn.dataset.checked = String(newState);
btn.classList.toggle("active", newState);
}
};
</script>