mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-19 07:29:14 +00:00
Compare commits
3 Commits
lm/theming
...
slider-fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18e5612564 | ||
|
|
99c6e68aa4 | ||
|
|
6403588285 |
@@ -20,5 +20,4 @@ packages/**/*/src/react/index.ts
|
||||
node_modules
|
||||
|
||||
packages/**/*/_site
|
||||
packages/**/*/_bundle_
|
||||
packages/webawesome/docs/assets/scripts/prism-downloaded.js
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
3.0.0
|
||||
3.1.0
|
||||
|
||||
@@ -70,7 +70,6 @@
|
||||
"exportparts",
|
||||
"fetchpriority",
|
||||
"fieldsets",
|
||||
"flexbox",
|
||||
"focusin",
|
||||
"focusout",
|
||||
"fontawesome",
|
||||
@@ -152,7 +151,6 @@
|
||||
"ParamagicDev",
|
||||
"peta",
|
||||
"petabit",
|
||||
"pointercancel",
|
||||
"Preact",
|
||||
"preconnect",
|
||||
"prerendered",
|
||||
@@ -206,8 +204,6 @@
|
||||
"thead",
|
||||
"Themer",
|
||||
"tinycolor",
|
||||
"touchcancel",
|
||||
"touchend",
|
||||
"transitionend",
|
||||
"treeitem",
|
||||
"treeshaking",
|
||||
@@ -241,6 +237,8 @@
|
||||
"src/translations/!(en).ts",
|
||||
"**/*.min.js"
|
||||
],
|
||||
"ignoreRegExpList": ["(^|[^a-z])sl[a-z]*(^|[^a-z])"],
|
||||
"ignoreRegExpList": [
|
||||
"(^|[^a-z])sl[a-z]*(^|[^a-z])"
|
||||
],
|
||||
"useGitignore": true
|
||||
}
|
||||
|
||||
183
package-lock.json
generated
183
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@webawesome/monorepo",
|
||||
"version": "3.1.0",
|
||||
"version": "3.0.0-alpha.13",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@webawesome/monorepo",
|
||||
"version": "3.1.0",
|
||||
"version": "3.0.0-alpha.13",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
@@ -593,10 +593,6 @@
|
||||
"resolved": "packages/webawesome",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@awesome.me/webawesome-pro": {
|
||||
"resolved": "packages/webawesome-pro",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.23.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
|
||||
@@ -2523,6 +2519,10 @@
|
||||
"resolved": "https://registry.npmjs.org/@shoelace-style/localize/-/localize-3.2.1.tgz",
|
||||
"integrity": "sha512-r4C9C/5kSfMBIr0D9imvpRdCNXtUNgyYThc4YlS6K5Hchv1UyxNQ9mxwj+BTRH2i1Neits260sR3OjKMnplsFA=="
|
||||
},
|
||||
"node_modules/@shoelace-style/webawesome-pro": {
|
||||
"resolved": "packages/webawesome-pro",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
|
||||
@@ -12139,16 +12139,6 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-typescript-paths": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-typescript-paths/-/rollup-plugin-typescript-paths-1.5.0.tgz",
|
||||
"integrity": "sha512-zly2aiGNjYJNq5YUi6eyGrQnCYUQ8b5czOtHZIGriwG9U3Ba2F9hlSklafXCdsNulK/IlNmE0Kzj0h+fVV32pA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"typescript": ">=3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/run-async": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
|
||||
@@ -14023,7 +14013,7 @@
|
||||
},
|
||||
"packages/webawesome": {
|
||||
"name": "@awesome.me/webawesome",
|
||||
"version": "3.1.0",
|
||||
"version": "3.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ctrl/tinycolor": "4.1.0",
|
||||
@@ -14047,8 +14037,8 @@
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro": {
|
||||
"name": "@awesome.me/webawesome-pro",
|
||||
"version": "3.1.0",
|
||||
"name": "@shoelace-style/webawesome-pro",
|
||||
"version": "3.0.0",
|
||||
"dependencies": {
|
||||
"@ctrl/tinycolor": "4.1.0",
|
||||
"@floating-ui/dom": "^1.6.13",
|
||||
@@ -14062,11 +14052,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wc-toolkit/jsx-types": "^1.3.0",
|
||||
"@web/dev-server-rollup": "^0.6.4",
|
||||
"eleventy-plugin-git-commit-date": "^0.1.3",
|
||||
"esbuild": "^0.25.11",
|
||||
"npm-check-updates": "^19.1.2",
|
||||
"rollup-plugin-typescript-paths": "^1.5.0"
|
||||
"npm-check-updates": "^19.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17.0"
|
||||
@@ -14480,84 +14468,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/@web/dev-server-core": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@web/dev-server-core/-/dev-server-core-0.7.5.tgz",
|
||||
"integrity": "sha512-Da65zsiN6iZPMRuj4Oa6YPwvsmZmo5gtPWhW2lx3GTUf5CAEapjVpZVlUXnKPL7M7zRuk72jSsIl8lo+XpTCtw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/koa": "^2.11.6",
|
||||
"@types/ws": "^7.4.0",
|
||||
"@web/parse5-utils": "^2.1.0",
|
||||
"chokidar": "^4.0.1",
|
||||
"clone": "^2.1.2",
|
||||
"es-module-lexer": "^1.0.0",
|
||||
"get-stream": "^6.0.0",
|
||||
"is-stream": "^2.0.0",
|
||||
"isbinaryfile": "^5.0.0",
|
||||
"koa": "^2.13.0",
|
||||
"koa-etag": "^4.0.0",
|
||||
"koa-send": "^5.0.1",
|
||||
"koa-static": "^5.0.0",
|
||||
"lru-cache": "^8.0.4",
|
||||
"mime-types": "^2.1.27",
|
||||
"parse5": "^6.0.1",
|
||||
"picomatch": "^2.2.2",
|
||||
"ws": "^7.5.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/@web/dev-server-rollup": {
|
||||
"version": "0.6.4",
|
||||
"resolved": "https://registry.npmjs.org/@web/dev-server-rollup/-/dev-server-rollup-0.6.4.tgz",
|
||||
"integrity": "sha512-sJZfTGCCrdku5xYnQQG51odGI092hKY9YFM0X3Z0tRY3iXKXcYRaLZrErw5KfCxr6g0JRuhe4BBhqXTA5Q2I3Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"@web/dev-server-core": "^0.7.2",
|
||||
"nanocolors": "^0.2.1",
|
||||
"parse5": "^6.0.1",
|
||||
"rollup": "^4.4.0",
|
||||
"whatwg-url": "^14.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/@web/parse5-utils": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@web/parse5-utils/-/parse5-utils-2.1.0.tgz",
|
||||
"integrity": "sha512-GzfK5disEJ6wEjoPwx8AVNwUe9gYIiwc+x//QYxYDAFKUp4Xb1OJAGLc2l2gVrSQmtPGLKrTRcW90Hv4pEq1qA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/parse5": "^6.0.1",
|
||||
"parse5": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/chokidar": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/esbuild": {
|
||||
"version": "0.25.11",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.11.tgz",
|
||||
@@ -14600,16 +14510,6 @@
|
||||
"@esbuild/win32-x64": "0.25.11"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/lru-cache": {
|
||||
"version": "8.0.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
|
||||
"integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16.14"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/nanoid": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz",
|
||||
@@ -14642,69 +14542,6 @@
|
||||
"npm": ">=8.12.1"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/readdirp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/tr46": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
|
||||
"integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/whatwg-url": {
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
|
||||
"integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tr46": "^5.1.0",
|
||||
"webidl-conversions": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"packages/webawesome-pro/node_modules/ws": {
|
||||
"version": "7.5.10",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
||||
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages/webawesome/node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.25.11",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@webawesome/monorepo",
|
||||
"private": true,
|
||||
"description": "A forward-thinking library of web components.",
|
||||
"version": "3.1.0",
|
||||
"version": "3.0.0",
|
||||
"homepage": "https://webawesome.com/",
|
||||
"author": "Web Awesome",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -196,8 +196,6 @@
|
||||
</h2>
|
||||
<ul>
|
||||
<li><a href="/docs/utilities/align-items/">Align Items</a></li>
|
||||
<!-- Pending 3.2.0 release -->
|
||||
<!-- <li><a href="/docs/utilities/justify-content/">Justify Content</a></li> -->
|
||||
<li><a href="/docs/utilities/gap/">Gap</a></li>
|
||||
<li><a href="/docs/utilities/cluster/">Cluster</a></li>
|
||||
<li><a href="/docs/utilities/flank/">Flank</a></li>
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
{% for palette in themer.palettes %}
|
||||
<link rel="stylesheet" href="/dist/styles/color/palettes/{{palette.filename}}" />
|
||||
{% endfor %}
|
||||
|
||||
<div id="color-palettes" class="wa-stack wa-gap-xl">
|
||||
<wa-radio-group id="palette-picker" value="default" class="radio-cards">
|
||||
<span slot="label" class="wa-visually-hidden">Color Palette</span>
|
||||
<div class="wa-grid">
|
||||
{%- for palette in themer.palettes -%}
|
||||
{%- if not palette.isPro -%}
|
||||
<wa-radio value="{{ palette.name | lower }}">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span>{{ palette.name }}</span>
|
||||
<div class="wa-palette-{{ palette.name | lower }} palette-preview wa-grid wa-gap-3xs">
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
</div>
|
||||
</div>
|
||||
</wa-radio>
|
||||
{%- else -%}
|
||||
{% raw %}{%- if currentUser.hasPro -%}{% endraw %}
|
||||
<wa-radio value="{{ palette.name | lower }}">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span>{{ palette.name }}</span>
|
||||
<div class="wa-palette-{{ palette.name | lower }} palette-preview wa-grid wa-gap-3xs">
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
<span class="preview-swatch"></span>
|
||||
</div>
|
||||
</div>
|
||||
</wa-radio>
|
||||
{% raw %}{%- endif -%}{% endraw %}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</wa-radio-group>
|
||||
|
||||
<div id="palette" class="wa-stack wa-gap-xs">
|
||||
{%- for color in themer.colors -%}
|
||||
<div class="color-scale wa-flank wa-gap-xs">
|
||||
<div class="color-name">{{ color }}</div>
|
||||
<div class="color-swatches wa-grid wa-gap-2xs">
|
||||
{%- for tint in themer.tints -%}
|
||||
<wa-copy-button
|
||||
class="color-swatch"
|
||||
copy-label="{{ color }} {{ tint }}"
|
||||
value="var(--wa-color-{{ color }}-{{ tint }})"
|
||||
style="--color: var(--wa-color-{{ color }}-{{ tint }}); --tint: '{{ tint }}'"
|
||||
>
|
||||
<span class="wa-visually-hidden">--wa-color-{{ color }}-{{ tint }}</span>
|
||||
</wa-copy-button>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
const paletteContainer = document.getElementById('color-palettes');
|
||||
const palettePreviewPicker = document.getElementById('palette-picker');
|
||||
|
||||
// Set first radio as checked and add initial palette class
|
||||
const firstPaletteRadio = palettePreviewPicker.querySelector('wa-radio');
|
||||
if (firstPaletteRadio) {
|
||||
firstPaletteRadio.checked = true;
|
||||
paletteContainer.classList.add(`wa-palette-${firstPaletteRadio.value}`);
|
||||
}
|
||||
|
||||
// Listen for radio changes
|
||||
palettePreviewPicker.addEventListener('input', function(event) {
|
||||
const selectedValue = event.target.value;
|
||||
|
||||
// Update palette container class
|
||||
const existingThemeClasses = [...paletteContainer.classList].filter(className => className.startsWith('wa-palette-'));
|
||||
existingThemeClasses.forEach(className => paletteContainer.classList.remove(className));
|
||||
paletteContainer.classList.add(`wa-palette-${selectedValue}`);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#color-palettes:has(+ *) {
|
||||
margin-block-end: var(--wa-content-spacing);
|
||||
}
|
||||
|
||||
wa-radio-group.radio-cards {
|
||||
&::part(form-control-input) {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
> .wa-grid {
|
||||
--max-column-count: 3;
|
||||
--min-column-size: 12ch;
|
||||
|
||||
--_max-gap-count: calc(var(--max-column-count) - 1);
|
||||
--_gap-width-sum: calc(var(--_max-gap-count) * var(--wa-space-m));
|
||||
--_max-column-width: calc((100% - var(--_gap-width-sum)) / var(--max-column-count));
|
||||
|
||||
grid-template-columns: repeat(auto-fill, minmax(max(var(--min-column-size), var(--_max-column-width)), 1fr));
|
||||
}
|
||||
|
||||
wa-radio {
|
||||
display: block;
|
||||
inline-size: var(--popover-min-inline-size);
|
||||
background-color: var(--wa-form-control-background-color);
|
||||
border: var(--wa-form-control-border-width) var(--wa-form-control-border-style) var(--wa-color-neutral-border-quiet);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
padding: 0.75em;
|
||||
font-size: var(--wa-font-size-s);
|
||||
color: var(--wa-color-text-quiet);
|
||||
|
||||
&::part(control) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::part(label) {
|
||||
font-weight: var(--wa-font-weight-bold);
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
&:hover {
|
||||
border-color: var(--wa-color-neutral-border-normal);
|
||||
}
|
||||
}
|
||||
|
||||
&:state(checked) {
|
||||
border-color: var(--wa-color-neutral-border-loud);
|
||||
box-shadow: 0 0 0 0.0625rem var(--wa-color-neutral-border-loud);
|
||||
color: var(--wa-color-text-normal);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: var(--wa-focus-ring);
|
||||
outline-offset: var(--wa-focus-ring-offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.palette-preview {
|
||||
--min-column-size: 0rem;
|
||||
}
|
||||
|
||||
.preview-swatch {
|
||||
aspect-ratio: 1 / 1;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
|
||||
&:nth-child(1) {
|
||||
background-color: var(--wa-color-red);
|
||||
}
|
||||
&:nth-child(2) {
|
||||
background-color: var(--wa-color-orange);
|
||||
}
|
||||
&:nth-child(3) {
|
||||
background-color: var(--wa-color-yellow);
|
||||
}
|
||||
&:nth-child(4) {
|
||||
background-color: var(--wa-color-green);
|
||||
}
|
||||
&:nth-child(5) {
|
||||
background-color: var(--wa-color-cyan);
|
||||
}
|
||||
&:nth-child(6) {
|
||||
background-color: var(--wa-color-blue);
|
||||
}
|
||||
&:nth-child(7) {
|
||||
background-color: var(--wa-color-indigo);
|
||||
}
|
||||
&:nth-child(8) {
|
||||
background-color: var(--wa-color-purple);
|
||||
}
|
||||
&:nth-child(9) {
|
||||
background-color: var(--wa-color-pink);
|
||||
}
|
||||
&:nth-child(10) {
|
||||
background-color: var(--wa-color-gray);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,302 +0,0 @@
|
||||
{% from "pro-badge.njk" import proBadge %}
|
||||
{% from "free-badge.njk" import freeBadge %}
|
||||
|
||||
<div id="using-themes">
|
||||
<fieldset class="theme-options wa-stack" style="margin-block-end: var(--wa-content-spacing);">
|
||||
<legend style="align-self: start;">Theme Options</legend>
|
||||
<wa-select id="pick-theme" label="Theme" value="default" size="small">
|
||||
<wa-badge slot="end" appearance="accent" pill class="pro pro-only-value">Pro</wa-badge>
|
||||
{%- for theme in themer.themes -%}
|
||||
{%- if not theme.isPro -%}
|
||||
<wa-option
|
||||
value="{{ theme.name | lower }}"
|
||||
data-palette="{{ theme.palette.filename | stripExtension}}"
|
||||
data-brand="{{ theme.colorBrand.color }}"
|
||||
>
|
||||
{{ theme.name | capitalize }}
|
||||
</wa-option>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{% raw %}{% if currentUser.hasPro %}{% endraw %}
|
||||
{%- for theme in themer.themes -%}
|
||||
{% if loop.first %}<wa-divider></wa-divider>{% endif %}
|
||||
{%- if theme.isPro -%}
|
||||
<wa-option
|
||||
value="{{ theme.name | lower }}"
|
||||
data-palette="{{ theme.palette.filename | stripExtension}}"
|
||||
data-brand="{{ theme.colorBrand.color }}"
|
||||
{% if theme.isPro %}data-is-pro{% endif %}
|
||||
>
|
||||
{{ theme.name | capitalize }}
|
||||
</wa-option>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{% raw %}{% endif %}{% endraw %}
|
||||
</wa-select>
|
||||
<wa-select id="pick-palette" label="Color Palette" value="default" size="small">
|
||||
<wa-badge slot="end" appearance="accent" pill class="pro pro-only-value">Pro</wa-badge>
|
||||
{%- for palette in themer.palettes -%}
|
||||
{%- if not palette.isPro -%}
|
||||
<wa-option
|
||||
value="{{ palette.name | lower }}"
|
||||
>
|
||||
{{ palette.name | capitalize }}
|
||||
</wa-option>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{% raw %}{% if currentUser.hasPro %}{% endraw %}
|
||||
{%- for palette in themer.palettes -%}
|
||||
{% if loop.first %}<wa-divider></wa-divider>{% endif %}
|
||||
{%- if palette.isPro -%}
|
||||
<wa-option
|
||||
value="{{ palette.name | lower }}"
|
||||
{% if palette.isPro %}data-is-pro{% endif %}
|
||||
>
|
||||
{{ palette.name | capitalize }}
|
||||
</wa-option>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{% raw %}{% endif %}{% endraw %}
|
||||
</wa-select>
|
||||
<div class="wa-grid">
|
||||
{%- set colorVariants = ['brand', 'neutral', 'success', 'warning', 'danger'] -%}
|
||||
{%- for colorVariant in colorVariants -%}
|
||||
<wa-select id="pick-{{ colorVariant }}" label="{{ colorVariant | capitalize }}" size="small">
|
||||
<wa-icon slot="start" name="square" class="selected-color"></wa-icon>
|
||||
{%- for color in themer.colors -%}
|
||||
<wa-option value="{{ color }}">
|
||||
{{ color | capitalize }}
|
||||
<wa-icon slot="start" name="square" style="--color: var(--wa-color-{{ color }}); color: var(--color);"></wa-icon>
|
||||
</wa-option>
|
||||
{%- endfor -%}
|
||||
</wa-select>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<wa-tab-group>
|
||||
<wa-tab panel="cdn"><wa-icon name="rocket-launch" variant="regular"></wa-icon> CDN</wa-tab>
|
||||
<wa-tab panel="npm"><wa-icon name="box-open" variant="regular"></wa-icon> npm</wa-tab>
|
||||
<wa-tab panel="self-hosted"><wa-icon name="arrow-down-to-line" variant="regular"></wa-icon> Self-Hosted</wa-tab>
|
||||
|
||||
<wa-tab-panel name="cdn">
|
||||
<div class="wa-stack wa-gap-xl">
|
||||
<wa-callout variant="neutral" size="small" id="pro-only-callout">
|
||||
<wa-icon name="info-circle" variant="regular"></wa-icon>
|
||||
This combination can only be used on teams with a Pro subscription.
|
||||
</wa-callout>
|
||||
<div id="free-instructions">
|
||||
<strong>For projects on <wa-badge appearance="filled" variant="neutral" pill class="free">Free</wa-badge> teams:</strong>
|
||||
<ol>
|
||||
<li>Head over to your project's <wa-icon name="gear" variant="regular"></wa-icon> <strong>Settings</strong>.</li>
|
||||
<li>For <strong>Theme</strong>, select <wa-icon name="paintbrush" variant="regular"></wa-icon> <strong class="theme-name"></strong>.</li>
|
||||
<li>For <strong>Color Palette</strong>, select <wa-icon name="swatchbook" variant="regular"></wa-icon> <strong class="palette-name"></strong>.</li>
|
||||
<li>Press <strong>Save Changes</strong> to update anywhere you're using your project.</li>
|
||||
<li class="custom-variants">In your own files, apply the following classes to the <code><html></code> element:<br />
|
||||
<pre><code class="variant-classes" class="language-html"></code></pre>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div id="pro-instructions">
|
||||
<strong>For projects on <wa-badge appearance="accent" pill class="pro">Pro</wa-badge> teams:</strong>
|
||||
<ol>
|
||||
<li>Head over to your project's <wa-icon name="gear" variant="regular"></wa-icon> <strong>Settings</strong>.</li>
|
||||
<li>Press <wa-icon name="paintbrush" variant="regular"></wa-icon> <strong>Edit Your Theme</strong> to open the Theme Builder.</li>
|
||||
<li>Open <strong>Theme</strong> and select <strong class="theme-name"></strong>.</li>
|
||||
<li>Open <strong>Colors</strong>. On the <strong>Basic</strong> tab, select <strong class="palette-name"></strong>. <span class="custom-variants">On the <strong>Advanced</strong> tab, select your preferred variant colors.</span></li>
|
||||
<li>Press <strong>Save Changes</strong> to update anywhere you're using your project.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</wa-tab-panel>
|
||||
|
||||
<wa-tab-panel name="npm">
|
||||
<p>To use this theme, include the following stylesheet(s):</p>
|
||||
<pre><code id="stylesheet-imports" class="language-html"></code></pre>
|
||||
<p>Then, apply the following classes to the <code><html></code> element:</p>
|
||||
<pre><code class="html-classes" class="language-html"></code></pre>
|
||||
</wa-tab-panel>
|
||||
|
||||
<wa-tab-panel name="self-hosted">
|
||||
<p>To use this theme, include the following stylesheet(s):</p>
|
||||
<pre><code id="stylesheet-links" class="language-html"></code></pre>
|
||||
<p>Then, apply the following classes to the <code><html></code> element:</p>
|
||||
<pre><code class="html-classes" class="language-html"></code></pre>
|
||||
</wa-tab-panel>
|
||||
</wa-tab-group>
|
||||
|
||||
<script type="module">
|
||||
const themePicker = document.getElementById('pick-theme');
|
||||
const palettePicker = document.getElementById('pick-palette');
|
||||
const brandPicker = document.getElementById('pick-brand');
|
||||
const neutralPicker = document.getElementById('pick-neutral');
|
||||
const successPicker = document.getElementById('pick-success');
|
||||
const warningPicker = document.getElementById('pick-warning');
|
||||
const dangerPicker = document.getElementById('pick-danger');
|
||||
|
||||
const stylesheetLinks = document.getElementById('stylesheet-links');
|
||||
const stylesheetImports = document.getElementById('stylesheet-imports');
|
||||
const htmlClassList = document.querySelectorAll('.html-classes');
|
||||
const variantClassList = document.querySelectorAll('.variant-classes');
|
||||
const themeNames = document.querySelectorAll('.theme-name');
|
||||
const paletteNames = document.querySelectorAll('.palette-name');
|
||||
|
||||
// Default values for color variants
|
||||
const defaultColors = {
|
||||
brand: 'blue',
|
||||
neutral: 'gray',
|
||||
success: 'green',
|
||||
warning: 'yellow',
|
||||
danger: 'red'
|
||||
};
|
||||
|
||||
// Update dynamic instructions based on current picker values
|
||||
function updateInstructions() {
|
||||
const theme = themePicker.value;
|
||||
const palette = palettePicker.value;
|
||||
const brand = brandPicker.value;
|
||||
const neutral = neutralPicker.value;
|
||||
const success = successPicker.value;
|
||||
const warning = warningPicker.value;
|
||||
const danger = dangerPicker.value;
|
||||
|
||||
// Get the default palette for the selected theme
|
||||
const selectedThemeOption = themePicker.querySelector(`wa-option[value="${theme}"]`);
|
||||
const themeDefaultPalette = selectedThemeOption?.getAttribute('data-palette') || 'default';
|
||||
const proOnlyTheme = selectedThemeOption?.hasAttribute('data-is-pro') || false;
|
||||
const proOnlyPalette = palettePicker.querySelector(`wa-option[value="${palette}"]`)?.hasAttribute('data-is-pro') || false;
|
||||
|
||||
// Show/hide Pro-only callout
|
||||
const proOnlyCallout = document.getElementById('pro-only-callout');
|
||||
const freeInstructions = document.getElementById('free-instructions');
|
||||
if (proOnlyTheme || proOnlyPalette) {
|
||||
proOnlyCallout.style.display = '';
|
||||
freeInstructions.style.display = 'none';
|
||||
} else {
|
||||
proOnlyCallout.style.display = 'none';
|
||||
freeInstructions.style.display = '';
|
||||
}
|
||||
|
||||
// Show/hide Pro badge on selected Pro values
|
||||
document.querySelectorAll('.pro-only-value').forEach(badge => {
|
||||
if ((badge.parentElement.id === 'pick-theme' && proOnlyTheme) ||
|
||||
(badge.parentElement.id === 'pick-palette' && proOnlyPalette)) {
|
||||
badge.style.display = '';
|
||||
} else {
|
||||
badge.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Build stylesheet links
|
||||
const links = [`<link rel="stylesheet" href="/dist/styles/themes/${theme}.css" />`];
|
||||
const imports = [`import '@awesome.me/webawesome/dist/styles/themes/${theme}.css';`];
|
||||
|
||||
// Only include palette link if it differs from theme's default
|
||||
if (palette !== themeDefaultPalette) {
|
||||
links.push(`<link rel="stylesheet" href="/dist/styles/color/palettes/${palette}.css" />`);
|
||||
imports.push(`import '@awesome.me/webawesome/dist/styles/color/palettes/${palette}.css';`);
|
||||
}
|
||||
|
||||
stylesheetLinks.textContent = links.join('\n');
|
||||
stylesheetImports.textContent = imports.join('\n');
|
||||
|
||||
// Build HTML classes
|
||||
const classes = [`wa-theme-${theme}`];
|
||||
const variantClasses = [];
|
||||
|
||||
// Only include palette class if it differs from theme's default
|
||||
if (palette !== themeDefaultPalette) {
|
||||
classes.push(`wa-palette-${palette}`);
|
||||
}
|
||||
|
||||
// Only include color classes if they differ from defaults
|
||||
if (brand !== defaultColors.brand) {
|
||||
[classes, variantClasses].forEach(classList => classList.push(`wa-brand-${brand}`));
|
||||
}
|
||||
if (neutral !== defaultColors.neutral) {
|
||||
[classes, variantClasses].forEach(classList => classList.push(`wa-neutral-${neutral}`));
|
||||
}
|
||||
if (success !== defaultColors.success) {
|
||||
[classes, variantClasses].forEach(classList => classList.push(`wa-success-${success}`));
|
||||
}
|
||||
if (warning !== defaultColors.warning) {
|
||||
[classes, variantClasses].forEach(classList => classList.push(`wa-warning-${warning}`));
|
||||
}
|
||||
if (danger !== defaultColors.danger) {
|
||||
[classes, variantClasses].forEach(classList => classList.push(`wa-danger-${danger}`));
|
||||
}
|
||||
|
||||
htmlClassList.forEach(instance => {
|
||||
instance.textContent = `class="${classes.join(' ')}"`;
|
||||
});
|
||||
|
||||
variantClassList.forEach(instance => {
|
||||
instance.textContent = `class="${variantClasses.join(' ')}"`;
|
||||
});
|
||||
|
||||
if (variantClasses.length === 0) {
|
||||
document.querySelectorAll('.custom-variants').forEach(el => el.style.display = 'none');
|
||||
} else {
|
||||
document.querySelectorAll('.custom-variants').forEach(el => el.style.display = '');
|
||||
}
|
||||
|
||||
// Update theme and palette names in CDN instructions
|
||||
themeNames.forEach(instance => {
|
||||
instance.textContent = theme;
|
||||
instance.style.textTransform = 'capitalize';
|
||||
});
|
||||
paletteNames.forEach(instance => {
|
||||
instance.textContent = palette;
|
||||
instance.style.textTransform = 'capitalize';
|
||||
});
|
||||
|
||||
// Match color picker icons to selected palette and color
|
||||
[brandPicker, neutralPicker, successPicker, warningPicker, dangerPicker].forEach(picker => {
|
||||
const color = picker.value;
|
||||
const selectedColorIcon = picker.querySelector('wa-icon.selected-color');
|
||||
const optionsColorIcons = picker.querySelectorAll('wa-option wa-icon[slot="start"]');
|
||||
|
||||
if (selectedColorIcon) {
|
||||
selectedColorIcon.style.setProperty('color', `var(--wa-color-${color})`);
|
||||
selectedColorIcon.classList.remove(...[...selectedColorIcon.classList].filter(className => className.startsWith('wa-palette-')));
|
||||
selectedColorIcon.classList.add(`wa-palette-${palette}`);
|
||||
}
|
||||
|
||||
|
||||
optionsColorIcons.forEach(icon => {
|
||||
icon.classList.remove(...[...icon.classList].filter(className => className.startsWith('wa-palette-')));
|
||||
icon.classList.add(`wa-palette-${palette}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Set palette and brand based on theme selection
|
||||
themePicker.addEventListener('input', function() {
|
||||
const selectedOption = themePicker.querySelector(`wa-option[value="${themePicker.value}"]`);
|
||||
const palette = selectedOption.getAttribute('data-palette');
|
||||
const brand = selectedOption.getAttribute('data-brand');
|
||||
|
||||
palettePicker.value = palette;
|
||||
brandPicker.value = brand;
|
||||
|
||||
updateInstructions();
|
||||
});
|
||||
|
||||
// Update instructions when any picker changes
|
||||
[palettePicker, brandPicker, neutralPicker, successPicker, warningPicker, dangerPicker].forEach(picker => {
|
||||
picker.addEventListener('input', updateInstructions);
|
||||
});
|
||||
|
||||
// Set initial values
|
||||
themePicker.value = 'default';
|
||||
palettePicker.value = 'default';
|
||||
brandPicker.value = 'blue';
|
||||
neutralPicker.value = 'gray';
|
||||
successPicker.value = 'green';
|
||||
warningPicker.value = 'yellow';
|
||||
dangerPicker.value = 'red';
|
||||
|
||||
// Initial update
|
||||
updateInstructions();
|
||||
</script>
|
||||
@@ -1,27 +0,0 @@
|
||||
{% set colorVariants = ["brand", "neutral", "success", "warning", "danger"] %}
|
||||
|
||||
<div id="color-variants" class="wa-stack wa-gap-xs">
|
||||
{%- for colorVariant in colorVariants -%}
|
||||
<div class="color-scale wa-flank wa-gap-xs">
|
||||
<div class="color-name">{{ colorVariant }}</div>
|
||||
<div class="color-swatches wa-grid wa-gap-2xs">
|
||||
{%- for tint in themer.tints -%}
|
||||
<wa-copy-button
|
||||
class="color-swatch"
|
||||
copy-label="{{ colorVariant }} {{ tint }}"
|
||||
value="var(--wa-color-{{ colorVariant }}-{{ tint }})"
|
||||
style="--color: var(--wa-color-{{ colorVariant }}-{{ tint }}); --tint: '{{ tint }}'"
|
||||
>
|
||||
<span class="wa-visually-hidden">--wa-color-{{ colorVariant }}-{{ tint }}</span>
|
||||
</wa-copy-button>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#color-variants:has(+ *) {
|
||||
margin-block-end: var(--wa-content-spacing);
|
||||
}
|
||||
</style>
|
||||
@@ -1,24 +1,12 @@
|
||||
// Search data
|
||||
const version = document.documentElement.getAttribute('data-version') || '';
|
||||
const res = await Promise.all([
|
||||
import('https://cdn.jsdelivr.net/npm/lunr/+esm'),
|
||||
fetch(`/search.json?v=${version}`),
|
||||
import('/assets/scripts/track.js').catch(() => null),
|
||||
]);
|
||||
const res = await Promise.all([import('https://cdn.jsdelivr.net/npm/lunr/+esm'), fetch(`/search.json?v=${version}`)]);
|
||||
const lunr = res[0].default;
|
||||
const searchData = await res[1].json();
|
||||
const searchIndex = lunr.Index.load(searchData.searchIndex);
|
||||
const map = searchData.map;
|
||||
const searchDebounce = 200;
|
||||
const queryTrackDelay = 1000;
|
||||
let searchTimeout;
|
||||
let queryTrackTimeout;
|
||||
let lastTrackedQuery = '';
|
||||
let resultSelected = false;
|
||||
|
||||
// Optional event tracking - works standalone if track.js isn't available
|
||||
const trackModule = res[2];
|
||||
const trackEvent = trackModule?.trackEvent || window.trackEvent || (() => {});
|
||||
|
||||
// We're using Turbo, so references to these elements aren't guaranteed to remain intact
|
||||
function getElements() {
|
||||
@@ -29,24 +17,6 @@ function getElements() {
|
||||
};
|
||||
}
|
||||
|
||||
function trackQuerySubmit(query, resultSelectedValue) {
|
||||
if (!query || query.length === 0) return;
|
||||
|
||||
const { results } = getElements();
|
||||
if (!results) return;
|
||||
|
||||
const matches = results.querySelectorAll('li').length;
|
||||
const truncatedQuery = query.length > 500 ? query.substring(0, 500) : query;
|
||||
|
||||
trackEvent('navigation:search_query_submit', {
|
||||
query: truncatedQuery,
|
||||
query_length: query.length,
|
||||
result_count: matches,
|
||||
has_results: matches > 0,
|
||||
result_selected: resultSelectedValue,
|
||||
});
|
||||
}
|
||||
|
||||
// Show the search dialog when slash (or CMD+K) is pressed and focus is not inside a form element
|
||||
document.addEventListener('keydown', event => {
|
||||
if (
|
||||
@@ -72,98 +42,40 @@ document.addEventListener('click', event => {
|
||||
|
||||
function show() {
|
||||
const { dialog, input, results } = getElements();
|
||||
if (!dialog || !input || !results) return;
|
||||
|
||||
const wasAlreadyOpen = dialog.open;
|
||||
|
||||
// Remove existing listeners before adding to prevent duplicates
|
||||
input.removeEventListener('input', handleInput);
|
||||
results.removeEventListener('click', handleSelection);
|
||||
dialog.removeEventListener('keydown', handleKeyDown);
|
||||
dialog.removeEventListener('wa-hide', handleClose);
|
||||
resultSelected = false;
|
||||
lastTrackedQuery = '';
|
||||
input.addEventListener('input', handleInput);
|
||||
results.addEventListener('click', handleSelection);
|
||||
dialog.addEventListener('keydown', handleKeyDown);
|
||||
dialog.addEventListener('wa-hide', handleClose);
|
||||
dialog.open = true;
|
||||
if (!wasAlreadyOpen) {
|
||||
trackEvent('navigation:search_dialog_open');
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
function hide() {
|
||||
const { dialog, input, results } = getElements();
|
||||
if (!dialog || !input || !results) return;
|
||||
clearTimeout(searchTimeout);
|
||||
clearTimeout(queryTrackTimeout);
|
||||
|
||||
input.removeEventListener('input', handleInput);
|
||||
results.removeEventListener('click', handleSelection);
|
||||
dialog.removeEventListener('keydown', handleKeyDown);
|
||||
dialog.removeEventListener('wa-hide', handleClose);
|
||||
|
||||
// Reset state to prevent leakage between dialog sessions
|
||||
resultSelected = false;
|
||||
lastTrackedQuery = '';
|
||||
dialog.open = false;
|
||||
}
|
||||
|
||||
async function handleClose() {
|
||||
const { dialog, input } = getElements();
|
||||
if (!dialog || !input) return;
|
||||
clearTimeout(queryTrackTimeout);
|
||||
queryTrackTimeout = null;
|
||||
dialog.removeEventListener('wa-hide', handleClose);
|
||||
if (!resultSelected) {
|
||||
const query = input.value.trim();
|
||||
if (query.length > 0 && query !== lastTrackedQuery) {
|
||||
trackQuerySubmit(query, false);
|
||||
lastTrackedQuery = query;
|
||||
}
|
||||
}
|
||||
function handleClose() {
|
||||
const { input } = getElements();
|
||||
|
||||
input.value = '';
|
||||
try {
|
||||
await updateResults();
|
||||
} catch (error) {
|
||||
// Silently handle errors - UI cleanup should continue
|
||||
}
|
||||
cleanup();
|
||||
trackEvent('navigation:search_dialog_close');
|
||||
updateResults();
|
||||
}
|
||||
|
||||
function handleInput() {
|
||||
const { input } = getElements();
|
||||
if (!input) return;
|
||||
|
||||
clearTimeout(searchTimeout);
|
||||
clearTimeout(queryTrackTimeout);
|
||||
|
||||
const query = input.value.trim();
|
||||
|
||||
if (query.length === 0) {
|
||||
lastTrackedQuery = '';
|
||||
}
|
||||
|
||||
searchTimeout = setTimeout(async () => {
|
||||
await updateResults(query);
|
||||
if (query.length > 0 && query !== lastTrackedQuery) {
|
||||
queryTrackTimeout = setTimeout(() => {
|
||||
const { input: currentInput, results } = getElements();
|
||||
if (!currentInput || resultSelected) return;
|
||||
|
||||
const currentQuery = currentInput.value.trim();
|
||||
if (currentQuery === query && currentQuery !== lastTrackedQuery) {
|
||||
trackQuerySubmit(currentQuery, false);
|
||||
lastTrackedQuery = currentQuery;
|
||||
}
|
||||
}, queryTrackDelay);
|
||||
}
|
||||
}, searchDebounce);
|
||||
searchTimeout = setTimeout(() => updateResults(input.value), searchDebounce);
|
||||
}
|
||||
|
||||
function handleKeyDown(event) {
|
||||
const { input, results } = getElements();
|
||||
if (!input || !results) return;
|
||||
|
||||
// Handle keyboard selections
|
||||
if (['ArrowDown', 'ArrowUp', 'Home', 'End', 'Enter'].includes(event.key)) {
|
||||
@@ -192,12 +104,7 @@ function handleKeyDown(event) {
|
||||
nextEl = items[items.length - 1];
|
||||
break;
|
||||
case 'Enter':
|
||||
if (currentEl) {
|
||||
const link = currentEl.querySelector('a');
|
||||
if (link) {
|
||||
selectResult(link, 'keyboard_enter');
|
||||
}
|
||||
}
|
||||
currentEl?.querySelector('a')?.click();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -214,62 +121,27 @@ function handleKeyDown(event) {
|
||||
}
|
||||
}
|
||||
|
||||
function selectResult(link, selectionMethod) {
|
||||
const { input, results } = getElements();
|
||||
if (!input || !link) return;
|
||||
|
||||
// Clear pending query tracking timeout to prevent duplicate events
|
||||
clearTimeout(queryTrackTimeout);
|
||||
queryTrackTimeout = null;
|
||||
resultSelected = true; // Set immediately so timeout callback (if executing) sees it
|
||||
|
||||
const query = input.value.trim();
|
||||
if (!link.dataset.searchResultIndex) return;
|
||||
const resultIndex = parseInt(link.dataset.searchResultIndex, 10);
|
||||
if (isNaN(resultIndex) || resultIndex < 1) return;
|
||||
|
||||
const resultUrl = link.dataset.searchResultUrl || link.getAttribute('href');
|
||||
if (!resultUrl) return;
|
||||
lastTrackedQuery = query;
|
||||
trackQuerySubmit(query, true);
|
||||
trackEvent('navigation:search_result_click', {
|
||||
query,
|
||||
result_index: resultIndex,
|
||||
result_url: resultUrl,
|
||||
selection_method: selectionMethod,
|
||||
});
|
||||
|
||||
const { dialog } = getElements();
|
||||
if (dialog) {
|
||||
dialog.removeEventListener('wa-hide', handleClose);
|
||||
cleanup();
|
||||
trackEvent('navigation:search_dialog_close');
|
||||
dialog.open = false;
|
||||
}
|
||||
|
||||
if (window.Turbo) {
|
||||
Turbo.visit(resultUrl);
|
||||
} else {
|
||||
location.href = resultUrl;
|
||||
}
|
||||
}
|
||||
|
||||
function handleSelection(event) {
|
||||
const link = event.target.closest('a');
|
||||
|
||||
if (link) {
|
||||
event.preventDefault();
|
||||
selectResult(link, 'mouse_click');
|
||||
hide();
|
||||
|
||||
if (window.Turbo) {
|
||||
Turbo.visit(link.href);
|
||||
} else {
|
||||
location.href = link.href;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Queries the search index and updates the results
|
||||
async function updateResults(query = '') {
|
||||
const { dialog, input, results } = getElements();
|
||||
if (!dialog || !input || !results) return;
|
||||
|
||||
try {
|
||||
const trimmedQuery = query.trim();
|
||||
const hasQuery = trimmedQuery.length > 0;
|
||||
const hasQuery = query.length > 0;
|
||||
let matches = [];
|
||||
|
||||
if (hasQuery) {
|
||||
@@ -277,13 +149,13 @@ async function updateResults(query = '') {
|
||||
const seenRefs = new Set();
|
||||
|
||||
// Start with a standard search to get the best "exact match" result
|
||||
searchIndex.search(`${trimmedQuery}`).forEach(match => {
|
||||
searchIndex.search(`${query}`).forEach(match => {
|
||||
matches.push(match);
|
||||
seenRefs.add(match.ref);
|
||||
});
|
||||
|
||||
// Add wildcard matches if not already included
|
||||
searchIndex.search(`${trimmedQuery}*`).forEach(match => {
|
||||
searchIndex.search(`${query}*`).forEach(match => {
|
||||
if (!seenRefs.has(match.ref)) {
|
||||
matches.push(match);
|
||||
seenRefs.add(match.ref);
|
||||
@@ -291,10 +163,11 @@ async function updateResults(query = '') {
|
||||
});
|
||||
|
||||
// Add fuzzy search matches last
|
||||
const fuzzyTokens = trimmedQuery
|
||||
const fuzzyTokens = query
|
||||
.split(' ')
|
||||
.map(term => `${term}~1`)
|
||||
.join(' ');
|
||||
|
||||
searchIndex.search(fuzzyTokens).forEach(match => {
|
||||
if (!seenRefs.has(match.ref)) {
|
||||
matches.push(match);
|
||||
@@ -307,12 +180,12 @@ async function updateResults(query = '') {
|
||||
|
||||
dialog.classList.toggle('has-results', hasQuery && hasResults);
|
||||
dialog.classList.toggle('no-results', hasQuery && !hasResults);
|
||||
|
||||
input.setAttribute('aria-activedescendant', '');
|
||||
results.innerHTML = '';
|
||||
|
||||
matches.forEach((match, index) => {
|
||||
const page = map[match.ref];
|
||||
if (!page || !page.url) return;
|
||||
|
||||
const li = document.createElement('li');
|
||||
const a = document.createElement('a');
|
||||
const displayTitle = page.title ?? '';
|
||||
@@ -324,10 +197,12 @@ async function updateResults(query = '') {
|
||||
li.setAttribute('role', 'option');
|
||||
li.setAttribute('id', `search-result-item-${match.ref}`);
|
||||
li.setAttribute('data-selected', index === 0 ? 'true' : 'false');
|
||||
|
||||
if (page.url === '/') icon = 'home';
|
||||
if (page.url.startsWith('/docs/utilities/native')) icon = 'code';
|
||||
if (page.url.startsWith('/docs/components')) icon = 'puzzle-piece';
|
||||
if (page.url.startsWith('/docs/theme') || page.url.startsWith('/docs/restyle')) icon = 'palette';
|
||||
|
||||
a.href = page.url;
|
||||
a.innerHTML = `
|
||||
<div class="site-search-result-icon" aria-hidden="true">
|
||||
@@ -343,9 +218,6 @@ async function updateResults(query = '') {
|
||||
a.querySelector('.site-search-result-description').textContent = displayDescription;
|
||||
a.querySelector('.site-search-result-url').textContent = displayUrl;
|
||||
|
||||
// Use 1-based indexing for analytics
|
||||
a.dataset.searchResultIndex = (index + 1).toString();
|
||||
a.dataset.searchResultUrl = page.url;
|
||||
li.appendChild(a);
|
||||
results.appendChild(li);
|
||||
});
|
||||
|
||||
@@ -10,13 +10,6 @@
|
||||
:root {
|
||||
--wa-brand-orange: #f36944;
|
||||
--wa-brand-grey: #30323b;
|
||||
|
||||
/* layout-based example style aspects */
|
||||
--layout-example-border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
--layout-example-border-radius: var(--wa-border-radius-l);
|
||||
--layout-example-padding: var(--wa-space-s);
|
||||
--layout-example-element-background: var(--wa-color-indigo-60);
|
||||
--layout-example-element-border-radius: var(--wa-border-radius-m);
|
||||
}
|
||||
|
||||
.wa-dark .only-light,
|
||||
@@ -634,68 +627,6 @@ table.colors {
|
||||
--icon-color: var(--wa-color-success-fill-quiet);
|
||||
}
|
||||
|
||||
/* Theming */
|
||||
|
||||
.color-scale.wa-flank {
|
||||
--flank-size: 6ch;
|
||||
--content-percentage: 88%;
|
||||
--reserved-tint-space: calc(var(--wa-font-size-xs) + var(--wa-space-xs)); /* TODO: rename */
|
||||
margin-bottom: var(--reserved-tint-space);
|
||||
|
||||
.color-swatches.wa-grid {
|
||||
--min-column-size: 2.5rem;
|
||||
grid-row-gap: calc(var(--reserved-tint-space) + var(--wa-space-xs));
|
||||
}
|
||||
|
||||
.color-name {
|
||||
font-weight: var(--wa-font-weight-bold);
|
||||
text-transform: capitalize;
|
||||
font-size: var(--wa-font-size-s);
|
||||
color: var(--wa-color-text-normal);
|
||||
}
|
||||
|
||||
wa-copy-button.color-swatch {
|
||||
padding: 0;
|
||||
aspect-ratio: 1;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: var(--tint);
|
||||
position: absolute;
|
||||
bottom: calc(-1 * var(--reserved-tint-space));
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-size: var(--wa-font-size-xs);
|
||||
line-height: 1;
|
||||
color: var(--wa-color-text-quiet);
|
||||
text-align: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&::part(button) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
background-color: var(--color);
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
transition: transform 0.1s ease, box-shadow 0.1s ease;
|
||||
}
|
||||
|
||||
&:hover::part(button) {
|
||||
transform: scale(1.075);
|
||||
box-shadow: var(--wa-shadow-s);
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&::part(copy-icon),
|
||||
&::part(success-icon),
|
||||
&::part(error-icon) {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Layout Examples */
|
||||
.layout-example-boundary {
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
|
||||
@@ -130,13 +130,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* dialogs */
|
||||
wa-dialog:has([slot='footer']) [slot='footer'] {
|
||||
border-block-start: var(--wa-border-width-s) solid var(--wa-color-surface-border);
|
||||
flex-grow: 1; /* make footer contents span entire width of dialog */
|
||||
padding-block-start: var(--wa-space-l);
|
||||
}
|
||||
|
||||
/* anchor headings */
|
||||
.anchor-heading a {
|
||||
opacity: 0;
|
||||
@@ -257,6 +250,7 @@
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
/* buttons with icon toggle on hover */
|
||||
wa-button .icon-hover {
|
||||
@@ -268,13 +262,6 @@
|
||||
wa-button:hover .icon-hover {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
/* buttons that are "shushed" (visually muted) by default, but have their full presentation otherwise */
|
||||
wa-button.shush {
|
||||
&:not(:hover):not(active)::part(base) {
|
||||
color: var(--wa-color-text-quiet);
|
||||
}
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
/* #region resets */
|
||||
|
||||
@@ -41,7 +41,7 @@ Use the `--spacing` custom property to change the amount of space between the di
|
||||
|
||||
### Orientation
|
||||
|
||||
The default orientation for dividers is `horizontal`. Set `orientation` attribute to `vertical` to draw a vertical divider. The divider will span the full height of its [Flexbox](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Flexbox) or [CSS Grid](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/grid) container.
|
||||
The default orientation for dividers is `horizontal`. Set `orientation` attribute to `vertical` to draw a vertical divider. The divider will span the full height of its container.
|
||||
|
||||
```html {.example}
|
||||
<div style="display: flex; align-items: center;">
|
||||
@@ -53,10 +53,6 @@ The default orientation for dividers is `horizontal`. Set `orientation` attribut
|
||||
</div>
|
||||
```
|
||||
|
||||
:::info
|
||||
If your container isn't Flexbox or CSS Grid, you may need to set an explicit height for the divider.
|
||||
:::
|
||||
|
||||
### Dropdown Dividers
|
||||
|
||||
Use dividers in [dropdowns](/docs/components/dropdown) to visually group dropdown items.
|
||||
|
||||
@@ -13,26 +13,10 @@ Components with the <wa-badge variant="warning">Experimental</wa-badge> badge sh
|
||||
|
||||
## Next
|
||||
|
||||
- Added `justify-content` CSS utilities [pr:1930]
|
||||
- Added missing `.wa-gap-4xl` utility class [pr:1931]
|
||||
- Added `pointercancel` and `touchcancel` event handling to draggable elements to prevent drags from getting stuck
|
||||
- Added `wa-justify-content-*` utility classes [pr:1930]
|
||||
- Added missing `wa-gap-4xl` utility class [pr:1931]
|
||||
- Fixed a bug in `<wa-combobox>` that prevented the listbox from opening when options were preselected [issue:1883]
|
||||
- Fixed a bug in `<wa-popup>` and `<wa-dropdown-item>` that caused an error when removing a popup while it was opening [issue:1910]
|
||||
- Fixed a bug in `<wa-popup>` and `<wa-dropdown>` that caused errors when shadow DOM queries returned null [issue:1911]
|
||||
- Fixed a bug in `<wa-combobox>` that prevented the listbox from opening when options were preselected [issue:1883]
|
||||
- Fixed a bug in draggable elements that caused a TypeError on `touchend` events when `event.touches` was empty
|
||||
- Fixed a bug in `<wa-tree-item>` that caused the cursor to show a pointer when no expand icon was present [pr:1936]
|
||||
- Modified `wa-align-items-*` utility classes to apply `display: flex` by default [pr:1943]
|
||||
|
||||
## 3.1.0
|
||||
|
||||
- Added `<wa-combobox>` as an experimental pro component [issue:1074]
|
||||
- Added version 2.0.0 of the [official Web Awesome Figma Design Kit](/docs/resources/figma)
|
||||
- Added npm support for Web Awesome Pro
|
||||
- Added `layers.css` to define cascade layer order and updated palettes, themes, native styles, and utilities to import the new rule for more fail-safe modularity [pr:1793]
|
||||
- [PRO]: Fixed a few sizing bugs in `<wa-page>` and `slot="footer"` no longer will always "overflow" the container.
|
||||
- Fixed a bug in `<wa-slider>` that caused some touch devices to end up with the incorrect value [issue:1703]
|
||||
- Fixed a bug in `<wa-card>` that prevented some slots from being detected correctly [discuss:1450]
|
||||
- Fixed a z-index bug in `<wa-scroller>` styles [issue:1724]
|
||||
@@ -531,4 +515,4 @@ Many of these changes and improvements were the direct result of feedback from u
|
||||
|
||||
</details>
|
||||
|
||||
Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome/discussions)
|
||||
Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome/discussions)
|
||||
@@ -1,165 +0,0 @@
|
||||
---
|
||||
title: Theming
|
||||
description: TODO
|
||||
layout: page-outline
|
||||
---
|
||||
|
||||
Web Awesome themes apply a cohesive look and feel across the entire library. A theme is a collection of predefined CSS custom properties that cover a range of styles from colors to transitions. We call these CSS custom properties design tokens.
|
||||
|
||||
There are 11 handcrafted themes to choose from; 3 are free to use with an additional 9 available in Web Awesome Pro. You can also build your own manually with CSS or with our Pro Theme Builder.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
Themes are made up of several layers of increasing specificity, each represented by a CSS class on the document.
|
||||
|
||||
### Color Palette
|
||||
`.wa-palette-{name}`
|
||||
|
||||
Color palettes give you a full spectrum of colors to use in your project. A color palette defines 10 hues — red, orange, yellow, green, cyan, blue, indigo, purple, pink, and gray — each with 11 tints. Tints are assigned numbers that correlate to their lightness.
|
||||
|
||||
There are 9 specially crafted color palettes; 3 are free to use with an additional 6 available in Web Awesome Pro.
|
||||
|
||||
{% include 'theming/color-palettes.njk' %}
|
||||
|
||||
Your color palette is determined by `class="wa-palette-{name}"` on the `<html>` element. If no class is specified, the default color palette for your chosen theme is used.
|
||||
|
||||
### Variants
|
||||
`.wa-{variant}-{hue}`
|
||||
|
||||
Variants convey a specific meaning through color. There are five variants:
|
||||
- **Brand** for product recognition
|
||||
- **Neutral** for generic and ordinary content
|
||||
- **Success** for validity or confirmation
|
||||
- **Warning** for caution or uncertainty
|
||||
- **Danger** for errors or risk
|
||||
|
||||
Brand and neutral are used by nearly every element, component, and pattern across the library. Success, warning, and danger are used selectively by components that could benefit from semantic reinforcement, such as buttons and callouts.
|
||||
|
||||
{% include 'theming/variants.njk' %}
|
||||
|
||||
Any hue from a color palette can be assigned to a variant. Each variant is determined by `class="wa-{variant}-{hue}"` on the `<html>` element. If no class is specified:
|
||||
- **Brand** defaults to <wa-icon name="square" style="color: var(--wa-color-blue);"></wa-icon> **blue**
|
||||
- **Neutral** defaults to <wa-icon name="square" style="color: var(--wa-color-gray);"></wa-icon> **gray**
|
||||
- **Success** defaults to <wa-icon name="square" style="color: var(--wa-color-green);"></wa-icon> **green**
|
||||
- **Warning** defaults to <wa-icon name="square" style="color: var(--wa-color-yellow);"></wa-icon> **yellow**
|
||||
- **Danger** defaults to <wa-icon name="square" style="color: var(--wa-color-red);"></wa-icon> **red**
|
||||
|
||||
### Theme Styles
|
||||
`.wa-theme-{name}`
|
||||
|
||||
Theme styles assign specific tints from your chosen variant colors — along with qualities like fonts, borders, space, and shadows — to design tokens that style elements and components. Themes may also contain custom CSS overrides to change the default look of components.
|
||||
|
||||
TODO: Add theme preview
|
||||
|
||||
Your theme is determined by `class="wa-theme-{name}"` on the `<html>` element. If no class is specified, the default theme is used.
|
||||
|
||||
### Light and Dark Mode
|
||||
`.wa-light` | `.wa-dark`
|
||||
|
||||
Every theme is designed to adapt to light and dark mode. Light mode styles are applied by default, but you can apply a specific color scheme to an entire page or just a section with `class="wa-light"` or `class="wa-dark"`.
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-grid">
|
||||
|
||||
<wa-card class="wa-light">
|
||||
<div slot="header" class="wa-split">
|
||||
<h4 class="wa-heading-m">Light</h4>
|
||||
<wa-icon name="brightness"></wa-icon>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<wa-input label="# of Waffles" type="number" value="3"></wa-input>
|
||||
<wa-select label="Toppings" multiple value="jelly-beans">
|
||||
<wa-option value="whipped-cream">Whipped cream</wa-option>
|
||||
<wa-option value="hershey">Hershey's Kisses</wa-option>
|
||||
<wa-option value="jelly-beans">Jelly beans</wa-option>
|
||||
</wa-select>
|
||||
<wa-button appearance="filled" variant="brand">
|
||||
<wa-icon slot="start" name="waffle"></wa-icon>
|
||||
Make Waffles
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
|
||||
<wa-card class="wa-dark">
|
||||
<div slot="header" class="wa-split">
|
||||
<h4 class="wa-heading-m">Dark</h4>
|
||||
<wa-icon name="moon-stars"></wa-icon>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<wa-input label="# of Waffles" type="number" value="3"></wa-input>
|
||||
<wa-select label="Toppings" multiple value="jelly-beans">
|
||||
<wa-option value="whipped-cream">Whipped cream</wa-option>
|
||||
<wa-option value="hershey">Hershey's Kisses</wa-option>
|
||||
<wa-option value="jelly-beans">Jelly beans</wa-option>
|
||||
</wa-select>
|
||||
<wa-button appearance="filled" variant="brand">
|
||||
<wa-icon slot="start" name="waffle"></wa-icon>
|
||||
Make Waffles
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
#### Inverting the Color Scheme
|
||||
`.wa-invert`
|
||||
|
||||
You can force a section to behave like `.wa-dark` in light mode and like `.wa-light` in dark mode by using `class="wa-invert"`.
|
||||
|
||||
```html {.example}
|
||||
<p>This card will always use the opposite of the color scheme applied to the docs.</p>
|
||||
|
||||
<wa-card class="wa-invert">
|
||||
<div slot="header" class="wa-split">
|
||||
<h4 class="wa-heading-m">Invert</h4>
|
||||
<wa-icon name="swap"></wa-icon>
|
||||
</div>
|
||||
<div class="wa-flank:end wa-align-items-end">
|
||||
<wa-select label="Location" value="upside-down">
|
||||
<wa-option value="lab">Hawkins Lab</wa-option>
|
||||
<wa-option value="mall">Starcourt Mall</wa-option>
|
||||
<wa-option value="upside-down">The Upside Down</wa-option>
|
||||
</wa-select>
|
||||
<wa-button id="go-button" appearance="filled" variant="brand">
|
||||
<wa-icon label="Go" name="person-to-portal" family="duotone"></wa-icon>
|
||||
</wa-button>
|
||||
<wa-tooltip for="go-button">
|
||||
Go!
|
||||
</wa-tooltip>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
|
||||
#### Detecting Color Scheme Preference
|
||||
|
||||
While both light and dark mode styles are built-in to all themes, Web Awesome doesn't automatically detect the user's color scheme preference. We recommend doing this at the application level.
|
||||
|
||||
Follow these best practices for supporting both light and dark mode:
|
||||
- Check for [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-color-scheme) and use its value by default
|
||||
- Allow the user to override this setting in your app
|
||||
- Remember the user's preference and restore it on subsequent visits
|
||||
|
||||
Let's assume you store the user's color scheme preference for your app in a variable called `colorScheme` (values: `auto` | `light` | `dark`). You can use the following JS snippet to apply `class="wa-dark"` to the `<html>` element accordingly:
|
||||
|
||||
```js
|
||||
const systemDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const applyDark = function (event = systemDark) {
|
||||
const isDark = colorScheme === 'auto' ? event.matches : colorScheme === 'dark';
|
||||
document.documentElement.classList.toggle('wa-dark', isDark);
|
||||
};
|
||||
systemDark.addEventListener('change', applyDark);
|
||||
applyDark();
|
||||
```
|
||||
|
||||
## Using Themes
|
||||
|
||||
Use and update themes instantly via CDN with [Web Awesome projects](/teams). Or, assemble the pieces together using npm or in your self-hosted app.
|
||||
|
||||
Select your favorite options and follow the instructions for your preferred method.
|
||||
|
||||
{% include 'theming/instructions.njk' %}
|
||||
|
||||
## Creating Your Own
|
||||
|
||||
TODO
|
||||
@@ -1,37 +1,35 @@
|
||||
---
|
||||
title: Align Items
|
||||
description: Align items utilities align items within flex and grid containers on the cross axis.
|
||||
description: Align items utilities set the gap property of flex and grid containers, like other Web Awesome layout utilities.
|
||||
layout: docs
|
||||
tags: layoutUtilities
|
||||
---
|
||||
|
||||
<style>
|
||||
.preview-wrapper {
|
||||
border: var(--layout-example-border);
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
min-block-size: 3em;
|
||||
min-inline-size: 5em;
|
||||
padding: var(--wa-space-2xs);
|
||||
}
|
||||
|
||||
.preview-block {
|
||||
aspect-ratio: 1 / 1;
|
||||
background-color: var(--layout-example-element-background);
|
||||
background-color: var(--wa-color-neutral-fill-loud);
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
min-block-size: 1em;
|
||||
}
|
||||
</style>
|
||||
|
||||
Web Awesome includes classes to set the `align-items` property of flex and grid containers. Use them alongside other Web Awesome layout utilities, like [cluster](/docs/utilities/cluster) and [stack](/docs/utilities/stack), to align items in a container on the container's [cross axis](#whats-the-cross-axis).
|
||||
Web Awesome includes classes to set the `align-items` property of flex and grid containers. They can be used alongside other Web Awesome layout utilities, like [cluster](/docs/utilities/cluster) and [stack](/docs/utilities/stack), to align children in container on the container's cross axis.
|
||||
|
||||
| Class Name | `align-items` Value | Preview |
|
||||
| ------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `wa-align-items-baseline` | `baseline` | <div class="wa-cluster wa-gap-2xs wa-align-items-baseline preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-align-items-center` | `center` | <div class="wa-cluster wa-gap-2xs wa-align-items-center preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-align-items-end` | `flex-end` | <div class="wa-cluster wa-gap-2xs wa-align-items-end preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-align-items-start` | `flex-start` | <div class="wa-cluster wa-gap-2xs wa-align-items-start preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-align-items-stretch` | `stretch` | <div class="wa-cluster wa-gap-2xs wa-align-items-stretch preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| Class Name | `align-items` Value | Preview |
|
||||
| ------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `wa-align-items-baseline` | `baseline` | <div class="wa-cluster wa-align-items-baseline preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-align-items-center` | `center` | <div class="wa-cluster wa-align-items-center preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-align-items-end` | `flex-end` | <div class="wa-cluster wa-align-items-end preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-align-items-start` | `flex-start` | <div class="wa-cluster wa-align-items-start preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-align-items-stretch` | `stretch` | <div class="wa-cluster wa-align-items-stretch preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
|
||||
## What's the Cross Axis?
|
||||
## What's a Cross Axis?
|
||||
|
||||
The cross axis runs perpendicular to a container's content direction. For containers where `flex-direction` is `row` and content flows in the inline direction, the cross axis runs in the block direction. For containers where `flex-direction` is `column` and content flows in the block direction, the cross axis runs in the inline direction.
|
||||
The cross axis runs perpendicular to a flex container's content direction. For containers where `flex-direction` is `row` and content flows in the inline direction, the cross axis runs in the block direction. For containers where `flex-direction` is `column` and content flows in the block direction, the cross axis runs in the inline direction.
|
||||
|
||||
@@ -7,21 +7,19 @@ tags: layoutUtilities
|
||||
|
||||
<style>
|
||||
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-cluster']:has(div:empty) {
|
||||
border: var(--layout-example-border);
|
||||
border-radius: var(--layout-example-border-radius);
|
||||
padding: var(--layout-example-padding);
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
padding: var(--wa-space-s);
|
||||
}
|
||||
|
||||
[class*='wa-cluster'] div:empty {
|
||||
background-color: var(--layout-example-element-background);
|
||||
border-radius: var(--layout-example-element-border-radius);
|
||||
background-color: var(--wa-color-indigo-60);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
min-block-size: 4rem;
|
||||
min-inline-size: 4rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
{{ description }}
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-cluster">
|
||||
<div></div>
|
||||
|
||||
@@ -7,20 +7,20 @@ tags: layoutUtilities
|
||||
|
||||
<style>
|
||||
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-flank']:has(div:empty) {
|
||||
border: var(--layout-example-border);
|
||||
border-radius: var(--layout-example-border-radius);
|
||||
padding: var(--layout-example-padding);
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
padding: var(--wa-space-s);
|
||||
}
|
||||
|
||||
[class*='wa-flank'] div:empty {
|
||||
background-color: var(--layout-example-element-background);
|
||||
border-radius: var(--layout-example-element-border-radius);
|
||||
background-color: var(--wa-color-indigo-60);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
min-block-size: 4rem;
|
||||
min-inline-size: 4rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
{{ description }} When space is limited, the items wrap.
|
||||
When space is limited, the items wrap.
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-flank">
|
||||
|
||||
@@ -7,20 +7,18 @@ tags: layoutUtilities
|
||||
|
||||
<style>
|
||||
[class*='wa-frame']:has(div:empty) {
|
||||
border: var(--layout-example-border);
|
||||
padding: var(--layout-example-padding);
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
padding: var(--wa-space-s);
|
||||
}
|
||||
|
||||
[class*='wa-frame'] div:empty {
|
||||
background-color: var(--layout-example-element-background);
|
||||
border-radius: var(--layout-example-element-border-radius);
|
||||
background-color: var(--wa-color-indigo-60);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
min-block-size: 4rem;
|
||||
min-inline-size: 4rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
{{ description }}
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-frame" style="max-inline-size: 20rem;">
|
||||
<div></div>
|
||||
|
||||
@@ -6,37 +6,28 @@ tags: layoutUtilities
|
||||
---
|
||||
|
||||
<style>
|
||||
.preview-wrapper {
|
||||
border: var(--layout-example-border);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
min-block-size: 3em;
|
||||
min-inline-size: 5em;
|
||||
padding: var(--wa-space-2xs);
|
||||
}
|
||||
|
||||
.preview-block {
|
||||
aspect-ratio: 1 / 1;
|
||||
background-color: var(--layout-example-element-background);
|
||||
background-color: var(--wa-color-neutral-fill-loud);
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
min-block-size: 1em;
|
||||
min-block-size: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
Web Awesome includes classes to set the `gap` property of flex and grid containers. Use them alone to create a flex container with a gap, or use them alongside other Web Awesome layout utilities, like [cluster](/docs/utilities/cluster) and [stack](/docs/utilities/stack), to change the space between items.
|
||||
Web Awesome includes classes to set the `gap` property of flex and grid containers. They can be used alongside other Web Awesome layout utilities, like [cluster](/docs/utilities/cluster) and [stack](/docs/utilities/stack), to change the space between items.
|
||||
Or even by themselves — all gap properties also set `display: flex` with a specificity of 0 so that it can be trivially overridden.
|
||||
|
||||
Besides `wa-gap-0`, which sets `gap` to zero, each class corresponds to one of the [`--wa-space-*`](/docs/tokens/space) tokens in your theme.
|
||||
|
||||
| Class Name | `gap` Value | Preview |
|
||||
| ------------ | ---------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| `wa-gap-0` | `0` | <div class="preview-wrapper wa-cluster wa-gap-0"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-3xs` | `--wa-space-3xs` | <div class="preview-wrapper wa-cluster wa-gap-3xs"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-2xs` | `--wa-space-2xs` | <div class="preview-wrapper wa-cluster wa-gap-2xs"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-xs` | `--wa-space-xs` | <div class="preview-wrapper wa-cluster wa-gap-xs"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-s` | `--wa-space-s` | <div class="preview-wrapper wa-cluster wa-gap-s"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-m` | `--wa-space-m` | <div class="preview-wrapper wa-cluster wa-gap-m"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-l` | `--wa-space-l` | <div class="preview-wrapper wa-cluster wa-gap-l"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-xl` | `--wa-space-xl` | <div class="preview-wrapper wa-cluster wa-gap-xl"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-2xl` | `--wa-space-2xl` | <div class="preview-wrapper wa-cluster wa-gap-2xl"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-3xl` | `--wa-space-3xl` | <div class="preview-wrapper wa-cluster wa-gap-3xl"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
<!-- Pending 3.2.0 release -->
|
||||
<!-- | `wa-gap-4xl` | `--wa-space-4xl` | <div class="preview-wrapper wa-cluster wa-gap-4xl"><div class="preview-block"></div><div class="preview-block"></div></div> | -->
|
||||
| `wa-gap-0` | `0` | <div class="wa-cluster wa-gap-0"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-3xs` | `--wa-space-3xs` | <div class="wa-cluster wa-gap-3xs"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-2xs` | `--wa-space-2xs` | <div class="wa-cluster wa-gap-2xs"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-xs` | `--wa-space-xs` | <div class="wa-cluster wa-gap-xs"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-s` | `--wa-space-s` | <div class="wa-cluster wa-gap-s"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-m` | `--wa-space-m` | <div class="wa-cluster wa-gap-m"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-l` | `--wa-space-l` | <div class="wa-cluster wa-gap-l"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-xl` | `--wa-space-xl` | <div class="wa-cluster wa-gap-xl"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-2xl` | `--wa-space-2xl` | <div class="wa-cluster wa-gap-2xl"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-gap-3xl` | `--wa-space-3xl` | <div class="wa-cluster wa-gap-3xl"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
|
||||
@@ -7,21 +7,19 @@ tags: layoutUtilities
|
||||
|
||||
<style>
|
||||
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-grid']:has(div:empty) {
|
||||
border: var(--layout-example-border);
|
||||
border-radius: var(--layout-example-border-radius);
|
||||
padding: var(--layout-example-padding);
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
padding: var(--wa-space-s);
|
||||
}
|
||||
|
||||
[class*='wa-grid'] div:empty {
|
||||
background-color: var(--layout-example-element-background);
|
||||
border-radius: var(--layout-example-element-border-radius);
|
||||
background-color: var(--wa-color-indigo-60);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
min-block-size: 4rem;
|
||||
min-inline-size: 4rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
{{ description }}
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-grid">
|
||||
<div></div>
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
title: Justify Content
|
||||
description: Justify content utilities determine how space is distributed between items in flex and grid containers.
|
||||
layout: docs
|
||||
tags: layoutUtilities
|
||||
unpublished: true
|
||||
unlisted: true
|
||||
---
|
||||
|
||||
<style>
|
||||
.preview-wrapper {
|
||||
border: var(--layout-example-border);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
min-block-size: 3em;
|
||||
min-inline-size: 5em;
|
||||
padding: var(--wa-space-2xs);
|
||||
}
|
||||
|
||||
.preview-block {
|
||||
aspect-ratio: 1 / 1;
|
||||
background-color: var(--layout-example-element-background);
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
min-block-size: 1em;
|
||||
}
|
||||
</style>
|
||||
|
||||
Web Awesome includes classes to set the `justify-content` property of flex and grid containers. Use them alongside other Web Awesome layout utilities, like [cluster](/docs/utilities/cluster) and [stack](/docs/utilities/stack), to distribute space between items along the container's [main axis](#whats-the-main-axis).
|
||||
|
||||
| Class Name | `justify-content` Value | Preview |
|
||||
| ---------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `wa-justify-content-start` | `flex-start` | <div class="wa-cluster wa-gap-2xs wa-justify-content-start preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-justify-content-end` | `flex-end` | <div class="wa-cluster wa-gap-2xs wa-justify-content-end preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-justify-content-center` | `center` | <div class="wa-cluster wa-gap-2xs wa-justify-content-center preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-justify-content-space-around` | `space-around` | <div class="wa-cluster wa-gap-2xs wa-justify-content-space-around preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-justify-content-space-between` | `space-between` | <div class="wa-cluster wa-gap-2xs wa-justify-content-space-between preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
| `wa-justify-content-space-evenly` | `space-evenly` | <div class="wa-cluster wa-gap-2xs wa-justify-content-space-evenly preview-wrapper"><div class="preview-block"></div><div class="preview-block"></div></div> |
|
||||
|
||||
## What's the Main Axis?
|
||||
|
||||
The main axis runs parallel to a container's content direction. For grid containers and flex containers where `flex-direction` is `row`, the main axis runs in the inline direction. For containers where `flex-direction` is `column`, the main axis runs in the block direction.
|
||||
@@ -7,21 +7,19 @@ tags: layoutUtilities
|
||||
|
||||
<style>
|
||||
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-split']:has(div:empty) {
|
||||
border: var(--layout-example-border);
|
||||
border-radius: var(--layout-example-border-radius);
|
||||
padding: var(--layout-example-padding);
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
padding: var(--wa-space-s);
|
||||
}
|
||||
|
||||
[class*='wa-split'] div:empty {
|
||||
background-color: var(--layout-example-element-background);
|
||||
border-radius: var(--layout-example-element-border-radius);
|
||||
background-color: var(--wa-color-indigo-60);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
min-block-size: 4rem;
|
||||
min-inline-size: 4rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
{{ description }}
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-split">
|
||||
<div></div>
|
||||
|
||||
@@ -7,21 +7,19 @@ tags: layoutUtilities
|
||||
|
||||
<style>
|
||||
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-stack']:has(div:empty) {
|
||||
border: var(--layout-example-border);
|
||||
border-radius: var(--layout-example-border-radius);
|
||||
padding: var(--layout-example-padding);
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
padding: var(--wa-space-s);
|
||||
}
|
||||
|
||||
[class*='wa-stack'] div:empty {
|
||||
background-color: var(--layout-example-element-background);
|
||||
border-radius: var(--layout-example-element-border-radius);
|
||||
background-color: var(--wa-color-indigo-60);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
min-block-size: 4rem;
|
||||
min-inline-size: 4rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
{{ description }}
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack">
|
||||
<div></div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"access": "public"
|
||||
},
|
||||
"description": "A forward-thinking library of web components.",
|
||||
"version": "3.1.0",
|
||||
"version": "3.0.0",
|
||||
"homepage": "https://webawesome.com/",
|
||||
"author": "Web Awesome",
|
||||
"license": "MIT",
|
||||
@@ -67,7 +67,7 @@
|
||||
"check-updates": "npm-check-updates --cooldown 7 --interactive --format group",
|
||||
"print-version": "echo $npm_package_version",
|
||||
"tag-version": "git tag -a \"v$(npm run print-version | tail -n1)\" -m \"tag v$(npm run print-version | tail -n1)\"",
|
||||
"postversion": "node ./scripts/update-root-version.js"
|
||||
"postversion": "npm run tag-version && node ./scripts/update-root-version.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17.0"
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function (plop) {
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: '../../src/components/{{ tagWithoutPrefix tag }}/{{ tagWithoutPrefix tag }}.styles.ts',
|
||||
path: '../../src/components/{{ tagWithoutPrefix tag }}/{{ tagWithoutPrefix tag }}.css',
|
||||
templateFile: 'templates/component/styles.hbs',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ import { html } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { watch } from '../../internal/watch.js';
|
||||
import WebAwesomeElement from '../../internal/webawesome-element.js';
|
||||
import styles from './{{ tagWithoutPrefix tag }}.styles.js';
|
||||
import styles from './{{ tagWithoutPrefix tag }}.css';
|
||||
|
||||
/**
|
||||
* @summary Short summary of the component's intended use.
|
||||
@@ -21,7 +21,7 @@ import styles from './{{ tagWithoutPrefix tag }}.styles.js';
|
||||
*/
|
||||
@customElement("{{ tag }}")
|
||||
export default class {{ properCase tag }} extends WebAwesomeElement {
|
||||
static css = [styles];
|
||||
static css = styles;
|
||||
|
||||
/** An example attribute. */
|
||||
@property() attr = 'example';
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import { css } from "lit";
|
||||
|
||||
export default css`
|
||||
:host {
|
||||
display: block;
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
`
|
||||
|
||||
@@ -10,8 +10,8 @@ const monorepoRoot = path.resolve(__dirname, '..', '..', '..');
|
||||
const rootPackageJSONFile = path.join(monorepoRoot, 'package.json');
|
||||
const webawesomePackageJSONFile = path.join(path.resolve(__dirname, '..'), 'package.json');
|
||||
|
||||
const rootPackageJSON = JSON.parse(fs.readFileSync(rootPackageJSONFile, { encoding: 'utf8' }));
|
||||
const webawesomePackageJSON = JSON.parse(fs.readFileSync(webawesomePackageJSONFile, { encoding: 'utf8' }));
|
||||
const rootPackageJSON = JSON.parse(fs.readFileSync(rootPackageJSONFile));
|
||||
const webawesomePackageJSON = JSON.parse(fs.readFileSync(webawesomePackageJSONFile));
|
||||
|
||||
const currentVersion = webawesomePackageJSON.version;
|
||||
rootPackageJSON.version = currentVersion;
|
||||
@@ -19,9 +19,9 @@ rootPackageJSON.version = currentVersion;
|
||||
fs.writeFileSync(rootPackageJSONFile, JSON.stringify(rootPackageJSON, null, 2));
|
||||
|
||||
const versionsFile = path.join(monorepoRoot, 'VERSIONS.txt');
|
||||
const versions = fs.readFileSync(versionsFile, { encoding: 'utf8' }).split(/\r?\n/);
|
||||
const versions = fs.readFileSync(versions).split(/\r?\n/);
|
||||
|
||||
// TODO: Make this smart and understand semver and "insert" in the correct spot instead of appending.
|
||||
if (!versions.includes(currentVersion)) {
|
||||
fs.appendFileSync(versionsFile, webawesomePackageJSON.version);
|
||||
fs.appendFileSync(webawesomePackageJSON.version);
|
||||
}
|
||||
|
||||
@@ -1277,14 +1277,7 @@ export default class WaColorPicker extends WebAwesomeFormAssociatedElement {
|
||||
})}
|
||||
part="trigger-container form-control"
|
||||
>
|
||||
<div
|
||||
part="form-control-label"
|
||||
class=${classMap({
|
||||
label: true,
|
||||
'has-label': hasLabel,
|
||||
})}
|
||||
id="form-control-label"
|
||||
>
|
||||
<div part="form-control-label" class="label" id="form-control-label">
|
||||
<slot name="label">${this.label}</slot>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -155,21 +155,20 @@ export default class WaDropdownItem extends WebAwesomeElement {
|
||||
|
||||
/** Opens the submenu. */
|
||||
async openSubmenu() {
|
||||
const submenu = this.submenuElement;
|
||||
if (!this.hasSubmenu || !submenu || !this.isConnected) return;
|
||||
if (!this.hasSubmenu || !this.submenuElement) return;
|
||||
|
||||
// Notify parent dropdown to handle positioning
|
||||
this.notifyParentOfOpening();
|
||||
|
||||
// Use Popover API to show the submenu
|
||||
submenu.showPopover?.();
|
||||
submenu.hidden = false;
|
||||
submenu.setAttribute('data-visible', '');
|
||||
this.submenuElement.showPopover();
|
||||
this.submenuElement.hidden = false;
|
||||
this.submenuElement.setAttribute('data-visible', '');
|
||||
this.submenuOpen = true;
|
||||
this.setAttribute('aria-expanded', 'true');
|
||||
|
||||
// Animate the submenu
|
||||
await animateWithClass(submenu, 'show');
|
||||
await animateWithClass(this.submenuElement, 'show');
|
||||
|
||||
// Set focus to the first submenu item
|
||||
setTimeout(() => {
|
||||
@@ -211,19 +210,16 @@ export default class WaDropdownItem extends WebAwesomeElement {
|
||||
|
||||
/** Closes the submenu. */
|
||||
async closeSubmenu() {
|
||||
const submenu = this.submenuElement;
|
||||
if (!this.hasSubmenu || !submenu) return;
|
||||
if (!this.hasSubmenu || !this.submenuElement) return;
|
||||
|
||||
this.submenuOpen = false;
|
||||
this.setAttribute('aria-expanded', 'false');
|
||||
|
||||
if (!submenu.hidden) {
|
||||
await animateWithClass(submenu, 'hide');
|
||||
if (submenu?.isConnected) {
|
||||
submenu.hidden = true;
|
||||
submenu.removeAttribute('data-visible');
|
||||
submenu.hidePopover?.();
|
||||
}
|
||||
if (!this.submenuElement.hidden) {
|
||||
await animateWithClass(this.submenuElement, 'hide');
|
||||
this.submenuElement.hidden = true;
|
||||
this.submenuElement.removeAttribute('data-visible');
|
||||
this.submenuElement.hidePopover();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -138,9 +138,9 @@ export default class WaDropdown extends WebAwesomeElement {
|
||||
|
||||
/** Gets all dropdown items slotted in the menu. */
|
||||
private getItems(includeDisabled = false): WaDropdownItem[] {
|
||||
const items = (this.defaultSlot?.assignedElements({ flatten: true }) ?? []).filter(
|
||||
el => el.localName === 'wa-dropdown-item',
|
||||
) as WaDropdownItem[];
|
||||
const items = this.defaultSlot
|
||||
.assignedElements({ flatten: true })
|
||||
.filter(el => el.localName === 'wa-dropdown-item') as WaDropdownItem[];
|
||||
|
||||
return includeDisabled ? items : items.filter(item => !item.disabled);
|
||||
}
|
||||
@@ -165,9 +165,9 @@ export default class WaDropdown extends WebAwesomeElement {
|
||||
|
||||
/** Syncs item sizes with the dropdown's size property. */
|
||||
private syncItemSizes() {
|
||||
const items = (this.defaultSlot?.assignedElements({ flatten: true }) ?? []).filter(
|
||||
el => el.localName === 'wa-dropdown-item',
|
||||
) as WaDropdownItem[];
|
||||
const items = this.defaultSlot
|
||||
.assignedElements({ flatten: true })
|
||||
.filter(el => el.localName === 'wa-dropdown-item') as WaDropdownItem[];
|
||||
items.forEach(item => (item.size = this.size));
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ export default class WaDropdown extends WebAwesomeElement {
|
||||
/** Shows the dropdown menu. This should only be called from within updated(). */
|
||||
private async showMenu() {
|
||||
const anchor = this.getTrigger();
|
||||
if (!anchor || !this.popup || !this.menu) return;
|
||||
if (!anchor) return;
|
||||
|
||||
const showEvent = new WaShowEvent();
|
||||
this.dispatchEvent(showEvent);
|
||||
@@ -270,8 +270,6 @@ export default class WaDropdown extends WebAwesomeElement {
|
||||
|
||||
/** Hides the dropdown menu. This should only be called from within updated(). */
|
||||
private async hideMenu() {
|
||||
if (!this.popup || !this.menu) return;
|
||||
|
||||
const hideEvent = new WaHideEvent({ source: this });
|
||||
this.dispatchEvent(hideEvent);
|
||||
if (hideEvent.defaultPrevented) {
|
||||
@@ -722,12 +720,12 @@ export default class WaDropdown extends WebAwesomeElement {
|
||||
nativeButton.setAttribute('aria-haspopup', 'menu');
|
||||
nativeButton.setAttribute('aria-expanded', this.open ? 'true' : 'false');
|
||||
|
||||
this.menu?.setAttribute('aria-expanded', 'false');
|
||||
this.menu.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
render() {
|
||||
// On initial render, we want to use this.open, for everything else, we sync off of this.popup.active to get animations working.
|
||||
let active = this.hasUpdated ? this.popup?.active : this.open;
|
||||
let active = this.hasUpdated ? this.popup.active : this.open;
|
||||
|
||||
return html`
|
||||
<wa-popup
|
||||
|
||||
@@ -6,6 +6,7 @@ export default css`
|
||||
}
|
||||
|
||||
.text-field {
|
||||
flex: auto;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: start;
|
||||
|
||||
@@ -48,27 +48,6 @@ describe('<wa-input>', () => {
|
||||
expect(input.title).to.equal('Test');
|
||||
});
|
||||
|
||||
it('should have label with "has-label" class if label has a slotted element', async () => {
|
||||
const el = await fixture<WaInput>(html` <wa-input><span slot="label">Name</span></wa-input> `);
|
||||
await el.updateComplete;
|
||||
const label = el.shadowRoot!.querySelector('[part~="form-control-label"]')!;
|
||||
expect(label.classList.contains('has-label')).to.equal(true);
|
||||
});
|
||||
|
||||
it('should have label with "has-label" class if label is provided as an attribute', async () => {
|
||||
const el = await fixture<WaInput>(html` <wa-input label="Name"></wa-input> `);
|
||||
await el.updateComplete;
|
||||
const label = el.shadowRoot!.querySelector('[part~="form-control-label"]')!;
|
||||
expect(label.classList.contains('has-label')).to.equal(true);
|
||||
});
|
||||
|
||||
it('should not have "has-label" class on label if no label content is provided', async () => {
|
||||
const el = await fixture<WaInput>(html` <wa-input></wa-input> `);
|
||||
await el.updateComplete;
|
||||
const label = el.shadowRoot!.querySelector('[part~="form-control-label"]')!;
|
||||
expect(label.classList.contains('has-label')).to.equal(false);
|
||||
});
|
||||
|
||||
it('should be disabled with the disabled attribute', async () => {
|
||||
const el = await fixture<WaInput>(html` <wa-input disabled></wa-input> `);
|
||||
await el.updateComplete;
|
||||
|
||||
@@ -342,15 +342,7 @@ export default class WaInput extends WebAwesomeFormAssociatedElement {
|
||||
(typeof this.value === 'number' || (this.value && this.value.length > 0));
|
||||
|
||||
return html`
|
||||
<label
|
||||
part="form-control-label label"
|
||||
class=${classMap({
|
||||
label: true,
|
||||
'has-label': hasLabel,
|
||||
})}
|
||||
for="input"
|
||||
aria-hidden=${hasLabel ? 'false' : 'true'}
|
||||
>
|
||||
<label part="form-control-label label" class="label" for="input" aria-hidden=${hasLabel ? 'false' : 'true'}>
|
||||
<slot name="label">${this.label}</slot>
|
||||
</label>
|
||||
|
||||
|
||||
@@ -286,11 +286,11 @@ export default class WaPopup extends WebAwesomeElement {
|
||||
|
||||
private start() {
|
||||
// We can't start the positioner without an anchor
|
||||
if (!this.anchorEl || !this.active || !this.isConnected) {
|
||||
if (!this.anchorEl || !this.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.popup?.showPopover?.();
|
||||
this.popup.showPopover?.();
|
||||
|
||||
this.cleanup = autoUpdate(this.anchorEl, this.popup, () => {
|
||||
this.reposition();
|
||||
@@ -299,7 +299,7 @@ export default class WaPopup extends WebAwesomeElement {
|
||||
|
||||
private async stop(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
this.popup?.hidePopover?.();
|
||||
this.popup.hidePopover?.();
|
||||
|
||||
if (this.cleanup) {
|
||||
this.cleanup();
|
||||
@@ -317,7 +317,7 @@ export default class WaPopup extends WebAwesomeElement {
|
||||
/** Forces the popup to recalculate and reposition itself. */
|
||||
reposition() {
|
||||
// Nothing to do if the popup is inactive or the anchor doesn't exist
|
||||
if (!this.active || !this.anchorEl || !this.popup) {
|
||||
if (!this.active || !this.anchorEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -498,7 +498,7 @@ export default class WaPopup extends WebAwesomeElement {
|
||||
}
|
||||
|
||||
private updateHoverBridge = () => {
|
||||
if (this.hoverBridge && this.anchorEl && this.popup) {
|
||||
if (this.hoverBridge && this.anchorEl) {
|
||||
const anchorRect = this.anchorEl.getBoundingClientRect();
|
||||
const popupRect = this.popup.getBoundingClientRect();
|
||||
const isVertical = this.placement.includes('top') || this.placement.includes('bottom');
|
||||
|
||||
@@ -352,10 +352,7 @@ export default class WaRadioGroup extends WebAwesomeFormAssociatedElement {
|
||||
<label
|
||||
part="form-control-label"
|
||||
id="label"
|
||||
class=${classMap({
|
||||
label: true,
|
||||
'has-label': hasLabel,
|
||||
})}
|
||||
class="label"
|
||||
aria-hidden=${hasLabel ? 'false' : 'true'}
|
||||
@click=${this.handleLabelClick}
|
||||
>
|
||||
|
||||
@@ -938,10 +938,7 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
|
||||
<label
|
||||
id="label"
|
||||
part="form-control-label label"
|
||||
class=${classMap({
|
||||
label: true,
|
||||
'has-label': hasLabel,
|
||||
})}
|
||||
class="label"
|
||||
aria-hidden=${hasLabel ? 'false' : 'true'}
|
||||
@click=${this.handleLabelClick}
|
||||
>
|
||||
|
||||
@@ -807,7 +807,7 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
id="label"
|
||||
part="label"
|
||||
for=${this.isRange ? 'thumb-min' : 'text-box'}
|
||||
class=${classMap({ vh: !hasLabel, 'has-label': hasLabel })}
|
||||
class=${classMap({ vh: !hasLabel })}
|
||||
@pointerdown=${this.handleLabelPointerDown}
|
||||
>
|
||||
<slot name="label">${this.label}</slot>
|
||||
|
||||
@@ -331,15 +331,7 @@ export default class WaTextarea extends WebAwesomeFormAssociatedElement {
|
||||
const hasHint = this.hint ? true : !!hasHintSlot;
|
||||
|
||||
return html`
|
||||
<label
|
||||
part="form-control-label label"
|
||||
class=${classMap({
|
||||
label: true,
|
||||
'has-label': hasLabel,
|
||||
})}
|
||||
for="input"
|
||||
aria-hidden=${hasLabel ? 'false' : 'true'}
|
||||
>
|
||||
<label part="form-control-label label" class="label" for="input" aria-hidden=${hasLabel ? 'false' : 'true'}>
|
||||
<slot name="label">${this.label}</slot>
|
||||
</label>
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ export default class WaTooltip extends WebAwesomeElement {
|
||||
/** The amount of time to wait before showing the tooltip when the user mouses in. */
|
||||
@property({ attribute: 'show-delay', type: Number }) showDelay = 150;
|
||||
|
||||
/** The amount of time to wait before hiding the tooltip when the user mouses out. */
|
||||
/** The amount of time to wait before hiding the tooltip when the user mouses out.. */
|
||||
@property({ attribute: 'hide-delay', type: Number }) hideDelay = 0;
|
||||
|
||||
/**
|
||||
|
||||
@@ -85,10 +85,6 @@ export default css`
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tree-item:not(.tree-item-has-expand-button):not(.tree-item-loading) .expand-button {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.tree-item-loading .expand-icon-slot wa-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -28,4 +28,3 @@ export type { WaSlideChangeEvent } from './slide-change.js';
|
||||
export type { WaStartEvent } from './start.js';
|
||||
export type { WaTabHideEvent } from './tab-hide.js';
|
||||
export type { WaTabShowEvent } from './tab-show.js';
|
||||
export type { WaVideoChangeEvent } from './video-change.js';
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
export class WaVideoChangeEvent extends Event {
|
||||
readonly detail: WaVideoChangeEventDetail;
|
||||
|
||||
constructor(detail: WaVideoChangeEventDetail) {
|
||||
super('wa-video-change', { bubbles: true, cancelable: false, composed: true });
|
||||
this.detail = detail;
|
||||
}
|
||||
}
|
||||
|
||||
export interface WaVideoChangeEventDetail {
|
||||
previousIndex: number;
|
||||
currentIndex: number;
|
||||
video: {
|
||||
title?: string;
|
||||
poster?: string;
|
||||
duration?: string;
|
||||
sources: { src: string; type: string }[];
|
||||
tracks: { src: string; kind: string; srclang: string; label: string }[];
|
||||
};
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface GlobalEventHandlersEventMap {
|
||||
'wa-video-change': WaVideoChangeEvent;
|
||||
}
|
||||
}
|
||||
@@ -99,24 +99,20 @@ export class DraggableElement {
|
||||
|
||||
document.addEventListener('pointerup', this.handleDragStop);
|
||||
document.addEventListener('pointermove', this.handleDragMove);
|
||||
document.addEventListener('pointercancel', this.handleDragStop);
|
||||
document.addEventListener('touchend', this.handleDragStop);
|
||||
document.addEventListener('touchmove', this.handleDragMove);
|
||||
document.addEventListener('touchcancel', this.handleDragStop);
|
||||
this.options.start(clientX, clientY);
|
||||
};
|
||||
|
||||
private handleDragStop = (event: PointerEvent | TouchEvent) => {
|
||||
const clientX = 'changedTouches' in event ? event.changedTouches[0].clientX : (event as PointerEvent).clientX;
|
||||
const clientY = 'changedTouches' in event ? event.changedTouches[0].clientY : (event as PointerEvent).clientY;
|
||||
const clientX = 'touches' in event ? event.touches[0].clientX : (event as PointerEvent).clientX;
|
||||
const clientY = 'touches' in event ? event.touches[0].clientY : (event as PointerEvent).clientY;
|
||||
|
||||
this.isDragging = false;
|
||||
document.removeEventListener('pointerup', this.handleDragStop);
|
||||
document.removeEventListener('pointermove', this.handleDragMove);
|
||||
document.removeEventListener('pointercancel', this.handleDragStop);
|
||||
document.removeEventListener('touchend', this.handleDragStop);
|
||||
document.removeEventListener('touchmove', this.handleDragMove);
|
||||
document.removeEventListener('touchcancel', this.handleDragStop);
|
||||
this.options.stop(clientX, clientY);
|
||||
};
|
||||
|
||||
@@ -145,10 +141,8 @@ export class DraggableElement {
|
||||
public stop() {
|
||||
document.removeEventListener('pointerup', this.handleDragStop);
|
||||
document.removeEventListener('pointermove', this.handleDragMove);
|
||||
document.removeEventListener('pointercancel', this.handleDragStop);
|
||||
document.removeEventListener('touchend', this.handleDragStop);
|
||||
document.removeEventListener('touchmove', this.handleDragMove);
|
||||
document.removeEventListener('touchcancel', this.handleDragStop);
|
||||
this.element.removeEventListener('pointerdown', this.handleDragStart);
|
||||
if (supportsTouch) {
|
||||
this.element.removeEventListener('touchstart', this.handleDragStart);
|
||||
|
||||
@@ -6,14 +6,8 @@ export default css`
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Treat wrapped labels, inputs, and hints as direct children of the host element */
|
||||
[part~='form-control'] {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
/* Label */
|
||||
:is([part~='form-control-label'], [part~='label']):has(*:not(:empty)),
|
||||
:is([part~='form-control-label'], [part~='label']).has-label {
|
||||
:is([part~='form-control-label'], [part~='label']):has(*:not(:empty)) {
|
||||
display: inline-flex;
|
||||
color: var(--wa-form-control-label-color);
|
||||
font-weight: var(--wa-form-control-label-font-weight);
|
||||
@@ -35,6 +29,7 @@ export default css`
|
||||
line-height: var(--wa-form-control-hint-line-height);
|
||||
margin-block-start: 0.5em;
|
||||
font-size: var(--wa-font-size-smaller);
|
||||
line-height: var(--wa-form-control-label-line-height);
|
||||
|
||||
&:not(.has-slotted) {
|
||||
display: none;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
@import url('utilities/scroll-lock.css');
|
||||
@import url('utilities/placeholder.css');
|
||||
@import url('utilities/align-items.css');
|
||||
@import url('utilities/justify-content.css');
|
||||
@import url('utilities/border-radius.css');
|
||||
@import url('utilities/gap.css');
|
||||
@import url('utilities/text.css');
|
||||
|
||||
@@ -1,15 +1,4 @@
|
||||
@layer wa-utilities {
|
||||
/* Apply Flexbox with 0 specificity to ensure an align-items util produces a visible change */
|
||||
:where(
|
||||
.wa-align-items-start,
|
||||
.wa-align-items-end,
|
||||
.wa-align-items-center,
|
||||
.wa-align-items-stretch,
|
||||
.wa-align-items-baseline
|
||||
) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.wa-align-items-start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,4 @@
|
||||
.wa-gap-3xl {
|
||||
gap: var(--wa-space-3xl);
|
||||
}
|
||||
.wa-gap-4xl {
|
||||
gap: var(--wa-space-4xl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
@layer wa-utilities {
|
||||
/* Apply Flexbox with 0 specificity to ensure a justify-content util produces a visible change */
|
||||
:where(
|
||||
.wa-justify-content-start,
|
||||
.wa-justify-content-end,
|
||||
.wa-justify-content-center,
|
||||
.wa-justify-content-space-around,
|
||||
.wa-justify-content-space-between,
|
||||
.wa-justify-content-space-evenly
|
||||
) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.wa-justify-content-start {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.wa-justify-content-end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.wa-justify-content-center {
|
||||
justify-content: center;
|
||||
}
|
||||
.wa-justify-content-space-around {
|
||||
justify-content: space-around;
|
||||
}
|
||||
.wa-justify-content-space-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.wa-justify-content-space-evenly {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
}
|
||||
@@ -27,11 +27,11 @@
|
||||
[class*='wa-cluster'] {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
:where([class*='wa-cluster']) {
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
[class*='wa-frame'] {
|
||||
display: flex;
|
||||
aspect-ratio: 1 / 1;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -97,7 +98,6 @@
|
||||
|
||||
:where([class*='wa-frame']) {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
@@ -118,6 +118,7 @@
|
||||
[class*='wa-split'] {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
[class*='wa-split'],
|
||||
@@ -140,7 +141,6 @@
|
||||
|
||||
:where([class*='wa-split']) {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
@@ -149,11 +149,11 @@
|
||||
[class*='wa-stack'] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
:where([class*='wa-stack']) {
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
/* #endregion */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user