Public
Edited
Jul 8, 2024
Importers
4 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
cssVariables = () => `:root {
--spacing-none: 0;
--spacing-extra-small: .25rem;
--spacing-small: .5rem;
--spacing-medium: 1rem;
--spacing-large: 2rem;
--spacing-extra-large: 4rem;
--spacing-extra-extra-large: 8rem;
--spacing-extra-extra-extra-large: 16rem;

--border-radius-0: 0;
--border-radius-1: .125rem;
--border-radius-2: .25rem;
--border-radius-3: .5rem;
--border-radius-4: 1rem;
}
`
Insert cell
Insert cell
colorUtils = ({colors}) => {
const keys = Object.keys(colors || {})

if (keys.length === 0) return "";

const cssVariables = `:root {
${keys.reduce((acc,k) => `${acc}--${k}: ${colors[k]};`, "")}
}`
const utilClasses = keys.reduce((acc, k) => {
return `${acc}
.${k} { color: var(--${k}); }
.hover-${k}:hover, .hover-${k}:focus { color: var(--${k}); }
.bg-${k} { background-color: var(--${k}); }
.hover-bg-${k}:hover, .hover-bg-${k}:focus { background-color: var(--${k}); }
.b--${k} { border-color: var(--${k}); }
`}, "")

return cssVariables + "\n" + utilClasses;
}
Insert cell
Insert cell
fontUtils = ({fonts}) => {
const keys = Object.keys(fonts || {})

if (keys.length === 0) return "";

const cssVariables = `:root {
${keys.reduce((acc,k) => `${acc}--${k}: ${fonts[k]};`, "")}
}`
const utilClasses = keys.reduce((acc, k) => {
return `${acc}
.${k} { font-family: ${fonts[k]}; }
`}, "")

return cssVariables + "\n" +utilClasses;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
spaceBetweenUtils = () => Object.keys(tokens.spaces).reduce((acc, k) => {
const v = tokens.spaces[k];
return `${acc}
.space-x-${k} > * + * {
margin-left: ${v}
}
.space-y-${k} > * + * {
margin-top: ${v};
}

.space-${k} {
margin: calc(-0.5 * ${v});
}

.space-${k} > * {
margin: calc(0.5 * ${v});
}`
}, "")
Insert cell
Insert cell
html`<div class="flex pa2">
${Array.from({length: 3}).map((_,i) => {
const n= i + 1;
return `<div class="[ box box--light ][ ba b--near-white flex-none ma2 f6 w4 h4 ][ solid-shadow-${n} ]">.solid-shadow-${n}</div>
<div class="[ box box--light ][ ba b--near-white flex-none ma2 f6 w4 h4 ][ solid-shadow-y-${n} ]">.solid-shadow-y-${n}</div>`
})}
</div>`
Insert cell
boxShadowUtils = () => `
.solid-shadow-1 {
box-shadow: 0.125rem 0.125rem rgba(0,0,0,0.08);
}

.solid-shadow-y-1 {
box-shadow: 0 0.125rem rgba(0,0,0,0.08);
}

.solid-shadow-2 {
box-shadow: 0.25rem 0.25rem rgba(0,0,0,0.06);
}

.solid-shadow-y-2 {
box-shadow: 0 0.25rem rgba(0,0,0,0.06);
}

.solid-shadow-3 {
box-shadow: 0.5rem 0.5rem rgba(0,0,0,0.06);
}

.solid-shadow-y-3 {
box-shadow: 0 0.5rem rgba(0,0,0,0.06);
}
`
Insert cell
Insert cell
trackedUtils = () => `.tracked-light { letter-spacing: .025em; }`
Insert cell
Insert cell
positionUtils = () => `.sticky { position: sticky }`
Insert cell
Insert cell
scrollUtils = () =>`.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}

.no-scrollbar::-webkit-scrollbar {
display: none; // Safari and Chrome
}`;
Insert cell
Insert cell
tachyonsVersion = "4.12.0"
Insert cell
defaultOptions = ({})
Insert cell
addElementsToDOM = (elements) => elements.forEach(n => document.querySelector("head").prepend(n));
Insert cell
removeElementsFromDOM = (elements) => elements.forEach(n => n.parentNode && n.parentNode.removeChild(n))
Insert cell
tachyons = loadStyles // Original name, deprecated
Insert cell
loadStyles = {
let elements = new Set();

function detach(elements) {
for (let n of elements) {
n.remove();
elements.delete(n);
}
}

function attach(nodes) {
for (let n of nodes) {
document.head.prepend(n);
elements.add(n);
}
}

invalidation.then(() => detach(elements));
return (userOptions) => {
const options = Object.assign({}, defaultOptions, userOptions);
const src = `https://unpkg.com/tachyons@${tachyonsVersion}/css/tachyons.min.css`;

detach(elements);
const newStyleElements = new Set([
html`<link rel=stylesheet href="${src}">`,
html`<style>
${cssVariables()}
${scrollUtils()}
${spaceBetweenUtils()}
${trackedUtils()}
${positionUtils()}
${boxShadowUtils()}
${colorUtils(options)}
${fontUtils(options)}`,
].reverse());
attach(newStyleElements);
}
}
Insert cell
tokens = ({
spaces: {
'0': '0', // none
'1': '0.25rem', // extra-small
'2': '0.5rem', // small
'3': '1rem', // medium
'4': '2rem', // large
'5': '4rem', // extra-large
'6': '8rem', // extra-extra-large
'7': '16rem', // extra-extra-extra-large
}
})
Insert cell
loadStyles({
colors: {
brand: "#007DB7",
accent: "#FDB515"
},
fonts: {
roboto: `"Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"`
},
})
Insert cell
Insert cell
Insert cell
Insert cell
demoStyles = html`<style>.box {
background-color: var(--brand);
color: white;
padding: 0.5rem;
font-family: system-ui, sans-serif;
}

.box--light {
color: var(--brand);
background-color: white;
}

.box--expand {
flex: 1;
}
</style>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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