mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-19 15:34:15 +00:00
Compare commits
30 Commits
preprocss
...
docs-card-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac376afbaa | ||
|
|
1283a696a5 | ||
|
|
d12b97b0b0 | ||
|
|
e5c2884880 | ||
|
|
1d600a77c4 | ||
|
|
db3c568ba2 | ||
|
|
4bb9805ba6 | ||
|
|
bd935fa8d5 | ||
|
|
c3e582b47b | ||
|
|
4d094a4e19 | ||
|
|
782c404bdf | ||
|
|
f1438981b2 | ||
|
|
18b88c2f5c | ||
|
|
a2d85f49a3 | ||
|
|
be00026cd3 | ||
|
|
58ed88bc5a | ||
|
|
1d14e186f3 | ||
|
|
5f672aabc2 | ||
|
|
db08e12a32 | ||
|
|
e0fc639226 | ||
|
|
e6c662b543 | ||
|
|
d1de9a9a73 | ||
|
|
4931de8eb4 | ||
|
|
71e7227763 | ||
|
|
dd671e15aa | ||
|
|
2daeea0349 | ||
|
|
3cb6625c1d | ||
|
|
c4b5446d01 | ||
|
|
41affca083 | ||
|
|
132dbfabcc |
@@ -1 +1 @@
|
|||||||
["red", "yellow", "green", "cyan", "blue", "indigo", "purple", "pink", "gray"]
|
["red", "orange", "yellow", "green", "cyan", "blue", "indigo", "purple", "pink", "gray"]
|
||||||
|
|||||||
@@ -18,11 +18,15 @@
|
|||||||
tweaking: tweaking.chroma,
|
tweaking: tweaking.chroma,
|
||||||
'tweaking-chroma': tweaking.chroma,
|
'tweaking-chroma': tweaking.chroma,
|
||||||
'tweaking-hue': tweaking.chroma,
|
'tweaking-hue': tweaking.chroma,
|
||||||
'tweaked-chroma': tweaked.chroma,
|
'tweaking-gray-chroma': tweaking.grayChroma,
|
||||||
'tweaked-hue': tweaked.hue,
|
'tweaked-chroma': tweaked?.chroma,
|
||||||
'tweaked-any': tweaked.chroma || tweaked.hue
|
'tweaked-hue': tweaked?.hue,
|
||||||
|
'tweaked-any': tweaked
|
||||||
}"
|
}"
|
||||||
:style="{ '--chroma-scale': chromaScale }">
|
:style="{
|
||||||
|
'--chroma-scale': chromaScale,
|
||||||
|
'--gray-chroma': tweaked?.grayChroma ? grayChroma : '',
|
||||||
|
}">
|
||||||
|
|
||||||
{% include 'breadcrumbs.njk' %}
|
{% include 'breadcrumbs.njk' %}
|
||||||
|
|
||||||
@@ -36,6 +40,9 @@
|
|||||||
<div class="block-info">
|
<div class="block-info">
|
||||||
<code class="class">.wa-palette-{{ paletteId }}</code>
|
<code class="class">.wa-palette-{{ paletteId }}</code>
|
||||||
{% include '../_includes/status.njk' %}
|
{% include '../_includes/status.njk' %}
|
||||||
|
{% if not isPro %}
|
||||||
|
<wa-badge class="pro" v-if="tweaked">PRO</wa-badge>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if description %}
|
{% if description %}
|
||||||
<p class="summary">
|
<p class="summary">
|
||||||
@@ -48,18 +55,20 @@
|
|||||||
|
|
||||||
{% set maxChroma = 0 %}
|
{% set maxChroma = 0 %}
|
||||||
|
|
||||||
<wa-callout size="small" class="tweaked-callout" variant="brand">
|
<wa-callout size="small" class="tweaked-callout" variant="warning">
|
||||||
<wa-icon name="sliders-simple" slot="icon" variant="regular"></wa-icon>
|
<wa-icon name="sliders-simple" slot="icon" variant="regular"></wa-icon>
|
||||||
This palette has been tweaked.
|
This palette has been tweaked.
|
||||||
<wa-tag v-for="tweakHumanReadable, param in tweaksHumanReadable" removable @wa-remove="removeTweak(param)">{% raw %}{{ tweakHumanReadable }}{% endraw %}</wa-tag>
|
<div class="wa-cluster wa-gap-xs">
|
||||||
|
<wa-tag v-for="tweakHumanReadable, param in tweaksHumanReadable" removable @wa-remove="reset(param)">{% raw %}{{ tweakHumanReadable }}{% endraw %}</wa-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
<wa-button @click="reset" appearance="outlined">
|
<wa-button @click="reset()" appearance="outlined" variant="danger">
|
||||||
<span slot="prefix" class="icon-modifier">
|
<span slot="prefix" class="icon-modifier">
|
||||||
<wa-icon name="circle-xmark" variant="regular"></wa-icon>
|
<wa-icon name="circle-xmark" variant="regular"></wa-icon>
|
||||||
</span>
|
</span>
|
||||||
Reset
|
Reset
|
||||||
</wa-button>
|
</wa-button>
|
||||||
<wa-button v-if="!saved" @click="save">
|
<wa-button v-if="!saved" @click="save" variant="success">
|
||||||
<span slot="prefix" class="icon-modifier">
|
<span slot="prefix" class="icon-modifier">
|
||||||
<wa-icon name="sidebar" variant="regular"></wa-icon>
|
<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>
|
<wa-icon name="circle-plus" class="modifier" style="color: light-dark(var(--wa-color-green-70), var(--wa-color-green-60));"></wa-icon>
|
||||||
@@ -81,25 +90,67 @@
|
|||||||
{# Initialize to last hue before gray #}
|
{# Initialize to last hue before gray #}
|
||||||
{%- set hueBefore = hues[hues|length - 2] -%}
|
{%- set hueBefore = hues[hues|length - 2] -%}
|
||||||
{% for hue in hues -%}
|
{% for hue in hues -%}
|
||||||
{%- set coreColor = palettes[paletteId][hue][palettes[paletteId][hue].maxChromaTint] -%}
|
{% set coreTint = palettes[paletteId][hue].maxChromaTint %}
|
||||||
|
{%- set coreColor = palettes[paletteId][hue][coreTint] -%}
|
||||||
{%- set maxChroma = coreColor.c if coreColor.c > maxChroma else maxChroma -%}
|
{%- set maxChroma = coreColor.c if coreColor.c > maxChroma else maxChroma -%}
|
||||||
<tr data-hue="{{ hue }}" class="color-scale" :class="{tweaking: tweaking.{{ hue }}, tweaked: hueShifts.{{ hue }} }"
|
{% if hue === 'gray' %}
|
||||||
|
<tr data-hue="{{ hue }}" class="color-scale"
|
||||||
|
:class="{tweaking: tweaking.grayChroma, tweaked: tweaked.grayChroma || tweaked.grayColor }">
|
||||||
|
{% else %}
|
||||||
|
<tr data-hue="{{ hue }}" class="color-scale"
|
||||||
|
:class="{tweaking: tweaking.{{ hue }}, tweaked: hueShifts.{{ hue }} }"
|
||||||
:style="{ '--hue-shift': hueShifts.{{ hue }} || '' }">
|
:style="{ '--hue-shift': hueShifts.{{ hue }} || '' }">
|
||||||
|
{% endif %}
|
||||||
<th>
|
<th>
|
||||||
{{ hue | capitalize }}
|
{{ hue | capitalize }}
|
||||||
</th>
|
</th>
|
||||||
<td class="core-column" style="--color: var(--wa-color-{{ hue }})">
|
<td class="core-column"
|
||||||
{% if hue !== 'gray' %}
|
style="--color: var(--wa-color-{{ hue }})"
|
||||||
{%- set hueAfter = hues[loop.index0 + 1] -%}
|
:style="{
|
||||||
{%- set hueAfter = hues[0] if hueAfter == 'gray' else hueAfter -%}
|
'--color-tweaked': colors.{{ hue }}[{{ coreTint }}],
|
||||||
{%- set minShift = hueRanges[hue].min - coreColor.h | round -%}
|
'--color-gray-undertone': colors[grayColor][{{coreTint}}],
|
||||||
{%- set maxShift = hueRanges[hue].max - coreColor.h | round -%}
|
'--color-tweaked-no-gray-chroma': colorsMinusGrayChroma.{{ hue }}[{{ coreTint }}],
|
||||||
|
}">
|
||||||
<wa-dropdown>
|
<wa-dropdown>
|
||||||
<div slot="trigger" id="core-{{ hue }}-swatch" data-tint="core" class="color swatch" style="background-color: var(--wa-color-{{ hue }}); color: var(--wa-color-{{ hue }}-{{ '05' if palettes[paletteId][hue].maxChromaTint > 60 else '95' }});">
|
<div slot="trigger" id="core-{{ hue }}-swatch" data-tint="core" class="color swatch"
|
||||||
{{ palettes[paletteId][hue].maxChromaTint }}
|
style="background-color: var(--wa-color-{{ hue }}); color: var(--wa-color-{{ hue }}-{{ '05' if palettes[paletteId][hue].maxChromaTint > 60 else '95' }});"
|
||||||
<wa-icon name="sliders-simple" class="tweak-icon"></wa-icon>
|
>
|
||||||
</div>
|
{{ palettes[paletteId][hue].maxChromaTint }}
|
||||||
<div class="popup">
|
<wa-icon name="sliders-simple" class="tweak-icon"></wa-icon>
|
||||||
|
</div>
|
||||||
|
<div class="popup">
|
||||||
|
{% if hue === 'gray' %}
|
||||||
|
<wa-radio-group class="core-color" orientation="horizontal" v-model="grayColor">
|
||||||
|
{% for h in hues -%}
|
||||||
|
{%- if h !== 'gray' -%}
|
||||||
|
<wa-radio-button id="gray-undertone-{{ h }}" value="{{ h }}" label="{{ h | capitalize }}" style="--color: var(--wa-color-{{ h }})"></wa-radio-button>
|
||||||
|
<wa-tooltip for="gray-undertone-{{ h }}" hoist>
|
||||||
|
{{ h | capitalize }}
|
||||||
|
</wa-tooltip>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
<div slot="label">
|
||||||
|
Gray undertone
|
||||||
|
</div>
|
||||||
|
</wa-radio-group>
|
||||||
|
<div class="decorated-slider gray-chroma-slider" :style="{'--max': maxGrayChroma}">
|
||||||
|
<wa-slider name="gray-chroma" v-model="grayChroma" ref="grayChromaSlider"
|
||||||
|
value="0" min="0" :max="maxGrayChroma" step="0.01"
|
||||||
|
@input="tweaking.grayChroma = true" @change="tweaking.grayChroma = false">
|
||||||
|
<div slot="label">
|
||||||
|
Gray colorfulness
|
||||||
|
<wa-icon-button @click="grayChroma = originalGrayChroma" class="clear-button" name="circle-xmark" library="system" variant="regular" label="Reset"></wa-icon-button>
|
||||||
|
</div>
|
||||||
|
</wa-slider>
|
||||||
|
<div class="label-min">Neutral</div>
|
||||||
|
<div class="label-max" v-content="moreHue[grayColor]">Warmer/Cooler</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{%- set hueAfter = hues[loop.index0 + 1] -%}
|
||||||
|
{%- set hueAfter = hues[0] if hueAfter == 'gray' else hueAfter -%}
|
||||||
|
{%- set minShift = hueRanges[hue].min - coreColor.h | round -%}
|
||||||
|
{%- set maxShift = hueRanges[hue].max - coreColor.h | round -%}
|
||||||
|
|
||||||
<div class="decorated-slider hue-shift-slider" style="--min: {{ minShift }}; --max: {{ maxShift }};">
|
<div class="decorated-slider hue-shift-slider" style="--min: {{ minShift }}; --max: {{ maxShift }};">
|
||||||
<wa-slider name="{{ hue }}-shift" v-model="hueShifts.{{ hue }}" value="0"
|
<wa-slider name="{{ hue }}-shift" v-model="hueShifts.{{ hue }}" value="0"
|
||||||
min="{{ minShift }}" max="{{ maxShift }}" step="1"
|
min="{{ minShift }}" max="{{ maxShift }}" step="1"
|
||||||
@@ -113,23 +164,23 @@
|
|||||||
<div class="label-min">More {{hueBefore}}</div>
|
<div class="label-min">More {{hueBefore}}</div>
|
||||||
<div class="label-max">More {{hueAfter}}</div>
|
<div class="label-max">More {{hueAfter}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
{%- set hueBefore = hue -%}
|
||||||
|
{% endif %}
|
||||||
<div class="wa-gap-s">
|
<div class="wa-gap-s">
|
||||||
<code>--wa-color-{{ hue }}</code>
|
<code>--wa-color-{{ hue }}</code>
|
||||||
<wa-copy-button value="--wa-color-{{ hue }}" copy-label="--wa-color-{{ hue }}"></wa-copy-button>
|
<wa-copy-button value="--wa-color-{{ hue }}" copy-label="--wa-color-{{ hue }}"></wa-copy-button>
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`
|
||||||
</wa-dropdown>
|
</wa-dropdown>
|
||||||
{%- set hueBefore = hue -%}
|
|
||||||
{% else %}
|
|
||||||
<div id="core-{{ hue }}-swatch" class="color swatch" data-tint="core" style="background-color: var(--wa-color-{{ hue }}); color: var(--wa-color-{{ hue }}-{{ '05' if palettes[paletteId][hue].maxChromaTint > 60 else '95' }});">
|
|
||||||
{{ palettes[paletteId][hue].maxChromaTint }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
</td>
|
||||||
{% for tint in tints -%}
|
{% for tint in tints -%}
|
||||||
{%- set color = palettes[paletteId][hue][tint] -%}
|
{%- set color = palettes[paletteId][hue][tint] -%}
|
||||||
<td data-tint="{{ tint }}" style="--color: var(--wa-color-{{ hue }}-{{ tint }})">
|
<td data-tint="{{ tint }}" style="--color: var(--wa-color-{{ hue }}-{{ tint }})"
|
||||||
<div class="color swatch" style="background-color: var(--wa-color-{{ hue }}-{{ tint }})">
|
:style="{
|
||||||
|
'--color-tweaked': colors.{{ hue }}[{{ tint }}],
|
||||||
|
'--color-tweaked-no-gray-chroma': colorsMinusGrayChroma.{{ hue }}[{{ tint }}],
|
||||||
|
}">
|
||||||
|
<div class="color swatch" style="--color: var(--wa-color-{{ hue }}-{{ tint }})">
|
||||||
<wa-copy-button value="--wa-color-{{ hue }}-{{ tint }}" copy-label="--wa-color-{{ hue }}-{{ tint }}"></wa-copy-button>
|
<wa-copy-button value="--wa-color-{{ hue }}-{{ tint }}" copy-label="--wa-color-{{ hue }}-{{ tint }}"></wa-copy-button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -144,7 +195,8 @@
|
|||||||
<div class="decorated-slider chroma-scale-slider wa-palette-{{ paletteId }}"
|
<div class="decorated-slider chroma-scale-slider wa-palette-{{ paletteId }}"
|
||||||
:class="{ tweaked: chromaScale !== 1 }"
|
:class="{ tweaked: chromaScale !== 1 }"
|
||||||
style="--min: {{ chromaScaleBounds[0] }}; --max: {{ chromaScaleBounds[1] }};">
|
style="--min: {{ chromaScaleBounds[0] }}; --max: {{ chromaScaleBounds[1] }};">
|
||||||
<wa-slider name="chroma-scale" v-model="chromaScale" value="1" step="0.01"
|
<wa-slider name="chroma-scale" ref="chromaScaleSlider"
|
||||||
|
v-model="chromaScale" value="1" step="0.01"
|
||||||
min="{{ chromaScaleBounds[0] }}" max="{{ chromaScaleBounds[1] }}"
|
min="{{ chromaScaleBounds[0] }}" max="{{ chromaScaleBounds[1] }}"
|
||||||
@input="tweaking.chroma = true"
|
@input="tweaking.chroma = true"
|
||||||
@change="tweaking.chroma = false">
|
@change="tweaking.chroma = false">
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ sidebar.palettes = {
|
|||||||
sidebar.updateCurrent();
|
sidebar.updateCurrent();
|
||||||
},
|
},
|
||||||
|
|
||||||
saved: localStorage.savedPalettes ? JSON.parse(localStorage.savedPalettes) : [],
|
updateSaved() {
|
||||||
|
this.saved = localStorage.savedPalettes ? JSON.parse(localStorage.savedPalettes) : [];
|
||||||
|
},
|
||||||
|
|
||||||
save(saved = this.saved) {
|
save(saved = this.saved) {
|
||||||
this.saved = saved ?? [];
|
this.saved = saved ?? [];
|
||||||
@@ -26,6 +28,9 @@ sidebar.palettes = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sidebar.palettes.updateSaved();
|
||||||
|
addEventListener('storage', event => sidebar.palettes.updateSaved());
|
||||||
|
|
||||||
sidebar.palette = {
|
sidebar.palette = {
|
||||||
getUid() {
|
getUid() {
|
||||||
let savedPalettes = sidebar.palettes.saved;
|
let savedPalettes = sidebar.palettes.saved;
|
||||||
@@ -36,7 +41,7 @@ sidebar.palette = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find first available number
|
// Find first available number
|
||||||
for (let i = 1; i < savedPalettes.length + 1; i++) {
|
for (let i = 1; i <= savedPalettes.length + 1; i++) {
|
||||||
if (!uids.has(i)) {
|
if (!uids.has(i)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@@ -94,7 +99,7 @@ sidebar.palette = {
|
|||||||
sidebar.palettes.save(savedPalettes);
|
sidebar.palettes.save(savedPalettes);
|
||||||
|
|
||||||
if (sidebar.palette.equals(globalThis.paletteApp?.saved, palette)) {
|
if (sidebar.palette.equals(globalThis.paletteApp?.saved, palette)) {
|
||||||
paletteApp.saved = null;
|
paletteApp.postDelete();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -184,18 +189,52 @@ sidebar.updateCurrent = function () {
|
|||||||
|
|
||||||
// We want to start from the longest prefix
|
// We want to start from the longest prefix
|
||||||
prefixes.reverse();
|
prefixes.reverse();
|
||||||
|
let candidates;
|
||||||
|
let matchingPrefix;
|
||||||
|
|
||||||
for (let prefix of prefixes) {
|
for (let prefix of prefixes) {
|
||||||
let a = document.querySelector(`#sidebar a[href^="${prefix}"]`);
|
candidates = document.querySelectorAll(`#sidebar a[href^="${prefix}"]`);
|
||||||
|
|
||||||
if (a) {
|
if (candidates.length > 0) {
|
||||||
for (let current of document.querySelectorAll('#sidebar a.current')) {
|
matchingPrefix = prefix;
|
||||||
current.classList.remove('current');
|
|
||||||
}
|
|
||||||
a.classList.add('current');
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!matchingPrefix) {
|
||||||
|
// Abort mission
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchingPrefix === pathParts.at(-1)) {
|
||||||
|
// Full path matches, check search
|
||||||
|
if (location.search) {
|
||||||
|
candidates = [...candidates];
|
||||||
|
|
||||||
|
let searchParams = new URLSearchParams(location.search);
|
||||||
|
|
||||||
|
if (searchParams.has('uid')) {
|
||||||
|
// Only consider candidates with the same uid
|
||||||
|
candidates = candidates.filter(a => {
|
||||||
|
let params = new URLSearchParams(a.search);
|
||||||
|
return params.get('uid') === searchParams.get('uid');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Sort candidates based on how many params they have in common, in descending order
|
||||||
|
candidates = candidates.sort((a, b) => {
|
||||||
|
return countSharedSearchParams(searchParams, b.search) - countSharedSearchParams(searchParams, a.search);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (candidates.length > 0) {
|
||||||
|
for (let current of document.querySelectorAll('#sidebar a.current')) {
|
||||||
|
current.classList.remove('current');
|
||||||
|
}
|
||||||
|
|
||||||
|
candidates[0].classList.add('current');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sidebar.render = function () {
|
sidebar.render = function () {
|
||||||
@@ -204,3 +243,12 @@ sidebar.render = function () {
|
|||||||
|
|
||||||
sidebar.render();
|
sidebar.render();
|
||||||
window.addEventListener('turbo:render', () => sidebar.render());
|
window.addEventListener('turbo:render', () => sidebar.render());
|
||||||
|
|
||||||
|
function countSharedSearchParams(searchParams, search) {
|
||||||
|
if (!search || search === '?') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let params = new URLSearchParams(search);
|
||||||
|
return [...searchParams.keys()].filter(k => params.get(k) === searchParams.get(k)).length;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Get import code for remixed themes and tweaked palettes.
|
* Get import code for remixed themes and tweaked palettes.
|
||||||
*/
|
*/
|
||||||
export { theme as getThemeCode } from './tweak/code.js';
|
export { getThemeCode } from './tweak/code.js';
|
||||||
export { cdnUrl, hueRanges, hues, selectors, tints, urls } from './tweak/data.js';
|
export { cdnUrl, hueRanges, hues, selectors, tints, urls } from './tweak/data.js';
|
||||||
export { default as Permalink } from './tweak/permalink.js';
|
export { default as Permalink } from './tweak/permalink.js';
|
||||||
|
|||||||
@@ -25,18 +25,23 @@ export function cssLiteral(value, options = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function theme(base, params, options) {
|
// Params in correct order
|
||||||
|
export const themeParams = ['colors', 'palette', 'brand', 'typography'];
|
||||||
|
|
||||||
|
export function getThemeCode(base, params, options) {
|
||||||
let ret = [];
|
let ret = [];
|
||||||
|
|
||||||
if (base) {
|
if (base) {
|
||||||
ret.push(urls.theme(base));
|
ret.push(urls.theme(base));
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.push(
|
for (let aspect of themeParams) {
|
||||||
...Object.entries(params)
|
let value = params[aspect];
|
||||||
.filter(([aspect, id]) => Boolean(id))
|
|
||||||
.map(([aspect, id]) => urls[aspect](id)),
|
if (value) {
|
||||||
);
|
ret.push(urls[aspect](value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret.map(url => cssImport(url, options)).join('\n');
|
return ret.map(url => cssImport(url, options)).join('\n');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,45 @@ export const hueRanges = {
|
|||||||
pink: { min: 320, max: 365 }, // 45
|
pink: { min: 320, max: 365 }, // 45
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const moreHue = {
|
||||||
|
red: 'Redder',
|
||||||
|
orange: 'More orange', // https://www.reddit.com/r/grammar/comments/u9n0uo/is_it_oranger_or_more_orange/
|
||||||
|
yellow: 'Yellower',
|
||||||
|
green: 'Greener',
|
||||||
|
cyan: 'More cyan',
|
||||||
|
blue: 'Bluer',
|
||||||
|
indigo: 'More indigo',
|
||||||
|
pink: 'Pinker',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max gray chroma (% of chroma of undertone) per hue
|
||||||
|
*/
|
||||||
|
export const maxGrayChroma = {
|
||||||
|
red: 0.2,
|
||||||
|
orange: 0.2,
|
||||||
|
yellow: 0.25,
|
||||||
|
green: 0.25,
|
||||||
|
cyan: 0.3,
|
||||||
|
blue: 0.35,
|
||||||
|
indigo: 0.35,
|
||||||
|
purple: 0.3,
|
||||||
|
pink: 0.25,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const docsURLs = {
|
||||||
|
colors: '/docs/themes/',
|
||||||
|
palette: '/docs/palettes/',
|
||||||
|
typography: '/docs/themes/',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const icons = {
|
||||||
|
colors: 'palette',
|
||||||
|
palette: 'swatchbook',
|
||||||
|
brand: 'droplet',
|
||||||
|
typography: 'font-case',
|
||||||
|
};
|
||||||
|
|
||||||
export const hues = Object.keys(hueRanges);
|
export const hues = Object.keys(hueRanges);
|
||||||
|
|
||||||
export const tints = ['05', '10', '20', '30', '40', '50', '60', '70', '80', '90', '95'];
|
export const tints = ['05', '10', '20', '30', '40', '50', '60', '70', '80', '90', '95'];
|
||||||
|
|||||||
36
docs/assets/scripts/tweak/util.js
Normal file
36
docs/assets/scripts/tweak/util.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
export function normalizeAngles(angles) {
|
||||||
|
// First, normalize
|
||||||
|
angles = angles.map(h => ((h % 360) + 360) % 360);
|
||||||
|
|
||||||
|
// Remove top and bottom 25% and find average
|
||||||
|
let averageHue =
|
||||||
|
angles
|
||||||
|
.toSorted((a, b) => a - b)
|
||||||
|
.slice(angles.length / 4, -angles.length / 4)
|
||||||
|
.reduce((a, b) => a + b, 0) / angles.length;
|
||||||
|
|
||||||
|
for (let i = 0; i < angles.length; i++) {
|
||||||
|
let h = angles[i];
|
||||||
|
let prevHue = angles[i - 1];
|
||||||
|
let delta = h - prevHue;
|
||||||
|
|
||||||
|
if (Math.abs(delta) > 180) {
|
||||||
|
let equivalent = [h + 360, h - 360];
|
||||||
|
// Offset hue to minimize difference in the direction that brings it closer to the average
|
||||||
|
let delta = h - averageHue;
|
||||||
|
|
||||||
|
if (Math.abs(equivalent[0] - prevHue) <= Math.abs(equivalent[1] - prevHue)) {
|
||||||
|
angles[i] = equivalent[0];
|
||||||
|
} else {
|
||||||
|
angles[i] = equivalent[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return angles;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function subtractAngles(θ1, θ2) {
|
||||||
|
let [a, b] = normalizeAngles([θ1, θ2]);
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
@@ -19,13 +19,13 @@ icon: card
|
|||||||
|
|
||||||
<div slot="footer">
|
<div slot="footer">
|
||||||
<wa-button variant="brand" pill>More Info</wa-button>
|
<wa-button variant="brand" pill>More Info</wa-button>
|
||||||
<wa-rating></wa-rating>
|
<wa-rating label="Rating"></wa-rating>
|
||||||
</div>
|
</div>
|
||||||
</wa-card>
|
</wa-card>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.card-overview {
|
.card-overview {
|
||||||
max-width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-overview small {
|
.card-overview small {
|
||||||
|
|||||||
@@ -42,6 +42,14 @@ wa-code-demo::part(preview) {
|
|||||||
<wa-input label="WA Input (url)" type="url"></wa-input>
|
<wa-input label="WA Input (url)" type="url"></wa-input>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Pill shaped text fields
|
||||||
|
|
||||||
|
Add the `wa-pill` class to an `<input>` to make it pill-shaped.
|
||||||
|
|
||||||
|
```html {.example}
|
||||||
|
<label>Input <input type="text" placeholder="placeholder" class="wa-pill"></label>
|
||||||
|
```
|
||||||
|
|
||||||
## Color Picker
|
## Color Picker
|
||||||
|
|
||||||
Basic:
|
Basic:
|
||||||
|
|||||||
@@ -25,9 +25,16 @@ wa-dropdown > .color.swatch {
|
|||||||
--track-color-inactive: transparent;
|
--track-color-inactive: transparent;
|
||||||
--track-color-active: transparent;
|
--track-color-active: transparent;
|
||||||
--thumb-color: var(--color-tweaked, var(--color));
|
--thumb-color: var(--color-tweaked, var(--color));
|
||||||
|
--thumb-shadow: 0 0 0 var(--thumb-gap) var(--wa-color-surface-default),
|
||||||
|
var(--wa-shadow-offset-x-m) var(--wa-shadow-offset-y-m) var(--wa-shadow-blur-m)
|
||||||
|
calc(var(--wa-shadow-offset-x-m) * -1 + var(--thumb-gap)) var(--wa-color-shadow);
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
--thumb-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
&::part(base) {
|
&::part(base) {
|
||||||
background: linear-gradient(to right in oklch, var(--color-1), var(--color-2));
|
background: linear-gradient(to right in var(--color-interpolation-space, oklab), var(--color-1), var(--color-2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,13 +70,20 @@ wa-dropdown > .color.swatch {
|
|||||||
.hue-shift-slider {
|
.hue-shift-slider {
|
||||||
--color-1: oklch(from var(--color) l c calc(h + var(--min, 0)));
|
--color-1: oklch(from var(--color) l c calc(h + var(--min, 0)));
|
||||||
--color-2: oklch(from var(--color) l c calc(h + var(--max, 0)));
|
--color-2: oklch(from var(--color) l c calc(h + var(--max, 0)));
|
||||||
|
--color-interpolation-space: oklch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chroma-scale-slider {
|
.chroma-scale-slider {
|
||||||
--color: var(--wa-color-brand);
|
--color: var(--wa-color-brand);
|
||||||
--color-1: oklch(from var(--color) l calc(c * var(--min)) h);
|
--color-1: oklch(from var(--color) l calc(c * var(--min)) h);
|
||||||
--color-2: oklch(from var(--color) l calc(c * var(--max)) h);
|
--color-2: oklch(from var(--color) l calc(c * var(--max)) h);
|
||||||
--color-tweaked: oklch(from var(--color) l calc(c * var(--chroma-scale)) h);
|
}
|
||||||
|
|
||||||
|
.gray-chroma-slider {
|
||||||
|
--color: var(--wa-color-gray);
|
||||||
|
--color-1: oklch(from var(--wa-color-gray) l 0 none);
|
||||||
|
--color-2: oklch(from var(--color-gray-undertone) l calc(c * var(--max)) h);
|
||||||
|
margin-top: var(--wa-space-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup {
|
.popup {
|
||||||
@@ -91,13 +105,13 @@ wa-dropdown > .color.swatch {
|
|||||||
td:not([data-hue='gray'] *) {
|
td:not([data-hue='gray'] *) {
|
||||||
--tweak-c: calc(c * var(--chroma-scale, 1));
|
--tweak-c: calc(c * var(--chroma-scale, 1));
|
||||||
--tweak-h: calc(h + var(--hue-shift, 0));
|
--tweak-h: calc(h + var(--hue-shift, 0));
|
||||||
--color-tweaked: oklch(from var(--color) l var(--tweak-c) var(--tweak-h));
|
|
||||||
--color-tweaked-no-chroma-scale: oklch(from var(--color) l c var(--tweak-h));
|
--color-tweaked-no-chroma-scale: oklch(from var(--color) l c var(--tweak-h));
|
||||||
--color-tweaked-no-hue-shift: oklch(from var(--color) l var(--tweak-c) h);
|
--color-tweaked-no-hue-shift: oklch(from var(--color) l var(--tweak-c) h);
|
||||||
|
|
||||||
&:is([data-tint='90'], [data-tint='95']) {
|
&:is([data-tint='90'], [data-tint='95']) {
|
||||||
/* Work around https://bugs.webkit.org/show_bug.cgi?id=287637 */
|
/* Work around https://bugs.webkit.org/show_bug.cgi?id=287637 */
|
||||||
--color-tweaked: lch(from var(--color) l var(--tweak-c) var(--tweak-h));
|
|
||||||
--color-tweaked-no-chroma-scale: lch(from var(--color) l c var(--tweak-h));
|
--color-tweaked-no-chroma-scale: lch(from var(--color) l c var(--tweak-h));
|
||||||
--color-tweaked-no-hue-shift: lch(from var(--color) l var(--tweak-c) h);
|
--color-tweaked-no-hue-shift: lch(from var(--color) l var(--tweak-c) h);
|
||||||
|
|
||||||
@@ -111,14 +125,18 @@ wa-dropdown > .color.swatch {
|
|||||||
|
|
||||||
&:is(.tweaking *) {
|
&:is(.tweaking *) {
|
||||||
--color-2-height: 70%;
|
--color-2-height: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
&:is(.tweaking-chroma *) {
|
&:is(.tweaking-chroma *) {
|
||||||
--color: var(--color-tweaked-no-chroma-scale);
|
--color: var(--color-tweaked-no-chroma-scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:is(.tweaking-hue *) {
|
&:is(.tweaking-hue *) {
|
||||||
--color: var(--color-tweaked-no-hue-shift);
|
--color: var(--color-tweaked-no-hue-shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:is(.tweaking-gray-chroma *) {
|
||||||
|
--color: var(--color-tweaked-no-gray-chroma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +177,29 @@ wa-dropdown > .color.swatch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[v-if='saved'] {
|
/* Better UI before Vue initializes */
|
||||||
|
[v-if='saved'],
|
||||||
|
[v-if^='tweaked'] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.core-color {
|
||||||
|
wa-radio-button::part(base) {
|
||||||
|
width: 2em;
|
||||||
|
height: 2em;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: var(--wa-border-radius-circle);
|
||||||
|
background: var(--color);
|
||||||
|
background-clip: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
wa-radio-button:is([checked], :state(checked))::part(base) {
|
||||||
|
box-shadow:
|
||||||
|
inset 0 0 0 var(--indicator-width) var(--indicator-color),
|
||||||
|
inset 0 0 0 calc(var(--indicator-width) + 1.5px) var(--wa-color-surface-default);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::part(form-control-input) {
|
||||||
|
gap: var(--wa-space-xs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import Color from 'https://colorjs.io/dist/color.js';
|
|||||||
import { createApp, nextTick } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.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 { cdnUrl, hueRanges, hues, Permalink, tints } from '../../assets/scripts/tweak.js';
|
||||||
import { cssImport, cssLiteral, cssRule } from '../../assets/scripts/tweak/code.js';
|
import { cssImport, cssLiteral, cssRule } from '../../assets/scripts/tweak/code.js';
|
||||||
import { selectors, urls } from '../../assets/scripts/tweak/data.js';
|
import { maxGrayChroma, moreHue, selectors, urls } from '../../assets/scripts/tweak/data.js';
|
||||||
|
import { subtractAngles } from '../../assets/scripts/tweak/util.js';
|
||||||
import Prism from '/assets/scripts/prism.js';
|
import Prism from '/assets/scripts/prism.js';
|
||||||
|
|
||||||
await Promise.all(['wa-slider'].map(tag => customElements.whenDefined(tag)));
|
await Promise.all(['wa-slider'].map(tag => customElements.whenDefined(tag)));
|
||||||
@@ -34,6 +35,8 @@ for (let palette in allPalettes) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const percentFormatter = value => value.toLocaleString(undefined, { style: 'percent' });
|
||||||
|
|
||||||
let paletteAppSpec = {
|
let paletteAppSpec = {
|
||||||
data() {
|
data() {
|
||||||
let appRoot = document.querySelector('#palette-app');
|
let appRoot = document.querySelector('#palette-app');
|
||||||
@@ -49,12 +52,17 @@ let paletteAppSpec = {
|
|||||||
hueRanges,
|
hueRanges,
|
||||||
hueShifts: Object.fromEntries(hues.map(hue => [hue, 0])),
|
hueShifts: Object.fromEntries(hues.map(hue => [hue, 0])),
|
||||||
chromaScale: 1,
|
chromaScale: 1,
|
||||||
|
grayChroma: undefined,
|
||||||
|
grayColor: undefined,
|
||||||
tweaking: {},
|
tweaking: {},
|
||||||
saved: null,
|
saved: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
|
// Non-reactive variables to expose
|
||||||
|
Object.assign(this, { moreHue });
|
||||||
|
|
||||||
// Read URL params and apply them. This facilitates permalinks.
|
// Read URL params and apply them. This facilitates permalinks.
|
||||||
this.permalink.mapObject(this.hueShifts, {
|
this.permalink.mapObject(this.hueShifts, {
|
||||||
keyTo: key => key.replace(/-shift$/, ''),
|
keyTo: key => key.replace(/-shift$/, ''),
|
||||||
@@ -63,30 +71,49 @@ let paletteAppSpec = {
|
|||||||
valueTo: value => (!value ? 0 : Number(value)),
|
valueTo: value => (!value ? 0 : Number(value)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.grayChroma = this.originalGrayChroma;
|
||||||
|
this.grayColor = this.originalGrayColor;
|
||||||
|
|
||||||
if (location.search) {
|
if (location.search) {
|
||||||
// Update from URL
|
// Update from URL
|
||||||
this.permalink.writeTo(this.hueShifts);
|
this.permalink.writeTo(this.hueShifts);
|
||||||
|
|
||||||
if (this.permalink.has('chroma-scale')) {
|
for (let param of ['chroma-scale', 'gray-color', 'gray-chroma']) {
|
||||||
this.chromaScale = Number(this.permalink.get('chroma-scale') || 1);
|
if (this.permalink.has(param)) {
|
||||||
|
let value = this.permalink.get(param);
|
||||||
|
|
||||||
|
if (!isNaN(value)) {
|
||||||
|
// Convert numeric values to numbers
|
||||||
|
value = Number(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
let prop = camelCase(param);
|
||||||
|
this[prop] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.permalink.has('uid')) {
|
if (this.permalink.has('uid')) {
|
||||||
this.uid = Number(this.permalink.get('uid'));
|
this.uid = Number(this.permalink.get('uid'));
|
||||||
}
|
}
|
||||||
|
|
||||||
let palette = { id: this.paletteId, uid: this.uid, search: location.search };
|
this.saved = sidebar.palette.getSaved(this.getPalette());
|
||||||
this.saved = sidebar.palette.getSaved(palette);
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
for (let ref in this.$refs) {
|
||||||
|
this.$refs[ref].tooltipFormatter = percentFormatter;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
global() {
|
|
||||||
return globalThis;
|
|
||||||
},
|
|
||||||
|
|
||||||
tweaks() {
|
tweaks() {
|
||||||
return { hueShifts: this.hueShifts, chromaScale: this.chromaScale };
|
return {
|
||||||
|
hueShifts: this.hueShifts,
|
||||||
|
chromaScale: this.chromaScale,
|
||||||
|
grayColor: this.grayColor,
|
||||||
|
grayChroma: this.grayChroma,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
isTweaked() {
|
isTweaked() {
|
||||||
@@ -96,7 +123,7 @@ let paletteAppSpec = {
|
|||||||
code() {
|
code() {
|
||||||
let ret = {};
|
let ret = {};
|
||||||
for (let language of ['html', 'css']) {
|
for (let language of ['html', 'css']) {
|
||||||
let code = getPaletteCode(this.paletteId, this.tweaks, { language, cdnUrl });
|
let code = getPaletteCode(this.paletteId, this.colors, this.tweaked, { language, cdnUrl });
|
||||||
ret[language] = {
|
ret[language] = {
|
||||||
raw: code,
|
raw: code,
|
||||||
highlighted: Prism.highlight(code, Prism.languages[language], language),
|
highlighted: Prism.highlight(code, Prism.languages[language], language),
|
||||||
@@ -107,47 +134,46 @@ let paletteAppSpec = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
colors() {
|
colors() {
|
||||||
let ret = {};
|
return applyTweaks.call(this, this.originalColors, this.tweaks, this.tweaked);
|
||||||
|
},
|
||||||
|
|
||||||
for (let hue in this.originalColors) {
|
colorsMinusChromaScale() {
|
||||||
let originalScale = this.originalColors[hue];
|
let tweaked = { ...this.tweaked, chromaScale: false };
|
||||||
let scale = (ret[hue] = {});
|
return applyTweaks.call(this, this.originalColors, this.tweaks, tweaked);
|
||||||
let descriptors = Object.getOwnPropertyDescriptors(originalScale);
|
},
|
||||||
Object.defineProperties(scale, {
|
|
||||||
maxChromaTint: { ...descriptors.maxChromaTint, enumerable: false },
|
|
||||||
maxChromaTintRaw: { ...descriptors.maxChromaTintRaw, enumerable: false },
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let tint of tints) {
|
colorsMinusHueShifts() {
|
||||||
let oklch = originalScale[tint].coords.slice();
|
let tweaked = { ...this.tweaked, hue: false };
|
||||||
|
return applyTweaks.call(this, this.originalColors, this.tweaks, tweaked);
|
||||||
|
},
|
||||||
|
|
||||||
if (this.hueShifts[hue]) {
|
colorsMinusGrayChroma() {
|
||||||
oklch[2] += this.hueShifts[hue];
|
let tweaked = { ...this.tweaked, grayChroma: false };
|
||||||
}
|
return applyTweaks.call(this, this.originalColors, this.tweaks, tweaked);
|
||||||
|
|
||||||
if (this.chromaScale !== 1) {
|
|
||||||
oklch[1] *= this.chromaScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
scale[tint] = new Color('oklch', oklch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
tweaked() {
|
tweaked() {
|
||||||
return {
|
let anyHueTweaked = Object.values(this.hueShifts).some(Boolean);
|
||||||
chroma: this.chromaScale !== 1,
|
let hue = anyHueTweaked
|
||||||
hue: Object.values(this.hueShifts).some(Boolean),
|
? Object.fromEntries(Object.entries(this.hueShifts).map(([hue, shift]) => [hue, shift !== 0]))
|
||||||
|
: false;
|
||||||
|
|
||||||
|
let ret = {
|
||||||
|
chromaScale: this.chromaScale !== 1,
|
||||||
|
hue,
|
||||||
|
grayChroma: this.grayChroma !== this.originalGrayChroma,
|
||||||
|
grayColor: this.grayColor !== this.originalGrayColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let anyTweaked = Object.values(ret).some(Boolean);
|
||||||
|
return anyTweaked ? ret : false;
|
||||||
},
|
},
|
||||||
|
|
||||||
tweaksHumanReadable() {
|
tweaksHumanReadable() {
|
||||||
let ret = {};
|
let ret = {};
|
||||||
|
|
||||||
if (this.chromaScale !== 1) {
|
if (this.chromaScale !== 1) {
|
||||||
ret.chromaScale = 'more ' + (this.chromaScale > 1 ? 'vibrant' : 'muted');
|
ret.chromaScale = 'More ' + (this.chromaScale > 1 ? 'vibrant' : 'muted');
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let hue in this.hueShifts) {
|
for (let hue in this.hueShifts) {
|
||||||
@@ -158,63 +184,99 @@ let paletteAppSpec = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let relHue = shift < 0 ? arrayPrevious(hues, hue) : arrayNext(hues, hue);
|
let relHue = shift < 0 ? arrayPrevious(hues, hue) : arrayNext(hues, hue);
|
||||||
let hueTweak =
|
let hueTweak = moreHue[relHue] ?? relHue + 'er';
|
||||||
{
|
|
||||||
red: 'redder',
|
|
||||||
orange: 'oranger',
|
|
||||||
indigo: 'more indigo',
|
|
||||||
}[relHue] ?? relHue + 'er';
|
|
||||||
|
|
||||||
ret[hue] = hueTweak + ' ' + hue + 's';
|
ret[hue] = capitalize(hueTweak + ' ' + hue + 's');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.tweaked.grayChroma || this.tweaked.grayColor) {
|
||||||
|
if (this.tweaked.grayChroma === 0) {
|
||||||
|
ret.grayChroma = 'Achromatic grays';
|
||||||
|
} else {
|
||||||
|
if (this.tweaked.grayColor) {
|
||||||
|
ret.grayColor = capitalize(this.grayColor) + ' gray undertone';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.tweaked.grayChroma) {
|
||||||
|
let more = this.tweaked.grayChroma > this.originalGrayChroma;
|
||||||
|
ret.grayChroma = `More ${more ? 'colorful' : 'neutral'} grays`;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
||||||
originalContrasts() {
|
originalContrasts() {
|
||||||
|
return getContrasts(this.originalColors);
|
||||||
|
},
|
||||||
|
|
||||||
|
contrasts() {
|
||||||
|
return getContrasts(this.colors, this.originalContrasts);
|
||||||
|
},
|
||||||
|
|
||||||
|
originalCoreColors() {
|
||||||
let ret = {};
|
let ret = {};
|
||||||
|
|
||||||
for (let hue in this.originalColors) {
|
for (let hue in this.originalColors) {
|
||||||
ret[hue] = {};
|
let maxChromaTintRaw = this.originalColors[hue].maxChromaTintRaw;
|
||||||
|
ret[hue] = this.originalColors[hue][maxChromaTintRaw];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
|
||||||
for (let tintBg of tints) {
|
coreColors() {
|
||||||
ret[hue][tintBg] = {};
|
let ret = {};
|
||||||
let bgColor = this.originalColors[hue][tintBg];
|
for (let hue in this.colors) {
|
||||||
|
let maxChromaTintRaw = this.colors[hue].maxChromaTintRaw;
|
||||||
if (!bgColor || !bgColor.contrast) {
|
ret[hue] = this.colors[hue][maxChromaTintRaw];
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let tintFg of tints) {
|
|
||||||
let contrast = bgColor.contrast(this.originalColors[hue][tintFg], 'WCAG21');
|
|
||||||
ret[hue][tintBg][tintFg] = contrast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
||||||
contrasts() {
|
originalGrayColor() {
|
||||||
let ret = {};
|
let grayHue = this.originalCoreColors.gray.get('h');
|
||||||
|
let minDistance = Infinity;
|
||||||
|
let closestHue = null;
|
||||||
|
|
||||||
for (let hue in this.colors) {
|
for (let name in this.originalCoreColors) {
|
||||||
ret[hue] = {};
|
if (name === 'gray') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (let tintBg in this.colors[hue]) {
|
let hue = this.originalCoreColors[name].get('h');
|
||||||
ret[hue][tintBg] = {};
|
let distance = Math.abs(subtractAngles(hue, grayHue));
|
||||||
let bgColor = this.colors[hue][tintBg];
|
if (distance < minDistance) {
|
||||||
|
minDistance = distance;
|
||||||
for (let tintFg in this.colors[hue]) {
|
closestHue = name;
|
||||||
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 };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return closestHue ?? 'indigo';
|
||||||
|
},
|
||||||
|
|
||||||
|
originalGrayChroma() {
|
||||||
|
let coreTint = this.originalColors.gray.maxChromaTint;
|
||||||
|
let grayChroma = this.originalColors.gray[coreTint].get('c');
|
||||||
|
if (grayChroma === 0 || grayChroma === null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let grayColorChroma = this.originalColors[this.originalGrayColor][coreTint].get('c');
|
||||||
|
return grayChroma / grayColorChroma;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We want to preserve the original grayChroma selection so that when the user switches to another undertone
|
||||||
|
* that supports higher chromas, their selection will be there.
|
||||||
|
* This property is the gray chroma % that is actually applied.
|
||||||
|
*/
|
||||||
|
computedGrayChroma() {
|
||||||
|
return Math.min(this.grayChroma, this.maxGrayChroma);
|
||||||
|
},
|
||||||
|
|
||||||
|
maxGrayChroma() {
|
||||||
|
return maxGrayChroma[this.grayColor] ?? 0.3;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -230,6 +292,14 @@ let paletteAppSpec = {
|
|||||||
this.permalink.set('chroma-scale', this.chromaScale, 1);
|
this.permalink.set('chroma-scale', this.chromaScale, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
grayColor() {
|
||||||
|
this.permalink.set('gray-color', this.grayColor, this.originalGrayColor);
|
||||||
|
},
|
||||||
|
|
||||||
|
grayChroma() {
|
||||||
|
this.permalink.set('gray-chroma', this.grayChroma, this.originalGrayChroma);
|
||||||
|
},
|
||||||
|
|
||||||
tweaks: {
|
tweaks: {
|
||||||
deep: true,
|
deep: true,
|
||||||
async handler(value, oldValue) {
|
async handler(value, oldValue) {
|
||||||
@@ -246,6 +316,10 @@ let paletteAppSpec = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
getPalette() {
|
||||||
|
return { id: this.paletteId, uid: this.uid, search: location.search };
|
||||||
|
},
|
||||||
|
|
||||||
save({ silent } = {}) {
|
save({ silent } = {}) {
|
||||||
let title = silent
|
let title = silent
|
||||||
? (this.saved?.title ?? this.paletteTitle)
|
? (this.saved?.title ?? this.paletteTitle)
|
||||||
@@ -258,13 +332,15 @@ let paletteAppSpec = {
|
|||||||
let uid = this.uid;
|
let uid = this.uid;
|
||||||
|
|
||||||
if (!uid) {
|
if (!uid) {
|
||||||
|
// First time saving
|
||||||
this.uid = uid = sidebar.palette.getUid();
|
this.uid = uid = sidebar.palette.getUid();
|
||||||
|
|
||||||
this.permalink.set('uid', uid);
|
this.permalink.set('uid', uid);
|
||||||
this.permalink.updateLocation();
|
this.permalink.updateLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
let palette = { title, id: this.paletteId, uid, search: location.search };
|
let palette = { ...this.getPalette(), uid, title };
|
||||||
|
|
||||||
sidebar.palette.save(palette, this.saved);
|
sidebar.palette.save(palette, this.saved);
|
||||||
this.saved = palette;
|
this.saved = palette;
|
||||||
},
|
},
|
||||||
@@ -286,21 +362,38 @@ let paletteAppSpec = {
|
|||||||
|
|
||||||
deleteSaved() {
|
deleteSaved() {
|
||||||
sidebar.palette.delete(this.saved);
|
sidebar.palette.delete(this.saved);
|
||||||
|
},
|
||||||
|
|
||||||
|
postDelete() {
|
||||||
this.saved = null;
|
this.saved = null;
|
||||||
|
this.permalink.delete('uid');
|
||||||
|
this.uid = undefined;
|
||||||
|
this.permalink.updateLocation();
|
||||||
},
|
},
|
||||||
|
|
||||||
reset() {
|
/**
|
||||||
for (let hue in this.hueShifts) {
|
* Remove a specific tweak or all tweaks
|
||||||
this.hueShifts[hue] = 0;
|
* @param {string} [param] - The tweak to remove. If not provided, all tweaks are removed.
|
||||||
}
|
*/
|
||||||
this.chromaScale = 1;
|
reset(param) {
|
||||||
},
|
if (!param || param === 'chromaScale') {
|
||||||
|
|
||||||
removeTweak(param) {
|
|
||||||
if (param === 'chromaScale') {
|
|
||||||
this.chromaScale = 1;
|
this.chromaScale = 1;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (param in this.hueShifts) {
|
||||||
this.hueShifts[param] = 0;
|
this.hueShifts[param] = 0;
|
||||||
|
} else if (!param) {
|
||||||
|
for (let hue in this.hueShifts) {
|
||||||
|
this.hueShifts[hue] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!param || param === 'grayColor') {
|
||||||
|
this.grayColor = this.originalGrayColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!param || param === 'grayChroma') {
|
||||||
|
this.grayChroma = this.originalGrayChroma;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -336,16 +429,20 @@ let paletteAppSpec = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
let paletteAppContainer = document.querySelector('#palette-app');
|
||||||
globalThis.paletteApp?.unmount?.();
|
globalThis.paletteApp?.unmount?.();
|
||||||
globalThis.paletteApp = createApp(paletteAppSpec).mount('#palette-app');
|
|
||||||
|
if (!paletteAppContainer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
globalThis.paletteApp = createApp(paletteAppSpec).mount(paletteAppContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
init();
|
||||||
addEventListener('turbo:render', init);
|
addEventListener('turbo:render', init);
|
||||||
|
|
||||||
export function getPaletteCode(paletteId, tweaks, options) {
|
export function getPaletteCode(paletteId, colors, tweaked, options) {
|
||||||
let palette = allPalettes[paletteId].colors;
|
|
||||||
|
|
||||||
let imports = [];
|
let imports = [];
|
||||||
|
|
||||||
if (paletteId) {
|
if (paletteId) {
|
||||||
@@ -353,37 +450,27 @@ export function getPaletteCode(paletteId, tweaks, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let css = '';
|
let css = '';
|
||||||
|
let declarations = [];
|
||||||
|
|
||||||
if (tweaks) {
|
if (tweaked) {
|
||||||
let { hueShifts, chromaScale = 1 } = tweaks;
|
for (let hue in colors) {
|
||||||
let declarations = [];
|
if (hue === 'orange') {
|
||||||
|
continue;
|
||||||
if (hueShifts || chromaScale !== 1) {
|
} else if (hue === 'gray') {
|
||||||
for (let hue in hueShifts) {
|
if (!tweaked.grayChroma && !tweaked.grayColor) {
|
||||||
let shift = hueShifts[hue];
|
|
||||||
|
|
||||||
if ((!shift && chromaScale === 1) || hue === 'orange') {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else if (!tweaked.chromaScale && !tweaked.hue?.[hue]) {
|
||||||
let scale = palette[hue];
|
continue;
|
||||||
|
|
||||||
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('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let tint of tints) {
|
||||||
|
let color = colors[hue][tint];
|
||||||
|
let stringified = color.toString({ format: color.inGamut('srgb') ? 'hex' : undefined });
|
||||||
|
declarations.push(`--wa-color-${hue}-${tint}: ${stringified};`);
|
||||||
|
}
|
||||||
|
|
||||||
|
declarations.push('');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declarations.length > 0) {
|
if (declarations.length > 0) {
|
||||||
@@ -409,3 +496,85 @@ function arrayPrevious(array, element) {
|
|||||||
let index = array.indexOf(element);
|
let index = array.indexOf(element);
|
||||||
return array[(index - 1 + array.length) % array.length];
|
return array[(index - 1 + array.length) % array.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyTweaks(originalColors, tweaks, tweaked) {
|
||||||
|
let ret = {};
|
||||||
|
let { hueShifts, chromaScale = 1, grayColor, grayChroma } = tweaks;
|
||||||
|
|
||||||
|
if (!tweaked) {
|
||||||
|
return originalColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tweaked.grayChroma) {
|
||||||
|
grayChroma = this.computedGrayChroma;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let hue in originalColors) {
|
||||||
|
let originalScale = originalColors[hue];
|
||||||
|
let scale = (ret[hue] = {});
|
||||||
|
let descriptors = Object.getOwnPropertyDescriptors(originalScale);
|
||||||
|
Object.defineProperties(scale, {
|
||||||
|
maxChromaTint: { ...descriptors.maxChromaTint, enumerable: false },
|
||||||
|
maxChromaTintRaw: { ...descriptors.maxChromaTintRaw, enumerable: false },
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let tint of tints) {
|
||||||
|
let color = originalScale[tint].clone();
|
||||||
|
|
||||||
|
if (tweaked.hue && hueShifts[hue]) {
|
||||||
|
color.set({ h: h => h + hueShifts[hue] });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tweaked.chromaScale && chromaScale !== 1) {
|
||||||
|
color.set({ c: c => c * chromaScale });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hue === 'gray' && (tweaked.grayChroma || tweaked.grayColor)) {
|
||||||
|
let colorUndertone = originalColors[grayColor][tint].clone();
|
||||||
|
color = colorUndertone.set({ c: c => c * grayChroma });
|
||||||
|
}
|
||||||
|
|
||||||
|
scale[tint] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function camelCase(str) {
|
||||||
|
return (str + '').replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
function capitalize(str) {
|
||||||
|
return str[0].toUpperCase() + str.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContrasts(colors, originalContrasts) {
|
||||||
|
let ret = {};
|
||||||
|
|
||||||
|
for (let hue in colors) {
|
||||||
|
ret[hue] = {};
|
||||||
|
|
||||||
|
for (let tintBg of tints) {
|
||||||
|
ret[hue][tintBg] = {};
|
||||||
|
let bgColor = colors[hue][tintBg];
|
||||||
|
|
||||||
|
if (!bgColor || !bgColor.contrast) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let tintFg of tints) {
|
||||||
|
let fgColor = colors[hue][tintFg];
|
||||||
|
let value = bgColor.contrast(fgColor, 'WCAG21');
|
||||||
|
if (originalContrasts) {
|
||||||
|
let original = originalContrasts[hue][tintBg][tintFg];
|
||||||
|
ret[hue][tintBg][tintFg] = { value, original, bgColor, fgColor };
|
||||||
|
} else {
|
||||||
|
ret[hue][tintBg][tintFg] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,11 +14,18 @@ During the alpha period, things might break! We take breaking changes very serio
|
|||||||
|
|
||||||
## Next
|
## Next
|
||||||
|
|
||||||
|
- Fixed `wa-pill` class for text fields
|
||||||
|
- Fixed `pill` style for `<wa-input>` elements
|
||||||
|
|
||||||
|
## 3.0.0-alpha.11
|
||||||
|
|
||||||
### Color Palettes
|
### Color Palettes
|
||||||
|
|
||||||
|
- Color palette tweaking UI. Tweak hue, grays, overall colorfulness, save or share the results.
|
||||||
- Added a `pink` scale to all color palettes
|
- Added a `pink` scale to all color palettes
|
||||||
- Fixed an incorrect CSS value in `<wa-select>`'s expand icon
|
|
||||||
- Tweaked hues of all color palettes to make them more distinct and make their hues more intentional
|
- Tweaked hues of all color palettes to make them more distinct and make their hues more intentional
|
||||||
|
- Dropped `violet` and `teal`, instead using `purple` and `cyan` (this is not just a renaming, the colors have been adjusted too).
|
||||||
|
- Fixed a bug in `<wa-switch>` that caused tooltips to work incorrectly when toggling the switch
|
||||||
|
|
||||||
### Design Tokens
|
### Design Tokens
|
||||||
|
|
||||||
@@ -27,32 +34,54 @@ You can find them in the first column of each color palette.
|
|||||||
|
|
||||||
### Themes
|
### Themes
|
||||||
|
|
||||||
|
- Improved UI for theme remixing:
|
||||||
|
- You can now override the brand color of any theme with any of the 9 hues supported.
|
||||||
|
- Rich previews
|
||||||
|
- Generated copyable code snippets.
|
||||||
|
- Permalinks
|
||||||
- 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.
|
- 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.
|
|
||||||
|
|
||||||
### Components
|
### Components
|
||||||
|
|
||||||
- Various `<wa-radio>` improvements:
|
#### `<wa-radio>`
|
||||||
- Dropped the `base` part. It can now be styled by directly applying CSS to the element itself.
|
|
||||||
- Added `hint` attribute and corresponding slot.
|
|
||||||
- Various `<wa-select>` improvements:
|
|
||||||
- Added the `tag` part (and associated exported parts) to `<wa-select>` to allow targeting the tag that shows when more than the max number of visible items have been selected
|
|
||||||
- Fixed a bug that prevented the placeholder color from being customized with the `--wa-form-control-placeholder-color` token
|
|
||||||
- Dropped the `base` part from `<wa-option>` for easier styling. CSS can now be applied directly to the element itself.
|
|
||||||
- Various `<wa-card>` improvements:
|
|
||||||
- Fixed a bug where child elements did not have correct rounding when headers and footers were absent.
|
|
||||||
- Re-introduced `--border-color` so that the card itself can have a different border color than its inner borders.
|
|
||||||
- Fixed a bug that prevented slots from showing automatically without `with-` attributes
|
|
||||||
- Fixed a bug in `<wa-select>` that prevented the description from being read by screen readers
|
|
||||||
|
|
||||||
|
- Dropped the `base` part. It can now be styled by directly applying CSS to the element itself.
|
||||||
|
- Added `hint` attribute and corresponding slot.
|
||||||
|
|
||||||
|
#### `<wa-select>`
|
||||||
|
|
||||||
|
- Added the `tag` part (and associated exported parts) to `<wa-select>` to allow targeting the tag that shows when more than the max number of visible items have been selected
|
||||||
|
- Fixed a bug that prevented the placeholder color from being customized with the `--wa-form-control-placeholder-color` token
|
||||||
|
- Fixed an incorrect CSS value in the expand icon
|
||||||
|
- Fixed a bug that prevented the description from being read by screen readers
|
||||||
|
|
||||||
|
#### `<wa-option>`
|
||||||
|
|
||||||
|
- `label` attribute to override the generated label (useful for rich content)
|
||||||
|
- `defaultLabel` property
|
||||||
|
- Dropped `getTextLabel()` method (if you need dynamic labels, just set the `label` attribute dynamically)
|
||||||
|
- Dropped `base` part for easier styling. CSS can now be applied directly to the element itself.
|
||||||
|
|
||||||
|
#### `<wa-menu-item>`
|
||||||
|
|
||||||
|
- `label` attribute to override the generated label (useful for rich content)
|
||||||
|
- `defaultLabel` property
|
||||||
|
- Dropped `getTextLabel()` method (if you need dynamic labels, just set the `label` attribute dynamically)
|
||||||
|
|
||||||
|
#### `<wa-card>`
|
||||||
|
- Fixed a bug where child elements did not have correct rounding when headers and footers were absent.
|
||||||
|
- Re-introduced `--border-color` so that the card itself can have a different border color than its inner borders.
|
||||||
|
- Fixed a bug that prevented slots from showing automatically without `with-` attributes
|
||||||
|
|
||||||
|
#### `<wa-tab>`
|
||||||
|
|
||||||
|
- Fixed a bug that caused `document.createElement('wa-tab')` to fail (which also meant it could not be used in VueJS and other frameworks)
|
||||||
|
|
||||||
### Docs
|
### Docs
|
||||||
|
|
||||||
- Added an orientation example to the native radio docs
|
- Added an orientation example to the native radio docs
|
||||||
- Fixed a number of broken event listeners throughout the docs
|
- Fixed a number of broken event listeners throughout the docs
|
||||||
|
|
||||||
|
|
||||||
## 3.0.0-alpha.10
|
## 3.0.0-alpha.10
|
||||||
|
|
||||||
- 🚨 BREAKING: updated all components to use native events instead of `wa-` prefixed events. This will allow components to work more like native elements in your code, frameworks, third-party plugins, etc. To update your code, simply remove the prefix from your event listeners for the following events.
|
- 🚨 BREAKING: updated all components to use native events instead of `wa-` prefixed events. This will allow components to work more like native elements in your code, frameworks, third-party plugins, etc. To update your code, simply remove the prefix from your event listeners for the following events.
|
||||||
|
|||||||
51
docs/docs/themes/demo.njk
vendored
51
docs/docs/themes/demo.njk
vendored
@@ -10,15 +10,17 @@ override:tags: []
|
|||||||
eleventyComputed:
|
eleventyComputed:
|
||||||
forceTheme: "{{ theme.fileSlug }}"
|
forceTheme: "{{ theme.fileSlug }}"
|
||||||
---
|
---
|
||||||
|
{% set isPro = theme.data.isPro %}
|
||||||
|
{% set status = theme.data.status %}
|
||||||
|
{% set since = theme.data.since %}
|
||||||
<link rel="stylesheet" href="/docs/themes/showcase.css" />
|
<link rel="stylesheet" href="/docs/themes/showcase.css" />
|
||||||
|
|
||||||
{% set content %}
|
{% set content %}
|
||||||
<header>
|
<header>
|
||||||
{% include 'breadcrumbs.njk' %}
|
{% include 'breadcrumbs.njk' %}
|
||||||
<h1 class="title">{{ theme.data.title }}</h1>
|
<h1 class="title">{{ theme.data.title }}</h1>
|
||||||
<p id="mix_and_match" hidden class="wa-size-s"></p>
|
<p id="mix_and_match" class="wa-size-s"></p>
|
||||||
<p>{% include 'status.njk' %}</p>
|
<p id="theme-status">{% include 'status.njk' %}</p>
|
||||||
<p id="theme-showcase-description">{{ theme.data.description | inlineMarkdown | safe }}</p>
|
<p id="theme-showcase-description">{{ theme.data.description | inlineMarkdown | safe }}</p>
|
||||||
</header>
|
</header>
|
||||||
{% include 'theme-showcase.njk' %}
|
{% include 'theme-showcase.njk' %}
|
||||||
@@ -34,30 +36,18 @@ eleventyComputed:
|
|||||||
</wa-image-comparer>
|
</wa-image-comparer>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { urls as stylesheetURLs } from "/assets/scripts/tweak/data.js";
|
import { urls as stylesheetURLs, docsURLs, icons } from "/assets/scripts/tweak/data.js";
|
||||||
import { theme as getThemeCode } from "/assets/scripts/tweak/code.js";
|
import { getThemeCode } from "/assets/scripts/tweak/code.js";
|
||||||
|
|
||||||
function updateTheme() {
|
function updateTheme() {
|
||||||
let params = new URLSearchParams(window.location.search);
|
let params = new URLSearchParams(window.location.search);
|
||||||
params = Object.fromEntries(params.entries());
|
params = Object.fromEntries(params.entries());
|
||||||
|
|
||||||
const docsURLs = {
|
|
||||||
colors: '/docs/themes/',
|
|
||||||
palette: '/docs/palettes/',
|
|
||||||
typography: '/docs/themes/'
|
|
||||||
};
|
|
||||||
const icons = {
|
|
||||||
colors: 'palette',
|
|
||||||
palette: 'swatchbook',
|
|
||||||
brand: 'droplet',
|
|
||||||
typography: 'font-case'
|
|
||||||
};
|
|
||||||
|
|
||||||
for (let link of document.querySelectorAll('link.mix-and-match')) {
|
for (let link of document.querySelectorAll('link.mix-and-match')) {
|
||||||
link.remove();
|
link.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
let msgs = [];
|
let tweaks = [];
|
||||||
let code = getThemeCode("{{ theme.fileSlug }}", params, {attributes: 'class="mix-and-match"'});
|
let code = getThemeCode("{{ theme.fileSlug }}", params, {attributes: 'class="mix-and-match"'});
|
||||||
document.head.insertAdjacentHTML('beforeend', code);
|
document.head.insertAdjacentHTML('beforeend', code);
|
||||||
|
|
||||||
@@ -72,18 +62,29 @@ function updateTheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let icon = icons[name];
|
let icon = icons[name];
|
||||||
msgs.push(`<wa-icon name="${icon}" variant="regular"></wa-icon> ${ title }`);
|
tweaks.push(`<wa-icon name="${icon}" variant="regular"></wa-icon> ${ title }`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let p of mix_and_match) {
|
let isRemixed = tweaks.length > 0;
|
||||||
p.hidden = msgs.length === 0;
|
document.documentElement.classList.toggle('is-remixed', isRemixed);
|
||||||
if (msgs.length) {
|
|
||||||
let icon =
|
if (isRemixed) {
|
||||||
p.innerHTML = `<strong><wa-icon name="arrows-rotate"></wa-icon> Remixed</strong> ` + msgs.map(msg => `<wa-badge appearance=outlined>
|
for (let p of document.querySelectorAll("#theme-status")) {
|
||||||
${ msg }</wa-badge>`).join(' ');
|
let proBadge = p.querySelector(".pro");
|
||||||
|
if (!proBadge) {
|
||||||
|
p.insertAdjacentHTML('beforeend', '<wa-badge class="pro">PRO</wa-badge>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let p of mix_and_match) {
|
||||||
|
if (tweaks.length) {
|
||||||
|
p.innerHTML = `<strong><wa-icon name="arrows-rotate"></wa-icon> Remixed</strong> ` + tweaks.map(msg => `<wa-badge appearance=outlined>
|
||||||
|
${ msg }</wa-badge>`).join(' ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
updateTheme();
|
updateTheme();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
4
docs/docs/themes/remix.js
vendored
4
docs/docs/themes/remix.js
vendored
@@ -107,6 +107,10 @@ function setDefault(select, value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function render(changedAspect) {
|
function render(changedAspect) {
|
||||||
|
if (!globalThis.demo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let url = new URL(demo.src);
|
let url = new URL(demo.src);
|
||||||
|
|
||||||
if (!changedAspect || changedAspect === 'colors') {
|
if (!changedAspect || changedAspect === 'colors') {
|
||||||
|
|||||||
5
docs/docs/themes/showcase.css
vendored
5
docs/docs/themes/showcase.css
vendored
@@ -12,6 +12,11 @@ body,
|
|||||||
#mix_and_match {
|
#mix_and_match {
|
||||||
font-weight: var(--wa-font-weight-semibold);
|
font-weight: var(--wa-font-weight-semibold);
|
||||||
color: var(--wa-color-text-quiet);
|
color: var(--wa-color-text-quiet);
|
||||||
|
margin-block-end: var(--wa-space-xs);
|
||||||
|
|
||||||
|
html:not(.is-remixed) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
wa-icon {
|
wa-icon {
|
||||||
vertical-align: -0.15em;
|
vertical-align: -0.15em;
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@shoelace-style/webawesome",
|
"name": "@shoelace-style/webawesome",
|
||||||
"version": "3.0.0-alpha.10",
|
"version": "3.0.0-alpha.11",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@shoelace-style/webawesome",
|
"name": "@shoelace-style/webawesome",
|
||||||
"version": "3.0.0-alpha.10",
|
"version": "3.0.0-alpha.11",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ctrl/tinycolor": "^4.1.0",
|
"@ctrl/tinycolor": "^4.1.0",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@shoelace-style/webawesome",
|
"name": "@shoelace-style/webawesome",
|
||||||
"description": "A forward-thinking library of web components.",
|
"description": "A forward-thinking library of web components.",
|
||||||
"version": "3.0.0-alpha.10",
|
"version": "3.0.0-alpha.11",
|
||||||
"homepage": "https://webawesome.com/",
|
"homepage": "https://webawesome.com/",
|
||||||
"author": "Web Awesome",
|
"author": "Web Awesome",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { dirname, join, relative } from 'path';
|
|||||||
import process from 'process';
|
import process from 'process';
|
||||||
import copy from 'recursive-copy';
|
import copy from 'recursive-copy';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { preprocessStylesheet } from './preprocess-css.js';
|
|
||||||
import { cdnDir, distDir, docsDir, rootDir, runScript, siteDir } from './utils.js';
|
import { cdnDir, distDir, docsDir, rootDir, runScript, siteDir } from './utils.js';
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
@@ -37,7 +36,6 @@ async function buildAll() {
|
|||||||
await generateManifest();
|
await generateManifest();
|
||||||
await generateReactWrappers();
|
await generateReactWrappers();
|
||||||
await generateTypes();
|
await generateTypes();
|
||||||
await preprocessStyles();
|
|
||||||
await generateStyles();
|
await generateStyles();
|
||||||
|
|
||||||
// copy everything to unbundled before we generate bundles.
|
// copy everything to unbundled before we generate bundles.
|
||||||
@@ -107,23 +105,6 @@ function generateReactWrappers() {
|
|||||||
return Promise.resolve();
|
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.
|
* Copies theme stylesheets to the dist.
|
||||||
*/
|
*/
|
||||||
@@ -390,7 +371,6 @@ if (isDeveloping) {
|
|||||||
try {
|
try {
|
||||||
const isTestFile = filename.includes('.test.ts');
|
const isTestFile = filename.includes('.test.ts');
|
||||||
const isCssStylesheet = filename.includes('.css');
|
const isCssStylesheet = filename.includes('.css');
|
||||||
const isPreprocessedStylesheet = filename.endsWith('.css.njk');
|
|
||||||
const isComponent =
|
const isComponent =
|
||||||
filename.includes('components/') && filename.includes('.ts') && !isCssStylesheet && !isTestFile;
|
filename.includes('components/') && filename.includes('.ts') && !isCssStylesheet && !isTestFile;
|
||||||
|
|
||||||
@@ -401,10 +381,6 @@ if (isDeveloping) {
|
|||||||
|
|
||||||
await regenerateBundle();
|
await regenerateBundle();
|
||||||
|
|
||||||
if (isPreprocessedStylesheet || filename.endsWith('src/styles/data.js')) {
|
|
||||||
await preprocessStyles();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy stylesheets when CSS files change
|
// Copy stylesheets when CSS files change
|
||||||
if (isCssStylesheet) {
|
if (isCssStylesheet) {
|
||||||
await generateStyles();
|
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;
|
|
||||||
}
|
|
||||||
@@ -52,6 +52,7 @@ import styles from './button.css';
|
|||||||
@customElement('wa-button')
|
@customElement('wa-button')
|
||||||
export default class WaButton extends WebAwesomeFormAssociatedElement {
|
export default class WaButton extends WebAwesomeFormAssociatedElement {
|
||||||
static shadowStyle = [variantStyles, appearanceStyles, sizeStyles, nativeStyles, styles];
|
static shadowStyle = [variantStyles, appearanceStyles, sizeStyles, nativeStyles, styles];
|
||||||
|
static rectProxy = 'button';
|
||||||
|
|
||||||
static get validators() {
|
static get validators() {
|
||||||
return [...super.validators, MirrorValidator()];
|
return [...super.validators, MirrorValidator()];
|
||||||
@@ -224,17 +225,6 @@ export default class WaButton extends WebAwesomeFormAssociatedElement {
|
|||||||
this.button.blur();
|
this.button.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
getBoundingClientRect(): DOMRect {
|
|
||||||
let rect = super.getBoundingClientRect();
|
|
||||||
let buttonRect = this.button.getBoundingClientRect();
|
|
||||||
|
|
||||||
if (rect.width === 0 && buttonRect.width > 0) {
|
|
||||||
return buttonRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const isLink = this.isLink();
|
const isLink = this.isLink();
|
||||||
const tag = isLink ? literal`a` : literal`button`;
|
const tag = isLink ? literal`a` : literal`button`;
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import styles from './radio-button.css';
|
|||||||
@customElement('wa-radio-button')
|
@customElement('wa-radio-button')
|
||||||
export default class WaRadioButton extends WebAwesomeFormAssociatedElement {
|
export default class WaRadioButton extends WebAwesomeFormAssociatedElement {
|
||||||
static shadowStyle = [variantStyles, appearanceStyles, sizeStyles, nativeStyles, buttonStyles, styles];
|
static shadowStyle = [variantStyles, appearanceStyles, sizeStyles, nativeStyles, buttonStyles, styles];
|
||||||
|
static rectProxy = 'input';
|
||||||
|
|
||||||
private readonly hasSlotController = new HasSlotController(this, '[default]', 'prefix', 'suffix');
|
private readonly hasSlotController = new HasSlotController(this, '[default]', 'prefix', 'suffix');
|
||||||
|
|
||||||
|
|||||||
@@ -208,13 +208,13 @@
|
|||||||
&::slotted(wa-divider) {
|
&::slotted(wa-divider) {
|
||||||
--spacing: var(--wa-space-xs);
|
--spacing: var(--wa-space-xs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
&::slotted(small) {
|
|
||||||
display: block;
|
slot:not([name])::slotted(small) {
|
||||||
font-size: var(--wa-font-size-s);
|
display: block;
|
||||||
font-weight: var(--wa-font-weight-semibold);
|
font-size: var(--wa-font-size-s);
|
||||||
color: var(--wa-color-text-quiet);
|
font-weight: var(--wa-font-weight-semibold);
|
||||||
padding-block: var(--wa-space-xs);
|
color: var(--wa-color-text-quiet);
|
||||||
padding-inline: var(--wa-space-xl);
|
padding-block: var(--wa-space-xs);
|
||||||
}
|
padding-inline: var(--wa-space-xl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import styles from './switch.css';
|
|||||||
*/
|
*/
|
||||||
@customElement('wa-switch')
|
@customElement('wa-switch')
|
||||||
export default class WaSwitch extends WebAwesomeFormAssociatedElement {
|
export default class WaSwitch extends WebAwesomeFormAssociatedElement {
|
||||||
|
static shadowRootOptions = { ...WebAwesomeFormAssociatedElement.shadowRootOptions, delegatesFocus: true };
|
||||||
static shadowStyle = [formControlStyles, sizeStyles, styles];
|
static shadowStyle = [formControlStyles, sizeStyles, styles];
|
||||||
|
|
||||||
static get validators() {
|
static get validators() {
|
||||||
|
|||||||
@@ -4,10 +4,16 @@
|
|||||||
--max-width: 30ch;
|
--max-width: 30ch;
|
||||||
--padding: var(--wa-space-2xs) var(--wa-space-xs);
|
--padding: var(--wa-space-2xs) var(--wa-space-xs);
|
||||||
|
|
||||||
|
/** These styles are added so we don't interfere in the DOM. */
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
||||||
/** These styles are added so we dont interfere in the DOM. */
|
/** Defaults for inherited CSS properties */
|
||||||
|
color: var(--wa-tooltip-content-color);
|
||||||
|
font-size: var(--wa-tooltip-font-size);
|
||||||
|
line-height: var(--wa-tooltip-line-height);
|
||||||
|
text-align: start;
|
||||||
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
@@ -41,12 +47,6 @@
|
|||||||
max-width: var(--max-width);
|
max-width: var(--max-width);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
font: inherit;
|
|
||||||
color: var(--wa-tooltip-content-color);
|
|
||||||
font-size: var(--wa-tooltip-font-size);
|
|
||||||
line-height: var(--wa-tooltip-line-height);
|
|
||||||
text-align: start;
|
|
||||||
white-space: normal;
|
|
||||||
padding: var(--padding);
|
padding: var(--padding);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
|
|||||||
@@ -35,11 +35,8 @@ import styles from './tooltip.css';
|
|||||||
*
|
*
|
||||||
* @cssproperty --background-color - The tooltip's background color.
|
* @cssproperty --background-color - The tooltip's background color.
|
||||||
* @cssproperty --border-radius - The radius of the tooltip's corners.
|
* @cssproperty --border-radius - The radius of the tooltip's corners.
|
||||||
* @cssproperty --text-color - The color of the tooltip's content.
|
|
||||||
* @cssproperty --max-width - The maximum width of the tooltip before its content will wrap.
|
* @cssproperty --max-width - The maximum width of the tooltip before its content will wrap.
|
||||||
* @cssproperty --padding - The padding within the tooltip.
|
* @cssproperty --padding - The padding within the tooltip.
|
||||||
* @cssproperty --hide-delay - The amount of time to wait before hiding the tooltip when hovering.
|
|
||||||
* @cssproperty --show-delay - The amount of time to wait before showing the tooltip when hovering.
|
|
||||||
*/
|
*/
|
||||||
@customElement('wa-tooltip')
|
@customElement('wa-tooltip')
|
||||||
export default class WaTooltip extends WebAwesomeElement {
|
export default class WaTooltip extends WebAwesomeElement {
|
||||||
|
|||||||
@@ -204,6 +204,32 @@ export default class WebAwesomeElement extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBoundingClientRect(): DOMRect {
|
||||||
|
let rect = super.getBoundingClientRect();
|
||||||
|
|
||||||
|
if (rect.width === 0 && rect.height === 0) {
|
||||||
|
let Self = this.constructor as typeof WebAwesomeElement;
|
||||||
|
|
||||||
|
if (Self.rectProxy) {
|
||||||
|
let element = this[Self.rectProxy as keyof this];
|
||||||
|
if (element instanceof Element) {
|
||||||
|
let childRect = element.getBoundingClientRect();
|
||||||
|
if (childRect.width > 0 || childRect.height > 0) {
|
||||||
|
return childRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If getBoundingClientRect() returns an empty rect,
|
||||||
|
* should we check another element?
|
||||||
|
*/
|
||||||
|
static rectProxy: undefined | string;
|
||||||
|
|
||||||
static createProperty(name: PropertyKey, options?: PropertyDeclaration): void {
|
static createProperty(name: PropertyKey, options?: PropertyDeclaration): void {
|
||||||
if (options) {
|
if (options) {
|
||||||
if (options.initial !== undefined && options.default === undefined) {
|
if (options.initial !== undefined && options.default === undefined) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* DO NOT EDIT THIS FILE. It is generated from "base.css.njk" */
|
|
||||||
:where(:root),
|
:where(:root),
|
||||||
:host,
|
:host,
|
||||||
:where([class^='wa-theme-'], [class*=' wa-theme-']),
|
: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-lt-N ➡️ 100% if key < N, 0% otherwise
|
||||||
* --wa-color-brand-if-gte-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-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-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-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-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-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));
|
--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-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-N-min ➡️ var(--color-brand) if key >= N, var(--color-brand-N) otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
--wa-color-brand-40-max: color-mix(
|
--wa-color-brand-40-max: color-mix(
|
||||||
in oklab,
|
in oklab,
|
||||||
var(--wa-color-brand) var(--wa-color-brand-if-lt-40),
|
var(--wa-color-brand) var(--wa-color-brand-if-lt-40),
|
||||||
|
|||||||
@@ -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');
|
@import url('base.css');
|
||||||
|
|
||||||
:where(:root),
|
:where(:root),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
|
||||||
@import url('base.css');
|
@import url('base.css');
|
||||||
|
|
||||||
:where(:root),
|
:where(:root),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
|
||||||
@import url('base.css');
|
@import url('base.css');
|
||||||
|
|
||||||
:where(:root),
|
:where(:root),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
|
||||||
@import url('base.css');
|
@import url('base.css');
|
||||||
|
|
||||||
:where(:root),
|
:where(:root),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
|
||||||
@import url('base.css');
|
@import url('base.css');
|
||||||
|
|
||||||
:where(:root),
|
:where(:root),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
|
||||||
@import url('base.css');
|
@import url('base.css');
|
||||||
|
|
||||||
:where(:root),
|
:where(:root),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
|
||||||
@import url('base.css');
|
@import url('base.css');
|
||||||
|
|
||||||
:where(:root),
|
:where(:root),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
|
||||||
@import url('base.css');
|
@import url('base.css');
|
||||||
|
|
||||||
:where(:root),
|
:where(:root),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* DO NOT EDIT THIS FILE. It is generated from "{{ hue }}.css.njk" */
|
|
||||||
@import url('base.css');
|
@import url('base.css');
|
||||||
|
|
||||||
:where(:root),
|
: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);
|
|
||||||
}
|
|
||||||
@@ -16,6 +16,20 @@
|
|||||||
--wa-color-red: var(--wa-color-red-70);
|
--wa-color-red: var(--wa-color-red-70);
|
||||||
--wa-color-red-key: 70;
|
--wa-color-red-key: 70;
|
||||||
|
|
||||||
|
--wa-color-orange-95: oklch(96.462% 0.02077 52.138);
|
||||||
|
--wa-color-orange-90: oklch(92.556% 0.04363 51.242);
|
||||||
|
--wa-color-orange-80: #fdbb96 /* oklch(84.396% 0.09052 50.397) */;
|
||||||
|
--wa-color-orange-70: #eb9c74 /* oklch(76.151% 0.10953 47.299) */;
|
||||||
|
--wa-color-orange-60: #cf8162 /* oklch(67.86% 0.10698 42.148) */;
|
||||||
|
--wa-color-orange-50: #aa6248 /* oklch(57.281% 0.1014 40.415) */;
|
||||||
|
--wa-color-orange-40: #864834 /* oklch(47.233% 0.08958 39.166) */;
|
||||||
|
--wa-color-orange-30: #6b3727 /* oklch(39.974% 0.07776 38.975) */;
|
||||||
|
--wa-color-orange-20: #50271a /* oklch(32.519% 0.0649 38.022) */;
|
||||||
|
--wa-color-orange-10: #32160e /* oklch(23.873% 0.04713 38.423) */;
|
||||||
|
--wa-color-orange-05: #210c06 /* oklch(18.614% 0.03797 38.589) */;
|
||||||
|
--wa-color-orange: var(--wa-color-orange-70);
|
||||||
|
--wa-color-orange-key: 70;
|
||||||
|
|
||||||
--wa-color-yellow-95: #faf3e1 /* oklch(96.479% 0.02487 89.211) */;
|
--wa-color-yellow-95: #faf3e1 /* oklch(96.479% 0.02487 89.211) */;
|
||||||
--wa-color-yellow-90: #f4e5be /* oklch(92.412% 0.0535 89.488) */;
|
--wa-color-yellow-90: #f4e5be /* oklch(92.412% 0.0535 89.488) */;
|
||||||
--wa-color-yellow-80: #eac673 /* oklch(84.03% 0.1101 86.581) */;
|
--wa-color-yellow-80: #eac673 /* oklch(84.03% 0.1101 86.581) */;
|
||||||
|
|||||||
@@ -16,6 +16,20 @@
|
|||||||
--wa-color-red: var(--wa-color-red-60);
|
--wa-color-red: var(--wa-color-red-60);
|
||||||
--wa-color-red-key: 60;
|
--wa-color-red-key: 60;
|
||||||
|
|
||||||
|
--wa-color-orange-95: oklch(96.406% 0.04001 53.476);
|
||||||
|
--wa-color-orange-90: oklch(92.395% 0.07984 53.06);
|
||||||
|
--wa-color-orange-80: oklch(84.389% 0.12224 47.981);
|
||||||
|
--wa-color-orange-70: oklch(76.55% 0.16521 42.512);
|
||||||
|
--wa-color-orange-60: #ea7237 /* oklch(68.444% 0.16501 44.349) */;
|
||||||
|
--wa-color-orange-50: #c0561a /* oklch(57.844% 0.15254 45.085) */;
|
||||||
|
--wa-color-orange-40: #963e05 /* oklch(47.639% 0.13153 45.898) */;
|
||||||
|
--wa-color-orange-30: oklch(40.376% 0.11554 45.517);
|
||||||
|
--wa-color-orange-20: oklch(32.94% 0.09927 45.913);
|
||||||
|
--wa-color-orange-10: oklch(24.083% 0.07743 46.027);
|
||||||
|
--wa-color-orange-05: oklch(18.817% 0.06098 48.455);
|
||||||
|
--wa-color-orange: var(--wa-color-orange-70);
|
||||||
|
--wa-color-orange-key: 70;
|
||||||
|
|
||||||
--wa-color-yellow-95: #fff4c0 /* oklch(96.32% 0.0677 97.497) */;
|
--wa-color-yellow-95: #fff4c0 /* oklch(96.32% 0.0677 97.497) */;
|
||||||
--wa-color-yellow-90: #ffe579 /* oklch(92.176% 0.13122 96.089) */;
|
--wa-color-yellow-90: #ffe579 /* oklch(92.176% 0.13122 96.089) */;
|
||||||
--wa-color-yellow-80: #ffbf18 /* oklch(84.069% 0.16897 83.446) */;
|
--wa-color-yellow-80: #ffbf18 /* oklch(84.069% 0.16897 83.446) */;
|
||||||
|
|||||||
@@ -16,6 +16,20 @@
|
|||||||
--wa-color-red: var(--wa-color-red-50);
|
--wa-color-red: var(--wa-color-red-50);
|
||||||
--wa-color-red-key: 50;
|
--wa-color-red-key: 50;
|
||||||
|
|
||||||
|
--wa-color-orange-95: oklch(96.245% 0.04153 59.224);
|
||||||
|
--wa-color-orange-90: oklch(92.468% 0.07656 58.647);
|
||||||
|
--wa-color-orange-80: oklch(84.375% 0.11283 54.179);
|
||||||
|
--wa-color-orange-70: #fb945a /* oklch(76.369% 0.14454 48.621) */;
|
||||||
|
--wa-color-orange-60: #f26b31 /* oklch(68.509% 0.18046 41.503) */;
|
||||||
|
--wa-color-orange-50: #cf4812 /* oklch(58.288% 0.18026 38.576) */;
|
||||||
|
--wa-color-orange-40: oklch(48.175% 0.16316 38.526);
|
||||||
|
--wa-color-orange-30: oklch(40.779% 0.13925 37.899);
|
||||||
|
--wa-color-orange-20: oklch(33.129% 0.11288 38.58);
|
||||||
|
--wa-color-orange-10: oklch(24.259% 0.0831 38.502);
|
||||||
|
--wa-color-orange-05: oklch(18.969% 0.06527 38.137);
|
||||||
|
--wa-color-orange: var(--wa-color-orange-60);
|
||||||
|
--wa-color-orange-key: 60;
|
||||||
|
|
||||||
--wa-color-yellow-95: #fef2bf /* oklch(95.823% 0.06674 96.369) */;
|
--wa-color-yellow-95: #fef2bf /* oklch(95.823% 0.06674 96.369) */;
|
||||||
--wa-color-yellow-90: #fde588 /* oklch(92.2% 0.11633 95.327) */;
|
--wa-color-yellow-90: #fde588 /* oklch(92.2% 0.11633 95.327) */;
|
||||||
--wa-color-yellow-80: #f4c34e /* oklch(83.998% 0.14252 85.76) */;
|
--wa-color-yellow-80: #f4c34e /* oklch(83.998% 0.14252 85.76) */;
|
||||||
|
|||||||
@@ -16,6 +16,20 @@
|
|||||||
--wa-color-red: var(--wa-color-red-50);
|
--wa-color-red: var(--wa-color-red-50);
|
||||||
--wa-color-red-key: 50;
|
--wa-color-red-key: 50;
|
||||||
|
|
||||||
|
--wa-color-orange-95: oklch(96.494% 0.0335 57.914);
|
||||||
|
--wa-color-orange-90: oklch(92.556% 0.06963 56.631);
|
||||||
|
--wa-color-orange-80: oklch(84.494% 0.12276 53.381);
|
||||||
|
--wa-color-orange-70: oklch(76.375% 0.17194 46.091);
|
||||||
|
--wa-color-orange-60: #eb713f /* oklch(68.398% 0.16422 41.446) */;
|
||||||
|
--wa-color-orange-50: #cb4b1d /* oklch(58.153% 0.17174 38.404) */;
|
||||||
|
--wa-color-orange-40: #a2310c /* oklch(48.028% 0.15488 36.538) */;
|
||||||
|
--wa-color-orange-30: #7f2810 /* oklch(40.591% 0.12506 35.663) */;
|
||||||
|
--wa-color-orange-20: #5d1d0e /* oklch(32.908% 0.09683 34.387) */;
|
||||||
|
--wa-color-orange-10: #3a1005 /* oklch(24.088% 0.06954 35.613) */;
|
||||||
|
--wa-color-orange-05: #270803 /* oklch(18.801% 0.05509 34.149) */;
|
||||||
|
--wa-color-orange: var(--wa-color-orange-70);
|
||||||
|
--wa-color-orange-key: 70;
|
||||||
|
|
||||||
--wa-color-yellow-95: #fef3cd /* oklch(96.322% 0.05069 93.748) */;
|
--wa-color-yellow-95: #fef3cd /* oklch(96.322% 0.05069 93.748) */;
|
||||||
--wa-color-yellow-90: #ffe495 /* oklch(92.377% 0.10246 91.296) */;
|
--wa-color-yellow-90: #ffe495 /* oklch(92.377% 0.10246 91.296) */;
|
||||||
--wa-color-yellow-80: #fac22b /* oklch(84.185% 0.16263 85.991) */;
|
--wa-color-yellow-80: #fac22b /* oklch(84.185% 0.16263 85.991) */;
|
||||||
|
|||||||
@@ -16,6 +16,20 @@
|
|||||||
--wa-color-red: var(--wa-color-red-40);
|
--wa-color-red: var(--wa-color-red-40);
|
||||||
--wa-color-red-key: 40;
|
--wa-color-red-key: 40;
|
||||||
|
|
||||||
|
--wa-color-orange-95: oklch(96.238% 0.02664 61.788);
|
||||||
|
--wa-color-orange-90: #fbe1cc /* oklch(92.512% 0.04019 60.45) */;
|
||||||
|
--wa-color-orange-80: #edc1a0 /* oklch(84.097% 0.06661 58.236) */;
|
||||||
|
--wa-color-orange-70: #dda178 /* oklch(75.734% 0.09064 55.123) */;
|
||||||
|
--wa-color-orange-60: #cd8351 /* oklch(67.646% 0.1134 53.172) */;
|
||||||
|
--wa-color-orange-50: #b65d22 /* oklch(57.437% 0.13446 49.881) */;
|
||||||
|
--wa-color-orange-40: oklch(47.576% 0.13426 46.452);
|
||||||
|
--wa-color-orange-30: oklch(40.382% 0.12087 47.003);
|
||||||
|
--wa-color-orange-20: oklch(32.846% 0.0965 46.227);
|
||||||
|
--wa-color-orange-10: oklch(24.06% 0.06873 45.849);
|
||||||
|
--wa-color-orange-05: #260900 /* oklch(18.727% 0.05359 44.791) */;
|
||||||
|
--wa-color-orange: var(--wa-color-orange-50);
|
||||||
|
--wa-color-orange-key: 50;
|
||||||
|
|
||||||
--wa-color-yellow-95: #f7f4da /* oklch(96.266% 0.03422 101.63) */;
|
--wa-color-yellow-95: #f7f4da /* oklch(96.266% 0.03422 101.63) */;
|
||||||
--wa-color-yellow-90: #ede7c3 /* oklch(92.349% 0.04769 99.435) */;
|
--wa-color-yellow-90: #ede7c3 /* oklch(92.349% 0.04769 99.435) */;
|
||||||
--wa-color-yellow-80: #d8ca96 /* oklch(83.793% 0.06999 94.829) */;
|
--wa-color-yellow-80: #d8ca96 /* oklch(83.793% 0.06999 94.829) */;
|
||||||
|
|||||||
@@ -16,6 +16,20 @@
|
|||||||
--wa-color-red: var(--wa-color-red-40);
|
--wa-color-red: var(--wa-color-red-40);
|
||||||
--wa-color-red-key: 40;
|
--wa-color-red-key: 40;
|
||||||
|
|
||||||
|
--wa-color-orange-95: oklch(96.126% 0.05417 66.333);
|
||||||
|
--wa-color-orange-90: oklch(92.413% 0.07898 62.545);
|
||||||
|
--wa-color-orange-80: #f9bd86 /* oklch(84.088% 0.09891 63.847) */;
|
||||||
|
--wa-color-orange-70: #e2a05f /* oklch(75.707% 0.11352 64.057) */;
|
||||||
|
--wa-color-orange-60: #d18228 /* oklch(67.572% 0.13809 64.146) */;
|
||||||
|
--wa-color-orange-50: oklch(57.202% 0.13583 64.309);
|
||||||
|
--wa-color-orange-40: oklch(47.462% 0.13789 64.939);
|
||||||
|
--wa-color-orange-30: oklch(40.049% 0.12025 65.207);
|
||||||
|
--wa-color-orange-20: oklch(32.552% 0.09777 64.859);
|
||||||
|
--wa-color-orange-10: oklch(23.884% 0.07141 64.246);
|
||||||
|
--wa-color-orange-05: oklch(18.698% 0.05597 65.589);
|
||||||
|
--wa-color-orange: var(--wa-color-orange-60);
|
||||||
|
--wa-color-orange-key: 60;
|
||||||
|
|
||||||
--wa-color-yellow-95: #fff4b3 /* oklch(96.064% 0.08319 99.657) */;
|
--wa-color-yellow-95: #fff4b3 /* oklch(96.064% 0.08319 99.657) */;
|
||||||
--wa-color-yellow-90: #fee58c /* oklch(92.346% 0.11242 94.205) */;
|
--wa-color-yellow-90: #fee58c /* oklch(92.346% 0.11242 94.205) */;
|
||||||
--wa-color-yellow-80: #e3c868 /* oklch(83.63% 0.12003 93.943) */;
|
--wa-color-yellow-80: #e3c868 /* oklch(83.63% 0.12003 93.943) */;
|
||||||
|
|||||||
@@ -16,6 +16,20 @@
|
|||||||
--wa-color-red: var(--wa-color-red-50);
|
--wa-color-red: var(--wa-color-red-50);
|
||||||
--wa-color-red-key: 50;
|
--wa-color-red-key: 50;
|
||||||
|
|
||||||
|
--wa-color-orange-95: #f8f0ec /* oklch(96.084% 0.01043 54.557) */;
|
||||||
|
--wa-color-orange-90: #f2e3d8 /* oklch(92.485% 0.02211 56.694) */;
|
||||||
|
--wa-color-orange-80: #e4c4ad /* oklch(84.166% 0.04799 57.553) */;
|
||||||
|
--wa-color-orange-70: #d3a583 /* oklch(75.674% 0.07148 57.481) */;
|
||||||
|
--wa-color-orange-60: #bc8a65 /* oklch(67.319% 0.08062 57.054) */;
|
||||||
|
--wa-color-orange-50: #9e6940 /* oklch(56.757% 0.08845 56.746) */;
|
||||||
|
--wa-color-orange-40: #7e4d27 /* oklch(46.949% 0.08447 57.382) */;
|
||||||
|
--wa-color-orange-30: #673a17 /* oklch(39.774% 0.0793 55.768) */;
|
||||||
|
--wa-color-orange-20: #4f2906 /* oklch(32.45% 0.0725 57.629) */;
|
||||||
|
--wa-color-orange-10: #311702 /* oklch(23.759% 0.05361 57.126) */;
|
||||||
|
--wa-color-orange-05: #200d01 /* oklch(18.517% 0.04211 57.178) */;
|
||||||
|
--wa-color-orange: var(--wa-color-orange-50);
|
||||||
|
--wa-color-orange-key: 50;
|
||||||
|
|
||||||
--wa-color-yellow-95: #f6f1ea /* oklch(96.009% 0.01076 76.598) */;
|
--wa-color-yellow-95: #f6f1ea /* oklch(96.009% 0.01076 76.598) */;
|
||||||
--wa-color-yellow-90: #eee5d7 /* oklch(92.521% 0.02111 79.091) */;
|
--wa-color-yellow-90: #eee5d7 /* oklch(92.521% 0.02111 79.091) */;
|
||||||
--wa-color-yellow-80: #dbc8a8 /* oklch(84.033% 0.04791 80.753) */;
|
--wa-color-yellow-80: #dbc8a8 /* oklch(84.033% 0.04791 80.753) */;
|
||||||
|
|||||||
@@ -16,6 +16,20 @@
|
|||||||
--wa-color-red: var(--wa-color-red-50);
|
--wa-color-red: var(--wa-color-red-50);
|
||||||
--wa-color-red-key: 50;
|
--wa-color-red-key: 50;
|
||||||
|
|
||||||
|
--wa-color-orange-95: oklch(96.488% 0.04965 58.92);
|
||||||
|
--wa-color-orange-90: oklch(92.244% 0.08759 57.789);
|
||||||
|
--wa-color-orange-80: oklch(84.32% 0.12702 56.232);
|
||||||
|
--wa-color-orange-70: oklch(76.31% 0.17967 50.95);
|
||||||
|
--wa-color-orange-60: #e87431 /* oklch(68.352% 0.16354 47.083) */;
|
||||||
|
--wa-color-orange-50: oklch(58.23% 0.17947 43.3);
|
||||||
|
--wa-color-orange-40: oklch(48.089% 0.16071 40.798);
|
||||||
|
--wa-color-orange-30: oklch(40.708% 0.13699 39.616);
|
||||||
|
--wa-color-orange-20: oklch(33.124% 0.1121 39.599);
|
||||||
|
--wa-color-orange-10: oklch(24.257% 0.08204 39.602);
|
||||||
|
--wa-color-orange-05: oklch(18.966% 0.06414 39.606);
|
||||||
|
--wa-color-orange: var(--wa-color-orange-70);
|
||||||
|
--wa-color-orange-key: 70;
|
||||||
|
|
||||||
--wa-color-yellow-95: #fff5b4 /* oklch(96.281% 0.08306 100.4) */;
|
--wa-color-yellow-95: #fff5b4 /* oklch(96.281% 0.08306 100.4) */;
|
||||||
--wa-color-yellow-90: #fde572 /* oklch(91.915% 0.13738 97.724) */;
|
--wa-color-yellow-90: #fde572 /* oklch(91.915% 0.13738 97.724) */;
|
||||||
--wa-color-yellow-80: #f4c403 /* oklch(83.862% 0.17104 90.777) */;
|
--wa-color-yellow-80: #f4c403 /* oklch(83.862% 0.17104 90.777) */;
|
||||||
|
|||||||
@@ -24,15 +24,22 @@ for (let paletteId in palettes) {
|
|||||||
palettes[paletteId] = tokens;
|
palettes[paletteId] = tokens;
|
||||||
|
|
||||||
for (let hue in tokens) {
|
for (let hue in tokens) {
|
||||||
let tints = Object.assign({}, tokens[hue]);
|
let scale = Object.assign({}, tokens[hue]);
|
||||||
tokens[hue] = tints;
|
tokens[hue] = scale;
|
||||||
|
|
||||||
let maxChromaTint = DEFAULT_ACCENT;
|
let maxChromaTint = DEFAULT_ACCENT; // TODO handle scale.core
|
||||||
let maxChroma = tints[DEFAULT_ACCENT].c || 0;
|
let maxChroma = scale.core?.get('oklch.c') ?? (scale[DEFAULT_ACCENT].c || 0);
|
||||||
|
|
||||||
for (let tint in tints) {
|
for (let tint in scale) {
|
||||||
let color = tints[tint].to('oklch');
|
let color = scale[tint];
|
||||||
tints[tint] = color;
|
|
||||||
|
if (!color || color.constructor.name !== 'Color') {
|
||||||
|
// Not a color
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
color = color.to('oklch');
|
||||||
|
scale[tint] = color;
|
||||||
|
|
||||||
if (tint === '05') {
|
if (tint === '05') {
|
||||||
// The object has both '5' and '05' keys, but '05' is out of order
|
// The object has both '5' and '05' keys, but '05' is out of order
|
||||||
@@ -47,14 +54,14 @@ for (let paletteId in palettes) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tints['05'] = tints['5'];
|
scale['05'] = scale['5'];
|
||||||
|
|
||||||
tints.maxChroma = tints.maxChromaRaw = maxChroma;
|
scale.maxChroma = scale.maxChromaRaw = maxChroma;
|
||||||
tints.maxChromaTint = tints.maxChromaTintRaw = maxChromaTint;
|
scale.maxChromaTint = scale.maxChromaTintRaw = maxChromaTint;
|
||||||
|
|
||||||
if (maxChromaTint < MIN_ACCENT || maxChromaTint > MAX_ACCENT) {
|
if (maxChromaTint < MIN_ACCENT || maxChromaTint > MAX_ACCENT) {
|
||||||
tints.maxChromaTint = clamp(MIN_ACCENT, maxChromaTint, MAX_ACCENT);
|
scale.maxChromaTint = clamp(MIN_ACCENT, maxChromaTint, MAX_ACCENT);
|
||||||
tints.maxChroma = tints[maxChromaTint].c;
|
scale.maxChroma = scale[maxChromaTint].c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { PALETTE_DIR } from './util.js';
|
|||||||
|
|
||||||
export const paletteFiles = fs.readdirSync(PALETTE_DIR + '/').filter(file => file.endsWith('.css'));
|
export const paletteFiles = fs.readdirSync(PALETTE_DIR + '/').filter(file => file.endsWith('.css'));
|
||||||
export const declarationRegex =
|
export const declarationRegex =
|
||||||
/^\s*--wa-color-(?<hue>[a-z]+)-(?<level>[0-9]+):\s*(?<color>.+?)\s*(\/\*.+?\*\/)?\s*;$/gm;
|
/^\s*--wa-color-(?<hue>[a-z]+)(?:-(?<level>[0-9]+|key))?:\s*(?<color>.+?)\s*(\/\*.+?\*\/)?\s*;$/gm;
|
||||||
export const rawCSS = {};
|
export const rawCSS = {};
|
||||||
|
|
||||||
function parse(contents, file) {
|
function parse(contents, file) {
|
||||||
@@ -24,8 +24,24 @@ function parse(contents, file) {
|
|||||||
const ret = {};
|
const ret = {};
|
||||||
|
|
||||||
for (let match of matches) {
|
for (let match of matches) {
|
||||||
let { hue, level, color } = match.groups;
|
let { hue, level = '', color } = match.groups;
|
||||||
ret[hue] ??= {};
|
ret[hue] ??= {};
|
||||||
|
let scale = ret[hue];
|
||||||
|
|
||||||
|
if (level === 'key') {
|
||||||
|
scale.maxChromaTint = color;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!level) {
|
||||||
|
if (color.startsWith('var(')) {
|
||||||
|
// Core color aliased to another color, ignore
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Custom core color
|
||||||
|
level = 'core';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to convert color to Color object, fall back to string if this fails
|
// Attempt to convert color to Color object, fall back to string if this fails
|
||||||
// This will happen for e.g. colors defined via color-mix()
|
// This will happen for e.g. colors defined via color-mix()
|
||||||
@@ -38,13 +54,13 @@ function parse(contents, file) {
|
|||||||
if (level.startsWith('0')) {
|
if (level.startsWith('0')) {
|
||||||
// Leading zeroes throw off sorting, add both properties
|
// Leading zeroes throw off sorting, add both properties
|
||||||
// NOTE: Ideally one of the two would be added as non-enumerable, but then we cannot access it via 11ty data
|
// NOTE: Ideally one of the two would be added as non-enumerable, but then we cannot access it via 11ty data
|
||||||
ret[hue][level] = color;
|
scale[level] = color;
|
||||||
|
|
||||||
// Drop leading zeroes
|
// Drop leading zeroes
|
||||||
level = level.replace(/^0+/, '');
|
level = level.replace(/^0+/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
ret[hue][level] = color;
|
scale[level] = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
162
src/styles/color/scripts/postprocess.js
Normal file
162
src/styles/color/scripts/postprocess.js
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/**
|
||||||
|
* Post-process palette CSS files to add core colors, oklch coordinates etc.
|
||||||
|
* Run via node postprocess.js
|
||||||
|
* Warning: Will overwrite existing files. Check the diff before committing!
|
||||||
|
*/
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import palettes from './palettes-analyzed.js';
|
||||||
|
import { PALETTE_DIR, formatComparison, hueToChalk } from './util.js';
|
||||||
|
|
||||||
|
// TODO import from global data file instead of duplicating this data
|
||||||
|
const hues = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'indigo', 'purple', 'pink', 'gray'];
|
||||||
|
const huesChromatic = hues.slice(0, -1);
|
||||||
|
|
||||||
|
/** If a hue is missing, how should it be generated from the neighboring hues? */
|
||||||
|
const mixPercentage = { orange: 0.6 };
|
||||||
|
const selector = paletteId =>
|
||||||
|
[':where(:root)', ':host', ":where([class^='wa-theme-'], [class*=' wa-theme-'])", `.wa-palette-${paletteId}`].join(
|
||||||
|
',\n',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Used for formatting warnings
|
||||||
|
const paletteIdMaxChars = Object.keys(palettes).reduce((max, id) => Math.max(max, id.length), 0);
|
||||||
|
const hueMaxChars = Object.keys(palettes.default).reduce((max, id) => Math.max(max, id.length), 0);
|
||||||
|
|
||||||
|
const indent = ' ';
|
||||||
|
|
||||||
|
const paletteIssues = { total: 0 };
|
||||||
|
|
||||||
|
for (let paletteId in palettes) {
|
||||||
|
const palette = palettes[paletteId];
|
||||||
|
|
||||||
|
let paletteCSS = '';
|
||||||
|
let hueCSS = Object.fromEntries(hues.map(hue => [hue, '']));
|
||||||
|
|
||||||
|
for (let hue in palette) {
|
||||||
|
let scale = palette[hue];
|
||||||
|
|
||||||
|
if (scale.maxChromaTint != scale.maxChromaTintRaw) {
|
||||||
|
reportPaletteIssue(
|
||||||
|
`Clamping accent color to ${chalk.bold(scale.maxChromaTint)}, but peak chroma is in ${chalk.bold(scale.maxChromaTintRaw)} (${formatComparison(scale[scale.maxChromaTintRaw].c, scale[scale.maxChromaTint].c)})`,
|
||||||
|
{ paletteId, hue: hue },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
hueCSS[hue] += scaleCSS(hue, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate missing hues
|
||||||
|
for (let i = 0; i < hues.length; i++) {
|
||||||
|
let hue = hues[i];
|
||||||
|
|
||||||
|
if (hueCSS[hue]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find previous and next hue to interpolate
|
||||||
|
// We assume gaps will always be at most 1 hue wide
|
||||||
|
let prevHue = huesChromatic[i - 1] ?? huesChromatic.at(-1);
|
||||||
|
let nextHue = huesChromatic[i + 1] ?? huesChromatic[0];
|
||||||
|
|
||||||
|
reportPaletteIssue(`Missing hue. Generating from ${prevHue} and ${nextHue}`, { paletteId, hue });
|
||||||
|
|
||||||
|
let prevScale = palette[prevHue];
|
||||||
|
let nextScale = palette[nextHue];
|
||||||
|
|
||||||
|
let progress = mixPercentage[hue] ?? 0.5;
|
||||||
|
let scale = (palette[hue] = {});
|
||||||
|
|
||||||
|
scale.maxChromaTint = (1 - progress) * prevScale.maxChromaTint + progress * nextScale.maxChromaTint;
|
||||||
|
scale.maxChromaTint = Math.round(scale.maxChromaTint / 10) * 10;
|
||||||
|
|
||||||
|
for (let tint in prevScale) {
|
||||||
|
if (tint === '05' || !(tint > 0)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let prevColor = palette[prevHue][tint];
|
||||||
|
let nextColor = palette[nextHue][tint];
|
||||||
|
|
||||||
|
let color = prevColor.mix(nextColor, progress, { space: 'oklch' });
|
||||||
|
scale[tint] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure core color has the max chroma
|
||||||
|
let coreColor = scale[scale.maxChromaTint];
|
||||||
|
coreColor.c = Math.max(...Object.values(scale).map(color => color.c || 0)) + 0.0002;
|
||||||
|
|
||||||
|
hueCSS[hue] += scaleCSS(hue, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
hueCSS = Object.values(hueCSS).filter(Boolean).join('\n\n');
|
||||||
|
// TODO apply Prettier instead of faking it
|
||||||
|
paletteCSS = `${selector(paletteId)} {\n${hueCSS.trimEnd().replace(/^(?=\S)/gm, indent)}\n}\n`;
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(PALETTE_DIR, paletteId + '.css'), paletteCSS, 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
let issuePaletteCount = Object.keys(paletteIssues).length - 1;
|
||||||
|
console.info(
|
||||||
|
`🎨 Wrote ${Object.keys(palettes).length} palette files.` +
|
||||||
|
(paletteIssues.total > 0
|
||||||
|
? ` ${chalk.bold(paletteIssues.total)} issues found across ${chalk.bold(issuePaletteCount)} palettes.`
|
||||||
|
: ''),
|
||||||
|
);
|
||||||
|
|
||||||
|
function reportPaletteIssue(issue, { paletteId, hue }) {
|
||||||
|
let palettePrefix = `[${paletteId}]`.padEnd(paletteIdMaxChars + 2);
|
||||||
|
|
||||||
|
if (!paletteIssues[paletteId]) {
|
||||||
|
// First time encountering an issue with this palette
|
||||||
|
paletteIssues[paletteId] = { count: 0 };
|
||||||
|
} else {
|
||||||
|
// Don't print palette id multiple times
|
||||||
|
palettePrefix = ' '.repeat(paletteIdMaxChars + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
paletteIssues[paletteId].count++;
|
||||||
|
paletteIssues.total++;
|
||||||
|
|
||||||
|
let msg = palettePrefix;
|
||||||
|
let huePrefix = '';
|
||||||
|
|
||||||
|
if (hue) {
|
||||||
|
huePrefix = hueToChalk(hue)(hue.padEnd(hueMaxChars + 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(`${msg}${huePrefix}${issue}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function declareColor(color, hue, tint) {
|
||||||
|
tint = tint.padStart(2, '0');
|
||||||
|
let ret = `--wa-color-${hue}-${tint}: `;
|
||||||
|
|
||||||
|
if (color.inGamut('srgb')) {
|
||||||
|
ret += `${color.toString({ format: 'hex' })} /* ${color.toString()} */;`;
|
||||||
|
} else {
|
||||||
|
ret += `${color.toString()};`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scaleCSS(hue, scale) {
|
||||||
|
let ret = [];
|
||||||
|
for (let tint in scale) {
|
||||||
|
if (tint === '05' || !(tint > 0)) {
|
||||||
|
// The object has both '5' and '05' keys, but '05' is out of order
|
||||||
|
// Also ignore non-tints
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let color = scale[tint];
|
||||||
|
ret.push(declareColor(color, hue, tint));
|
||||||
|
}
|
||||||
|
ret.reverse();
|
||||||
|
|
||||||
|
ret.push(`--wa-color-${hue}: var(--wa-color-${hue}-${scale.maxChromaTint});`);
|
||||||
|
ret.push(`--wa-color-${hue}-key: ${scale.maxChromaTint};`);
|
||||||
|
return ret.join('\n');
|
||||||
|
}
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
/**
|
|
||||||
* Add tintless variables and OKLCH coords as comments to palette CSS files.
|
|
||||||
* Run via node tintless.js
|
|
||||||
* Warning: Will overwrite existing files. Check the diff before committing!
|
|
||||||
*/
|
|
||||||
import chalk from 'chalk';
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import palettes, { rawPalettes } from './palettes-analyzed.js';
|
|
||||||
import { PALETTE_DIR, formatComparison, hueToChalk } from './util.js';
|
|
||||||
|
|
||||||
const selector = paletteId =>
|
|
||||||
[':where(:root)', ':host', ":where([class^='wa-theme-'], [class*=' wa-theme-'])", `.wa-palette-${paletteId}`].join(
|
|
||||||
',\n',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Used for formatting warnings
|
|
||||||
const paletteIdMaxChars = Object.keys(palettes).reduce((max, id) => Math.max(max, id.length), 0);
|
|
||||||
const hueMaxChars = Object.keys(palettes.default).reduce((max, id) => Math.max(max, id.length), 0);
|
|
||||||
|
|
||||||
let issueCount = 0;
|
|
||||||
let issuePaletteCount = 0;
|
|
||||||
|
|
||||||
for (let paletteId in palettes) {
|
|
||||||
const tokens = palettes[paletteId];
|
|
||||||
|
|
||||||
let css = '';
|
|
||||||
let prefix = `[${paletteId}]`.padEnd(paletteIdMaxChars + 2);
|
|
||||||
|
|
||||||
for (let hue in tokens) {
|
|
||||||
let tints = tokens[hue];
|
|
||||||
|
|
||||||
let tintCSS = '';
|
|
||||||
|
|
||||||
for (let tint in tints) {
|
|
||||||
if (tint === '05' || !(tint > 0)) {
|
|
||||||
// The object has both '5' and '05' keys, but '05' is out of order
|
|
||||||
// Also ignore non-tints
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let color = tints[tint];
|
|
||||||
tint = tint.padStart(2, '0');
|
|
||||||
|
|
||||||
tintCSS =
|
|
||||||
`--wa-color-${hue}-${tint}: ${color.toString({ format: 'hex' })} /* ${color.toString()} */;\n` + tintCSS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tints.maxChromaTint != tints.maxChromaTintRaw) {
|
|
||||||
let huePrefix = hueToChalk(hue)(hue.padEnd(hueMaxChars + 2));
|
|
||||||
|
|
||||||
console.warn(
|
|
||||||
`${prefix} ${huePrefix}: Clamping accent color to ${chalk.bold(tints.maxChromaTint)}, but peak chroma is in ${chalk.bold(tints.maxChromaTintRaw)} (${formatComparison(tints[tints.maxChromaTintRaw].c, tints[tints.maxChromaTint].c)})`,
|
|
||||||
);
|
|
||||||
issueCount++;
|
|
||||||
|
|
||||||
if (prefix.trim()) {
|
|
||||||
// First time encountering an issue with this palette
|
|
||||||
issuePaletteCount++;
|
|
||||||
|
|
||||||
// Don't print palette id multiple times
|
|
||||||
prefix = ' '.repeat(paletteIdMaxChars + 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tintCSS += `--wa-color-${hue}: var(--wa-color-${hue}-${tints.maxChromaTint});\n`;
|
|
||||||
tintCSS += `--wa-color-${hue}-key: ${tints.maxChromaTint};\n`;
|
|
||||||
css += tintCSS + '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
let indent = ' ';
|
|
||||||
css = `${selector(paletteId)} {\n${css.trimEnd().replace(/^(?=\S)/gm, indent)}\n}\n`;
|
|
||||||
|
|
||||||
fs.writeFileSync(path.join(PALETTE_DIR, paletteId + '.css'), css, 'utf8');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.info(
|
|
||||||
`🎨 Wrote ${Object.keys(palettes).length} palette files.` +
|
|
||||||
(issueCount > 0 ? ` ${chalk.bold(issueCount)} issues found across ${chalk.bold(issuePaletteCount)} palettes.` : ''),
|
|
||||||
);
|
|
||||||
@@ -16,6 +16,20 @@
|
|||||||
--wa-color-red: var(--wa-color-red-50);
|
--wa-color-red: var(--wa-color-red-50);
|
||||||
--wa-color-red-key: 50;
|
--wa-color-red-key: 50;
|
||||||
|
|
||||||
|
--wa-color-orange-95: oklch(96.355% 0.05982 62.448);
|
||||||
|
--wa-color-orange-90: oklch(92.371% 0.10134 60.314);
|
||||||
|
--wa-color-orange-80: oklch(84.228% 0.13101 54.157);
|
||||||
|
--wa-color-orange-70: oklch(76.275% 0.16839 51.143);
|
||||||
|
--wa-color-orange-60: #e67530 /* oklch(68.22% 0.16179 47.997) */;
|
||||||
|
--wa-color-orange-50: oklch(58.011% 0.16819 44.953);
|
||||||
|
--wa-color-orange-40: #9b390d /* oklch(47.739% 0.14004 40.585) */;
|
||||||
|
--wa-color-orange-30: #7a2b17 /* oklch(40.323% 0.11475 35.602) */;
|
||||||
|
--wa-color-orange-20: #5c1e0f /* oklch(32.963% 0.09552 34.666) */;
|
||||||
|
--wa-color-orange-10: #3a0f06 /* oklch(24.042% 0.07066 34.715) */;
|
||||||
|
--wa-color-orange-05: #270803 /* oklch(18.867% 0.05444 34.696) */;
|
||||||
|
--wa-color-orange: var(--wa-color-orange-70);
|
||||||
|
--wa-color-orange-key: 70;
|
||||||
|
|
||||||
--wa-color-yellow-95: #fef6ab /* oklch(96.234% 0.09455 102.83) */;
|
--wa-color-yellow-95: #fef6ab /* oklch(96.234% 0.09455 102.83) */;
|
||||||
--wa-color-yellow-90: #fde761 /* oklch(92.138% 0.15325 99.997) */;
|
--wa-color-yellow-90: #fde761 /* oklch(92.138% 0.15325 99.997) */;
|
||||||
--wa-color-yellow-80: #f5c308 /* oklch(83.774% 0.17019 89.81) */;
|
--wa-color-yellow-80: #f5c308 /* oklch(83.774% 0.17019 89.81) */;
|
||||||
|
|||||||
@@ -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'];
|
|
||||||
@@ -121,7 +121,8 @@ input:where(:not(
|
|||||||
font: inherit;
|
font: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wa-pill,
|
input.wa-pill,
|
||||||
:host([pill]) {
|
textarea.wa-pill,
|
||||||
border-radius: var(--wa-border-radius-pill);
|
:host([pill]) .wa-text-field {
|
||||||
|
border-radius: var(--wa-border-radius-pill) !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ input[type='range'] {
|
|||||||
0 0 0 var(--thumb-gap) var(--wa-color-surface-default);
|
0 0 0 var(--thumb-gap) var(--wa-color-surface-default);
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
margin-top: calc(var(--thumb-size) / -2 + var(--track-height) / 2);
|
margin-top: calc(var(--thumb-size) / -2 + var(--track-height) / 2);
|
||||||
|
transition: var(--wa-transition-fast);
|
||||||
|
transition-property: width, height;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:enabled {
|
&:enabled {
|
||||||
|
|||||||
@@ -45,7 +45,8 @@
|
|||||||
|
|
||||||
--outlined-border-color: var(--wa-color-border-normal);
|
--outlined-border-color: var(--wa-color-border-normal);
|
||||||
|
|
||||||
--text-color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
|
--text-color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
|
||||||
|
--text-color-hover: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
|
||||||
}
|
}
|
||||||
|
|
||||||
.wa-plain,
|
.wa-plain,
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
:host {
|
:host {
|
||||||
/* Components are meant to override these */
|
/* Components are meant to override these */
|
||||||
--size-xs: var(--wa-space-xs);
|
--size-xs: var(--wa-font-size-xs);
|
||||||
--size-s: var(--wa-space-s);
|
--size-s: var(--wa-font-size-s);
|
||||||
--size-m: var(--wa-space-m);
|
--size-m: var(--wa-font-size-m);
|
||||||
--size-l: var(--wa-space-l);
|
--size-l: var(--wa-font-size-l);
|
||||||
|
|
||||||
--space-xs: var(--wa-space-xs);
|
--space-xs: var(--wa-space-xs);
|
||||||
--space-s: var(--wa-space-s);
|
--space-s: var(--wa-space-s);
|
||||||
|
|||||||
@@ -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.
|
* Register color properties so that the space toggle hack can work.
|
||||||
*/
|
*/
|
||||||
@@ -61,6 +64,7 @@
|
|||||||
* Element defaults.
|
* Element defaults.
|
||||||
We want these to resolve to inherit when inside a variant, and only be applied when not inside an explicit variant.
|
We want these to resolve to inherit when inside a variant, and only be applied when not inside an explicit variant.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
:host(wa-button),
|
:host(wa-button),
|
||||||
.wa-button,
|
.wa-button,
|
||||||
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