Unlisted
Edited
Feb 13, 2023
Paused
Importers
2 stars
Insert cell
Insert cell
Insert cell
tabbed(htl.html`<div>${[
details("intro", md`Lorem ipsum`),
details("table", Inputs.table(aapl)),
htl.html`<details>
<summary>custom</summary>
<p>hello</p>
<p>world</p>`
]}`, {selected: 1})
Insert cell
viewof tabbed_inputs = Inputs.form({
foo: Inputs.text(),
bar: Inputs.range(),
baz: Inputs.checkbox("abc"),
}, {
template: ({foo, ...rest}) => tabbed(htl.html`<div>${[
details("foo", foo),
details("bar", rest)
]}`)
})
Insert cell
Insert cell
function tabbed(view, options = {}) {
const {
defaultLabel = "Settings",
selected = 0,
scope = DOM.uid("tabbed").id
} = options;
const tabs = html`<ul class="${scope}-tabs">`;
const body = html`<div class="${scope}-body">`;
const style = html`<style>${theme(scope)}`;

const registerTab = (title, node, active = false) => {
const tab = tabs.appendChild(html`<li>${title}`);
const content = html`<div>`;
content.append(...node.children);
const cActive = `${scope}-active`;
if (active) tab.classList.add(cActive);
tab.classList.add(`${scope}-tab`);

tab.onclick = () => {
for (const n of tabs.children) n.classList.remove(cActive);
for (const n of body.children) n.remove();
tab.classList.add(cActive);
body.append(content);
};

return tab;
};

view.querySelectorAll("summary").forEach((summary) => {
const details = summary.parentElement;
let parent = details.parent;
details.remove();
summary.remove();
registerTab(summary.textContent, details);
while (parent && parent !== view && !parent.children.length) {
const n = parent;
parent = parent.parentElement;
n.remove();
}
});

if (view.children.length && defaultLabel != null) {
const common = html`<div>`;
common.append(...view.children);
registerTab(defaultLabel, common);
tabs.prepend(tabs.lastElementChild);
}
(tabs.children[selected] || tabs.firstElementChild).click();

view.append(html`<div class="${scope}">${tabs}${body}${style}`);
return view;
}
Insert cell
function details(summary, body, {open = true} = {}) {
const template = body => {
if(typeof body === 'object' && !(body instanceof Element)) {
if(body instanceof Set || body instanceof Map) body = body.values();
else if(!Array.isArray(body)) body = Object.values(body);
}
return html`<details ${{open}}><summary>${summary}</summary>${body}`;
};
return template(body);
}
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more