mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-13 04:29:14 +00:00
Compare commits
1 Commits
preprocss
...
select-hin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3360355972 |
@@ -10,7 +10,6 @@
|
||||
<script type="module" src="/assets/scripts/turbo.js"></script>
|
||||
<script type="module" src="/assets/scripts/search.js"></script>
|
||||
<script type="module" src="/assets/scripts/outline.js"></script>
|
||||
{% if hasSidebar %}<script type="module" src="/assets/scripts/sidebar-tweaks.js"></script>{% endif %}
|
||||
<script defer data-domain="backers.webawesome.com" src="https://plausible.io/js/script.js"></script>
|
||||
|
||||
{# Docs styles #}
|
||||
|
||||
@@ -19,24 +19,12 @@
|
||||
{% for tint_fg in tints | reverse -%}
|
||||
{% set color_fg = palettes[paletteId][hue][tint_fg] %}
|
||||
{% if (tint_fg - tint_bg) | abs == difference %}
|
||||
{% set contrast_wcag = '' %}
|
||||
{% if color_fg and color_bg -%}
|
||||
{% set contrast_wcag = color_bg.contrast(color_fg, 'WCAG21') %}
|
||||
{%- endif %}
|
||||
<td v-for="contrast of [contrasts.{{ hue }}['{{ tint_bg }}']['{{ tint_fg }}']]"
|
||||
data-tint-bg="{{ tint_bg }}" data-tint-fg="{{ tint_fg }}" data-original-contrast="{{ contrast_wcag }}">
|
||||
<div v-content:number="contrast.value"
|
||||
class="color swatch" :class="{
|
||||
'value-up': contrast.value - contrast.original > 0.0001,
|
||||
'value-down': contrast.original - contrast.value > 0.0001,
|
||||
'contrast-fail': contrast.value < {{ minContrast }}
|
||||
}"
|
||||
style="--color: var(--wa-color-{{ hue }}-{{ tint_bg }}); color: var(--wa-color-{{ hue }}-{{ tint_fg }})"
|
||||
:style="{
|
||||
'--color': contrast.bgColor,
|
||||
color: contrast.fgColor,
|
||||
}"
|
||||
>
|
||||
<td data-tint-bg="{{ tint_bg }}" data-tint-fg="{{ tint_fg }}">
|
||||
<div class="color swatch" style="--color: var(--wa-color-{{ hue }}-{{ tint_bg }}); color: var(--wa-color-{{ hue }}-{{ tint_fg }})">
|
||||
{% set contrast_wcag = '' %}
|
||||
{% if color_fg and color_bg %}
|
||||
{% set contrast_wcag = color_bg.contrast(color_fg, 'WCAG21') %}
|
||||
{% endif %}
|
||||
{% if contrast_wcag %}
|
||||
{{ contrast_wcag | number({maximumSignificantDigits: 2}) }}
|
||||
{% else %}
|
||||
|
||||
@@ -1,72 +1,22 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
{% set paletteId = page.fileSlug %}
|
||||
{% set tints = ["95", "90", "80", "70", "60", "50", "40", "30", "20", "10", "05"] %}
|
||||
|
||||
{% extends '../_includes/base.njk' %}
|
||||
{% extends '../_layouts/block.njk' %}
|
||||
|
||||
{% block head %}
|
||||
<style>@import url('/dist/styles/color/{{ paletteId }}.css') layer(palette.{{ paletteId }});</style>
|
||||
<link href="{{ page.url }}../tweak.css" rel="stylesheet">
|
||||
<script type="module" src="{{ page.url }}../tweak.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
<div id="palette-app" data-palette-id="{{ paletteId }}">
|
||||
<div
|
||||
:class="{
|
||||
tweaking: tweaking.chroma,
|
||||
'tweaking-chroma': tweaking.chroma,
|
||||
'tweaking-hue': tweaking.chroma,
|
||||
'tweaked-chroma': tweaked.chroma,
|
||||
'tweaked-hue': tweaked.hue,
|
||||
'tweaked-any': tweaked.chroma || tweaked.hue
|
||||
}"
|
||||
:style="{ '--chroma-scale': chromaScale }">
|
||||
|
||||
{% include 'breadcrumbs.njk' %}
|
||||
|
||||
<h1 v-if="saved" class="title">
|
||||
{% raw %}{{ saved.title }}{% endraw %}
|
||||
<wa-icon-button name="pencil" label="Rename palette" @click="rename"></wa-icon-button>
|
||||
<wa-icon-button class="delete" name="trash" label="Delete palette" @click="deleteSaved"></wa-icon-button>
|
||||
</h1>
|
||||
<h1 v-if="!saved" class="title">{{ title }}</h1>
|
||||
|
||||
<div class="block-info">
|
||||
<code class="class">.wa-palette-{{ paletteId }}</code>
|
||||
{% include '../_includes/status.njk' %}
|
||||
</div>
|
||||
{% if description %}
|
||||
<p class="summary">
|
||||
{{ description | inlineMarkdown | safe }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block afterContent %}
|
||||
|
||||
{% set tints = ["95", "90", "80", "70", "60", "50", "40", "30", "20", "10", "05"] %}
|
||||
{% set maxChroma = 0 %}
|
||||
|
||||
<wa-callout size="small" class="tweaked-callout" variant="brand">
|
||||
<wa-icon name="sliders-simple" slot="icon" variant="regular"></wa-icon>
|
||||
This palette has been tweaked.
|
||||
<wa-tag v-for="tweakHumanReadable, param in tweaksHumanReadable" removable @wa-remove="removeTweak(param)">{% raw %}{{ tweakHumanReadable }}{% endraw %}</wa-tag>
|
||||
|
||||
<wa-button @click="reset" appearance="outlined">
|
||||
<span slot="prefix" class="icon-modifier">
|
||||
<wa-icon name="circle-xmark" variant="regular"></wa-icon>
|
||||
</span>
|
||||
Reset
|
||||
</wa-button>
|
||||
<wa-button v-if="!saved" @click="save">
|
||||
<span slot="prefix" class="icon-modifier">
|
||||
<wa-icon name="sidebar" variant="regular"></wa-icon>
|
||||
<wa-icon name="circle-plus" class="modifier" style="color: light-dark(var(--wa-color-green-70), var(--wa-color-green-60));"></wa-icon>
|
||||
</span>
|
||||
Save
|
||||
</wa-button>
|
||||
</wa-callout>
|
||||
<div id="palette-app">
|
||||
<div
|
||||
:class="{ tweaking: tweaking.chroma, 'tweaking-chroma': tweaking.chroma, 'tweaking-hue': tweaking.chroma }"
|
||||
:style="{ '--chroma-scale': chromaScale }">
|
||||
|
||||
<table class="colors main wa-palette-{{ paletteId }}">
|
||||
<thead>
|
||||
@@ -157,6 +107,18 @@ style="--min: {{ chromaScaleBounds[0] }}; --max: {{ chromaScaleBounds[1] }};">
|
||||
<div class="label-max">More vibrant</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
globalThis.wa_data = {
|
||||
paletteId: '{{ paletteId }}',
|
||||
colors: {{ palettes[paletteId] | dump | safe }},
|
||||
maxChroma: {{ maxChroma }},
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="{{ page.url }}../tweak.js"></script>
|
||||
|
||||
<h2>Used By</h2>
|
||||
|
||||
<section class="index-grid">
|
||||
@@ -239,28 +201,7 @@ If you are using a Web Awesome theme that uses this palette, it will already be
|
||||
To use a different palette than a theme default, or to use it in a custom theme, you can import this palette directly from the Web Awesome CDN.
|
||||
|
||||
{% set stylesheet = 'styles/color/' + page.fileSlug + '.css' %}
|
||||
<wa-tab-group class="import-stylesheet-code">
|
||||
<wa-tab panel="html">In HTML</wa-tab>
|
||||
<wa-tab panel="css">In CSS</wa-tab>
|
||||
<wa-tab-panel name="html">
|
||||
|
||||
Add the following code to the `<head>` of your page:
|
||||
```html { v-content:html="code.html.highlighted" }
|
||||
<link rel="stylesheet" href="{% cdnUrl stylesheet %}" />
|
||||
```
|
||||
</wa-tab-panel>
|
||||
<wa-tab-panel name="css">
|
||||
|
||||
Add the following code at the top of your CSS file:
|
||||
```css { v-content:html="code.css.highlighted" }
|
||||
@import url('{% cdnUrl stylesheet %}');
|
||||
```
|
||||
</wa-tab-panel>
|
||||
</wa-tab-group>
|
||||
|
||||
{% include 'import-stylesheet-code.md.njk' %}
|
||||
|
||||
{% endmarkdown %}
|
||||
</div></div> {# end palette app #}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
@@ -1,206 +0,0 @@
|
||||
const sidebar = (globalThis.sidebar = {});
|
||||
|
||||
sidebar.palettes = {
|
||||
render() {
|
||||
if (this.saved.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let palette of this.saved) {
|
||||
sidebar.palette.render(palette);
|
||||
}
|
||||
|
||||
sidebar.updateCurrent();
|
||||
},
|
||||
|
||||
saved: localStorage.savedPalettes ? JSON.parse(localStorage.savedPalettes) : [],
|
||||
|
||||
save(saved = this.saved) {
|
||||
this.saved = saved ?? [];
|
||||
|
||||
if (saved.length > 0) {
|
||||
localStorage.savedPalettes = JSON.stringify(saved);
|
||||
} else {
|
||||
delete localStorage.savedPalettes;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
sidebar.palette = {
|
||||
getUid() {
|
||||
let savedPalettes = sidebar.palettes.saved;
|
||||
let uids = new Set(savedPalettes.map(p => p.uid));
|
||||
|
||||
if (savedPalettes.length === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Find first available number
|
||||
for (let i = 1; i < savedPalettes.length + 1; i++) {
|
||||
if (!uids.has(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
equals(p1, p2) {
|
||||
if (!p1 || !p2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p1.id === p2.id && p1.uid === p2.uid;
|
||||
},
|
||||
|
||||
delete(palette) {
|
||||
let savedPalettes = sidebar.palettes.saved;
|
||||
let count = savedPalettes.length;
|
||||
if (count === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO improve UX of this
|
||||
if (!confirm(`Are you sure you want to delete palette “${palette.title}”?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
savedPalettes = savedPalettes.filter(p => !sidebar.palette.equals(palette, p));
|
||||
|
||||
if (savedPalettes.length === count) {
|
||||
// Nothing was removed
|
||||
return;
|
||||
}
|
||||
|
||||
// Update UI
|
||||
let pathname = `/docs/palettes/${palette.id}/`;
|
||||
let url = pathname + palette.search;
|
||||
let uls = new Set();
|
||||
|
||||
for (let a of document.querySelectorAll(`#sidebar a[href="${url}"]`)) {
|
||||
let li = a.closest('li');
|
||||
let ul = li.closest('ul');
|
||||
uls.add(ul);
|
||||
li.remove();
|
||||
}
|
||||
|
||||
// Remove empty lists
|
||||
for (let ul of uls) {
|
||||
if (!ul.children.length) {
|
||||
ul.remove();
|
||||
}
|
||||
}
|
||||
|
||||
sidebar.updateCurrent();
|
||||
|
||||
sidebar.palettes.save(savedPalettes);
|
||||
|
||||
if (sidebar.palette.equals(globalThis.paletteApp?.saved, palette)) {
|
||||
paletteApp.saved = null;
|
||||
}
|
||||
},
|
||||
|
||||
getSaved(palette, savedPalettes = sidebar.palettes.saved) {
|
||||
return savedPalettes.find(p => sidebar.palette.equals(p, palette));
|
||||
},
|
||||
|
||||
render(palette) {
|
||||
// Find existing <a>
|
||||
let { title, id, search, uid } = palette;
|
||||
|
||||
for (let a of document.querySelectorAll(`#sidebar a[href^="/docs/palettes/${id}/"][data-uid="${uid}"]`)) {
|
||||
// Palette already in sidebar, just update it
|
||||
a.textContent = palette.title;
|
||||
a.href = `/docs/palettes/${id}/${search}`;
|
||||
return;
|
||||
}
|
||||
|
||||
let pathname = `/docs/palettes/${id}/`;
|
||||
let url = pathname + search;
|
||||
let parentA = document.querySelector(`a[href="${pathname}"]`);
|
||||
let parentLi = parentA?.closest('li');
|
||||
let a;
|
||||
|
||||
if (parentLi) {
|
||||
a = Object.assign(document.createElement('a'), { href: url, textContent: title });
|
||||
a.dataset.uid = uid;
|
||||
let badges = [...parentLi.querySelectorAll('wa-badge')].map(badge => badge.cloneNode(true));
|
||||
let ul = parentLi.querySelector('ul') ?? parentLi.appendChild(document.createElement('ul'));
|
||||
let li = document.createElement('li');
|
||||
let deleteButton = Object.assign(document.createElement('wa-icon-button'), {
|
||||
name: 'trash',
|
||||
label: 'Delete',
|
||||
className: 'delete',
|
||||
});
|
||||
|
||||
deleteButton.addEventListener('click', () => {
|
||||
let palette = { id, uid, title: a.textContent, search: a.search };
|
||||
sidebar.palette.delete(palette);
|
||||
});
|
||||
|
||||
li.append(a, ' ', ...badges, deleteButton);
|
||||
ul.appendChild(li);
|
||||
}
|
||||
},
|
||||
|
||||
save(palette, saved) {
|
||||
let savedPalettes = sidebar.palettes.saved;
|
||||
let existing = this.getSaved(saved ?? palette, savedPalettes);
|
||||
let oldValues;
|
||||
|
||||
if (existing) {
|
||||
// Rename
|
||||
oldValues = { ...existing };
|
||||
Object.assign(existing, palette);
|
||||
} else {
|
||||
savedPalettes.push(palette);
|
||||
}
|
||||
|
||||
this.render(palette, oldValues);
|
||||
sidebar.updateCurrent();
|
||||
|
||||
sidebar.palettes.save(savedPalettes);
|
||||
},
|
||||
};
|
||||
|
||||
sidebar.updateCurrent = function () {
|
||||
// Find the sidebar link with the longest shared prefix with the current URL
|
||||
let pathParts = location.pathname.split('/').filter(Boolean);
|
||||
let prefixes = [];
|
||||
|
||||
if (pathParts.length === 1) {
|
||||
// If at /docs/ we just use that, otherwise we want at least two parts (/docs/xxx/)
|
||||
prefixes.push('/' + pathParts[0] + '/');
|
||||
} else {
|
||||
for (let i = 2; i <= pathParts.length; i++) {
|
||||
prefixes.push('/' + pathParts.slice(0, i).join('/') + '/');
|
||||
}
|
||||
}
|
||||
|
||||
// Last prefix includes the search too (if any)
|
||||
if (location.search) {
|
||||
let params = new URLSearchParams(location.search);
|
||||
params.sort();
|
||||
prefixes.push(prefixes.at(-1) + location.search);
|
||||
}
|
||||
|
||||
// We want to start from the longest prefix
|
||||
prefixes.reverse();
|
||||
|
||||
for (let prefix of prefixes) {
|
||||
let a = document.querySelector(`#sidebar a[href^="${prefix}"]`);
|
||||
|
||||
if (a) {
|
||||
for (let current of document.querySelectorAll('#sidebar a.current')) {
|
||||
current.classList.remove('current');
|
||||
}
|
||||
a.classList.add('current');
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sidebar.render = function () {
|
||||
this.palettes.render();
|
||||
};
|
||||
|
||||
sidebar.render();
|
||||
window.addEventListener('turbo:render', () => sidebar.render());
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Get import code for remixed themes and tweaked palettes.
|
||||
*/
|
||||
export { theme as getThemeCode } from './tweak/code.js';
|
||||
export { palette as getPaletteCode, theme as getThemeCode } from './tweak/code.js';
|
||||
export { cdnUrl, hueRanges, hues, selectors, tints, urls } from './tweak/data.js';
|
||||
export { default as Permalink } from './tweak/permalink.js';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Get import code for remixed themes and tweaked palettes.
|
||||
*/
|
||||
import { urls } from './data.js';
|
||||
import { selectors, urls } from './data.js';
|
||||
|
||||
export function cssImport(url, options = {}) {
|
||||
let { language = 'html', cdnUrl = '/dist/', attributes } = options;
|
||||
@@ -41,6 +41,66 @@ export function theme(base, params, options) {
|
||||
return ret.map(url => cssImport(url, options)).join('\n');
|
||||
}
|
||||
|
||||
export function palette(paletteId, tweaks, options) {
|
||||
let imports = [];
|
||||
|
||||
if (paletteId) {
|
||||
imports.push(urls.palette(paletteId));
|
||||
}
|
||||
|
||||
let css = '';
|
||||
|
||||
if (tweaks) {
|
||||
let { hueShifts, chromaScale = 1 } = tweaks;
|
||||
let declarations = [];
|
||||
|
||||
if (chromaScale !== 1) {
|
||||
declarations.push(`--wa-chroma-scale: ${chromaScale};`);
|
||||
}
|
||||
|
||||
if (hueShifts || chromaScale !== 1) {
|
||||
let element = document.querySelector(`.wa-palette-${paletteId}`) ?? document.documentElement;
|
||||
let cs = getComputedStyle(element);
|
||||
|
||||
for (let hue in hueShifts) {
|
||||
let shift = hueShifts[hue];
|
||||
|
||||
if ((!shift && chromaScale === 1) || hue === 'orange') {
|
||||
continue;
|
||||
}
|
||||
|
||||
let shiftCode = shift > 0 ? `+ ${shift}` : `- ${-shift}`;
|
||||
let c = chromaScale === 1 ? 'c' : `calc(c * var(--wa-chroma-scale))`;
|
||||
let h = shift ? `calc(h ${shiftCode})` : 'h';
|
||||
declarations.push(`--wa-color-${hue}-tweak: l ${c} ${h});`);
|
||||
|
||||
for (let suffix of ['', '-05', '-10', '-20', '-30', '-40', '-50', '-60', '-70', '-80', '-90', '-95']) {
|
||||
let baseColor = cs.getPropertyValue(`--wa-color-${hue}${suffix}`);
|
||||
// Work around https://bugs.webkit.org/show_bug.cgi?id=287637
|
||||
let colorSpace = ['-95', '-90'].includes(suffix) ? ' lch' : 'oklch';
|
||||
let value = `${colorSpace}(from ${baseColor.padEnd(7)} var(--wa-color-${hue}-tweak))`;
|
||||
suffix = (suffix + ':').padEnd(4);
|
||||
declarations.push(`--wa-color-${hue}${suffix} ${value};`);
|
||||
}
|
||||
|
||||
declarations.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (declarations.length > 0) {
|
||||
css += cssRule(selectors.palette(paletteId), declarations);
|
||||
}
|
||||
}
|
||||
|
||||
let ret = imports.map(url => cssImport(url, options)).join('\n');
|
||||
|
||||
if (css) {
|
||||
ret += `\n\n${cssLiteral(css, options)}`;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function cssRule(selector, declarations, { indent = ' ' } = {}) {
|
||||
selector = Array.isArray(selector) ? selector.flat().join(',\n') : selector;
|
||||
declarations = Array.isArray(declarations) ? declarations.flat() : declarations;
|
||||
|
||||
@@ -61,8 +61,6 @@ export default class Permalink extends URLSearchParams {
|
||||
this.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.sort();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -156,7 +156,7 @@ wa-page > header {
|
||||
}
|
||||
|
||||
/* Pro badges */
|
||||
wa-badge.pro {
|
||||
wa-badge.pro::part(base) {
|
||||
background-color: var(--wa-brand-orange);
|
||||
border-color: var(--wa-brand-orange);
|
||||
}
|
||||
@@ -188,29 +188,6 @@ wa-badge.pro {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wa-icon-button.delete {
|
||||
vertical-align: -0.2em;
|
||||
margin-inline-start: var(--wa-space-xs);
|
||||
|
||||
&:not(li:hover > *, :focus) {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wa-icon-button.delete {
|
||||
&:hover {
|
||||
color: var(--wa-color-danger-on-quiet);
|
||||
}
|
||||
|
||||
&::part(base):hover {
|
||||
background: var(--wa-color-danger-fill-quiet);
|
||||
}
|
||||
|
||||
&:not(:hover, :focus) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
#sidebar-close-button {
|
||||
@@ -255,32 +232,16 @@ wa-page > main {
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
h1.title {
|
||||
wa-icon-button {
|
||||
font-size: var(--wa-font-size-l);
|
||||
color: var(--wa-color-text-quiet);
|
||||
h1.title wa-badge {
|
||||
vertical-align: middle;
|
||||
|
||||
&:not(:hover, :focus) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
wa-badge {
|
||||
vertical-align: middle;
|
||||
&::part(base) {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.block-info {
|
||||
display: flex;
|
||||
gap: var(--wa-space-xs);
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
margin-block-end: var(--wa-flow-spacing);
|
||||
|
||||
code {
|
||||
line-height: var(--wa-line-height-condensed);
|
||||
}
|
||||
}
|
||||
|
||||
/* Current link */
|
||||
@@ -539,27 +500,6 @@ table.colors {
|
||||
--icon-color: var(--wa-color-success-fill-quiet);
|
||||
}
|
||||
|
||||
.icon-modifier {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
|
||||
.modifier {
|
||||
position: absolute;
|
||||
bottom: -0.1em;
|
||||
right: -0.3em;
|
||||
font-size: 60%;
|
||||
|
||||
&::part(svg) {
|
||||
stroke: var(--background-color, var(--wa-color-surface-default));
|
||||
stroke-width: 100px;
|
||||
paint-order: stroke;
|
||||
overflow: visible;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Layout Examples */
|
||||
.layout-example-boundary {
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
layout: null
|
||||
permalink: "/docs/palettes/data.json"
|
||||
eleventyExcludeFromCollections: true
|
||||
---
|
||||
{
|
||||
{% for palette in collections.palettes %}
|
||||
{% set paletteId = palette.fileSlug -%}
|
||||
{% set colors = palettes[paletteId] -%}
|
||||
"{{ paletteId }}": {
|
||||
"title": "{{ palette.data.title }}",
|
||||
"colors": {
|
||||
{% for hue, tints in colors -%}
|
||||
"{{ hue }}": {
|
||||
{% for tint, value in tints -%}
|
||||
{% if tint != "05" -%}
|
||||
{% set value = value.coords or value -%}
|
||||
{% set key = "05" if tint == "5" else tint -%}
|
||||
"{{ key }}": {{ value | dump | safe }}{{ ', ' if not loop.last }}
|
||||
{%- endif %}
|
||||
{% endfor -%}
|
||||
}{{ ', ' if not loop.last }}
|
||||
{% endfor %} {# end of hue #}
|
||||
}
|
||||
}{{ ', ' if not loop.last }} {# end of palette #}
|
||||
{% endfor %}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
title: Default
|
||||
description: This is the palette used in the default theme.
|
||||
order: 0
|
||||
---
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"layout": "palette.njk",
|
||||
"tags": ["palettes", "palette"],
|
||||
"wide": true,
|
||||
"eleventyComputed": {
|
||||
"snippet": ".wa-palette-{{ page.fileSlug }}",
|
||||
"icon": "palette",
|
||||
|
||||
@@ -138,27 +138,3 @@ wa-dropdown > .color.swatch {
|
||||
--tweak-icon-opacity: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.tweaked-callout {
|
||||
padding: var(--wa-space-xs);
|
||||
padding-inline-start: var(--wa-space-m);
|
||||
align-items: center;
|
||||
|
||||
&:not(.tweaked-any *) {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&::part(message) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
wa-button:first-of-type {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
}
|
||||
|
||||
[v-if='saved'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// TODO move these to local imports
|
||||
import Color from 'https://colorjs.io/dist/color.js';
|
||||
import { createApp, nextTick } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
|
||||
import { cdnUrl, hueRanges, hues, Permalink, tints } from '../../assets/scripts/tweak.js';
|
||||
import { cssImport, cssLiteral, cssRule } from '../../assets/scripts/tweak/code.js';
|
||||
import { selectors, urls } from '../../assets/scripts/tweak/data.js';
|
||||
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
|
||||
|
||||
import { cdnUrl, getPaletteCode, hueRanges, hues, Permalink, tints } from '../../assets/scripts/tweak.js';
|
||||
import Prism from '/assets/scripts/prism.js';
|
||||
|
||||
await Promise.all(['wa-slider'].map(tag => customElements.whenDefined(tag)));
|
||||
@@ -18,39 +17,26 @@ await Promise.all(['wa-slider'].map(tag => customElements.whenDefined(tag)));
|
||||
// return computedColor.endsWith(' 0)');
|
||||
// })();
|
||||
|
||||
let allPalettes = await fetch('/docs/palettes/data.json').then(r => r.json());
|
||||
globalThis.allPalettes = allPalettes;
|
||||
|
||||
for (let palette in allPalettes) {
|
||||
for (let hue in allPalettes[palette].colors) {
|
||||
let scale = allPalettes[palette].colors[hue];
|
||||
for (let tint of tints) {
|
||||
let color = scale[tint];
|
||||
|
||||
if (Array.isArray(color)) {
|
||||
scale[tint] = new Color('oklch', color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let paletteAppSpec = {
|
||||
data() {
|
||||
let appRoot = document.querySelector('#palette-app');
|
||||
let paletteId = appRoot.dataset.paletteId;
|
||||
let palette = allPalettes[paletteId];
|
||||
const { paletteId, colors, maxChroma } = wa_data;
|
||||
|
||||
// Replace colors with their oklch coords (since they're all opaque and all in the same color space)
|
||||
for (let hue in colors) {
|
||||
for (let tint of tints) {
|
||||
colors[hue][tint] = colors[hue][tint].coords;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
uid: undefined,
|
||||
paletteId,
|
||||
paletteTitle: palette.title,
|
||||
originalColors: palette.colors,
|
||||
permalink: new Permalink(),
|
||||
hueRanges,
|
||||
hueShifts: Object.fromEntries(hues.map(hue => [hue, 0])),
|
||||
paletteId,
|
||||
originalColors: colors,
|
||||
maxChroma,
|
||||
chromaScale: 1,
|
||||
tweaking: {},
|
||||
saved: null,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -68,23 +54,19 @@ let paletteAppSpec = {
|
||||
this.permalink.writeTo(this.hueShifts);
|
||||
|
||||
if (this.permalink.has('chroma-scale')) {
|
||||
this.chromaScale = Number(this.permalink.get('chroma-scale') || 1);
|
||||
this.chromaScale = Number(this.permalink.get('chromaScale') || 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
if (this.permalink.has('uid')) {
|
||||
this.uid = Number(this.permalink.get('uid'));
|
||||
}
|
||||
|
||||
let palette = { id: this.paletteId, uid: this.uid, search: location.search };
|
||||
this.saved = sidebar.palette.getSaved(palette);
|
||||
mounted() {
|
||||
if (this.isTweaked) {
|
||||
// Update contrast colors
|
||||
updateContrastTables(this.colors);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
global() {
|
||||
return globalThis;
|
||||
},
|
||||
|
||||
tweaks() {
|
||||
return { hueShifts: this.hueShifts, chromaScale: this.chromaScale };
|
||||
},
|
||||
@@ -93,123 +75,29 @@ let paletteAppSpec = {
|
||||
return Object.values(this.hueShifts).some(Boolean);
|
||||
},
|
||||
|
||||
code() {
|
||||
let ret = {};
|
||||
for (let language of ['html', 'css']) {
|
||||
let code = getPaletteCode(this.paletteId, this.tweaks, { language, cdnUrl });
|
||||
ret[language] = {
|
||||
raw: code,
|
||||
highlighted: Prism.highlight(code, Prism.languages[language], language),
|
||||
};
|
||||
}
|
||||
paletteHTML() {
|
||||
return getPaletteCode(this.paletteId, this.tweaks, { language: 'html', cdnUrl });
|
||||
},
|
||||
|
||||
return ret;
|
||||
paletteCSS() {
|
||||
return getPaletteCode(this.paletteId, this.tweaks, { language: 'css', cdnUrl });
|
||||
},
|
||||
|
||||
colors() {
|
||||
let ret = {};
|
||||
|
||||
for (let hue in this.originalColors) {
|
||||
let originalScale = this.originalColors[hue];
|
||||
let scale = (ret[hue] = {});
|
||||
let descriptors = Object.getOwnPropertyDescriptors(originalScale);
|
||||
Object.defineProperties(scale, {
|
||||
maxChromaTint: { ...descriptors.maxChromaTint, enumerable: false },
|
||||
maxChromaTintRaw: { ...descriptors.maxChromaTintRaw, enumerable: false },
|
||||
});
|
||||
ret[hue] = {};
|
||||
|
||||
for (let tint of tints) {
|
||||
let oklch = originalScale[tint].coords.slice();
|
||||
ret[hue][tint] = this.originalColors[hue][tint].slice();
|
||||
|
||||
if (this.hueShifts[hue]) {
|
||||
oklch[2] += this.hueShifts[hue];
|
||||
ret[hue][tint][2] += this.hueShifts[hue];
|
||||
}
|
||||
|
||||
if (this.chromaScale !== 1) {
|
||||
oklch[1] *= this.chromaScale;
|
||||
}
|
||||
|
||||
scale[tint] = new Color('oklch', oklch);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
tweaked() {
|
||||
return {
|
||||
chroma: this.chromaScale !== 1,
|
||||
hue: Object.values(this.hueShifts).some(Boolean),
|
||||
};
|
||||
},
|
||||
|
||||
tweaksHumanReadable() {
|
||||
let ret = {};
|
||||
|
||||
if (this.chromaScale !== 1) {
|
||||
ret.chromaScale = 'more ' + (this.chromaScale > 1 ? 'vibrant' : 'muted');
|
||||
}
|
||||
|
||||
for (let hue in this.hueShifts) {
|
||||
let shift = this.hueShifts[hue];
|
||||
|
||||
if (!shift) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let relHue = shift < 0 ? arrayPrevious(hues, hue) : arrayNext(hues, hue);
|
||||
let hueTweak =
|
||||
{
|
||||
red: 'redder',
|
||||
orange: 'oranger',
|
||||
indigo: 'more indigo',
|
||||
}[relHue] ?? relHue + 'er';
|
||||
|
||||
ret[hue] = hueTweak + ' ' + hue + 's';
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
originalContrasts() {
|
||||
let ret = {};
|
||||
|
||||
for (let hue in this.originalColors) {
|
||||
ret[hue] = {};
|
||||
|
||||
for (let tintBg of tints) {
|
||||
ret[hue][tintBg] = {};
|
||||
let bgColor = this.originalColors[hue][tintBg];
|
||||
|
||||
if (!bgColor || !bgColor.contrast) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let tintFg of tints) {
|
||||
let contrast = bgColor.contrast(this.originalColors[hue][tintFg], 'WCAG21');
|
||||
ret[hue][tintBg][tintFg] = contrast;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
contrasts() {
|
||||
let ret = {};
|
||||
|
||||
for (let hue in this.colors) {
|
||||
ret[hue] = {};
|
||||
|
||||
for (let tintBg in this.colors[hue]) {
|
||||
ret[hue][tintBg] = {};
|
||||
let bgColor = this.colors[hue][tintBg];
|
||||
|
||||
for (let tintFg in this.colors[hue]) {
|
||||
let fgColor = this.colors[hue][tintFg];
|
||||
let value = bgColor.contrast(fgColor, 'WCAG21');
|
||||
let original = this.originalContrasts[hue][tintBg][tintFg];
|
||||
ret[hue][tintBg][tintFg] = { value, original, bgColor, fgColor };
|
||||
ret[hue][tint][1] *= this.chromaScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,114 +107,44 @@ let paletteAppSpec = {
|
||||
},
|
||||
|
||||
watch: {
|
||||
// Note: These could move to `v-html` directives if we widen the app root
|
||||
paletteHTML() {
|
||||
let codeElement = document.querySelector('#usage ~ wa-tab-group.import-stylesheet-code code.language-html');
|
||||
codeElement.textContent = this.paletteHTML;
|
||||
let copyButton = codeElement.previousElementSibling;
|
||||
copyButton.value = this.paletteHTML;
|
||||
Prism.highlightElement(codeElement);
|
||||
},
|
||||
|
||||
paletteCSS() {
|
||||
let codeElement = document.querySelector('#usage ~ wa-tab-group.import-stylesheet-code code.language-css');
|
||||
codeElement.textContent = this.paletteCSS;
|
||||
let copyButton = codeElement.previousElementSibling;
|
||||
copyButton.value = this.paletteCSS;
|
||||
Prism.highlightElement(codeElement);
|
||||
},
|
||||
|
||||
hueShifts: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.permalink.readFrom(this.hueShifts);
|
||||
|
||||
// Update page URL
|
||||
this.permalink.updateLocation();
|
||||
|
||||
// Update contrast colors
|
||||
updateContrastTables(this.colors);
|
||||
},
|
||||
},
|
||||
|
||||
chromaScale() {
|
||||
this.permalink.set('chroma-scale', this.chromaScale, 1);
|
||||
},
|
||||
|
||||
tweaks: {
|
||||
deep: true,
|
||||
async handler(value, oldValue) {
|
||||
await nextTick(); // must run after individual watchers
|
||||
// Update page URL
|
||||
this.permalink.updateLocation();
|
||||
|
||||
// Update page URL
|
||||
this.permalink.updateLocation();
|
||||
|
||||
if (this.saved) {
|
||||
this.save({ silent: true });
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
save({ silent } = {}) {
|
||||
let title = silent
|
||||
? (this.saved?.title ?? this.paletteTitle)
|
||||
: prompt('Palette title:', `${this.paletteTitle} (tweaked)`);
|
||||
|
||||
if (!title) {
|
||||
return;
|
||||
}
|
||||
|
||||
let uid = this.uid;
|
||||
|
||||
if (!uid) {
|
||||
this.uid = uid = sidebar.palette.getUid();
|
||||
|
||||
this.permalink.set('uid', uid);
|
||||
this.permalink.updateLocation();
|
||||
}
|
||||
|
||||
let palette = { title, id: this.paletteId, uid, search: location.search };
|
||||
sidebar.palette.save(palette, this.saved);
|
||||
this.saved = palette;
|
||||
},
|
||||
|
||||
rename() {
|
||||
if (!this.saved) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newTitle = prompt('New title:', this.saved.title);
|
||||
|
||||
if (!newTitle) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.saved.title = newTitle;
|
||||
sidebar.palette.save(this.saved);
|
||||
},
|
||||
|
||||
deleteSaved() {
|
||||
sidebar.palette.delete(this.saved);
|
||||
this.saved = null;
|
||||
},
|
||||
|
||||
reset() {
|
||||
for (let hue in this.hueShifts) {
|
||||
this.hueShifts[hue] = 0;
|
||||
}
|
||||
this.chromaScale = 1;
|
||||
},
|
||||
|
||||
removeTweak(param) {
|
||||
if (param === 'chromaScale') {
|
||||
this.chromaScale = 1;
|
||||
} else {
|
||||
this.hueShifts[param] = 0;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
directives: {
|
||||
// Like v-text, but doesn't complain if the element has content,
|
||||
// making it possible to use in a PE fashion, with the contents being the fallback
|
||||
content(el, { value, arg }) {
|
||||
if (!el.dataset.fallback) {
|
||||
// Store the original content as a fallback the first time
|
||||
el.dataset.fallback = el.textContent;
|
||||
}
|
||||
|
||||
if (value === '') {
|
||||
value = el.dataset.fallback;
|
||||
} else {
|
||||
if (arg === 'number') {
|
||||
value = Number(value).toLocaleString(undefined, { maximumSignificantDigits: 2 });
|
||||
}
|
||||
}
|
||||
|
||||
if (arg === 'html') {
|
||||
el.innerHTML = value;
|
||||
} else {
|
||||
el.textContent = value;
|
||||
}
|
||||
// Update contrast colors
|
||||
updateContrastTables(this.colors);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -336,76 +154,41 @@ let paletteAppSpec = {
|
||||
};
|
||||
|
||||
function init() {
|
||||
globalThis.paletteApp?.unmount?.();
|
||||
globalThis.paletteApp = createApp(paletteAppSpec).mount('#palette-app');
|
||||
}
|
||||
|
||||
function updateContrastTables(colors) {
|
||||
for (let table of document.querySelectorAll('.contrast-table')) {
|
||||
let { minContrast } = table.dataset;
|
||||
|
||||
for (let tr of table.querySelectorAll('tr[data-hue]')) {
|
||||
let { hue } = tr.dataset;
|
||||
|
||||
for (let td of tr.querySelectorAll('td[data-tint-bg][data-tint-fg]')) {
|
||||
let swatch = td.querySelector('.color.swatch');
|
||||
|
||||
let { tintBg, tintFg, originalContrast } = td.dataset;
|
||||
|
||||
let bg = new Color('oklch', colors[hue][tintBg]);
|
||||
let fg = new Color('oklch', colors[hue][tintFg]);
|
||||
|
||||
if (!originalContrast) {
|
||||
td.dataset.originalContrast = originalContrast = swatch.textContent.trim();
|
||||
}
|
||||
|
||||
let contrast = bg.contrast(fg, 'WCAG21').toLocaleString(undefined, { maximumSignificantDigits: 2 });
|
||||
swatch.textContent = contrast;
|
||||
|
||||
swatch.classList.toggle('value-up', contrast > originalContrast);
|
||||
swatch.classList.toggle('value-down', contrast < originalContrast);
|
||||
swatch.classList.toggle('contrast-fail', contrast < minContrast);
|
||||
|
||||
swatch.style.setProperty('--color', bg.display());
|
||||
swatch.style.setProperty('color', fg.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
addEventListener('turbo:render', init);
|
||||
|
||||
export function getPaletteCode(paletteId, tweaks, options) {
|
||||
let palette = allPalettes[paletteId].colors;
|
||||
|
||||
let imports = [];
|
||||
|
||||
if (paletteId) {
|
||||
imports.push(urls.palette(paletteId));
|
||||
}
|
||||
|
||||
let css = '';
|
||||
|
||||
if (tweaks) {
|
||||
let { hueShifts, chromaScale = 1 } = tweaks;
|
||||
let declarations = [];
|
||||
|
||||
if (hueShifts || chromaScale !== 1) {
|
||||
for (let hue in hueShifts) {
|
||||
let shift = hueShifts[hue];
|
||||
|
||||
if ((!shift && chromaScale === 1) || hue === 'orange') {
|
||||
continue;
|
||||
}
|
||||
|
||||
let scale = palette[hue];
|
||||
|
||||
for (let tint of ['05', '10', '20', '30', '40', '50', '60', '70', '80', '90', '95']) {
|
||||
let color = scale[tint];
|
||||
|
||||
if (Array.isArray(color)) {
|
||||
color = new Color('oklch', coords);
|
||||
} else {
|
||||
color = color.clone();
|
||||
}
|
||||
color.set({ h: h => h + shift, c: c => c * chromaScale });
|
||||
let stringified = color.toString({ format: color.inGamut('srgb') ? 'hex' : undefined });
|
||||
|
||||
declarations.push(`--wa-color-${hue}-${tint}: ${stringified};`);
|
||||
}
|
||||
|
||||
declarations.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (declarations.length > 0) {
|
||||
css += cssRule(selectors.palette(paletteId), declarations);
|
||||
}
|
||||
}
|
||||
|
||||
let ret = imports.map(url => cssImport(url, options)).join('\n');
|
||||
|
||||
if (css) {
|
||||
ret += `\n\n${cssLiteral(css, options)}`;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function arrayNext(array, element) {
|
||||
let index = array.indexOf(element);
|
||||
return array[(index + 1) % array.length];
|
||||
}
|
||||
|
||||
function arrayPrevious(array, element) {
|
||||
let index = array.indexOf(element);
|
||||
return array[(index - 1 + array.length) % array.length];
|
||||
}
|
||||
|
||||
@@ -27,9 +27,8 @@ You can find them in the first column of each color palette.
|
||||
|
||||
### Themes
|
||||
|
||||
- Updated Active, Glossy, Playful, and Premium themes so that `--wa-color-brand-fill-loud` uses the core color of the chosen brand color, regardless of tint.
|
||||
- You can now override the brand color of any theme with any of the 9 hues supported.
|
||||
- Improved UI for theme remixing, with previews and generated copyable code snippets.
|
||||
- Improved UI for theme remixing, with previews and generated copyable code snippets
|
||||
|
||||
### Components
|
||||
|
||||
|
||||
2
docs/docs/themes/remix.js
vendored
2
docs/docs/themes/remix.js
vendored
@@ -139,8 +139,10 @@ function render(changedAspect) {
|
||||
// Update code snippets
|
||||
for (let language in codeSnippets) {
|
||||
let codeSnippet = codeSnippets[language];
|
||||
let copyButton = codeSnippet.previousElementSibling;
|
||||
let code = getThemeCode(data.baseTheme, data.params, { language, cdnUrl });
|
||||
codeSnippet.textContent = code;
|
||||
copyButton.value = code;
|
||||
Prism.highlightElement(codeSnippet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import { dirname, join, relative } from 'path';
|
||||
import process from 'process';
|
||||
import copy from 'recursive-copy';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { preprocessStylesheet } from './preprocess-css.js';
|
||||
import { cdnDir, distDir, docsDir, rootDir, runScript, siteDir } from './utils.js';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
@@ -37,7 +36,6 @@ async function buildAll() {
|
||||
await generateManifest();
|
||||
await generateReactWrappers();
|
||||
await generateTypes();
|
||||
await preprocessStyles();
|
||||
await generateStyles();
|
||||
|
||||
// copy everything to unbundled before we generate bundles.
|
||||
@@ -107,23 +105,6 @@ function generateReactWrappers() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate preprocessed CSS
|
||||
*/
|
||||
async function preprocessStyles() {
|
||||
const preprocessedCSSFiles = await globby(join(rootDir, 'src/styles/**/*.css.njk'));
|
||||
|
||||
if (preprocessedCSSFiles.length > 0) {
|
||||
spinner.start('Preprocessing stylesheets');
|
||||
|
||||
for (let filePath of preprocessedCSSFiles) {
|
||||
await preprocessStylesheet(filePath);
|
||||
}
|
||||
|
||||
spinner.succeed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies theme stylesheets to the dist.
|
||||
*/
|
||||
@@ -390,7 +371,6 @@ if (isDeveloping) {
|
||||
try {
|
||||
const isTestFile = filename.includes('.test.ts');
|
||||
const isCssStylesheet = filename.includes('.css');
|
||||
const isPreprocessedStylesheet = filename.endsWith('.css.njk');
|
||||
const isComponent =
|
||||
filename.includes('components/') && filename.includes('.ts') && !isCssStylesheet && !isTestFile;
|
||||
|
||||
@@ -401,10 +381,6 @@ if (isDeveloping) {
|
||||
|
||||
await regenerateBundle();
|
||||
|
||||
if (isPreprocessedStylesheet || filename.endsWith('src/styles/data.js')) {
|
||||
await preprocessStyles();
|
||||
}
|
||||
|
||||
// Copy stylesheets when CSS files change
|
||||
if (isCssStylesheet) {
|
||||
await generateStyles();
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import { readFile, writeFile } from 'fs/promises';
|
||||
import nunjucks from 'nunjucks';
|
||||
import * as prettier from 'prettier';
|
||||
import prettierConfig from '../prettier.config.js';
|
||||
import * as globalData from '../src/styles/data.js';
|
||||
|
||||
const prelude = inputFilename => `/* DO NOT EDIT THIS FILE. It is generated from "${inputFilename}" */`;
|
||||
|
||||
let env = nunjucks.configure({ autoescape: false });
|
||||
let filenameVariables = Object.keys(globalData)
|
||||
.filter(key => key.endsWith('s'))
|
||||
.map(key => key.slice(0, -1));
|
||||
let filenameVariablesRegex = RegExp(`\\{\\{\\s*(${filenameVariables.join('|')})\\s*\\}\\}`, 'g');
|
||||
|
||||
export async function preprocessStylesheet(inputPath) {
|
||||
const content = await readFile(inputPath, 'utf-8');
|
||||
let outputPath = inputPath.replace(/\.njk$/, '');
|
||||
let filename = outputPath.split('/').pop();
|
||||
|
||||
if (filenameVariablesRegex.test(filename)) {
|
||||
// NOTE only supports a single variable right now
|
||||
filenameVariablesRegex.lastIndex = 0;
|
||||
let ret = [];
|
||||
|
||||
for (let match of filename.matchAll(filenameVariablesRegex)) {
|
||||
let variable = match[1];
|
||||
let values = globalData[variable + 's'];
|
||||
|
||||
for (let value of values) {
|
||||
let data = { [variable]: value };
|
||||
let css = await renderCSS(content, { data, inputPath, outputPath });
|
||||
|
||||
// Now use Nunjucks *again*, to render the actual filename
|
||||
let localOutputFilePath = env.renderString(outputPath, data);
|
||||
|
||||
ret.push(writeFile(localOutputFilePath, css, 'utf-8'));
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.all(ret);
|
||||
} else {
|
||||
let css = await renderCSS(content, { inputPath, outputPath });
|
||||
return writeFile(outputPath, css, 'utf-8');
|
||||
}
|
||||
|
||||
// TODO add generated files to .gitignore?
|
||||
}
|
||||
|
||||
export async function renderCSS(content, { data, inputPath, outputPath } = {}) {
|
||||
let inputFilename = inputPath.split('/').pop();
|
||||
data = data ? { ...globalData, ...data } : globalData;
|
||||
let css = env.renderString(content, data);
|
||||
|
||||
if (prelude) {
|
||||
css = prelude(inputFilename) + '\n' + css;
|
||||
}
|
||||
|
||||
css = await prettier.format(css, { ...prettierConfig, filepath: outputPath });
|
||||
|
||||
return css;
|
||||
}
|
||||
@@ -194,7 +194,7 @@
|
||||
background: var(--wa-color-surface-raised);
|
||||
border-color: var(--wa-color-surface-border);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
border-style: var(--wa-border-style);
|
||||
border-style: var(--border-style);
|
||||
border-width: var(--border-width);
|
||||
padding-block: var(--wa-space-xs);
|
||||
padding-inline: 0;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "base.css.njk" */
|
||||
:where(:root),
|
||||
:host,
|
||||
:where([class^='wa-theme-'], [class*=' wa-theme-']),
|
||||
@@ -9,20 +8,16 @@
|
||||
* --wa-color-brand-if-lt-N ➡️ 100% if key < N, 0% otherwise
|
||||
* --wa-color-brand-if-gte-N ➡️ 100% if key >= N, 0% otherwise
|
||||
*/
|
||||
|
||||
--wa-color-brand-if-lt-40: calc(clamp(0, 40 - var(--wa-color-brand-key), 1) * 100%);
|
||||
--wa-color-brand-if-gte-40: calc(100% - var(--wa-color-brand-if-lt-40));
|
||||
|
||||
--wa-color-brand-if-lt-50: calc(clamp(0, 50 - var(--wa-color-brand-key), 1) * 100%);
|
||||
--wa-color-brand-if-gte-50: calc(100% - var(--wa-color-brand-if-lt-50));
|
||||
|
||||
--wa-color-brand-if-lt-60: calc(clamp(0, 60 - var(--wa-color-brand-key), 1) * 100%);
|
||||
--wa-color-brand-if-gte-60: calc(100% - var(--wa-color-brand-if-lt-60));
|
||||
|
||||
--wa-color-brand-if-lt-70: calc(clamp(0, 70 - var(--wa-color-brand-key), 1) * 100%);
|
||||
--wa-color-brand-if-gte-70: calc(100% - var(--wa-color-brand-if-lt-70));
|
||||
|
||||
--wa-color-brand-if-lt-80: calc(clamp(0, 80 - var(--wa-color-brand-key), 1) * 100%);
|
||||
|
||||
--wa-color-brand-if-gte-40: calc(100% - var(--wa-color-brand-if-lt-40));
|
||||
--wa-color-brand-if-gte-50: calc(100% - var(--wa-color-brand-if-lt-50));
|
||||
--wa-color-brand-if-gte-60: calc(100% - var(--wa-color-brand-if-lt-60));
|
||||
--wa-color-brand-if-gte-70: calc(100% - var(--wa-color-brand-if-lt-70));
|
||||
--wa-color-brand-if-gte-80: calc(100% - var(--wa-color-brand-if-lt-80));
|
||||
|
||||
/*
|
||||
@@ -30,7 +25,6 @@
|
||||
* --wa-color-brand-N-max ➡️ var(--color-brand) if key <= N, var(--color-brand-N) otherwise
|
||||
* --wa-color-brand-N-min ➡️ var(--color-brand) if key >= N, var(--color-brand-N) otherwise
|
||||
*/
|
||||
|
||||
--wa-color-brand-40-max: color-mix(
|
||||
in oklab,
|
||||
var(--wa-color-brand) var(--wa-color-brand-if-lt-40),
|
||||
@@ -64,17 +58,6 @@
|
||||
var(--wa-color-brand-60)
|
||||
);
|
||||
|
||||
--wa-color-brand-70-max: color-mix(
|
||||
in oklab,
|
||||
var(--wa-color-brand) var(--wa-color-brand-if-lt-70),
|
||||
var(--wa-color-brand-70)
|
||||
);
|
||||
--wa-color-brand-70-min: color-mix(
|
||||
in oklab,
|
||||
var(--wa-color-brand) var(--wa-color-brand-if-gte-70),
|
||||
var(--wa-color-brand-70)
|
||||
);
|
||||
|
||||
/* Text color: white if key < 60, brand-10 otherwise */
|
||||
/* Text color: white if key < 70, brand-10 otherwise */
|
||||
--wa-color-brand-on: color-mix(in oklab, var(--wa-color-brand-10) var(--wa-color-brand-if-gte-60), white);
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
:where(:root),
|
||||
:host,
|
||||
:where([class^='wa-theme-'], [class*=' wa-theme-']),
|
||||
:where([class^='wa-palette-'], [class*=' wa-palette-']),
|
||||
:where([class^='wa-brand-'], [class*=' wa-brand-']) {
|
||||
/**
|
||||
* Conditional tokens for use in color-mix()
|
||||
* --wa-color-brand-if-lt-N ➡️ 100% if key < N, 0% otherwise
|
||||
* --wa-color-brand-if-gte-N ➡️ 100% if key >= N, 0% otherwise
|
||||
*/
|
||||
{% for tint in ['40', '50', '60', '70', '80'] %}
|
||||
--wa-color-brand-if-lt-{{ tint }}: calc(clamp(0, {{ tint }} - var(--wa-color-brand-key), 1) * 100%);
|
||||
--wa-color-brand-if-gte-{{ tint }}: calc(100% - var(--wa-color-brand-if-lt-{{ tint }}));
|
||||
{% endfor %}
|
||||
|
||||
/*
|
||||
* Convenience tokens for common tint cutoffs
|
||||
* --wa-color-brand-N-max ➡️ var(--color-brand) if key <= N, var(--color-brand-N) otherwise
|
||||
* --wa-color-brand-N-min ➡️ var(--color-brand) if key >= N, var(--color-brand-N) otherwise
|
||||
*/
|
||||
{% for tint in ['40', '50', '60', '70'] %}
|
||||
--wa-color-brand-{{ tint }}-max: color-mix(
|
||||
in oklab,
|
||||
var(--wa-color-brand) var(--wa-color-brand-if-lt-{{ tint }}),
|
||||
var(--wa-color-brand-{{ tint }})
|
||||
);
|
||||
--wa-color-brand-{{ tint }}-min: color-mix(
|
||||
in oklab,
|
||||
var(--wa-color-brand) var(--wa-color-brand-if-gte-{{ tint }}),
|
||||
var(--wa-color-brand-{{ tint }})
|
||||
);
|
||||
{% endfor %}
|
||||
|
||||
/* Text color: white if key < 60, brand-10 otherwise */
|
||||
--wa-color-brand-on: color-mix(in oklab, var(--wa-color-brand-10) var(--wa-color-brand-if-gte-60), white);
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
@import url('base.css');
|
||||
|
||||
:where(:root),
|
||||
:host,
|
||||
:where([class^='wa-theme-'], [class*=' wa-theme-']),
|
||||
:where([class^='wa-palette-'], [class*=' wa-palette-']),
|
||||
.wa-brand-{{ hue }} {
|
||||
{%- for tint in tints | reverse %}
|
||||
--wa-color-brand-{{ tint }}: var(--wa-color-{{ hue }}-{{ tint }});
|
||||
{%- endfor %}
|
||||
--wa-color-brand: var(--wa-color-{{ hue }});
|
||||
--wa-color-brand-key: var(--wa-color-{{ hue }}-key);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
/**
|
||||
* Any data relating to the design system.
|
||||
*/
|
||||
export const hues = ['red', 'yellow', 'green', 'cyan', 'blue', 'indigo', 'purple', 'pink', 'gray'];
|
||||
export const tints = ['05', '10', '20', '30', '40', '50', '60', '70', '80', '90', '95'];
|
||||
export const variants = ['neutral', 'brand', 'success', 'warning', 'danger'];
|
||||
@@ -26,13 +26,13 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-95);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-90);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-90);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-70);
|
||||
--wa-color-brand-on-quiet: var(--wa-color-brand-40);
|
||||
--wa-color-brand-on-normal: var(--wa-color-brand-30);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-on);
|
||||
--wa-color-brand-on-loud: black;
|
||||
|
||||
--wa-color-success-fill-quiet: var(--wa-color-green-95);
|
||||
--wa-color-success-fill-normal: var(--wa-color-green-90);
|
||||
@@ -90,13 +90,13 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-10);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-20);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-20);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-30);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-60);
|
||||
--wa-color-brand-on-quiet: var(--wa-color-brand-80);
|
||||
--wa-color-brand-on-normal: var(--wa-color-brand-90);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-on);
|
||||
--wa-color-brand-on-loud: black;
|
||||
|
||||
--wa-color-success-fill-quiet: var(--wa-color-green-10);
|
||||
--wa-color-success-fill-normal: var(--wa-color-green-20);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-95);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-90);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-70-min);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-70);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-70);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-50);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-30);
|
||||
@@ -77,7 +77,7 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-10);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-20);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50-max);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-30);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-50);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-80);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-95);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-90);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50-max);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-60);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-40);
|
||||
@@ -96,7 +96,7 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-20);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-30);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-70-min);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-70);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-30);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-40);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-80);
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-95);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-90);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50-max);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-90);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-60);
|
||||
@@ -149,7 +149,7 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-10);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-20);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50-max);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-20);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-30);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-40);
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-95);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-90);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-40);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-90);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-60);
|
||||
--wa-color-brand-on-quiet: var(--wa-color-brand-40);
|
||||
--wa-color-brand-on-normal: var(--wa-color-brand-30);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-on);
|
||||
--wa-color-brand-on-loud: white;
|
||||
|
||||
--wa-color-success-fill-loud: var(--wa-color-green-40);
|
||||
|
||||
@@ -51,13 +51,13 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-10);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-20);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-40);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-20);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-30);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-40);
|
||||
--wa-color-brand-on-quiet: var(--wa-color-brand-60);
|
||||
--wa-color-brand-on-normal: var(--wa-color-brand-70);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-on);
|
||||
--wa-color-brand-on-loud: white;
|
||||
|
||||
--wa-color-success-fill-loud: var(--wa-color-green-40);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-90);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-80);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50-max);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-40);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-70);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-60);
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
--wa-color-success-fill-quiet: var(--wa-color-green-90);
|
||||
--wa-color-success-fill-normal: var(--wa-color-green-80);
|
||||
--wa-color-success-fill-loud: var(--wa-color-green-50);
|
||||
--wa-color-success-fill-loud: var(--wa-color-green-40);
|
||||
--wa-color-success-border-quiet: var(--wa-color-green-80);
|
||||
--wa-color-success-border-normal: var(--wa-color-green-70);
|
||||
--wa-color-success-border-loud: var(--wa-color-green-60);
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
--wa-color-warning-fill-quiet: var(--wa-color-yellow-90);
|
||||
--wa-color-warning-fill-normal: var(--wa-color-yellow-80);
|
||||
--wa-color-warning-fill-loud: var(--wa-color-yellow-50);
|
||||
--wa-color-warning-fill-loud: var(--wa-color-yellow-40);
|
||||
--wa-color-warning-border-quiet: var(--wa-color-yellow-80);
|
||||
--wa-color-warning-border-normal: var(--wa-color-yellow-70);
|
||||
--wa-color-warning-border-loud: var(--wa-color-yellow-60);
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
--wa-color-danger-fill-quiet: var(--wa-color-red-90);
|
||||
--wa-color-danger-fill-normal: var(--wa-color-red-80);
|
||||
--wa-color-danger-fill-loud: var(--wa-color-red-50);
|
||||
--wa-color-danger-fill-loud: var(--wa-color-red-40);
|
||||
--wa-color-danger-border-quiet: var(--wa-color-red-80);
|
||||
--wa-color-danger-border-normal: var(--wa-color-red-70);
|
||||
--wa-color-danger-border-loud: var(--wa-color-red-60);
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
--wa-color-neutral-fill-quiet: var(--wa-color-gray-90);
|
||||
--wa-color-neutral-fill-normal: var(--wa-color-gray-80);
|
||||
--wa-color-neutral-fill-loud: var(--wa-color-gray-50);
|
||||
--wa-color-neutral-fill-loud: var(--wa-color-gray-40);
|
||||
--wa-color-neutral-border-quiet: var(--wa-color-gray-80);
|
||||
--wa-color-neutral-border-normal: var(--wa-color-gray-70);
|
||||
--wa-color-neutral-border-loud: var(--wa-color-gray-60);
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-90);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-80);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-90);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-70);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-50);
|
||||
--wa-color-brand-on-quiet: var(--wa-color-brand-30);
|
||||
--wa-color-brand-on-normal: var(--wa-color-brand-30);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-on);
|
||||
--wa-color-brand-on-loud: white;
|
||||
|
||||
--wa-color-success-fill-quiet: var(--wa-color-green-90);
|
||||
--wa-color-success-fill-normal: var(--wa-color-green-80);
|
||||
@@ -94,13 +94,13 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-20);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-40);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-50);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-30);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-40);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-50);
|
||||
--wa-color-brand-on-quiet: var(--wa-color-brand-70);
|
||||
--wa-color-brand-on-normal: var(--wa-color-brand-90);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-on);
|
||||
--wa-color-brand-on-loud: white;
|
||||
|
||||
--wa-color-success-fill-quiet: var(--wa-color-green-20);
|
||||
--wa-color-success-fill-normal: var(--wa-color-green-40);
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-95);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-90);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-70);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-50);
|
||||
--wa-color-brand-on-quiet: var(--wa-color-brand-40);
|
||||
--wa-color-brand-on-normal: var(--wa-color-brand-30);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-on);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-20);
|
||||
|
||||
--wa-color-success-fill-quiet: var(--wa-color-green-95);
|
||||
--wa-color-success-fill-normal: var(--wa-color-green-90);
|
||||
@@ -98,13 +98,13 @@
|
||||
*/
|
||||
--wa-color-brand-fill-quiet: var(--wa-color-brand-30);
|
||||
--wa-color-brand-fill-normal: var(--wa-color-brand-40);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand);
|
||||
--wa-color-brand-fill-loud: var(--wa-color-brand-80);
|
||||
--wa-color-brand-border-quiet: var(--wa-color-brand-30);
|
||||
--wa-color-brand-border-normal: var(--wa-color-brand-40);
|
||||
--wa-color-brand-border-loud: var(--wa-color-brand-70);
|
||||
--wa-color-brand-on-quiet: var(--wa-color-brand-70);
|
||||
--wa-color-brand-on-normal: var(--wa-color-brand-90);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-on);
|
||||
--wa-color-brand-on-loud: var(--wa-color-brand-20);
|
||||
|
||||
--wa-color-success-fill-quiet: var(--wa-color-green-30);
|
||||
--wa-color-success-fill-normal: var(--wa-color-green-40);
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/* DO NOT EDIT THIS FILE. It is generated from "variants.css.njk" */
|
||||
/**
|
||||
* Do not edit this file directly. It is generated via variants.css.js
|
||||
*/
|
||||
|
||||
/**
|
||||
* Register color properties so that the space toggle hack can work.
|
||||
*/
|
||||
@@ -61,6 +64,7 @@
|
||||
* Element defaults.
|
||||
We want these to resolve to inherit when inside a variant, and only be applied when not inside an explicit variant.
|
||||
*/
|
||||
|
||||
:host(wa-button),
|
||||
.wa-button,
|
||||
button,
|
||||
|
||||
68
src/styles/utilities/variants.css.js
Normal file
68
src/styles/utilities/variants.css.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Generate variants.css
|
||||
* To use: node variants.css.js > variants.css
|
||||
*/
|
||||
const variants = ['neutral', 'brand', 'success', 'warning', 'danger'];
|
||||
const roles = ['fill', 'border', 'on'];
|
||||
const noise = ['loud', 'normal', 'quiet'];
|
||||
const defaults = {
|
||||
neutral: [
|
||||
[':host(wa-button)', '.wa-button', 'button', "input[type='button']", "input[type='submit']"],
|
||||
[':host(wa-tag)', '.wa-tag'],
|
||||
],
|
||||
brand: [
|
||||
[':host(wa-callout)', '.wa-callout'],
|
||||
[':host(wa-badge)', '.wa-badge'],
|
||||
],
|
||||
};
|
||||
const types = roles.map(layer => noise.map(priority => layer + '-' + priority)).flat();
|
||||
|
||||
let ret = comment('Do not edit this file directly. It is generated via variants.css.js').trimStart();
|
||||
|
||||
ret += comment('Register color properties so that the space toggle hack can work.');
|
||||
|
||||
for (let type of types) {
|
||||
ret += cssRule(`@property --wa-color-${type}`, [
|
||||
`syntax: '<color>';`,
|
||||
'inherits: true;',
|
||||
'initial-value: transparent;',
|
||||
]);
|
||||
}
|
||||
|
||||
ret += comment(`Element defaults.
|
||||
We want these to resolve to inherit when inside a variant, and only be applied when not inside an explicit variant.`);
|
||||
|
||||
for (let variant in defaults) {
|
||||
let selector = defaults[variant];
|
||||
let declarations = types.map(type => `--wa-color-${type}: var(--wa-no-variant, var(--wa-color-${variant}-${type}));`);
|
||||
|
||||
ret += cssRule(selector, declarations);
|
||||
}
|
||||
|
||||
ret += comment('Variants');
|
||||
|
||||
for (let variant of variants) {
|
||||
let selector = [`.wa-${variant}`, `:host([variant='${variant}'])`];
|
||||
|
||||
if (variant === 'neutral') {
|
||||
selector.unshift(':root');
|
||||
}
|
||||
|
||||
let declarations = types.map(type => `--wa-color-${type}: var(--wa-color-${variant}-${type});`);
|
||||
ret += cssRule(selector, declarations);
|
||||
}
|
||||
|
||||
ret += cssRule([variants.map(variant => `.wa-${variant}`), ':host([variant])'], '--wa-no-variant: /* space toggle */;');
|
||||
|
||||
console.log(ret.trimEnd());
|
||||
|
||||
function cssRule(selector, declarations) {
|
||||
selector = Array.isArray(selector) ? selector.flat().join(',\n') : selector;
|
||||
declarations = Array.isArray(declarations) ? declarations.flat().join('\n') : declarations;
|
||||
declarations = declarations.replace(/^/gm, ' ');
|
||||
return `\n${selector} {\n${declarations}\n}\n`;
|
||||
}
|
||||
|
||||
function comment(text) {
|
||||
return ['\n/**', ` * ${text}`, ' */\n'].join('\n');
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
{% set suffixes = [
|
||||
'fill-loud', 'fill-normal', 'fill-quiet',
|
||||
'border-loud', 'border-normal', 'border-quiet',
|
||||
'on-loud', 'on-normal', 'on-quiet'
|
||||
] -%}
|
||||
|
||||
/**
|
||||
* Register color properties so that the space toggle hack can work.
|
||||
*/
|
||||
{% for suffix in suffixes %}
|
||||
@property --wa-color-{{ suffix }} {
|
||||
syntax: '<color>';
|
||||
inherits: true;
|
||||
initial-value: transparent;
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
/**
|
||||
* Element defaults.
|
||||
We want these to resolve to inherit when inside a variant, and only be applied when not inside an explicit variant.
|
||||
*/
|
||||
:host(wa-button), .wa-button, button, input[type='button'], input[type='submit'],
|
||||
:host(wa-tag), .wa-tag {
|
||||
{%- for suffix in suffixes %}
|
||||
--wa-color-{{ suffix }}: var(--wa-no-variant, var(--wa-color-neutral-{{ suffix }}));
|
||||
{%- endfor %}
|
||||
}
|
||||
|
||||
:host(wa-callout), .wa-callout,
|
||||
:host(wa-badge), .wa-badge {
|
||||
{%- for suffix in suffixes %}
|
||||
--wa-color-{{ suffix }}: var(--wa-no-variant, var(--wa-color-brand-{{ suffix }}));
|
||||
{%- endfor %}
|
||||
}
|
||||
|
||||
/**
|
||||
* Variants
|
||||
*/
|
||||
{% for variant in variants %}
|
||||
{{ ':root,' if variant === 'neutral' }}
|
||||
.wa-{{ variant }},
|
||||
:host([variant='{{ variant }}']) {
|
||||
{%- for suffix in suffixes %}
|
||||
--wa-color-{{ suffix }}: var(--wa-color-{{ variant }}-{{ suffix }});
|
||||
{%- endfor %}
|
||||
}
|
||||
{%- endfor %}
|
||||
|
||||
{% for variant in variants %}
|
||||
.wa-{{ variant }},
|
||||
{%- endfor %}
|
||||
:host([variant]) {
|
||||
--wa-no-variant: /* space toggle */;
|
||||
}
|
||||
Reference in New Issue
Block a user