Published
Edited
Aug 29, 2021
70 forks
Importers
78 stars
Insert cell
Insert cell
Insert cell
Insert cell
data = FileAttachment("palmer-penguins.csv").csv({typed: true})
Insert cell
Insert cell
Insert cell
Insert cell
Inputs.table(data)
Insert cell
Insert cell
Insert cell
Plot // Plot is available in Observable by default
Insert cell
Insert cell
Insert cell
Insert cell
// change the code to replace … by the field’s name, e.g. body_mass
Plot.dot(data, {x: "...", fill: "black", fillOpacity: 0.2}).plot()
Insert cell
Insert cell
Insert cell
// change the code to replace … by the field’s name, e.g. body_mass
Plot.dot(data, {x: "…", y: "…"}).plot()
Insert cell
Insert cell
Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
// type your question here


Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function answer({
title,
questions = [],
guides = [],
hints = [],
solutions = [],
open = !!showAll
}) {

const div = d3.create("div").classed("answer", true);

if (title) {
div.append("hr");
div.append("h2").html(title);
}

div.call(renderGroup, questions, "question", true, d => md`${d}`);
// div.call(renderGroup, guides, "guide", open, d => md`${d}`);
div.call(renderGuide, guides, "guide", open, d => md`${d}`);
div.call(renderGroup, hints, "hint", open, d => code(d, "hint"));
div.call(renderGroup, solutions, "solution", open, d => code(d, "solution", renderSnippet));

return div.node();
}
Insert cell
function Q(q) {
return Object.assign(answer({
...q,
guides: null,
hints: null,
solutions: null
}), {value: q})
}
Insert cell
function A(q) {
return answer({
...q,
title: null,
questions: null
})
}
Insert cell
function renderGroup(div, group, type, open, render) {
if (group?.length) {
const details = div.append(type==="question" ? "div" : "details");
if (open) details.attr("open", "open")
if (type !== "question") details.append("summary").append("strong").text(`${type}${group.length > 1 ? "s" : ""}`);
details.append("ul").selectAll().data(group).join("li").append(render);
}
}
Insert cell
function renderGuide(div, group, type, open, render) {
if (group?.length) {
const details = div.append("div");
if (open) details.attr("open", "open")
// details.append("span").append("strong").text(`${type}${group.length > 1 ? "s" : ""}`);
details.append("ul").selectAll().data(group).join("li").append(render);
}
}
Insert cell
function renderSnippet(str) {
try {
const func = new Function("data", "Plot", "d3", "width", `return ${str}`)
return func(data, Plot, d3, width);
}
catch(e) {}
}
Insert cell
function code(code, type, visual) {
return html`
<div class="copy">${Copier("Copy", {value: code})}</div>
<textarea class=${type} rows=${rows(code)}>${code}</textarea>
${visual ? visual(code) : ""}`;

}
Insert cell
function rows(code) {
const lines = code.trim().split("\n").length;
return Math.max(Math.min(lines, 15), 2);
}
Insert cell
styles = html`<style>
.answer {
font-family: system-ui, sans-serif;
font-size: 14px;
}
.answer summary strong {
text-transform: capitalize;
}
.answer li {
list-style: none;
position: relative;
}
.answer textarea {
font: var(--monospace-font);
font-size: 12px;
width: 100%;
padding: 5px;
border: 2px solid #3b5fc0;
background: #F6F9FF;
border-radius: 5px;
margin-bottom: 2em;
resize: none;
}
.answer .copy form {
position: absolute;
right: -4px;
top: 4px;
width: initial;
}
.answer summary {
display: inline-block;
padding: 2px 6px;
border: 2px solid #3b5fc0;
background: #F6F9FF;
border-radius: 5px;
margin: 2px 0;
outline-offset: -2px;
list-style: none;
cursor: pointer;
min-width: 62px;
text-align: center;
}

.answer details[open] > summary {
background: #3b5fc0;
color: white;
}

`
Insert cell
html = htl.html
Insert cell
import {Copier} from "@mbostock/pbcopy"
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more