Skip to content

Instantly share code, notes, and snippets.

@pch
Last active November 19, 2021 09:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pch/9c6e1727fa62065673f92ab88f17f751 to your computer and use it in GitHub Desktop.
Save pch/9c6e1727fa62065673f92ab88f17f751 to your computer and use it in GitHub Desktop.
function initComponent(root, goDeep = true) {
const component = root.dataset.component;
const targets = {};
const state = {};
root.querySelectorAll(`[data-${component}-target]`).forEach((attr) => {
targets[attr.getAttribute(`data-${component}-target`)] = attr;
});
Array.from(root.attributes).forEach((attr) => {
const match = attr.name.match(/data-component-state-([a-z0-9]+)/);
if (match) {
state[match[1]] = JSON.parse(attr.nodeValue);
}
});
window[component]({ root, targets, state });
if (!goDeep) return;
root.querySelectorAll("[data-component]").forEach((el) => {
initComponent(el, false);
});
}
function setState(root, state) {
for (const [key, value] of Object.entries(state)) {
root.setAttribute(`data-component-state-${key}`, JSON.stringify(value));
}
initComponent(root);
}
function main() {
const page = document.querySelector("[data-component=page]");
if (page) {
initComponent(page);
}
}
document.addEventListener("DOMContentLoaded", (event) => {
main();
});
// Components
// ----------------------------------------------------------------------------
function page({}) {
document.querySelectorAll("pre code").forEach((el) => {
hljs.highlightElement(el);
});
}
function section({ root, targets, state }) {
const { toggle } = targets;
const { collapsed } = state;
toggle.onclick = () => {
setState(root, { ...state, collapsed: !collapsed });
};
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<div class="page-wrapper" data-component="page">
<main class="page-content">
<div class="sections">
<section
class="section"
data-component="section"
data-component-state-collapsed="true"
>
<header class="section__header">
Section 1
<button class="section__toggle-btn" data-section-target="toggle">
Toggle
</button>
</header>
<div class="section__content" data-section-target="content">
Content
</div>
</section>
<section
class="section"
data-component="section"
data-component-state-collapsed="true"
>
<header class="section__header">
Section 2
<button class="section__toggle-btn" data-section-target="toggle">
Toggle
</button>
</header>
<div class="section__content" data-section-target="content">
Content
</div>
</section>
</div>
</main>
</div>
</body>
</html>
[data-section-target="content"] {
overflow: hidden;
transition: max-height 0.4s ease-in-out;
}
[data-component="section"][data-component-state-collapsed="false"] {
background: var(--background-color-accent-3);
}
[data-component="section"][data-component-state-collapsed="true"]
[data-section-target="content"] {
max-height: 0px;
}
[data-component="section"][data-component-state-collapsed="false"]
[data-section-target="content"] {
max-height: 1000px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment