Compare commits

..

59 Commits

Author SHA1 Message Date
lindsaym-fa
5779e0a8e4 Merge branch 'next' into lm/theming-docs 2026-01-15 12:00:46 -05:00
Cory LaViska
67785f64cb update changelog (#1952) 2026-01-15 11:48:26 -05:00
Leon Vogt
39ab883802 Set default cursor for empty <wa-tree-item> expand buttons (#1936) 2026-01-15 11:46:08 -05:00
Lindsay M
08ef969db3 Add missing layout utility descriptions (#1946) 2026-01-15 11:31:29 -05:00
Konnor Rogers
72c4fb7af7 update plop templates (#1940) 2026-01-15 11:14:06 -05:00
Cory LaViska
827d70b2f5 Fix popover and dropdown bugs (#1913)
* fix popover bug; closes #1911

* fixes #1911

* reword guard
2026-01-15 09:53:54 -05:00
Lindsay M
46aa1429a7 Apply flexbox by default with wa-align-items-* and wa-justify-content-* utils (#1943)
* add `display: flex` with 0 specificity to utils

* add changelog
2026-01-13 15:44:37 -05:00
Brian Talbot
4b68a741bd abstracting layout docs example styling (#1935) 2026-01-13 15:31:37 -05:00
Cory LaViska
bd58f7f0a1 Divider docs (#1945)
* don't you know me

* clarify and add note
2026-01-13 15:08:25 -05:00
Alex Rao
e8f366835c Update tooltip.ts (#1928)
This removes the second period in the docs, which gets reflected on the website
2026-01-13 14:52:17 -05:00
Cory LaViska
70df6fea1f fix drag bug; closes #1905 (#1908) 2026-01-13 14:12:29 -05:00
Lindsay M
d76bef5dbb Unlist unreleased utilities from the docs (#1938) 2026-01-13 11:17:36 -05:00
Lindsay M
f8f54d543a Add justify-content utility classes (#1930)
* add `justify-content` utilities

* add docs

* fix up Align Items docs

* add Justify Content to sidebar

* add changelog

* add PR to changelog

* drop specificity of `justify-content` in layout utilities
2026-01-12 16:53:00 -05:00
Lindsay M
5b0e3ed1e8 Add missing .wa-gap-4xl utility class (#1931)
* add missing `.wa-gap-4xl`

* update the docs

* update changelog

* add PR to changelog
2026-01-12 16:35:01 -05:00
Brian Talbot
09ace44c17 A Glow Up for Dialogs That Pop Up (#1927)
* adding visual divider + padding to wa-dialog footers

* adding `wa-button`-focused `.shush` to `utils.css`
2026-01-09 14:52:23 -05:00
Lindsay M
f3de45803f Ensure consistent input heights in flex/grid containers (#1915)
* apply flex rules to `form-control` parts

* prevent input heights from growing in flex containers

* change approach: ignore `form-control` wrapper for styling
2025-12-31 11:35:37 -05:00
Steve Matney
ede1f0725d Ensuring styles apply for input labels when using 'slot="label"' (#1757)
* Ensuring styles apply for input labels when using 'slot="label"'

* Using 'has-slotted' class for codebase consistency

* Fleshing out 'has-slotted' label class to relevant form elements

* Ensuring label line height uses the correct token; removing unrelated PR changes

* Using 'has-label' class instead of 'has-slotted' for labels; applying it with all label content
2025-12-30 12:13:28 -05:00
Kelsey Jackson
56b1196265 got it working, but may revert to use on repo (#1888) 2025-12-19 10:54:45 -06:00
Cory LaViska
7e5f18ea97 update changelog (#1889) 2025-12-18 14:25:22 -05:00
Brian Talbot
c748721f12 adding event tracking to site search (#1872) 2025-12-17 15:22:18 -05:00
konnorrogers
6e5a720f51 update lockfiles and prettierignore 2025-12-16 13:42:13 -05:00
konnorrogers
f739121aaf updae lockfile 2025-12-16 13:30:16 -05:00
konnorrogers
5fb3625ee5 fix script 2025-12-16 13:22:32 -05:00
konnorrogers
da206a8787 update versions 2025-12-16 13:21:46 -05:00
konnorrogers
2b69fa74a5 Bump package.json version 2025-12-16 13:21:23 -05:00
konnorrogers
d1b6628d59 update package lock 2025-12-16 11:48:56 -05:00
konnorrogers
4dca4185e7 Bump changelog 2025-12-16 11:48:29 -05:00
Konnor Rogers
1e6d468959 add changelog entry (#1877) 2025-12-16 11:46:01 -05:00
Cory LaViska
00b8150f3e ensure min/max/step are numbers; fixes #1823 (#1832)
Co-authored-by: konnorrogers <konnor5456@gmail.com>
2025-12-16 11:06:27 -05:00
Konnor Rogers
3d395653fc Bug fix: el.form = 'foo' no longer sets the el.form property (#1815)
* Bug fix: el.form = 'foo' no longer sets the el.form property

* add changelog entry

* add changelog entry

* prettier

* fix form

* skip style attr for button

* prettier
2025-12-16 10:59:40 -05:00
Konnor Rogers
b3844ef77f fixing deploy scripts, and updating root version (#1857)
* fixing deploy scripts

* update root version script

* prettier
2025-12-16 10:29:26 -05:00
Lindsay M
a50648c6e8 Update changelog with leftover items (#1874)
* add leftover logs

* remove video component log
2025-12-15 17:49:56 -05:00
Cory LaViska
b6b82fb0ac Revert "updated sidebar (#1873)" (#1875)
This reverts commit fa073e8d21.
2025-12-15 15:59:38 -05:00
Kelsey Jackson
fa073e8d21 updated sidebar (#1873)
* updated sidebar

* added video item

* fixed formatting

* update

---------

Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
2025-12-15 15:01:32 -05:00
Cory LaViska
e0f6ff11ec Combobox (supporting contributions in free) (#1838)
* hold the mustard! let's make it yellower

* words

* update sidebar

* update changelog

* fix icon cropping

* add combobox support

* preserve user-selected order

* add quick pro flag

* move import to the top

* fix custom tag example
2025-12-11 13:04:42 -05:00
Cory LaViska
895fb304e0 Revert .css => .styles.ts (#1865)
* revert .css => .styles.ts; fixes #1812

* fix native styles and vh util

* remove layers in component CSS

* add layer
2025-12-11 11:32:51 -05:00
Brian Talbot
079c09b9a3 Space Junk Analytics: Remove Plausible Code + Details (#1801)
* removing plausible-based code

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-10 09:38:46 -05:00
Brian Talbot
fa6ccc1ee2 adding cookie consent dialog to base layout (#1840) 2025-12-09 12:10:24 -05:00
David Enke
579e86fc49 fix(wa-button): add missing css transition property (#1850)
fixes #1844
2025-12-08 13:49:22 -05:00
Cory LaViska
2baebca230 remove old and unsupported example (#1842) 2025-12-08 13:37:00 -05:00
Patrick McDougle
c0ced13f06 Add Intersection Observer component to the Utilities Category (#1837) 2025-12-02 11:29:04 -05:00
Cory LaViska
8ae90ef2b2 add missing icon dep (#1828) 2025-11-25 16:35:31 -05:00
Konnor Rogers
5fb6faf527 update webawesome simulation to be closer to the app. (#1789)
* update webawesome simulation to be closer to the app.

* prettier
2025-11-25 12:09:56 -05:00
Cory LaViska
fa558eeda0 update npm-check-updates and set a cooldown (#1820) 2025-11-24 15:58:08 -05:00
Brian Talbot
ed3cb6d782 marking planned pro components in sidebar (#1819) 2025-11-24 12:31:15 -05:00
Lindsay M
09c8f02f79 Use tokens for <wa-dropdown-item> transitions (#1693)
* use tokens for `<wa-dropdown-item>` transitions

* add changelog
2025-11-19 17:50:47 -05:00
Lindsay M
d6fe9f7819 Define and import cascade layers (#1793)
* define cascade layers

* invoke cascade layers in kitchen sink styles

* invoke cascade layers in utilities and native styles

* invoke cascade layers in palettes + consolidate shared palette rules

* invoke cascade layers in themes

* add changelog

* prettier demands whitespace
2025-11-19 17:43:55 -05:00
Cory LaViska
200b02f023 fix scroller styles; closes #1724 (#1785) 2025-11-19 07:34:22 -05:00
Cory LaViska
1429095eed Fix SVG fill in <wa-icon> (#1784)
* fix svg fill; closes #1733

* remove fill
2025-11-19 07:33:56 -05:00
Cory LaViska
9706964511 Fix spinner when <wa-tree-item> is lazy loaded (#1786)
* fix spinner when lazy; closes #1678

* remove redundant entry
2025-11-18 15:31:51 -05:00
Cory LaViska
bb0a961784 remove offending property; fixes #1614 (#1792) 2025-11-18 15:29:57 -05:00
lindsaym-fa
c3ddc303cc minor refactor 2025-11-10 16:14:24 -05:00
lindsaym-fa
b57225d5b0 tweaks to color palette logic 2025-11-07 18:56:25 -05:00
lindsaym-fa
c29e4cadf5 make a mess with usage instructions 2025-11-07 18:56:03 -05:00
lindsaym-fa
e5cf6e8757 Merge branch 'next' into lm/theming-docs 2025-11-07 13:04:50 -05:00
lindsaym-fa
69ea84b490 add variants, share styles with color palettes 2025-11-07 11:21:46 -05:00
lindsaym-fa
f83707a9e4 add color palettes preview, color scheme preference info 2025-11-06 18:33:45 -05:00
lindsaym-fa
05bb1f3630 🔧 tweaks 2025-11-06 10:32:53 -05:00
lindsaym-fa
b2a2d0b9fd initial progress 2025-11-05 18:31:41 -05:00
226 changed files with 7561 additions and 5879 deletions

View File

@@ -20,4 +20,5 @@ packages/**/*/src/react/index.ts
node_modules
packages/**/*/_site
packages/**/*/_bundle_
packages/webawesome/docs/assets/scripts/prism-downloaded.js

View File

@@ -1 +1,2 @@
3.0.0
3.1.0

View File

@@ -70,6 +70,7 @@
"exportparts",
"fetchpriority",
"fieldsets",
"flexbox",
"focusin",
"focusout",
"fontawesome",
@@ -105,6 +106,7 @@
"keydown",
"keyframes",
"keymaker",
"Kickstarter",
"Konnor",
"Kool",
"labelledby",
@@ -117,6 +119,7 @@
"lowercasing",
"Lucide",
"maxlength",
"mdash",
"Menlo",
"menuitemcheckbox",
"menuitemradio",
@@ -130,6 +133,7 @@
"mouseout",
"mouseup",
"multiselectable",
"nbsp",
"nextjs",
"nocheck",
"noindex",
@@ -148,6 +152,7 @@
"ParamagicDev",
"peta",
"petabit",
"pointercancel",
"Preact",
"preconnect",
"prerendered",
@@ -179,6 +184,7 @@
"shadowrootmode",
"Shortcode",
"Shortcodes",
"signup",
"sitedir",
"slotchange",
"smartquotes",
@@ -200,6 +206,8 @@
"thead",
"Themer",
"tinycolor",
"touchcancel",
"touchend",
"transitionend",
"treeitem",
"treeshaking",
@@ -233,8 +241,6 @@
"src/translations/!(en).ts",
"**/*.min.js"
],
"ignoreRegExpList": [
"(^|[^a-z])sl[a-z]*(^|[^a-z])"
],
"ignoreRegExpList": ["(^|[^a-z])sl[a-z]*(^|[^a-z])"],
"useGitignore": true
}

216
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@webawesome/monorepo",
"version": "3.0.0-alpha.13",
"version": "3.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@webawesome/monorepo",
"version": "3.0.0-alpha.13",
"version": "3.1.0",
"license": "MIT",
"workspaces": [
"packages/*"
@@ -593,6 +593,10 @@
"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",
@@ -2519,10 +2523,6 @@
"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,6 +12139,16 @@
"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",
@@ -14013,7 +14023,7 @@
},
"packages/webawesome": {
"name": "@awesome.me/webawesome",
"version": "3.0.0",
"version": "3.1.0",
"license": "MIT",
"dependencies": {
"@ctrl/tinycolor": "4.1.0",
@@ -14029,15 +14039,16 @@
"devDependencies": {
"@wc-toolkit/jsx-types": "^1.3.0",
"eleventy-plugin-git-commit-date": "^0.1.3",
"esbuild": "^0.25.11"
"esbuild": "^0.25.11",
"npm-check-updates": "^19.1.2"
},
"engines": {
"node": ">=14.17.0"
}
},
"packages/webawesome-pro": {
"name": "@shoelace-style/webawesome-pro",
"version": "3.0.0-beta.6",
"name": "@awesome.me/webawesome-pro",
"version": "3.1.0",
"dependencies": {
"@ctrl/tinycolor": "4.1.0",
"@floating-ui/dom": "^1.6.13",
@@ -14051,8 +14062,11 @@
},
"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"
"esbuild": "^0.25.11",
"npm-check-updates": "^19.1.2",
"rollup-plugin-typescript-paths": "^1.5.0"
},
"engines": {
"node": ">=14.17.0"
@@ -14466,6 +14480,84 @@
"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",
@@ -14508,6 +14600,16 @@
"@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",
@@ -14525,6 +14627,84 @@
"node": "^18 || >=20"
}
},
"packages/webawesome-pro/node_modules/npm-check-updates": {
"version": "19.1.2",
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-19.1.2.tgz",
"integrity": "sha512-FNeFCVgPOj0fz89hOpGtxP2rnnRHR7hD2E8qNU8SMWfkyDZXA/xpgjsL3UMLSo3F/K13QvJDnbxPngulNDDo/g==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"ncu": "build/cli.js",
"npm-check-updates": "build/cli.js"
},
"engines": {
"node": ">=20.0.0",
"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",
@@ -14966,6 +15146,20 @@
"engines": {
"node": "^18 || >=20"
}
},
"packages/webawesome/node_modules/npm-check-updates": {
"version": "19.1.2",
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-19.1.2.tgz",
"integrity": "sha512-FNeFCVgPOj0fz89hOpGtxP2rnnRHR7hD2E8qNU8SMWfkyDZXA/xpgjsL3UMLSo3F/K13QvJDnbxPngulNDDo/g==",
"dev": true,
"bin": {
"ncu": "build/cli.js",
"npm-check-updates": "build/cli.js"
},
"engines": {
"node": ">=20.0.0",
"npm": ">=8.12.1"
}
}
}
}

View File

@@ -2,7 +2,7 @@
"name": "@webawesome/monorepo",
"private": true,
"description": "A forward-thinking library of web components.",
"version": "3.0.0-alpha.13",
"version": "3.1.0",
"homepage": "https://webawesome.com/",
"author": "Web Awesome",
"license": "MIT",
@@ -85,4 +85,4 @@
"prettier --write"
]
}
}
}

View File

@@ -14,8 +14,8 @@
<p>Celebrate our official launch with a 20% discount on a Web Awesome Pro plan&hellip;<span class="appearance-underlined variant-drawn" style="--underline-color: var(--wa-color-brand);">for life</span>! But hurry, this lifetime discount is only available for a limited time.</p>
<div class="wa-split">
<wa-button type="button" appearance="plain" data-dialog="close" class="plausible-event-name=launch_dialog:close_button_click">Maybe Later</wa-button>
<wa-button variant="neutral" appearance="accent" href="/purchase" class="brand-font plausible-event-name=launch_dialog:pro_purchase_button_click">
<wa-button type="button" appearance="plain" data-dialog="close">Maybe Later</wa-button>
<wa-button variant="neutral" appearance="accent" href="/purchase" class="brand-font">
<wa-icon slot="start" variant="regular" name="rocket-launch"></wa-icon>
Get Pro + Save 20%
</wa-button>
@@ -43,13 +43,6 @@
return;
}
// Helper function to safely track Plausible events
const trackEvent = (eventName) => {
if (typeof plausible !== 'undefined') {
plausible(eventName);
}
};
// Initialize dialog functionality
let initCalled = false;
const initDialog = () => {
@@ -59,19 +52,8 @@
}
initCalled = true;
// Track when dialog is shown
dialog.addEventListener('wa-show', () => {
trackEvent('launch_dialog:view');
}, { once: true });
// Track when dialog is dismissed
// Save dismissal state when dialog is hidden
dialog.addEventListener('wa-hide', (event) => {
// Track overlay click or Escape key dismissal
// Button clicks are tracked via CSS classes, so we only track non-button dismissals
if (event.detail?.source === dialog) {
trackEvent('launch_dialog:overlay_click');
}
// Save dismissal state to localStorage
try {
localStorage.setItem(SITE_DIALOG_DISMISSED_KEY, 'true');

View File

@@ -17,7 +17,6 @@
<script type="module" src="/assets/scripts/color-scheme.js"></script>
<script type="module" src="/assets/scripts/theme.js"></script>
{% if hasSidebar %}<script type="module" src="/assets/scripts/sidebar.js"></script>{% endif %}
<script defer data-domain="webawesome.com" src="https://plausible.io/js/script.js"></script>
{% block head %}
<link rel="stylesheet" href="/assets/styles/docs.css" />
@@ -142,6 +141,9 @@
{% include "_dialog-wa-launch.njk" ignore missing %}
{% endif %}
{#- Cookie Consent Dialog -#}
{% include "cookie-consent.njk" ignore missing %}
{# Footer #}
{% block pageFooter %}{% endblock %}
</wa-page>

View File

@@ -78,10 +78,18 @@
</li>
</ul>
</li>
<li><span class="is-planned wa-split">Charts <a href="https://github.com/shoelace-style/webawesome/issues/1073" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
<li><span class="is-planned wa-split">Charts <span><a href="https://github.com/shoelace-style/webawesome/issues/1073" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge({ description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
<li><a href="/docs/components/checkbox/">Checkbox</a></li>
<li><a href="/docs/components/color-picker/">Color Picker</a></li>
<li><span class="is-planned wa-split">Combobox <a href="https://github.com/shoelace-style/webawesome/issues/1074" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
<li>
<span class="wa-split">
<span>
<a href="/docs/components/combobox">Combobox</a>
<wa-icon name="flask" aria-hidden="true" class="icon-shrink"></wa-icon>
</span>
{{ proBadge() }}
</span>
</li>
<li><a href="/docs/components/comparison/">Comparison</a></li>
<li>
<a class="wa-cluster wa-gap-xs" href="/docs/components/copy-button/">
@@ -89,8 +97,8 @@
<wa-icon name="flask" aria-hidden="true" class="icon-shrink"></wa-icon>
</a>
</li>
<li><span class="is-planned wa-split">Data Grid <a href="https://github.com/shoelace-style/webawesome/issues/1072" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
<li><span class="is-planned wa-split">Datepicker <a href="https://github.com/shoelace-style/webawesome/issues/1075" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
<li><span class="is-planned wa-split">Data Grid <span><a href="https://github.com/shoelace-style/webawesome/issues/1072" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge({ description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
<li><span class="is-planned wa-split">Date Picker <span><a href="https://github.com/shoelace-style/webawesome/issues/1075" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge({ description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
<li><a href="/docs/components/details/">Details</a></li>
<li><a href="/docs/components/dialog/">Dialog</a></li>
<li><a href="/docs/components/divider/">Divider</a></li>
@@ -101,7 +109,7 @@
<li><a href="/docs/components/dropdown-item">Dropdown Item</a></li>
</ul>
</li>
<li><span class="is-planned wa-split">File Input <a href="https://github.com/shoelace-style/webawesome/issues/1240" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
<li><span class="is-planned wa-split">File Input <span><a href="https://github.com/shoelace-style/webawesome/issues/1240" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge({ description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
<li><a href="/docs/components/format-bytes/">Format Bytes</a></li>
<li><a href="/docs/components/format-date/">Format Date</a></li>
<li><a href="/docs/components/format-number/">Format Number</a></li>
@@ -146,7 +154,7 @@
</li>
<li><a href="/docs/components/tag/">Tag</a></li>
<li><a href="/docs/components/textarea/">Textarea</a></li>
<li><span class="is-planned wa-split">Toast <a href="https://github.com/shoelace-style/webawesome/issues/105" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
<li><span class="is-planned wa-split">Toast <span><a href="https://github.com/shoelace-style/webawesome/issues/105" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge( { description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
<li><a href="/docs/components/tooltip/">Tooltip</a></li>
<li>
<a href="/docs/components/tree/">Tree</a>
@@ -154,7 +162,7 @@
<li><a href="/docs/components/tree-item/">Tree Item</a></li>
</ul>
</li>
<li><span class="is-planned wa-split">Video <a href="https://github.com/shoelace-style/webawesome/issues/985" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a></span></li>
<li><span class="is-planned wa-split">Video <span><a href="https://github.com/shoelace-style/webawesome/issues/985" target="_blank">{{ plannedBadge("A Web Awesome Kickstarter stretch goal!") }}</a>{{ proBadge( { description: "This will require access to Web Awesome Pro" }) }}</span></span></li>
<li><a href="/docs/components/zoomable-frame">Zoomable Frame</a></li>
{# PLOP_NEW_COMPONENT_PLACEHOLDER #}
</ul>
@@ -188,6 +196,8 @@
</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>

View File

@@ -0,0 +1,195 @@
{% 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>

View File

@@ -0,0 +1,302 @@
{% 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>&lt;html&gt;</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>&lt;html&gt;</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>&lt;html&gt;</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>

View File

@@ -0,0 +1,27 @@
{% 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>

View File

@@ -8,10 +8,13 @@
<wa-badge variant="neutral">Since {{ component.since }}</wa-badge>
<wa-badge
{% if component.status == 'stable' %}variant="brand"{% endif %}
{% if component.status == 'experimental' %}variant="warning"{% endif %}
{% if component.status == 'experimental' %}variant="warning" appearance="filled"{% endif %}
>
{{ component.status }}
</wa-badge>
{% if isProComponent %}
<wa-badge class="pro">Pro</wa-badge>
{% endif %}
</div>
<p class="component-summary">
{{ component.summary | inlineMarkdown | safe }}
@@ -20,6 +23,37 @@
{# Component API #}
{% block afterContent %}
{# Importing #}
<h2>Importing</h2>
<p>
Autoloading components via <a href="/docs/#using-a-project">projects</a> is the recommended way to import components. If you prefer to do it manually, use one of the following code snippets.
</p>
{% set componentName = component.tagName | stripPrefix %}
{% set componentPath = ["components/", componentName, "/", componentName, ".js"] | join("") %}
<wa-tab-group label="How would you like to import this component?">
<wa-tab panel="cdn">CDN</wa-tab>
<wa-tab panel="npm">npm</wa-tab>
<wa-tab panel="react">React</wa-tab>
<wa-tab-panel name="cdn">
<p>
Let your project code do the work! <a href="/signup">Sign up for free</a> to use a project with your very own CDN &mdash; it's the fastest and easiest way to use Web Awesome.
</p>
</wa-tab-panel>
<wa-tab-panel name="npm">
<p>
To manually import this component from NPM, use the following code.
</p>
<pre><code class="language-js">import '@awesome.me/webawesome/dist/{{ componentPath }}';</code></pre>
</wa-tab-panel>
<wa-tab-panel name="react">
<p>
To manually import this component from React, use the following code.
</p>
<pre><code class="language-js">import {{ component.name }} from '@awesome.me/webawesome/dist/react/{{ componentName }}';</code></pre>
</wa-tab-panel>
</wa-tab-group>
{# Slots #}
{% if component.slots.length %}
<h2>Slots</h2>
@@ -270,38 +304,6 @@
</ul>
{% endif %}
{# Importing #}
<h2>Importing</h2>
<p>
Autoloading components via <a href="/docs/#using-a-project">projects</a> is the recommended way to import components. If you prefer to do it manually, use one of the following code snippets.
</p>
{% set componentName = component.tagName | stripPrefix %}
{% set componentPath = ["components/", componentName, "/", componentName, ".js"] | join("") %}
<wa-tab-group label="How would you like to import this component?">
<wa-tab panel="cdn">CDN</wa-tab>
<wa-tab panel="npm">npm</wa-tab>
<wa-tab panel="react">React</wa-tab>
<wa-tab-panel name="cdn">
<p>
Let your project code do the work! <a href="/signup">Sign up for free</a> to use a project with your very own CDN &mdash; it's the fastest and easiest way to use Web Awesome.
</p>
</wa-tab-panel>
<wa-tab-panel name="npm">
<p>
To manually import this component from NPM, use the following code.
</p>
<pre><code class="language-js">import '@awesome.me/webawesome/dist/{{ componentPath }}';</code></pre>
</wa-tab-panel>
<wa-tab-panel name="react">
<p>
To manually import this component from React, use the following code.
</p>
<pre><code class="language-js">import {{ component.name }} from '@awesome.me/webawesome/dist/react/{{ componentName }}';</code></pre>
</wa-tab-panel>
</wa-tab-group>
<wa-divider></wa-divider>
<div class="component-help">

View File

@@ -1,10 +1,20 @@
import * as path from 'node:path';
import nunjucks from 'nunjucks';
const baseDir = process.env.BASE_DIR || 'docs';
const views = [path.join(baseDir), path.join(baseDir, '_layouts'), path.join(baseDir, '_includes')];
const nunjucksEnv = new nunjucks.Environment(new nunjucks.FileSystemLoader(views), {
autoescape: true,
noCache: process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test',
});
/**
* This function simulates what a server would do running "on top" of eleventy.
*/
export function SimulateWebAwesomeApp(str) {
return nunjucks.renderString(str, {
return nunjucksEnv.renderString(str, {
// Stub the server EJS shortcodes.
currentUser: {
hasPro: false,

View File

@@ -1,12 +1,24 @@
// 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}`)]);
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 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() {
@@ -17,6 +29,24 @@ 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 (
@@ -42,40 +72,98 @@ 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 hide() {
function cleanup() {
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);
dialog.open = false;
// Reset state to prevent leakage between dialog sessions
resultSelected = false;
lastTrackedQuery = '';
}
function handleClose() {
const { input } = getElements();
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;
}
}
input.value = '';
updateResults();
try {
await updateResults();
} catch (error) {
// Silently handle errors - UI cleanup should continue
}
cleanup();
trackEvent('navigation:search_dialog_close');
}
function handleInput() {
const { input } = getElements();
if (!input) return;
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => updateResults(input.value), searchDebounce);
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);
}
function handleKeyDown(event) {
const { input, results } = getElements();
if (!input || !results) return;
// Handle keyboard selections
if (['ArrowDown', 'ArrowUp', 'Home', 'End', 'Enter'].includes(event.key)) {
@@ -104,7 +192,12 @@ function handleKeyDown(event) {
nextEl = items[items.length - 1];
break;
case 'Enter':
currentEl?.querySelector('a')?.click();
if (currentEl) {
const link = currentEl.querySelector('a');
if (link) {
selectResult(link, 'keyboard_enter');
}
}
break;
}
@@ -121,27 +214,62 @@ 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();
hide();
if (window.Turbo) {
Turbo.visit(link.href);
} else {
location.href = link.href;
}
selectResult(link, 'mouse_click');
}
}
// Queries the search index and updates the results
async function updateResults(query = '') {
const { dialog, input, results } = getElements();
if (!dialog || !input || !results) return;
try {
const hasQuery = query.length > 0;
const trimmedQuery = query.trim();
const hasQuery = trimmedQuery.length > 0;
let matches = [];
if (hasQuery) {
@@ -149,13 +277,13 @@ async function updateResults(query = '') {
const seenRefs = new Set();
// Start with a standard search to get the best "exact match" result
searchIndex.search(`${query}`).forEach(match => {
searchIndex.search(`${trimmedQuery}`).forEach(match => {
matches.push(match);
seenRefs.add(match.ref);
});
// Add wildcard matches if not already included
searchIndex.search(`${query}*`).forEach(match => {
searchIndex.search(`${trimmedQuery}*`).forEach(match => {
if (!seenRefs.has(match.ref)) {
matches.push(match);
seenRefs.add(match.ref);
@@ -163,11 +291,10 @@ async function updateResults(query = '') {
});
// Add fuzzy search matches last
const fuzzyTokens = query
const fuzzyTokens = trimmedQuery
.split(' ')
.map(term => `${term}~1`)
.join(' ');
searchIndex.search(fuzzyTokens).forEach(match => {
if (!seenRefs.has(match.ref)) {
matches.push(match);
@@ -180,12 +307,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 ?? '';
@@ -197,12 +324,10 @@ 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">
@@ -218,6 +343,9 @@ 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);
});

View File

@@ -10,6 +10,13 @@
: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,
@@ -627,6 +634,68 @@ 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);

View File

@@ -5,7 +5,6 @@
border-radius: var(--wa-border-radius-l);
padding: 0;
margin: 0 auto;
overflow: hidden;
&::part(dialog) {
margin-block-start: 10vh;

View File

@@ -130,6 +130,13 @@
}
}
/* 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;
@@ -250,7 +257,6 @@
z-index: 0;
}
}
/* #endregion */
/* buttons with icon toggle on hover */
wa-button .icon-hover {
@@ -262,6 +268,13 @@
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 */

View File

@@ -40,60 +40,6 @@ Set the `orientation` attribute to `vertical` to make a vertical button group.
</wa-button-group>
```
### Theme Buttons
Theme buttons are supported through the button group's `variant` attribute.
```html {.example}
<wa-button-group label="Alignment" variant="brand">
<wa-button>Left</wa-button>
<wa-button>Center</wa-button>
<wa-button>Right</wa-button>
</wa-button-group>
<br /><br />
<wa-button-group label="Alignment" variant="success">
<wa-button>Left</wa-button>
<wa-button>Center</wa-button>
<wa-button>Right</wa-button>
</wa-button-group>
<br /><br />
<wa-button-group label="Alignment">
<wa-button>Left</wa-button>
<wa-button>Center</wa-button>
<wa-button>Right</wa-button>
</wa-button-group>
<br /><br />
<wa-button-group label="Alignment" variant="warning">
<wa-button>Left</wa-button>
<wa-button>Center</wa-button>
<wa-button>Right</wa-button>
</wa-button-group>
<br /><br />
<wa-button-group label="Alignment" variant="danger">
<wa-button>Left</wa-button>
<wa-button>Center</wa-button>
<wa-button>Right</wa-button>
</wa-button-group>
```
You can still use the buttons own `variant` attribute to override the inherited variant.
```html {.example}
<wa-button-group label="Alignment" variant="brand">
<wa-button>Left</wa-button>
<wa-button>Center</wa-button>
<wa-button variant="neutral">Right</wa-button>
</wa-button-group>
```
### Pill Buttons
Pill buttons are supported through the button's `pill` attribute.

View File

@@ -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 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 [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.
```html {.example}
<div style="display: flex; align-items: center;">
@@ -53,6 +53,10 @@ 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.

View File

@@ -2,6 +2,7 @@
title: Intersection Observer
description: Tracks immediate child elements and fires events as they move in and out of view.
layout: component
category: Utilities
---
This component leverages the [IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) to track when its direct children enter or leave a designated root element. The `wa-intersect` event fires whenever elements cross the visibility threshold.

View File

@@ -285,9 +285,10 @@ Remember that custom tags are rendered in a shadow root. To style them, you can
const name = option.querySelector('wa-icon[slot="start"]').name;
// You can return a string, a Lit Template, or an HTMLElement here
// Important: include data-value so the tag can be removed properly!
return `
<wa-tag with-remove>
<wa-icon name="${name}" style="padding-inline-end: .5rem;"></wa-icon>
<wa-tag with-remove data-value="${option.value}">
<wa-icon name="${name}"></wa-icon>
${option.label}
</wa-tag>
`;
@@ -299,6 +300,10 @@ Remember that custom tags are rendered in a shadow root. To style them, you can
Be sure you trust the content you are outputting! Passing unsanitized user input to `getTag()` can result in XSS vulnerabilities.
:::
:::info
When using custom tags with `with-remove`, you must include the `data-value` attribute set to the option's value. This allows the select to identify which option to deselect when the tag's remove button is clicked.
:::
### Lazy loading options
Lazy loading options works similarly to native `<select>` elements. The select component handles various scenarios intelligently:

View File

@@ -13,17 +13,45 @@ Components with the <wa-badge variant="warning">Experimental</wa-badge> badge sh
## Next
- 🚨 BREAKING: Changed `appearance="filled outlined"` to `appearance="filled-outlined"` in `<wa-card>` [issue:1671]
- 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]
- Fixed a bug in `<wa-icon>` that caused some icon libraries to render with the incorrect SVG fill [issue:1733]
- Fixed a bug in `<wa-tree-item>` that caused the spinner to not show when lazy loading [issue:1678]
- Fixed a bug in `<wa-dropdown>` that caused the browser to hang when cancelling the `wa-hide` event [issue:1483]
- Fixed a bug in `<wa-spinner>` that caused `--track-width` to not work correctly [issue:1317]
- Fixed a bug in `<wa-dropdown-item>` that prevented the icon dependency from being imported [issue:1825]
- Fixed a bug in `<wa-select>` that prevented clicks on the tag's remove button from removing options in multiple mode
- Fixed a bug in `<wa-select>` that caused tags to appear in alphabetical order instead of selection order when using `multiple`
- Improved performance of `<wa-icon>` so initial rendering occurs faster, especially with multiple icons on the page [issue:1729]
- Improved `<wa-slider>` to not throw an error when string values are passed to the `min`, `max`, and `step` properties [issue:1823]
- Fixed a bug in Web Awesome form controls that caused `<wa-input form="foo">` to set the form property to equal `"foo"` instead of returning an `HTMLFormElement` breaking platform expectations. [pr:1815]
- Fixed a bug in `<wa-button>` causing it to not copy over attributes for form submissions. [pr:1815]
- Improved performance of all components by fixing how CSS is imported and reused [issue:1812]
- Modified the default `transition` styles of `<wa-dropdown-item>` to use design tokens [pr:1693]
## 3.0.0
- 🚨 BREAKING: Changed `appearance="filled outlined"` to `appearance="filled-outlined"` in the following elements [issue:1127]
- `<wa-badge>`
- `<wa-button>`
- `<wa-callout>`
- `<wa-card>`

View File

@@ -0,0 +1,165 @@
---
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

View File

@@ -1,35 +1,37 @@
---
title: Align Items
description: Align items utilities set the gap property of flex and grid containers, like other Web Awesome layout utilities.
description: Align items utilities align items within flex and grid containers on the cross axis.
layout: docs
tags: layoutUtilities
---
<style>
.preview-wrapper {
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
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(--wa-color-neutral-fill-loud);
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 `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.
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).
| 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> |
| 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> |
## What's a Cross Axis?
## What's the Cross Axis?
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.
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.

View File

@@ -7,19 +7,21 @@ tags: layoutUtilities
<style>
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-cluster']:has(div:empty) {
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);
border: var(--layout-example-border);
border-radius: var(--layout-example-border-radius);
padding: var(--layout-example-padding);
}
[class*='wa-cluster'] div:empty {
background-color: var(--wa-color-indigo-60);
border-radius: var(--wa-border-radius-m);
background-color: var(--layout-example-element-background);
border-radius: var(--layout-example-element-border-radius);
min-block-size: 4rem;
min-inline-size: 4rem;
}
</style>
{{ description }}
```html {.example}
<div class="wa-cluster">
<div></div>

View File

@@ -7,20 +7,20 @@ tags: layoutUtilities
<style>
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-flank']:has(div:empty) {
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);
border: var(--layout-example-border);
border-radius: var(--layout-example-border-radius);
padding: var(--layout-example-padding);
}
[class*='wa-flank'] div:empty {
background-color: var(--wa-color-indigo-60);
border-radius: var(--wa-border-radius-m);
background-color: var(--layout-example-element-background);
border-radius: var(--layout-example-element-border-radius);
min-block-size: 4rem;
min-inline-size: 4rem;
}
</style>
When space is limited, the items wrap.
{{ description }} When space is limited, the items wrap.
```html {.example}
<div class="wa-flank">

View File

@@ -7,18 +7,20 @@ tags: layoutUtilities
<style>
[class*='wa-frame']:has(div:empty) {
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
padding: var(--wa-space-s);
border: var(--layout-example-border);
padding: var(--layout-example-padding);
}
[class*='wa-frame'] div:empty {
background-color: var(--wa-color-indigo-60);
border-radius: var(--wa-border-radius-m);
background-color: var(--layout-example-element-background);
border-radius: var(--layout-example-element-border-radius);
min-block-size: 4rem;
min-inline-size: 4rem;
}
</style>
{{ description }}
```html {.example}
<div class="wa-frame" style="max-inline-size: 20rem;">
<div></div>

View File

@@ -6,28 +6,37 @@ 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(--wa-color-neutral-fill-loud);
background-color: var(--layout-example-element-background);
border-radius: var(--wa-border-radius-s);
min-block-size: 1.5em;
min-block-size: 1em;
}
</style>
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.
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.
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="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> |
| `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> | -->

View File

@@ -7,19 +7,21 @@ tags: layoutUtilities
<style>
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-grid']:has(div:empty) {
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);
border: var(--layout-example-border);
border-radius: var(--layout-example-border-radius);
padding: var(--layout-example-padding);
}
[class*='wa-grid'] div:empty {
background-color: var(--wa-color-indigo-60);
border-radius: var(--wa-border-radius-m);
background-color: var(--layout-example-element-background);
border-radius: var(--layout-example-element-border-radius);
min-block-size: 4rem;
min-inline-size: 4rem;
}
</style>
{{ description }}
```html {.example}
<div class="wa-grid">
<div></div>

View File

@@ -0,0 +1,40 @@
---
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.

View File

@@ -7,19 +7,21 @@ tags: layoutUtilities
<style>
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-split']:has(div:empty) {
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);
border: var(--layout-example-border);
border-radius: var(--layout-example-border-radius);
padding: var(--layout-example-padding);
}
[class*='wa-split'] div:empty {
background-color: var(--wa-color-indigo-60);
border-radius: var(--wa-border-radius-m);
background-color: var(--layout-example-element-background);
border-radius: var(--layout-example-element-border-radius);
min-block-size: 4rem;
min-inline-size: 4rem;
}
</style>
{{ description }}
```html {.example}
<div class="wa-split">
<div></div>

View File

@@ -7,19 +7,21 @@ tags: layoutUtilities
<style>
:is(.wa-flank, .wa-grid, .wa-stack) > [class*='wa-stack']:has(div:empty) {
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);
border: var(--layout-example-border);
border-radius: var(--layout-example-border-radius);
padding: var(--layout-example-padding);
}
[class*='wa-stack'] div:empty {
background-color: var(--wa-color-indigo-60);
border-radius: var(--wa-border-radius-m);
background-color: var(--layout-example-element-background);
border-radius: var(--layout-example-element-border-radius);
min-block-size: 4rem;
min-inline-size: 4rem;
}
</style>
{{ description }}
```html {.example}
<div class="wa-stack">
<div></div>

View File

@@ -4,7 +4,7 @@
"access": "public"
},
"description": "A forward-thinking library of web components.",
"version": "3.0.0",
"version": "3.1.0",
"homepage": "https://webawesome.com/",
"author": "Web Awesome",
"license": "MIT",
@@ -64,10 +64,10 @@
"spellcheck": "cspell \"**/*.{js,ts,json,html,css,md}\" --no-progress --config=\"../../cspell.json\"",
"verify": "npm run prettier && npm run build && npm run test",
"prepublishOnly": "npm run verify",
"check-updates": "npx npm-check-updates --interactive --format group",
"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": "npm run tag-version"
"postversion": "node ./scripts/update-root-version.js"
},
"engines": {
"node": ">=14.17.0"
@@ -91,6 +91,7 @@
"devDependencies": {
"@wc-toolkit/jsx-types": "^1.3.0",
"eleventy-plugin-git-commit-date": "^0.1.3",
"esbuild": "^0.25.11"
"esbuild": "^0.25.11",
"npm-check-updates": "^19.1.2"
}
}

View File

@@ -230,9 +230,6 @@ export async function build(options = {}) {
js: `/*! Copyright ${currentYear} Fonticons, Inc. - https://webawesome.com/license */`,
},
plugins: [replace({ __WEBAWESOME_VERSION__: await getVersion() })],
loader: {
'.css': 'text',
},
};
const unbundledConfig = {

View File

@@ -37,7 +37,7 @@ export default function (plop) {
},
{
type: 'add',
path: '../../src/components/{{ tagWithoutPrefix tag }}/{{ tagWithoutPrefix tag }}.css',
path: '../../src/components/{{ tagWithoutPrefix tag }}/{{ tagWithoutPrefix tag }}.styles.ts',
templateFile: 'templates/component/styles.hbs',
},
{

View File

@@ -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 }}.css';
import styles from './{{ tagWithoutPrefix tag }}.styles.js';
/**
* @summary Short summary of the component's intended use.
@@ -21,7 +21,7 @@ import styles from './{{ tagWithoutPrefix tag }}.css';
*/
@customElement("{{ tag }}")
export default class {{ properCase tag }} extends WebAwesomeElement {
static css = styles;
static css = [styles];
/** An example attribute. */
@property() attr = 'example';

View File

@@ -1,3 +1,7 @@
:host {
display: block;
import { css } from "lit";
export default css`
:host {
display: block;
}
`

View File

@@ -0,0 +1,27 @@
#!/usr/bin/env node
import * as fs from 'node:fs';
import * as path from 'node:path';
import * as url from 'url';
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
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 currentVersion = webawesomePackageJSON.version;
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/);
// 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);
}

View File

@@ -1,65 +0,0 @@
:host {
--control-box-size: 3rem;
--icon-size: calc(var(--control-box-size) * 0.625);
display: inline-flex;
position: relative;
cursor: pointer;
}
img {
display: block;
width: 100%;
height: 100%;
}
img[aria-hidden='true'] {
display: none;
}
.control-box {
display: flex;
position: absolute;
align-items: center;
justify-content: center;
top: calc(50% - var(--control-box-size) / 2);
right: calc(50% - var(--control-box-size) / 2);
width: var(--control-box-size);
height: var(--control-box-size);
font-size: calc(var(--icon-size) * 0.75);
background: none;
border: solid var(--wa-border-width-s) currentColor;
background-color: rgb(0 0 0 / 50%);
border-radius: var(--wa-border-radius-circle);
color: white;
pointer-events: none;
transition: opacity var(--wa-transition-normal) var(--wa-transition-easing);
}
@media (hover: hover) {
:host([play]:hover) .control-box {
opacity: 1;
}
}
:where(:host([play]:not(:hover))) .control-box {
opacity: 0;
}
:host([play]) slot[name='play-icon'],
:host(:not([play])) slot[name='pause-icon'] {
display: none;
}
/* Show control box on keyboard focus */
.animated-image {
&:focus {
outline: none;
}
&:focus-visible .control-box {
opacity: 1;
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
}

View File

@@ -0,0 +1,69 @@
import { css } from 'lit';
export default css`
:host {
--control-box-size: 3rem;
--icon-size: calc(var(--control-box-size) * 0.625);
display: inline-flex;
position: relative;
cursor: pointer;
}
img {
display: block;
width: 100%;
height: 100%;
}
img[aria-hidden='true'] {
display: none;
}
.control-box {
display: flex;
position: absolute;
align-items: center;
justify-content: center;
top: calc(50% - var(--control-box-size) / 2);
right: calc(50% - var(--control-box-size) / 2);
width: var(--control-box-size);
height: var(--control-box-size);
font-size: calc(var(--icon-size) * 0.75);
background: none;
border: solid var(--wa-border-width-s) currentColor;
background-color: rgb(0 0 0 / 50%);
border-radius: var(--wa-border-radius-circle);
color: white;
pointer-events: none;
transition: opacity var(--wa-transition-normal) var(--wa-transition-easing);
}
@media (hover: hover) {
:host([play]:hover) .control-box {
opacity: 1;
}
}
:where(:host([play]:not(:hover))) .control-box {
opacity: 0;
}
:host([play]) slot[name='play-icon'],
:host(:not([play])) slot[name='pause-icon'] {
display: none;
}
/* Show control box on keyboard focus */
.animated-image {
&:focus {
outline: none;
}
&:focus-visible .control-box {
opacity: 1;
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
}
`;

View File

@@ -6,7 +6,7 @@ import { watch } from '../../internal/watch.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import { LocalizeController } from '../../utilities/localize.js';
import '../icon/icon.js';
import styles from './animated-image.css';
import styles from './animated-image.styles.js';
/**
* @summary A component for displaying animated GIFs and WEBPs that play and pause on interaction.

View File

@@ -1,3 +0,0 @@
:host {
display: contents;
}

View File

@@ -0,0 +1,7 @@
import { css } from 'lit';
export default css`
:host {
display: contents;
}
`;

View File

@@ -5,7 +5,7 @@ import { WaFinishEvent } from '../../events/finish.js';
import { WaStartEvent } from '../../events/start.js';
import { watch } from '../../internal/watch.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import styles from './animation.css';
import styles from './animation.styles.js';
import { animations } from './animations.js';
/**

View File

@@ -1,53 +0,0 @@
:host {
--size: 3rem;
display: inline-flex;
align-items: center;
justify-content: center;
position: relative;
width: var(--size);
height: var(--size);
color: var(--wa-color-neutral-on-normal);
font: inherit;
font-size: calc(var(--size) * 0.4);
vertical-align: middle;
background-color: var(--wa-color-neutral-fill-normal);
border-radius: var(--wa-border-radius-circle);
user-select: none;
-webkit-user-select: none;
}
:host([shape='square']) {
border-radius: 0;
}
:host([shape='rounded']) {
border-radius: var(--wa-border-radius-m);
}
.icon {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.initials {
line-height: 1;
text-transform: uppercase;
}
.image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
overflow: hidden;
border-radius: inherit;
}

View File

@@ -0,0 +1,57 @@
import { css } from 'lit';
export default css`
:host {
--size: 3rem;
display: inline-flex;
align-items: center;
justify-content: center;
position: relative;
width: var(--size);
height: var(--size);
color: var(--wa-color-neutral-on-normal);
font: inherit;
font-size: calc(var(--size) * 0.4);
vertical-align: middle;
background-color: var(--wa-color-neutral-fill-normal);
border-radius: var(--wa-border-radius-circle);
user-select: none;
-webkit-user-select: none;
}
:host([shape='square']) {
border-radius: 0;
}
:host([shape='rounded']) {
border-radius: var(--wa-border-radius-m);
}
.icon {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.initials {
line-height: 1;
text-transform: uppercase;
}
.image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
overflow: hidden;
border-radius: inherit;
}
`;

View File

@@ -4,7 +4,7 @@ import { WaErrorEvent } from '../../events/error.js';
import { watch } from '../../internal/watch.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import '../icon/icon.js';
import styles from './avatar.css';
import styles from './avatar.styles.js';
/**
* @summary Avatars are used to represent a person or object.

View File

@@ -1,104 +0,0 @@
:host {
--pulse-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.375em 0.625em;
color: var(--wa-color-on-loud, var(--wa-color-brand-on-loud));
font-size: max(var(--wa-font-size-2xs), 0.75em);
font-weight: var(--wa-font-weight-semibold);
line-height: 1;
white-space: nowrap;
background-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
border-color: transparent;
border-radius: var(--wa-border-radius-s);
border-style: var(--wa-border-style);
border-width: var(--wa-border-width-s);
user-select: none;
-webkit-user-select: none;
cursor: inherit;
}
/* Appearance modifiers */
:host([appearance='outlined']) {
--pulse-color: var(--wa-color-border-loud, var(--wa-color-brand-border-loud));
color: var(--wa-color-on-quiet, var(--wa-color-brand-on-quiet));
background-color: transparent;
border-color: var(--wa-color-border-loud, var(--wa-color-brand-border-loud));
}
:host([appearance='filled']) {
--pulse-color: var(--wa-color-fill-normal, var(--wa-color-brand-fill-normal));
color: var(--wa-color-on-normal, var(--wa-color-brand-on-normal));
background-color: var(--wa-color-fill-normal, var(--wa-color-brand-fill-normal));
border-color: transparent;
}
:host([appearance='filled-outlined']) {
--pulse-color: var(--wa-color-border-normal, var(--wa-color-brand-border-normal));
color: var(--wa-color-on-normal, var(--wa-color-brand-on-normal));
background-color: var(--wa-color-fill-normal, var(--wa-color-brand-fill-normal));
border-color: var(--wa-color-border-normal, var(--wa-color-brand-border-normal));
}
:host([appearance='accent']) {
--pulse-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
color: var(--wa-color-on-loud, var(--wa-color-brand-on-loud));
background-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
border-color: transparent;
}
/* Pill modifier */
:host([pill]) {
border-radius: var(--wa-border-radius-pill);
}
/* Pulse attention */
:host([attention='pulse']) {
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 var(--pulse-color);
}
70% {
box-shadow: 0 0 0 0.5rem transparent;
}
100% {
box-shadow: 0 0 0 0 transparent;
}
}
/* Bounce attention */
:host([attention='bounce']) {
animation: bounce 1s cubic-bezier(0.28, 0.84, 0.42, 1) infinite;
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-5px);
}
60% {
transform: translateY(-2px);
}
}
::slotted(wa-icon) {
margin-inline-end: var(--wa-space-2xs, 0.25em);
opacity: 90%;
line-height: 1;
height: 0.85em;
}

View File

@@ -0,0 +1,108 @@
import { css } from 'lit';
export default css`
:host {
--pulse-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.375em 0.625em;
color: var(--wa-color-on-loud, var(--wa-color-brand-on-loud));
font-size: max(var(--wa-font-size-2xs), 0.75em);
font-weight: var(--wa-font-weight-semibold);
line-height: 1;
white-space: nowrap;
background-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
border-color: transparent;
border-radius: var(--wa-border-radius-s);
border-style: var(--wa-border-style);
border-width: var(--wa-border-width-s);
user-select: none;
-webkit-user-select: none;
cursor: inherit;
}
/* Appearance modifiers */
:host([appearance='outlined']) {
--pulse-color: var(--wa-color-border-loud, var(--wa-color-brand-border-loud));
color: var(--wa-color-on-quiet, var(--wa-color-brand-on-quiet));
background-color: transparent;
border-color: var(--wa-color-border-loud, var(--wa-color-brand-border-loud));
}
:host([appearance='filled']) {
--pulse-color: var(--wa-color-fill-normal, var(--wa-color-brand-fill-normal));
color: var(--wa-color-on-normal, var(--wa-color-brand-on-normal));
background-color: var(--wa-color-fill-normal, var(--wa-color-brand-fill-normal));
border-color: transparent;
}
:host([appearance='filled-outlined']) {
--pulse-color: var(--wa-color-border-normal, var(--wa-color-brand-border-normal));
color: var(--wa-color-on-normal, var(--wa-color-brand-on-normal));
background-color: var(--wa-color-fill-normal, var(--wa-color-brand-fill-normal));
border-color: var(--wa-color-border-normal, var(--wa-color-brand-border-normal));
}
:host([appearance='accent']) {
--pulse-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
color: var(--wa-color-on-loud, var(--wa-color-brand-on-loud));
background-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
border-color: transparent;
}
/* Pill modifier */
:host([pill]) {
border-radius: var(--wa-border-radius-pill);
}
/* Pulse attention */
:host([attention='pulse']) {
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 var(--pulse-color);
}
70% {
box-shadow: 0 0 0 0.5rem transparent;
}
100% {
box-shadow: 0 0 0 0 transparent;
}
}
/* Bounce attention */
:host([attention='bounce']) {
animation: bounce 1s cubic-bezier(0.28, 0.84, 0.42, 1) infinite;
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-5px);
}
60% {
transform: translateY(-2px);
}
}
::slotted(wa-icon) {
margin-inline-end: var(--wa-space-2xs, 0.25em);
opacity: 90%;
line-height: 1;
height: 0.85em;
}
`;

View File

@@ -1,8 +1,8 @@
import { html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import variantStyles from '../../styles/utilities/variants.css';
import styles from './badge.css';
import variantStyles from '../../styles/component/variants.styles.js';
import styles from './badge.styles.js';
/**
* @summary Badges are used to draw attention and display statuses or counts.

View File

@@ -1,81 +0,0 @@
:host {
color: var(--wa-color-text-link);
display: inline-flex;
align-items: center;
font: inherit;
font-weight: var(--wa-font-weight-action);
line-height: var(--wa-line-height-normal);
white-space: nowrap;
}
:host(:last-of-type) {
color: var(--wa-color-text-quiet);
}
.label {
display: inline-block;
font: inherit;
text-decoration: none;
color: currentColor;
background: none;
border: none;
border-radius: var(--wa-border-radius-m);
padding: 0;
margin: 0;
cursor: pointer;
transition: color var(--wa-transition-normal) var(--wa-transition-easing);
}
@media (hover: hover) {
:host(:not(:last-of-type)) .label:hover {
color: color-mix(in oklab, currentColor, var(--wa-color-mix-hover));
}
}
:host(:not(:last-of-type)) .label:active {
color: color-mix(in oklab, currentColor, var(--wa-color-mix-active));
}
.label:focus {
outline: none;
}
.label:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
.start,
.end {
display: none;
flex: 0 0 auto;
display: flex;
align-items: center;
}
.start,
.end {
display: inline-flex;
color: var(--wa-color-text-quiet);
}
::slotted([slot='start']) {
margin-inline-end: var(--wa-space-s);
}
::slotted([slot='end']) {
margin-inline-start: var(--wa-space-s);
}
:host(:last-of-type) .separator {
display: none;
}
.separator {
color: var(--wa-color-text-quiet);
display: inline-flex;
align-items: center;
margin: 0 var(--wa-space-s);
user-select: none;
-webkit-user-select: none;
}

View File

@@ -0,0 +1,85 @@
import { css } from 'lit';
export default css`
:host {
color: var(--wa-color-text-link);
display: inline-flex;
align-items: center;
font: inherit;
font-weight: var(--wa-font-weight-action);
line-height: var(--wa-line-height-normal);
white-space: nowrap;
}
:host(:last-of-type) {
color: var(--wa-color-text-quiet);
}
.label {
display: inline-block;
font: inherit;
text-decoration: none;
color: currentColor;
background: none;
border: none;
border-radius: var(--wa-border-radius-m);
padding: 0;
margin: 0;
cursor: pointer;
transition: color var(--wa-transition-normal) var(--wa-transition-easing);
}
@media (hover: hover) {
:host(:not(:last-of-type)) .label:hover {
color: color-mix(in oklab, currentColor, var(--wa-color-mix-hover));
}
}
:host(:not(:last-of-type)) .label:active {
color: color-mix(in oklab, currentColor, var(--wa-color-mix-active));
}
.label:focus {
outline: none;
}
.label:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
.start,
.end {
display: none;
flex: 0 0 auto;
display: flex;
align-items: center;
}
.start,
.end {
display: inline-flex;
color: var(--wa-color-text-quiet);
}
::slotted([slot='start']) {
margin-inline-end: var(--wa-space-s);
}
::slotted([slot='end']) {
margin-inline-start: var(--wa-space-s);
}
:host(:last-of-type) .separator {
display: none;
}
.separator {
color: var(--wa-color-text-quiet);
display: inline-flex;
align-items: center;
margin: 0 var(--wa-space-s);
user-select: none;
-webkit-user-select: none;
}
`;

View File

@@ -3,7 +3,7 @@ import { customElement, property, query, state } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { watch } from '../../internal/watch.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import styles from './breadcrumb-item.css';
import styles from './breadcrumb-item.styles.js';
/**
* @summary Breadcrumb Items are used inside breadcrumbs to represent different links.

View File

@@ -1,5 +0,0 @@
.breadcrumb {
display: flex;
align-items: center;
flex-wrap: wrap;
}

View File

@@ -0,0 +1,9 @@
import { css } from 'lit';
export default css`
.breadcrumb {
display: flex;
align-items: center;
flex-wrap: wrap;
}
`;

View File

@@ -4,7 +4,7 @@ import WebAwesomeElement from '../../internal/webawesome-element.js';
import { LocalizeController } from '../../utilities/localize.js';
import type WaBreadcrumbItem from '../breadcrumb-item/breadcrumb-item.js';
import '../icon/icon.js';
import styles from './breadcrumb.css';
import styles from './breadcrumb.styles.js';
/**
* @summary Breadcrumbs provide a group of links so users can easily navigate a website's hierarchy.

View File

@@ -1,44 +0,0 @@
:host {
display: inline-flex;
}
.button-group {
display: flex;
position: relative;
isolation: isolate;
flex-wrap: wrap;
gap: 1px;
@media (hover: hover) {
> :hover,
&::slotted(:hover) {
z-index: 1;
}
}
/* Focus and checked are always on top */
> :focus,
&::slotted(:focus),
> [aria-checked='true'],
&::slotted([aria-checked='true']),
> [checked],
&::slotted([checked]) {
z-index: 2 !important;
}
}
:host([orientation='vertical']) .button-group {
flex-direction: column;
}
/* Button groups with at least one outlined button will not have a gap and instead have borders overlap */
.button-group.has-outlined {
gap: 0;
&:not([aria-orientation='vertical']):not(.button-group-vertical)::slotted(:not(:first-child)) {
margin-inline-start: calc(-1 * var(--border-width));
}
&:is([aria-orientation='vertical'], .button-group-vertical)::slotted(:not(:first-child)) {
margin-block-start: calc(-1 * var(--border-width));
}
}

View File

@@ -0,0 +1,48 @@
import { css } from 'lit';
export default css`
:host {
display: inline-flex;
}
.button-group {
display: flex;
position: relative;
isolation: isolate;
flex-wrap: wrap;
gap: 1px;
@media (hover: hover) {
> :hover,
&::slotted(:hover) {
z-index: 1;
}
}
/* Focus and checked are always on top */
> :focus,
&::slotted(:focus),
> [aria-checked='true'],
&::slotted([aria-checked='true']),
> [checked],
&::slotted([checked]) {
z-index: 2 !important;
}
}
:host([orientation='vertical']) .button-group {
flex-direction: column;
}
/* Button groups with at least one outlined button will not have a gap and instead have borders overlap */
.button-group.has-outlined {
gap: 0;
&:not([aria-orientation='vertical']):not(.button-group-vertical)::slotted(:not(:first-child)) {
margin-inline-start: calc(-1 * var(--border-width));
}
&:is([aria-orientation='vertical'], .button-group-vertical)::slotted(:not(:first-child)) {
margin-block-start: calc(-1 * var(--border-width));
}
}
`;

View File

@@ -4,7 +4,7 @@ import { customElement, property, query, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import type WaButton from '../button/button.js';
import styles from './button-group.css';
import styles from './button-group.styles.js';
/**
* @summary Button groups can be used to group related buttons into sections.

View File

@@ -1,372 +0,0 @@
@layer wa-component {
:host {
display: inline-block;
/* Workaround because Chrome doesn't like :host(:has()) below
* https://issues.chromium.org/issues/40062355
* Firefox doesn't like this nested rule, so both are needed */
&:has(wa-badge) {
position: relative;
}
}
/* Apply relative positioning only when needed to position wa-badge
* This avoids creating a new stacking context for every button */
:host(:has(wa-badge)) {
position: relative;
}
}
.button {
display: inline-flex;
align-items: center;
justify-content: center;
text-decoration: none;
user-select: none;
-webkit-user-select: none;
white-space: nowrap;
vertical-align: middle;
transition-property: background, border, box-shadow, color;
transition-duration: var(--wa-transition-fast);
transition-timing-function: var(--wa-transition-easing);
cursor: pointer;
padding: 0 var(--wa-form-control-padding-inline);
font-family: inherit;
font-size: inherit;
font-weight: var(--wa-font-weight-action);
line-height: calc(var(--wa-form-control-height) - var(--border-width) * 2);
height: var(--wa-form-control-height);
width: 100%;
background-color: var(--wa-color-fill-loud, var(--wa-color-neutral-fill-loud));
border-color: transparent;
color: var(--wa-color-on-loud, var(--wa-color-neutral-on-loud));
border-radius: var(--wa-form-control-border-radius);
border-style: var(--wa-border-style);
border-width: var(--wa-border-width-s);
}
/* Appearance modifiers */
:host([appearance='plain']) {
.button {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: transparent;
border-color: transparent;
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: var(--wa-color-fill-quiet, var(--wa-color-neutral-fill-quiet));
}
}
.button:not(.disabled):not(.loading):active {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: color-mix(
in oklab,
var(--wa-color-fill-quiet, var(--wa-color-neutral-fill-quiet)),
var(--wa-color-mix-active)
);
}
}
:host([appearance='outlined']) {
.button {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: transparent;
border-color: var(--wa-color-border-loud, var(--wa-color-neutral-border-loud));
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: var(--wa-color-fill-quiet, var(--wa-color-neutral-fill-quiet));
}
}
.button:not(.disabled):not(.loading):active {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: color-mix(
in oklab,
var(--wa-color-fill-quiet, var(--wa-color-neutral-fill-quiet)),
var(--wa-color-mix-active)
);
}
}
:host([appearance='filled']) {
.button {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal));
border-color: transparent;
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: color-mix(
in oklab,
var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal)),
var(--wa-color-mix-hover)
);
}
}
.button:not(.disabled):not(.loading):active {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: color-mix(
in oklab,
var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal)),
var(--wa-color-mix-active)
);
}
}
:host([appearance='filled-outlined']) {
.button {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal));
border-color: var(--wa-color-border-normal, var(--wa-color-neutral-border-normal));
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: color-mix(
in oklab,
var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal)),
var(--wa-color-mix-hover)
);
}
}
.button:not(.disabled):not(.loading):active {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: color-mix(
in oklab,
var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal)),
var(--wa-color-mix-active)
);
}
}
:host([appearance='accent']) {
.button {
color: var(--wa-color-on-loud, var(--wa-color-neutral-on-loud));
background-color: var(--wa-color-fill-loud, var(--wa-color-neutral-fill-loud));
border-color: transparent;
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
background-color: color-mix(
in oklab,
var(--wa-color-fill-loud, var(--wa-color-neutral-fill-loud)),
var(--wa-color-mix-hover)
);
}
}
.button:not(.disabled):not(.loading):active {
background-color: color-mix(
in oklab,
var(--wa-color-fill-loud, var(--wa-color-neutral-fill-loud)),
var(--wa-color-mix-active)
);
}
}
/* Focus states */
.button:focus {
outline: none;
}
.button:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
/* Disabled state */
.button.disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* When disabled, prevent mouse events from bubbling up from children */
.button.disabled * {
pointer-events: none;
}
/* Keep it last so Safari doesn't stop parsing this block */
.button::-moz-focus-inner {
border: 0;
}
/* Icon buttons */
.button.is-icon-button {
outline-offset: 2px;
width: var(--wa-form-control-height);
aspect-ratio: 1;
}
.button.is-icon-button:has(wa-icon) {
width: auto;
}
/* Pill modifier */
:host([pill]) .button {
border-radius: var(--wa-border-radius-pill);
}
/*
* Label
*/
.start,
.end {
flex: 0 0 auto;
display: flex;
align-items: center;
pointer-events: none;
}
.label {
display: inline-block;
}
.is-icon-button .label {
display: flex;
}
.label::slotted(wa-icon) {
align-self: center;
}
/*
* Caret modifier
*/
wa-icon[part='caret'] {
display: flex;
align-self: center;
align-items: center;
&::part(svg) {
width: 0.875em;
height: 0.875em;
}
.button:has(&) .end {
display: none;
}
}
/*
* Loading modifier
*/
.loading {
position: relative;
cursor: wait;
.start,
.label,
.end,
.caret {
visibility: hidden;
}
wa-spinner {
--indicator-color: currentColor;
--track-color: color-mix(in oklab, currentColor, transparent 90%);
position: absolute;
font-size: 1em;
height: 1em;
width: 1em;
top: calc(50% - 0.5em);
left: calc(50% - 0.5em);
}
}
/*
* Badges
*/
.button ::slotted(wa-badge) {
border-color: var(--wa-color-surface-default);
position: absolute;
inset-block-start: 0;
inset-inline-end: 0;
translate: 50% -50%;
pointer-events: none;
}
:host(:dir(rtl)) ::slotted(wa-badge) {
translate: -50% -50%;
}
/*
* Button spacing
*/
slot[name='start']::slotted(*) {
margin-inline-end: 0.75em;
}
slot[name='end']::slotted(*),
.button:not(.visually-hidden-label) [part='caret'] {
margin-inline-start: 0.75em;
}
/*
* Button group border radius modifications
*/
/* Remove border radius from all grouped buttons by default */
:host(.wa-button-group__button) .button {
border-radius: 0;
}
/* Horizontal orientation */
:host(.wa-button-group__horizontal.wa-button-group__button-first) .button {
border-start-start-radius: var(--wa-form-control-border-radius);
border-end-start-radius: var(--wa-form-control-border-radius);
}
:host(.wa-button-group__horizontal.wa-button-group__button-last) .button {
border-start-end-radius: var(--wa-form-control-border-radius);
border-end-end-radius: var(--wa-form-control-border-radius);
}
/* Vertical orientation */
:host(.wa-button-group__vertical) {
flex: 1 1 auto;
}
:host(.wa-button-group__vertical) .button {
width: 100%;
justify-content: start;
}
:host(.wa-button-group__vertical.wa-button-group__button-first) .button {
border-start-start-radius: var(--wa-form-control-border-radius);
border-start-end-radius: var(--wa-form-control-border-radius);
}
:host(.wa-button-group__vertical.wa-button-group__button-last) .button {
border-end-start-radius: var(--wa-form-control-border-radius);
border-end-end-radius: var(--wa-form-control-border-radius);
}
/* Handle pill modifier for button groups */
:host([pill].wa-button-group__horizontal.wa-button-group__button-first) .button {
border-start-start-radius: var(--wa-border-radius-pill);
border-end-start-radius: var(--wa-border-radius-pill);
}
:host([pill].wa-button-group__horizontal.wa-button-group__button-last) .button {
border-start-end-radius: var(--wa-border-radius-pill);
border-end-end-radius: var(--wa-border-radius-pill);
}
:host([pill].wa-button-group__vertical.wa-button-group__button-first) .button {
border-start-start-radius: var(--wa-border-radius-pill);
border-start-end-radius: var(--wa-border-radius-pill);
}
:host([pill].wa-button-group__vertical.wa-button-group__button-last) .button {
border-end-start-radius: var(--wa-border-radius-pill);
border-end-end-radius: var(--wa-border-radius-pill);
}

View File

@@ -0,0 +1,376 @@
import { css } from 'lit';
export default css`
@layer wa-component {
:host {
display: inline-block;
/* Workaround because Chrome doesn't like :host(:has()) below
* https://issues.chromium.org/issues/40062355
* Firefox doesn't like this nested rule, so both are needed */
&:has(wa-badge) {
position: relative;
}
}
/* Apply relative positioning only when needed to position wa-badge
* This avoids creating a new stacking context for every button */
:host(:has(wa-badge)) {
position: relative;
}
}
.button {
display: inline-flex;
align-items: center;
justify-content: center;
text-decoration: none;
user-select: none;
-webkit-user-select: none;
white-space: nowrap;
vertical-align: middle;
transition-property: background, border, box-shadow, color, opacity;
transition-duration: var(--wa-transition-fast);
transition-timing-function: var(--wa-transition-easing);
cursor: pointer;
padding: 0 var(--wa-form-control-padding-inline);
font-family: inherit;
font-size: inherit;
font-weight: var(--wa-font-weight-action);
line-height: calc(var(--wa-form-control-height) - var(--border-width) * 2);
height: var(--wa-form-control-height);
width: 100%;
background-color: var(--wa-color-fill-loud, var(--wa-color-neutral-fill-loud));
border-color: transparent;
color: var(--wa-color-on-loud, var(--wa-color-neutral-on-loud));
border-radius: var(--wa-form-control-border-radius);
border-style: var(--wa-border-style);
border-width: var(--wa-border-width-s);
}
/* Appearance modifiers */
:host([appearance='plain']) {
.button {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: transparent;
border-color: transparent;
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: var(--wa-color-fill-quiet, var(--wa-color-neutral-fill-quiet));
}
}
.button:not(.disabled):not(.loading):active {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: color-mix(
in oklab,
var(--wa-color-fill-quiet, var(--wa-color-neutral-fill-quiet)),
var(--wa-color-mix-active)
);
}
}
:host([appearance='outlined']) {
.button {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: transparent;
border-color: var(--wa-color-border-loud, var(--wa-color-neutral-border-loud));
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: var(--wa-color-fill-quiet, var(--wa-color-neutral-fill-quiet));
}
}
.button:not(.disabled):not(.loading):active {
color: var(--wa-color-on-quiet, var(--wa-color-neutral-on-quiet));
background-color: color-mix(
in oklab,
var(--wa-color-fill-quiet, var(--wa-color-neutral-fill-quiet)),
var(--wa-color-mix-active)
);
}
}
:host([appearance='filled']) {
.button {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal));
border-color: transparent;
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: color-mix(
in oklab,
var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal)),
var(--wa-color-mix-hover)
);
}
}
.button:not(.disabled):not(.loading):active {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: color-mix(
in oklab,
var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal)),
var(--wa-color-mix-active)
);
}
}
:host([appearance='filled-outlined']) {
.button {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal));
border-color: var(--wa-color-border-normal, var(--wa-color-neutral-border-normal));
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: color-mix(
in oklab,
var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal)),
var(--wa-color-mix-hover)
);
}
}
.button:not(.disabled):not(.loading):active {
color: var(--wa-color-on-normal, var(--wa-color-neutral-on-normal));
background-color: color-mix(
in oklab,
var(--wa-color-fill-normal, var(--wa-color-neutral-fill-normal)),
var(--wa-color-mix-active)
);
}
}
:host([appearance='accent']) {
.button {
color: var(--wa-color-on-loud, var(--wa-color-neutral-on-loud));
background-color: var(--wa-color-fill-loud, var(--wa-color-neutral-fill-loud));
border-color: transparent;
}
@media (hover: hover) {
.button:not(.disabled):not(.loading):hover {
background-color: color-mix(
in oklab,
var(--wa-color-fill-loud, var(--wa-color-neutral-fill-loud)),
var(--wa-color-mix-hover)
);
}
}
.button:not(.disabled):not(.loading):active {
background-color: color-mix(
in oklab,
var(--wa-color-fill-loud, var(--wa-color-neutral-fill-loud)),
var(--wa-color-mix-active)
);
}
}
/* Focus states */
.button:focus {
outline: none;
}
.button:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
/* Disabled state */
.button.disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* When disabled, prevent mouse events from bubbling up from children */
.button.disabled * {
pointer-events: none;
}
/* Keep it last so Safari doesn't stop parsing this block */
.button::-moz-focus-inner {
border: 0;
}
/* Icon buttons */
.button.is-icon-button {
outline-offset: 2px;
width: var(--wa-form-control-height);
aspect-ratio: 1;
}
.button.is-icon-button:has(wa-icon) {
width: auto;
}
/* Pill modifier */
:host([pill]) .button {
border-radius: var(--wa-border-radius-pill);
}
/*
* Label
*/
.start,
.end {
flex: 0 0 auto;
display: flex;
align-items: center;
pointer-events: none;
}
.label {
display: inline-block;
}
.is-icon-button .label {
display: flex;
}
.label::slotted(wa-icon) {
align-self: center;
}
/*
* Caret modifier
*/
wa-icon[part='caret'] {
display: flex;
align-self: center;
align-items: center;
&::part(svg) {
width: 0.875em;
height: 0.875em;
}
.button:has(&) .end {
display: none;
}
}
/*
* Loading modifier
*/
.loading {
position: relative;
cursor: wait;
.start,
.label,
.end,
.caret {
visibility: hidden;
}
wa-spinner {
--indicator-color: currentColor;
--track-color: color-mix(in oklab, currentColor, transparent 90%);
position: absolute;
font-size: 1em;
height: 1em;
width: 1em;
top: calc(50% - 0.5em);
left: calc(50% - 0.5em);
}
}
/*
* Badges
*/
.button ::slotted(wa-badge) {
border-color: var(--wa-color-surface-default);
position: absolute;
inset-block-start: 0;
inset-inline-end: 0;
translate: 50% -50%;
pointer-events: none;
}
:host(:dir(rtl)) ::slotted(wa-badge) {
translate: -50% -50%;
}
/*
* Button spacing
*/
slot[name='start']::slotted(*) {
margin-inline-end: 0.75em;
}
slot[name='end']::slotted(*),
.button:not(.visually-hidden-label) [part='caret'] {
margin-inline-start: 0.75em;
}
/*
* Button group border radius modifications
*/
/* Remove border radius from all grouped buttons by default */
:host(.wa-button-group__button) .button {
border-radius: 0;
}
/* Horizontal orientation */
:host(.wa-button-group__horizontal.wa-button-group__button-first) .button {
border-start-start-radius: var(--wa-form-control-border-radius);
border-end-start-radius: var(--wa-form-control-border-radius);
}
:host(.wa-button-group__horizontal.wa-button-group__button-last) .button {
border-start-end-radius: var(--wa-form-control-border-radius);
border-end-end-radius: var(--wa-form-control-border-radius);
}
/* Vertical orientation */
:host(.wa-button-group__vertical) {
flex: 1 1 auto;
}
:host(.wa-button-group__vertical) .button {
width: 100%;
justify-content: start;
}
:host(.wa-button-group__vertical.wa-button-group__button-first) .button {
border-start-start-radius: var(--wa-form-control-border-radius);
border-start-end-radius: var(--wa-form-control-border-radius);
}
:host(.wa-button-group__vertical.wa-button-group__button-last) .button {
border-end-start-radius: var(--wa-form-control-border-radius);
border-end-end-radius: var(--wa-form-control-border-radius);
}
/* Handle pill modifier for button groups */
:host([pill].wa-button-group__horizontal.wa-button-group__button-first) .button {
border-start-start-radius: var(--wa-border-radius-pill);
border-end-start-radius: var(--wa-border-radius-pill);
}
:host([pill].wa-button-group__horizontal.wa-button-group__button-last) .button {
border-start-end-radius: var(--wa-border-radius-pill);
border-end-end-radius: var(--wa-border-radius-pill);
}
:host([pill].wa-button-group__vertical.wa-button-group__button-first) .button {
border-start-start-radius: var(--wa-border-radius-pill);
border-start-end-radius: var(--wa-border-radius-pill);
}
:host([pill].wa-button-group__vertical.wa-button-group__button-last) .button {
border-end-start-radius: var(--wa-border-radius-pill);
border-end-end-radius: var(--wa-border-radius-pill);
}
`;

View File

@@ -7,13 +7,13 @@ import { HasSlotController } from '../../internal/slot.js';
import { MirrorValidator } from '../../internal/validators/mirror-validator.js';
import { watch } from '../../internal/watch.js';
import { WebAwesomeFormAssociatedElement } from '../../internal/webawesome-form-associated-element.js';
import sizeStyles from '../../styles/utilities/size.css';
import variantStyles from '../../styles/utilities/variants.css';
import sizeStyles from '../../styles/component/size.styles.js';
import variantStyles from '../../styles/component/variants.styles.js';
import { LocalizeController } from '../../utilities/localize.js';
import '../icon/icon.js';
import type WaIcon from '../icon/icon.js';
import '../spinner/spinner.js';
import styles from './button.css';
import styles from './button.styles.js';
/**
* @summary Buttons represent actions that are available to the user.
@@ -115,7 +115,6 @@ export default class WaButton extends WebAwesomeFormAssociatedElement {
* The "form owner" to associate the button with. If omitted, the closest containing form will be used instead. The
* value of this attribute must be an id of a form in the same document or shadow root as the button.
*/
@property({ reflect: true }) form: string | null = null;
/** Used to override the form owner's `action` attribute. */
@property({ attribute: 'formaction' }) formAction: string;
@@ -135,24 +134,27 @@ export default class WaButton extends WebAwesomeFormAssociatedElement {
private constructLightDOMButton() {
const button = document.createElement('button');
for (const attribute of this.attributes) {
if (attribute.name === 'style') {
// Skip style attributes as they *shouldn't* be necessary
continue;
}
button.setAttribute(attribute.name, attribute.value);
}
button.type = this.type;
button.style.position = 'absolute';
button.style.width = '0';
button.style.height = '0';
button.style.clipPath = 'inset(50%)';
button.style.overflow = 'hidden';
button.style.whiteSpace = 'nowrap';
button.style.position = 'absolute !important';
button.style.width = '0 !important';
button.style.height = '0 !important';
button.style.clipPath = 'inset(50%) !important';
button.style.overflow = 'hidden !important';
button.style.whiteSpace = 'nowrap !important';
if (this.name) {
button.name = this.name;
}
button.value = this.value || '';
['form', 'formaction', 'formenctype', 'formmethod', 'formnovalidate', 'formtarget'].forEach(attr => {
if (this.hasAttribute(attr)) {
button.setAttribute(attr, this.getAttribute(attr)!);
}
});
return button;
}

View File

@@ -1,60 +0,0 @@
:host {
display: flex;
position: relative;
align-items: stretch;
border-radius: var(--wa-panel-border-radius);
background-color: var(--wa-color-fill-quiet, var(--wa-color-brand-fill-quiet));
border-color: var(--wa-color-border-quiet, var(--wa-color-brand-border-quiet));
border-style: var(--wa-panel-border-style);
border-width: var(--wa-panel-border-width);
color: var(--wa-color-text-normal);
padding: 1em;
}
/* Appearance modifiers */
:host([appearance~='plain']) {
background-color: transparent;
border-color: transparent;
}
:host([appearance~='outlined']) {
background-color: transparent;
border-color: var(--wa-color-border-loud, var(--wa-color-brand-border-loud));
}
:host([appearance~='filled']) {
background-color: var(--wa-color-fill-quiet, var(--wa-color-brand-fill-quiet));
border-color: transparent;
}
:host([appearance~='filled-outlined']) {
border-color: var(--wa-color-border-quiet, var(--wa-color-brand-border-quiet));
}
:host([appearance~='accent']) {
color: var(--wa-color-on-loud, var(--wa-color-brand-on-loud));
background-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
border-color: transparent;
[part~='icon'] {
color: currentColor;
}
}
[part~='icon'] {
flex: 0 0 auto;
display: flex;
align-items: center;
color: var(--wa-color-on-quiet);
font-size: 1.25em;
}
::slotted([slot='icon']) {
margin-inline-end: var(--wa-form-control-padding-inline);
}
[part~='message'] {
flex: 1 1 auto;
display: block;
overflow: hidden;
}

View File

@@ -0,0 +1,64 @@
import { css } from 'lit';
export default css`
:host {
display: flex;
position: relative;
align-items: stretch;
border-radius: var(--wa-panel-border-radius);
background-color: var(--wa-color-fill-quiet, var(--wa-color-brand-fill-quiet));
border-color: var(--wa-color-border-quiet, var(--wa-color-brand-border-quiet));
border-style: var(--wa-panel-border-style);
border-width: var(--wa-panel-border-width);
color: var(--wa-color-text-normal);
padding: 1em;
}
/* Appearance modifiers */
:host([appearance~='plain']) {
background-color: transparent;
border-color: transparent;
}
:host([appearance~='outlined']) {
background-color: transparent;
border-color: var(--wa-color-border-loud, var(--wa-color-brand-border-loud));
}
:host([appearance~='filled']) {
background-color: var(--wa-color-fill-quiet, var(--wa-color-brand-fill-quiet));
border-color: transparent;
}
:host([appearance~='filled-outlined']) {
border-color: var(--wa-color-border-quiet, var(--wa-color-brand-border-quiet));
}
:host([appearance~='accent']) {
color: var(--wa-color-on-loud, var(--wa-color-brand-on-loud));
background-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
border-color: transparent;
[part~='icon'] {
color: currentColor;
}
}
[part~='icon'] {
flex: 0 0 auto;
display: flex;
align-items: center;
color: var(--wa-color-on-quiet);
font-size: 1.25em;
}
::slotted([slot='icon']) {
margin-inline-end: var(--wa-form-control-padding-inline);
}
[part~='message'] {
flex: 1 1 auto;
display: block;
overflow: hidden;
}
`;

View File

@@ -1,9 +1,9 @@
import { html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import sizeStyles from '../../styles/utilities/size.css';
import variantStyles from '../../styles/utilities/variants.css';
import styles from './callout.css';
import sizeStyles from '../../styles/component/size.styles.js';
import variantStyles from '../../styles/component/variants.styles.js';
import styles from './callout.styles.js';
/**
* @summary Callouts are used to display important messages inline.

View File

@@ -1,141 +0,0 @@
:host {
--spacing: var(--wa-space-l);
/* Internal calculated properties */
--inner-border-radius: calc(var(--wa-panel-border-radius) - var(--wa-panel-border-width));
display: flex;
flex-direction: column;
background-color: var(--wa-color-surface-default);
border-color: var(--wa-color-surface-border);
border-radius: var(--wa-panel-border-radius);
border-style: var(--wa-panel-border-style);
box-shadow: var(--wa-shadow-s);
border-width: var(--wa-panel-border-width);
color: var(--wa-color-text-normal);
}
/* Appearance modifiers */
:host([appearance='plain']) {
background-color: transparent;
border-color: transparent;
box-shadow: none;
}
:host([appearance='outlined']) {
background-color: var(--wa-color-surface-default);
border-color: var(--wa-color-surface-border);
}
:host([appearance='filled']) {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: transparent;
}
:host([appearance='filled-outlined']) {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: var(--wa-color-surface-border);
}
:host([appearance='accent']) {
color: var(--wa-color-neutral-on-loud);
background-color: var(--wa-color-neutral-fill-loud);
border-color: transparent;
}
/* Take care of top and bottom radii */
.media,
:host(:not([with-media])) .header,
:host(:not([with-media], [with-header])) .body {
border-start-start-radius: var(--inner-border-radius);
border-start-end-radius: var(--inner-border-radius);
}
:host(:not([with-footer])) .body,
.footer {
border-end-start-radius: var(--inner-border-radius);
border-end-end-radius: var(--inner-border-radius);
}
.media {
display: flex;
overflow: hidden;
&::slotted(*) {
display: block;
width: 100%;
border-radius: 0 !important;
}
}
/* Round all corners for plain appearance */
:host([appearance='plain']) .media {
border-radius: var(--inner-border-radius);
&::slotted(*) {
border-radius: inherit !important;
}
}
.header {
display: block;
border-block-end-style: inherit;
border-block-end-color: var(--wa-color-surface-border);
border-block-end-width: var(--wa-panel-border-width);
padding: calc(var(--spacing) / 2) var(--spacing);
}
.body {
display: block;
padding: var(--spacing);
}
.footer {
display: block;
border-block-start-style: inherit;
border-block-start-color: var(--wa-color-surface-border);
border-block-start-width: var(--wa-panel-border-width);
padding: var(--spacing);
}
/* Push slots to sides when the action slots renders */
.has-actions {
display: flex;
align-items: center;
justify-content: space-between;
}
:host(:not([with-header])) .header,
:host(:not([with-footer])) .footer,
:host(:not([with-media])) .media {
display: none;
}
/* Orientation Styles */
:host([orientation='horizontal']) {
flex-direction: row;
.media {
border-start-start-radius: var(--inner-border-radius);
border-end-start-radius: var(--inner-border-radius);
border-start-end-radius: 0;
&::slotted(*) {
block-size: 100%;
inline-size: 100%;
object-fit: cover;
}
}
}
:host([orientation='horizontal']) ::slotted([slot='body']) {
display: block;
height: 100%;
margin: 0;
}
:host([orientation='horizontal']) ::slotted([slot='actions']) {
display: flex;
align-items: center;
padding: var(--spacing);
}

View File

@@ -0,0 +1,145 @@
import { css } from 'lit';
export default css`
:host {
--spacing: var(--wa-space-l);
/* Internal calculated properties */
--inner-border-radius: calc(var(--wa-panel-border-radius) - var(--wa-panel-border-width));
display: flex;
flex-direction: column;
background-color: var(--wa-color-surface-default);
border-color: var(--wa-color-surface-border);
border-radius: var(--wa-panel-border-radius);
border-style: var(--wa-panel-border-style);
box-shadow: var(--wa-shadow-s);
border-width: var(--wa-panel-border-width);
color: var(--wa-color-text-normal);
}
/* Appearance modifiers */
:host([appearance='plain']) {
background-color: transparent;
border-color: transparent;
box-shadow: none;
}
:host([appearance='outlined']) {
background-color: var(--wa-color-surface-default);
border-color: var(--wa-color-surface-border);
}
:host([appearance='filled']) {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: transparent;
}
:host([appearance='filled-outlined']) {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: var(--wa-color-surface-border);
}
:host([appearance='accent']) {
color: var(--wa-color-neutral-on-loud);
background-color: var(--wa-color-neutral-fill-loud);
border-color: transparent;
}
/* Take care of top and bottom radii */
.media,
:host(:not([with-media])) .header,
:host(:not([with-media], [with-header])) .body {
border-start-start-radius: var(--inner-border-radius);
border-start-end-radius: var(--inner-border-radius);
}
:host(:not([with-footer])) .body,
.footer {
border-end-start-radius: var(--inner-border-radius);
border-end-end-radius: var(--inner-border-radius);
}
.media {
display: flex;
overflow: hidden;
&::slotted(*) {
display: block;
width: 100%;
border-radius: 0 !important;
}
}
/* Round all corners for plain appearance */
:host([appearance='plain']) .media {
border-radius: var(--inner-border-radius);
&::slotted(*) {
border-radius: inherit !important;
}
}
.header {
display: block;
border-block-end-style: inherit;
border-block-end-color: var(--wa-color-surface-border);
border-block-end-width: var(--wa-panel-border-width);
padding: calc(var(--spacing) / 2) var(--spacing);
}
.body {
display: block;
padding: var(--spacing);
}
.footer {
display: block;
border-block-start-style: inherit;
border-block-start-color: var(--wa-color-surface-border);
border-block-start-width: var(--wa-panel-border-width);
padding: var(--spacing);
}
/* Push slots to sides when the action slots renders */
.has-actions {
display: flex;
align-items: center;
justify-content: space-between;
}
:host(:not([with-header])) .header,
:host(:not([with-footer])) .footer,
:host(:not([with-media])) .media {
display: none;
}
/* Orientation Styles */
:host([orientation='horizontal']) {
flex-direction: row;
.media {
border-start-start-radius: var(--inner-border-radius);
border-end-start-radius: var(--inner-border-radius);
border-start-end-radius: 0;
&::slotted(*) {
block-size: 100%;
inline-size: 100%;
object-fit: cover;
}
}
}
:host([orientation='horizontal']) ::slotted([slot='body']) {
display: block;
height: 100%;
margin: 0;
}
:host([orientation='horizontal']) ::slotted([slot='actions']) {
display: flex;
align-items: center;
padding: var(--spacing);
}
`;

View File

@@ -2,8 +2,8 @@ import { html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { HasSlotController } from '../../internal/slot.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import sizeStyles from '../../styles/utilities/size.css';
import styles from './card.css';
import sizeStyles from '../../styles/component/size.styles.js';
import styles from './card.styles.js';
/**
* @summary Cards can be used to group related subjects in a container.

View File

@@ -1,19 +0,0 @@
:host {
--aspect-ratio: inherit;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 100%;
max-height: 100%;
aspect-ratio: var(--aspect-ratio);
scroll-snap-align: start;
scroll-snap-stop: always;
}
::slotted(img) {
width: 100% !important;
height: 100% !important;
object-fit: cover;
}

View File

@@ -0,0 +1,23 @@
import { css } from 'lit';
export default css`
:host {
--aspect-ratio: inherit;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 100%;
max-height: 100%;
aspect-ratio: var(--aspect-ratio);
scroll-snap-align: start;
scroll-snap-stop: always;
}
::slotted(img) {
width: 100% !important;
height: 100% !important;
object-fit: cover;
}
`;

View File

@@ -1,7 +1,7 @@
import { html } from 'lit';
import { customElement } from 'lit/decorators.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import styles from './carousel-item.css';
import styles from './carousel-item.styles.js';
/**
* @summary A carousel item represent a slide within a carousel.

View File

@@ -1,154 +0,0 @@
:host {
--aspect-ratio: 16 / 9;
--scroll-hint: 0px;
--slide-gap: var(--wa-space-m, 1rem); /* fallback value is necessary */
display: flex;
}
.carousel {
display: grid;
grid-template-columns: min-content 1fr min-content;
grid-template-rows: 1fr min-content;
grid-template-areas:
'. slides .'
'. pagination .';
gap: var(--wa-space-m);
align-items: center;
min-height: 100%;
min-width: 100%;
position: relative;
}
.pagination {
grid-area: pagination;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: var(--wa-space-s);
}
.slides {
grid-area: slides;
display: grid;
height: 100%;
width: 100%;
align-items: center;
justify-items: center;
overflow: auto;
overscroll-behavior-x: contain;
scrollbar-width: none;
aspect-ratio: calc(var(--aspect-ratio) * var(--slides-per-page));
border-radius: var(--wa-border-radius-m);
--slide-size: calc((100% - (var(--slides-per-page) - 1) * var(--slide-gap)) / var(--slides-per-page));
}
@media (prefers-reduced-motion) {
:where(.slides) {
scroll-behavior: auto;
}
}
.slides-horizontal {
grid-auto-flow: column;
grid-auto-columns: var(--slide-size);
grid-auto-rows: 100%;
column-gap: var(--slide-gap);
scroll-snap-type: x mandatory;
scroll-padding-inline: var(--scroll-hint);
padding-inline: var(--scroll-hint);
overflow-y: hidden;
}
.slides-vertical {
grid-auto-flow: row;
grid-auto-columns: 100%;
grid-auto-rows: var(--slide-size);
row-gap: var(--slide-gap);
scroll-snap-type: y mandatory;
scroll-padding-block: var(--scroll-hint);
padding-block: var(--scroll-hint);
overflow-x: hidden;
}
.slides-dragging,
.slides-dropping {
scroll-snap-type: unset;
}
:host([vertical]) ::slotted(wa-carousel-item) {
height: 100%;
}
.slides::-webkit-scrollbar {
display: none;
}
.navigation {
grid-area: navigation;
display: contents;
font-size: var(--wa-font-size-l);
}
.navigation-button {
flex: 0 0 auto;
display: flex;
align-items: center;
background: none;
border: none;
border-radius: var(--wa-border-radius-m);
font-size: inherit;
color: var(--wa-color-text-quiet);
padding: var(--wa-space-xs);
cursor: pointer;
transition: var(--wa-transition-normal) color;
appearance: none;
}
.navigation-button-disabled {
opacity: 0.5;
cursor: not-allowed;
}
.navigation-button-disabled::part(base) {
pointer-events: none;
}
.navigation-button-previous {
grid-column: 1;
grid-row: 1;
}
.navigation-button-next {
grid-column: 3;
grid-row: 1;
}
.pagination-item {
display: block;
cursor: pointer;
background: none;
border: 0;
border-radius: var(--wa-border-radius-circle);
width: var(--wa-space-s);
height: var(--wa-space-s);
background-color: var(--wa-color-neutral-fill-normal);
padding: 0;
margin: 0;
transition: transform var(--wa-transition-slow);
}
.pagination-item-active {
background-color: var(--wa-form-control-activated-color);
transform: scale(1.25);
}
/* Focus styles */
.slides:focus-visible,
.navigation-button:focus-visible,
.pagination-item:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}

View File

@@ -0,0 +1,158 @@
import { css } from 'lit';
export default css`
:host {
--aspect-ratio: 16 / 9;
--scroll-hint: 0px;
--slide-gap: var(--wa-space-m, 1rem); /* fallback value is necessary */
display: flex;
}
.carousel {
display: grid;
grid-template-columns: min-content 1fr min-content;
grid-template-rows: 1fr min-content;
grid-template-areas:
'. slides .'
'. pagination .';
gap: var(--wa-space-m);
align-items: center;
min-height: 100%;
min-width: 100%;
position: relative;
}
.pagination {
grid-area: pagination;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: var(--wa-space-s);
}
.slides {
grid-area: slides;
display: grid;
height: 100%;
width: 100%;
align-items: center;
justify-items: center;
overflow: auto;
overscroll-behavior-x: contain;
scrollbar-width: none;
aspect-ratio: calc(var(--aspect-ratio) * var(--slides-per-page));
border-radius: var(--wa-border-radius-m);
--slide-size: calc((100% - (var(--slides-per-page) - 1) * var(--slide-gap)) / var(--slides-per-page));
}
@media (prefers-reduced-motion) {
:where(.slides) {
scroll-behavior: auto;
}
}
.slides-horizontal {
grid-auto-flow: column;
grid-auto-columns: var(--slide-size);
grid-auto-rows: 100%;
column-gap: var(--slide-gap);
scroll-snap-type: x mandatory;
scroll-padding-inline: var(--scroll-hint);
padding-inline: var(--scroll-hint);
overflow-y: hidden;
}
.slides-vertical {
grid-auto-flow: row;
grid-auto-columns: 100%;
grid-auto-rows: var(--slide-size);
row-gap: var(--slide-gap);
scroll-snap-type: y mandatory;
scroll-padding-block: var(--scroll-hint);
padding-block: var(--scroll-hint);
overflow-x: hidden;
}
.slides-dragging,
.slides-dropping {
scroll-snap-type: unset;
}
:host([vertical]) ::slotted(wa-carousel-item) {
height: 100%;
}
.slides::-webkit-scrollbar {
display: none;
}
.navigation {
grid-area: navigation;
display: contents;
font-size: var(--wa-font-size-l);
}
.navigation-button {
flex: 0 0 auto;
display: flex;
align-items: center;
background: none;
border: none;
border-radius: var(--wa-border-radius-m);
font-size: inherit;
color: var(--wa-color-text-quiet);
padding: var(--wa-space-xs);
cursor: pointer;
transition: var(--wa-transition-normal) color;
appearance: none;
}
.navigation-button-disabled {
opacity: 0.5;
cursor: not-allowed;
}
.navigation-button-disabled::part(base) {
pointer-events: none;
}
.navigation-button-previous {
grid-column: 1;
grid-row: 1;
}
.navigation-button-next {
grid-column: 3;
grid-row: 1;
}
.pagination-item {
display: block;
cursor: pointer;
background: none;
border: 0;
border-radius: var(--wa-border-radius-circle);
width: var(--wa-space-s);
height: var(--wa-space-s);
background-color: var(--wa-color-neutral-fill-normal);
padding: 0;
margin: 0;
transition: transform var(--wa-transition-slow);
}
.pagination-item-active {
background-color: var(--wa-form-control-activated-color);
transform: scale(1.25);
}
/* Focus styles */
.slides:focus-visible,
.navigation-button:focus-visible,
.pagination-item:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
`;

View File

@@ -16,7 +16,7 @@ import { LocalizeController } from '../../utilities/localize.js';
import type WaCarouselItem from '../carousel-item/carousel-item.js';
import '../icon/icon.js';
import { AutoplayController } from './autoplay-controller.js';
import styles from './carousel.css';
import styles from './carousel.styles.js';
/**
* @summary Carousels display an arbitrary number of content slides along a horizontal or vertical axis.

View File

@@ -1,100 +0,0 @@
:host {
--checked-icon-color: var(--wa-color-brand-on-loud);
--checked-icon-scale: 0.8;
display: inline-flex;
color: var(--wa-form-control-value-color);
font-family: inherit;
font-weight: var(--wa-form-control-value-font-weight);
line-height: var(--wa-form-control-value-line-height);
user-select: none;
-webkit-user-select: none;
}
[part~='control'] {
display: inline-flex;
flex: 0 0 auto;
position: relative;
align-items: center;
justify-content: center;
width: var(--wa-form-control-toggle-size);
height: var(--wa-form-control-toggle-size);
border-color: var(--wa-form-control-border-color);
border-radius: min(
calc(var(--wa-form-control-toggle-size) * 0.375),
var(--wa-border-radius-s)
); /* min prevents entirely circular checkbox */
border-style: var(--wa-border-style);
border-width: var(--wa-form-control-border-width);
background-color: var(--wa-form-control-background-color);
transition:
background var(--wa-transition-normal),
border-color var(--wa-transition-fast),
box-shadow var(--wa-transition-fast),
color var(--wa-transition-fast);
transition-timing-function: var(--wa-transition-easing);
margin-inline-end: 0.5em;
}
[part~='base'] {
display: flex;
align-items: flex-start;
position: relative;
color: currentColor;
vertical-align: middle;
cursor: pointer;
}
[part~='label'] {
display: inline;
}
/* Checked */
[part~='control']:has(:checked, :indeterminate) {
color: var(--checked-icon-color);
border-color: var(--wa-form-control-activated-color);
background-color: var(--wa-form-control-activated-color);
}
/* Focus */
[part~='control']:has(> input:focus-visible:not(:disabled)) {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
/* Disabled */
:host [part~='base']:has(input:disabled) {
opacity: 0.5;
cursor: not-allowed;
}
input {
position: absolute;
padding: 0;
margin: 0;
height: 100%;
width: 100%;
opacity: 0;
pointer-events: none;
}
[part~='icon'] {
display: flex;
scale: var(--checked-icon-scale);
/* Without this, Safari renders the icon slightly to the left */
&::part(svg) {
translate: 0.0009765625em;
}
input:not(:checked, :indeterminate) + & {
visibility: hidden;
}
}
:host([required]) [part~='label']::after {
content: var(--wa-form-control-required-content);
color: var(--wa-form-control-required-content-color);
margin-inline-start: var(--wa-form-control-required-content-offset);
}

View File

@@ -0,0 +1,104 @@
import { css } from 'lit';
export default css`
:host {
--checked-icon-color: var(--wa-color-brand-on-loud);
--checked-icon-scale: 0.8;
display: inline-flex;
color: var(--wa-form-control-value-color);
font-family: inherit;
font-weight: var(--wa-form-control-value-font-weight);
line-height: var(--wa-form-control-value-line-height);
user-select: none;
-webkit-user-select: none;
}
[part~='control'] {
display: inline-flex;
flex: 0 0 auto;
position: relative;
align-items: center;
justify-content: center;
width: var(--wa-form-control-toggle-size);
height: var(--wa-form-control-toggle-size);
border-color: var(--wa-form-control-border-color);
border-radius: min(
calc(var(--wa-form-control-toggle-size) * 0.375),
var(--wa-border-radius-s)
); /* min prevents entirely circular checkbox */
border-style: var(--wa-border-style);
border-width: var(--wa-form-control-border-width);
background-color: var(--wa-form-control-background-color);
transition:
background var(--wa-transition-normal),
border-color var(--wa-transition-fast),
box-shadow var(--wa-transition-fast),
color var(--wa-transition-fast);
transition-timing-function: var(--wa-transition-easing);
margin-inline-end: 0.5em;
}
[part~='base'] {
display: flex;
align-items: flex-start;
position: relative;
color: currentColor;
vertical-align: middle;
cursor: pointer;
}
[part~='label'] {
display: inline;
}
/* Checked */
[part~='control']:has(:checked, :indeterminate) {
color: var(--checked-icon-color);
border-color: var(--wa-form-control-activated-color);
background-color: var(--wa-form-control-activated-color);
}
/* Focus */
[part~='control']:has(> input:focus-visible:not(:disabled)) {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
/* Disabled */
:host [part~='base']:has(input:disabled) {
opacity: 0.5;
cursor: not-allowed;
}
input {
position: absolute;
padding: 0;
margin: 0;
height: 100%;
width: 100%;
opacity: 0;
pointer-events: none;
}
[part~='icon'] {
display: flex;
scale: var(--checked-icon-scale);
/* Without this, Safari renders the icon slightly to the left */
&::part(svg) {
translate: 0.0009765625em;
}
input:not(:checked, :indeterminate) + & {
visibility: hidden;
}
}
:host([required]) [part~='label']::after {
content: var(--wa-form-control-required-content);
color: var(--wa-form-control-required-content-color);
margin-inline-start: var(--wa-form-control-required-content-offset);
}
`;

View File

@@ -8,10 +8,10 @@ import { HasSlotController } from '../../internal/slot.js';
import { RequiredValidator } from '../../internal/validators/required-validator.js';
import { watch } from '../../internal/watch.js';
import { WebAwesomeFormAssociatedElement } from '../../internal/webawesome-form-associated-element.js';
import formControlStyles from '../../styles/component/form-control.css';
import sizeStyles from '../../styles/utilities/size.css';
import formControlStyles from '../../styles/component/form-control.styles.js';
import sizeStyles from '../../styles/component/size.styles.js';
import '../icon/icon.js';
import styles from './checkbox.css';
import styles from './checkbox.styles.js';
/**
* @summary Checkboxes allow the user to toggle an option on or off.
@@ -108,13 +108,6 @@ export default class WaCheckbox extends WebAwesomeFormAssociatedElement {
@property({ type: Boolean, reflect: true, attribute: 'checked' }) defaultChecked: boolean =
this.hasAttribute('checked');
/**
* By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you
* to place the form control outside of a form and associate it with the form that has this `id`. The form must be in
* the same document or shadow root for this to work.
*/
@property({ reflect: true }) form = null;
/** Makes the checkbox a required field. */
@property({ type: Boolean, reflect: true }) required = false;

View File

@@ -1,341 +0,0 @@
:host {
--grid-width: 17em;
--grid-height: 12em;
--grid-handle-size: 1.25em;
--slider-height: 1em;
--slider-handle-size: calc(var(--slider-height) + 0.25em);
}
.color-picker {
background-color: var(--wa-color-surface-raised);
border-radius: var(--wa-border-radius-m);
border-style: var(--wa-border-style);
border-width: var(--wa-border-width-s);
border-color: var(--wa-color-surface-border);
box-shadow: var(--wa-shadow-m);
color: var(--color);
font: inherit;
font-size: inherit;
user-select: none;
width: var(--grid-width);
-webkit-user-select: none;
}
.grid {
position: relative;
height: var(--grid-height);
background-image:
linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%),
linear-gradient(to right, #fff 0%, rgba(255, 255, 255, 0) 100%);
border-top-left-radius: calc(var(--wa-border-radius-m) - var(--wa-border-width-s));
border-top-right-radius: calc(var(--wa-border-radius-m) - var(--wa-border-width-s));
cursor: crosshair;
forced-color-adjust: none;
}
.grid-handle {
position: absolute;
width: var(--grid-handle-size);
height: var(--grid-handle-size);
border-radius: var(--wa-border-radius-circle);
box-shadow: 0 0 0 0.0625rem rgba(0, 0, 0, 0.2);
border: solid 0.125rem white;
margin-top: calc(var(--grid-handle-size) / -2);
margin-left: calc(var(--grid-handle-size) / -2);
transition: scale var(--wa-transition-normal) var(--wa-transition-easing);
}
.grid-handle-dragging {
cursor: none;
scale: 1.5;
}
.grid-handle:focus-visible {
outline: var(--wa-focus-ring);
}
.controls {
padding: 0.75em;
display: flex;
align-items: center;
}
.sliders {
flex: 1 1 auto;
}
.slider {
position: relative;
height: var(--slider-height);
border-radius: var(--wa-border-radius-s);
box-shadow: inset 0 0 0 0.0625rem rgba(0, 0, 0, 0.2);
forced-color-adjust: none;
}
.slider:not(:last-of-type) {
margin-bottom: 0.75em;
}
.slider-handle {
position: absolute;
top: calc(50% - var(--slider-handle-size) / 2);
width: var(--slider-handle-size);
height: var(--slider-handle-size);
border-radius: var(--wa-border-radius-circle);
border: solid 0.125rem white;
box-shadow: 0 0 0 0.0625rem rgba(0, 0, 0, 0.2);
margin-left: calc(var(--slider-handle-size) / -2);
}
.slider-handle:focus-visible {
outline: var(--wa-focus-ring);
}
.hue {
background-image: linear-gradient(
to right,
rgb(255, 0, 0) 0%,
rgb(255, 255, 0) 17%,
rgb(0, 255, 0) 33%,
rgb(0, 255, 255) 50%,
rgb(0, 0, 255) 67%,
rgb(255, 0, 255) 83%,
rgb(255, 0, 0) 100%
);
}
.alpha .alpha-gradient {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: inherit;
}
.preview {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
position: relative;
width: 3em;
height: 3em;
border: none;
border-radius: var(--wa-border-radius-circle);
background: none;
font-size: inherit;
margin-inline-start: 0.75em;
cursor: copy;
forced-color-adjust: none;
}
.preview:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: inherit;
box-shadow: inset 0 0 0 0.0625rem rgba(0, 0, 0, 0.2);
/* We use a custom property in lieu of currentColor because of https://bugs.webkit.org/show_bug.cgi?id=216780 */
background-color: var(--preview-color);
}
.preview:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
.preview-color {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: solid 0.0625rem rgba(0, 0, 0, 0.125);
}
.preview-color-copied {
animation: pulse 850ms;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 var(--wa-color-brand-fill-loud);
}
70% {
box-shadow: 0 0 0 0.5rem transparent;
}
100% {
box-shadow: 0 0 0 0 transparent;
}
}
.user-input {
display: flex;
align-items: center;
padding: 0 0.75em 0.75em 0.75em;
}
.user-input wa-input {
min-width: 0; /* fix input width in Safari */
flex: 1 1 auto;
&::part(form-control-label) {
/* Visually hidden */
position: absolute !important;
width: 1px !important;
height: 1px !important;
clip: rect(0 0 0 0) !important;
clip-path: inset(50%) !important;
border: none !important;
overflow: hidden !important;
white-space: nowrap !important;
padding: 0 !important;
}
}
.user-input wa-button-group {
margin-inline-start: 0.75em;
&::part(base) {
flex-wrap: nowrap;
}
}
.user-input wa-button:first-of-type {
min-width: 3em;
max-width: 3em;
}
.swatches {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(1.5em, 100%), 1fr));
grid-gap: 0.5em;
justify-items: center;
border-block-start: var(--wa-form-control-border-style) var(--wa-form-control-border-width)
var(--wa-color-surface-border);
padding: 0.5em;
forced-color-adjust: none;
}
.swatch {
position: relative;
aspect-ratio: 1 / 1;
width: 100%;
border-radius: var(--wa-border-radius-s);
}
.swatch .swatch-color {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: solid 0.0625rem rgba(0, 0, 0, 0.125);
border-radius: inherit;
cursor: pointer;
}
.swatch:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
.transparent-bg {
background-image:
linear-gradient(45deg, var(--wa-color-neutral-fill-normal) 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, var(--wa-color-neutral-fill-normal) 75%),
linear-gradient(45deg, transparent 75%, var(--wa-color-neutral-fill-normal) 75%),
linear-gradient(45deg, var(--wa-color-neutral-fill-normal) 25%, transparent 25%);
background-size: 0.5rem 0.5rem;
background-position:
0 0,
0 0,
-0.25rem -0.25rem,
0.25rem 0.25rem;
}
:host([disabled]) {
opacity: 0.5;
cursor: not-allowed;
.grid,
.grid-handle,
.slider,
.slider-handle,
.preview,
.swatch,
.swatch-color {
pointer-events: none;
}
}
/*
* Color dropdown
*/
.color-dropdown {
display: contents;
}
.color-dropdown::part(panel) {
max-height: none;
background-color: var(--wa-color-surface-raised);
border: var(--wa-border-style) var(--wa-border-width-s) var(--wa-color-surface-border);
border-radius: var(--wa-border-radius-m);
overflow: visible;
}
.trigger {
display: block;
position: relative;
background-color: transparent;
border: none;
cursor: pointer;
font-size: inherit;
forced-color-adjust: none;
width: var(--wa-form-control-height);
height: var(--wa-form-control-height);
border-radius: var(--wa-form-control-border-radius);
}
.trigger:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: inherit;
background-color: currentColor;
box-shadow:
inset 0 0 0 var(--wa-form-control-border-width) var(--wa-form-control-border-color),
inset 0 0 0 calc(var(--wa-form-control-border-width) * 3) var(--wa-color-surface-default);
}
.trigger-empty:before {
background-color: transparent;
}
.trigger:focus-visible {
outline: none;
}
.trigger:focus-visible:not(.trigger:disabled) {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
:host([disabled]) :is(.label, .trigger) {
opacity: 0.5;
cursor: not-allowed;
}
.form-control.form-control-has-label .label {
cursor: pointer;
display: inline-block;
}

View File

@@ -0,0 +1,345 @@
import { css } from 'lit';
export default css`
:host {
--grid-width: 17em;
--grid-height: 12em;
--grid-handle-size: 1.25em;
--slider-height: 1em;
--slider-handle-size: calc(var(--slider-height) + 0.25em);
}
.color-picker {
background-color: var(--wa-color-surface-raised);
border-radius: var(--wa-border-radius-m);
border-style: var(--wa-border-style);
border-width: var(--wa-border-width-s);
border-color: var(--wa-color-surface-border);
box-shadow: var(--wa-shadow-m);
color: var(--color);
font: inherit;
font-size: inherit;
user-select: none;
width: var(--grid-width);
-webkit-user-select: none;
}
.grid {
position: relative;
height: var(--grid-height);
background-image:
linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%),
linear-gradient(to right, #fff 0%, rgba(255, 255, 255, 0) 100%);
border-top-left-radius: calc(var(--wa-border-radius-m) - var(--wa-border-width-s));
border-top-right-radius: calc(var(--wa-border-radius-m) - var(--wa-border-width-s));
cursor: crosshair;
forced-color-adjust: none;
}
.grid-handle {
position: absolute;
width: var(--grid-handle-size);
height: var(--grid-handle-size);
border-radius: var(--wa-border-radius-circle);
box-shadow: 0 0 0 0.0625rem rgba(0, 0, 0, 0.2);
border: solid 0.125rem white;
margin-top: calc(var(--grid-handle-size) / -2);
margin-left: calc(var(--grid-handle-size) / -2);
transition: scale var(--wa-transition-normal) var(--wa-transition-easing);
}
.grid-handle-dragging {
cursor: none;
scale: 1.5;
}
.grid-handle:focus-visible {
outline: var(--wa-focus-ring);
}
.controls {
padding: 0.75em;
display: flex;
align-items: center;
}
.sliders {
flex: 1 1 auto;
}
.slider {
position: relative;
height: var(--slider-height);
border-radius: var(--wa-border-radius-s);
box-shadow: inset 0 0 0 0.0625rem rgba(0, 0, 0, 0.2);
forced-color-adjust: none;
}
.slider:not(:last-of-type) {
margin-bottom: 0.75em;
}
.slider-handle {
position: absolute;
top: calc(50% - var(--slider-handle-size) / 2);
width: var(--slider-handle-size);
height: var(--slider-handle-size);
border-radius: var(--wa-border-radius-circle);
border: solid 0.125rem white;
box-shadow: 0 0 0 0.0625rem rgba(0, 0, 0, 0.2);
margin-left: calc(var(--slider-handle-size) / -2);
}
.slider-handle:focus-visible {
outline: var(--wa-focus-ring);
}
.hue {
background-image: linear-gradient(
to right,
rgb(255, 0, 0) 0%,
rgb(255, 255, 0) 17%,
rgb(0, 255, 0) 33%,
rgb(0, 255, 255) 50%,
rgb(0, 0, 255) 67%,
rgb(255, 0, 255) 83%,
rgb(255, 0, 0) 100%
);
}
.alpha .alpha-gradient {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: inherit;
}
.preview {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
position: relative;
width: 3em;
height: 3em;
border: none;
border-radius: var(--wa-border-radius-circle);
background: none;
font-size: inherit;
margin-inline-start: 0.75em;
cursor: copy;
forced-color-adjust: none;
}
.preview:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: inherit;
box-shadow: inset 0 0 0 0.0625rem rgba(0, 0, 0, 0.2);
/* We use a custom property in lieu of currentColor because of https://bugs.webkit.org/show_bug.cgi?id=216780 */
background-color: var(--preview-color);
}
.preview:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
.preview-color {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: solid 0.0625rem rgba(0, 0, 0, 0.125);
}
.preview-color-copied {
animation: pulse 850ms;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 var(--wa-color-brand-fill-loud);
}
70% {
box-shadow: 0 0 0 0.5rem transparent;
}
100% {
box-shadow: 0 0 0 0 transparent;
}
}
.user-input {
display: flex;
align-items: center;
padding: 0 0.75em 0.75em 0.75em;
}
.user-input wa-input {
min-width: 0; /* fix input width in Safari */
flex: 1 1 auto;
&::part(form-control-label) {
/* Visually hidden */
position: absolute !important;
width: 1px !important;
height: 1px !important;
clip: rect(0 0 0 0) !important;
clip-path: inset(50%) !important;
border: none !important;
overflow: hidden !important;
white-space: nowrap !important;
padding: 0 !important;
}
}
.user-input wa-button-group {
margin-inline-start: 0.75em;
&::part(base) {
flex-wrap: nowrap;
}
}
.user-input wa-button:first-of-type {
min-width: 3em;
max-width: 3em;
}
.swatches {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(1.5em, 100%), 1fr));
grid-gap: 0.5em;
justify-items: center;
border-block-start: var(--wa-form-control-border-style) var(--wa-form-control-border-width)
var(--wa-color-surface-border);
padding: 0.5em;
forced-color-adjust: none;
}
.swatch {
position: relative;
aspect-ratio: 1 / 1;
width: 100%;
border-radius: var(--wa-border-radius-s);
}
.swatch .swatch-color {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: solid 0.0625rem rgba(0, 0, 0, 0.125);
border-radius: inherit;
cursor: pointer;
}
.swatch:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
.transparent-bg {
background-image:
linear-gradient(45deg, var(--wa-color-neutral-fill-normal) 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, var(--wa-color-neutral-fill-normal) 75%),
linear-gradient(45deg, transparent 75%, var(--wa-color-neutral-fill-normal) 75%),
linear-gradient(45deg, var(--wa-color-neutral-fill-normal) 25%, transparent 25%);
background-size: 0.5rem 0.5rem;
background-position:
0 0,
0 0,
-0.25rem -0.25rem,
0.25rem 0.25rem;
}
:host([disabled]) {
opacity: 0.5;
cursor: not-allowed;
.grid,
.grid-handle,
.slider,
.slider-handle,
.preview,
.swatch,
.swatch-color {
pointer-events: none;
}
}
/*
* Color dropdown
*/
.color-dropdown {
display: contents;
}
.color-dropdown::part(panel) {
max-height: none;
background-color: var(--wa-color-surface-raised);
border: var(--wa-border-style) var(--wa-border-width-s) var(--wa-color-surface-border);
border-radius: var(--wa-border-radius-m);
overflow: visible;
}
.trigger {
display: block;
position: relative;
background-color: transparent;
border: none;
cursor: pointer;
font-size: inherit;
forced-color-adjust: none;
width: var(--wa-form-control-height);
height: var(--wa-form-control-height);
border-radius: var(--wa-form-control-border-radius);
}
.trigger:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: inherit;
background-color: currentColor;
box-shadow:
inset 0 0 0 var(--wa-form-control-border-width) var(--wa-form-control-border-color),
inset 0 0 0 calc(var(--wa-form-control-border-width) * 3) var(--wa-color-surface-default);
}
.trigger-empty:before {
background-color: transparent;
}
.trigger:focus-visible {
outline: none;
}
.trigger:focus-visible:not(.trigger:disabled) {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
:host([disabled]) :is(.label, .trigger) {
opacity: 0.5;
cursor: not-allowed;
}
.form-control.form-control-has-label .label {
cursor: pointer;
display: inline-block;
}
`;

View File

@@ -14,9 +14,9 @@ import { HasSlotController } from '../../internal/slot.js';
import { RequiredValidator } from '../../internal/validators/required-validator.js';
import { watch } from '../../internal/watch.js';
import { WebAwesomeFormAssociatedElement } from '../../internal/webawesome-form-associated-element.js';
import formControlStyles from '../../styles/component/form-control.css';
import sizeStyles from '../../styles/utilities/size.css';
import visuallyHidden from '../../styles/utilities/visually-hidden.css';
import formControlStyles from '../../styles/component/form-control.styles.js';
import sizeStyles from '../../styles/component/size.styles.js';
import visuallyHidden from '../../styles/component/visually-hidden.styles.js';
import { LocalizeController } from '../../utilities/localize.js';
import '../button-group/button-group.js';
import '../button/button.js';
@@ -25,7 +25,7 @@ import '../input/input.js';
import type WaInput from '../input/input.js';
import '../popup/popup.js';
import type WaPopup from '../popup/popup.js';
import styles from './color-picker.css';
import styles from './color-picker.styles.js';
interface EyeDropperConstructor {
new (): EyeDropperInterface;
@@ -220,13 +220,6 @@ export default class WaColorPicker extends WebAwesomeFormAssociatedElement {
*/
@property() swatches: string | string[] = '';
/**
* By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you
* to place the form control outside of a form and associate it with the form that has this `id`. The form must be in
* the same document or shadow root for this to work.
*/
@property({ reflect: true }) form = null;
/** Makes the color picker a required field. */
@property({ type: Boolean, reflect: true }) required = false;
@@ -1284,7 +1277,14 @@ export default class WaColorPicker extends WebAwesomeFormAssociatedElement {
})}
part="trigger-container form-control"
>
<div part="form-control-label" class="label" id="form-control-label">
<div
part="form-control-label"
class=${classMap({
label: true,
'has-label': hasLabel,
})}
id="form-control-label"
>
<slot name="label">${this.label}</slot>
</div>

View File

@@ -1,76 +0,0 @@
:host {
--divider-width: 0.125rem;
--handle-size: 2.5rem;
display: block;
position: relative;
max-width: 100%;
max-height: 100%;
overflow: hidden;
}
.before,
.after {
display: block;
&::slotted(img),
&::slotted(svg) {
display: block;
max-width: 100% !important;
height: auto;
}
&::slotted(:not(img, svg)) {
isolation: isolate;
}
}
.after {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
/* Disable pointer-events while dragging. This is especially important for iframes. */
:host(:state(dragging)) {
.before,
.after {
pointer-events: none;
}
}
.divider {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
width: var(--divider-width);
height: 100%;
background-color: var(--wa-color-surface-default);
translate: calc(var(--divider-width) / -2);
cursor: ew-resize;
}
.handle {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: calc(50% - (var(--handle-size) / 2));
width: var(--handle-size);
height: var(--handle-size);
background-color: var(--wa-color-surface-default);
border-radius: var(--wa-border-radius-circle);
font-size: calc(var(--handle-size) * 0.4);
color: var(--wa-color-neutral-on-quiet);
cursor: inherit;
z-index: 10;
}
.handle:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}

View File

@@ -0,0 +1,80 @@
import { css } from 'lit';
export default css`
:host {
--divider-width: 0.125rem;
--handle-size: 2.5rem;
display: block;
position: relative;
max-width: 100%;
max-height: 100%;
overflow: hidden;
}
.before,
.after {
display: block;
&::slotted(img),
&::slotted(svg) {
display: block;
max-width: 100% !important;
height: auto;
}
&::slotted(:not(img, svg)) {
isolation: isolate;
}
}
.after {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
/* Disable pointer-events while dragging. This is especially important for iframes. */
:host(:state(dragging)) {
.before,
.after {
pointer-events: none;
}
}
.divider {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
width: var(--divider-width);
height: 100%;
background-color: var(--wa-color-surface-default);
translate: calc(var(--divider-width) / -2);
cursor: ew-resize;
}
.handle {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: calc(50% - (var(--handle-size) / 2));
width: var(--handle-size);
height: var(--handle-size);
background-color: var(--wa-color-surface-default);
border-radius: var(--wa-border-radius-circle);
font-size: calc(var(--handle-size) * 0.4);
color: var(--wa-color-neutral-on-quiet);
cursor: inherit;
z-index: 10;
}
.handle:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
`;

View File

@@ -7,7 +7,7 @@ import { watch } from '../../internal/watch.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import { LocalizeController } from '../../utilities/localize.js';
import '../icon/icon.js';
import styles from './comparison.css';
import styles from './comparison.styles.js';
/**
* @summary Compare visual differences between similar content with a sliding panel.

View File

@@ -1,75 +0,0 @@
:host {
display: inline-block;
color: var(--wa-color-neutral-on-quiet);
}
.button {
flex: 0 0 auto;
display: flex;
align-items: center;
background-color: transparent;
border: none;
border-radius: var(--wa-form-control-border-radius);
color: inherit;
font-size: inherit;
padding: 0.5em;
cursor: pointer;
transition: color var(--wa-transition-fast) var(--wa-transition-easing);
}
@media (hover: hover) {
.button:hover:not([disabled]) {
background-color: var(--wa-color-neutral-fill-quiet);
color: color-mix(in oklab, currentColor, var(--wa-color-mix-hover));
}
}
.button:focus-visible:not([disabled]) {
background-color: var(--wa-color-neutral-fill-quiet);
color: color-mix(in oklab, currentColor, var(--wa-color-mix-hover));
}
.button:active:not([disabled]) {
color: color-mix(in oklab, currentColor, var(--wa-color-mix-active));
}
slot[name='success-icon'] {
color: var(--wa-color-success-on-quiet);
}
slot[name='error-icon'] {
color: var(--wa-color-danger-on-quiet);
}
.button:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
.button[disabled] {
opacity: 0.5;
cursor: not-allowed !important;
}
slot {
display: inline-flex;
}
.show {
animation: show 100ms ease;
}
.hide {
animation: show 100ms ease reverse;
}
@keyframes show {
from {
scale: 0.25;
opacity: 0.25;
}
to {
scale: 1;
opacity: 1;
}
}

View File

@@ -0,0 +1,79 @@
import { css } from 'lit';
export default css`
:host {
display: inline-block;
color: var(--wa-color-neutral-on-quiet);
}
.button {
flex: 0 0 auto;
display: flex;
align-items: center;
background-color: transparent;
border: none;
border-radius: var(--wa-form-control-border-radius);
color: inherit;
font-size: inherit;
padding: 0.5em;
cursor: pointer;
transition: color var(--wa-transition-fast) var(--wa-transition-easing);
}
@media (hover: hover) {
.button:hover:not([disabled]) {
background-color: var(--wa-color-neutral-fill-quiet);
color: color-mix(in oklab, currentColor, var(--wa-color-mix-hover));
}
}
.button:focus-visible:not([disabled]) {
background-color: var(--wa-color-neutral-fill-quiet);
color: color-mix(in oklab, currentColor, var(--wa-color-mix-hover));
}
.button:active:not([disabled]) {
color: color-mix(in oklab, currentColor, var(--wa-color-mix-active));
}
slot[name='success-icon'] {
color: var(--wa-color-success-on-quiet);
}
slot[name='error-icon'] {
color: var(--wa-color-danger-on-quiet);
}
.button:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
.button[disabled] {
opacity: 0.5;
cursor: not-allowed !important;
}
slot {
display: inline-flex;
}
.show {
animation: show 100ms ease;
}
.hide {
animation: show 100ms ease reverse;
}
@keyframes show {
from {
scale: 0.25;
opacity: 0.25;
}
to {
scale: 1;
opacity: 1;
}
}
`;

View File

@@ -5,12 +5,12 @@ import { WaCopyEvent } from '../../events/copy.js';
import { WaErrorEvent } from '../../events/error.js';
import { animateWithClass } from '../../internal/animate.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import visuallyHidden from '../../styles/utilities/visually-hidden.css';
import visuallyHidden from '../../styles/component/visually-hidden.styles.js';
import { LocalizeController } from '../../utilities/localize.js';
import '../icon/icon.js';
import '../tooltip/tooltip.js';
import type WaTooltip from '../tooltip/tooltip.js';
import styles from './copy-button.css';
import styles from './copy-button.styles.js';
/**
* @summary Copies text data to the clipboard when the user clicks the trigger.

View File

@@ -1,122 +0,0 @@
:host {
--spacing: var(--wa-space-m);
--show-duration: 200ms;
--hide-duration: 200ms;
display: block;
}
details {
display: block;
overflow-anchor: none;
border: var(--wa-panel-border-width) var(--wa-color-surface-border) var(--wa-panel-border-style);
background-color: var(--wa-color-surface-default);
border-radius: var(--wa-panel-border-radius);
color: var(--wa-color-text-normal);
/* Print styles */
@media print {
background: none;
border: solid var(--wa-border-width-s) var(--wa-color-surface-border);
summary {
list-style: none;
}
}
}
/* Appearance modifiers */
:host([appearance='plain']) details {
background-color: transparent;
border-color: transparent;
border-radius: 0;
}
:host([appearance='outlined']) details {
background-color: var(--wa-color-surface-default);
border-color: var(--wa-color-surface-border);
}
:host([appearance='filled']) details {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: transparent;
}
:host([appearance='filled-outlined']) details {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: var(--wa-color-neutral-border-quiet);
}
:host([disabled]) details {
opacity: 0.5;
cursor: not-allowed;
}
summary {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing);
padding: var(--spacing); /* Add padding here */
border-radius: calc(var(--wa-panel-border-radius) - var(--wa-panel-border-width));
user-select: none;
-webkit-user-select: none;
cursor: pointer;
&::marker,
&::-webkit-details-marker {
display: none;
}
&:focus {
outline: none;
}
&:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: calc(var(--wa-panel-border-width) + var(--wa-focus-ring-offset));
}
}
:host([open]) summary {
border-end-start-radius: 0;
border-end-end-radius: 0;
}
/* 'Start' icon placement */
:host([icon-placement='start']) summary {
flex-direction: row-reverse;
justify-content: start;
}
[part~='icon'] {
flex: 0 0 auto;
display: flex;
align-items: center;
color: var(--wa-color-text-quiet);
transition: rotate var(--wa-transition-normal) var(--wa-transition-easing);
}
:host([open]) [part~='icon'] {
rotate: 90deg;
}
:host([open]:dir(rtl)) [part~='icon'] {
rotate: -90deg;
}
:host([open]) slot[name='expand-icon'],
:host(:not([open])) slot[name='collapse-icon'] {
display: none;
}
.body.animating {
overflow: hidden;
}
.content {
display: block;
padding-block-start: var(--spacing);
padding-inline: var(--spacing); /* Add horizontal padding */
padding-block-end: var(--spacing); /* Add bottom padding */
}

View File

@@ -0,0 +1,126 @@
import { css } from 'lit';
export default css`
:host {
--spacing: var(--wa-space-m);
--show-duration: 200ms;
--hide-duration: 200ms;
display: block;
}
details {
display: block;
overflow-anchor: none;
border: var(--wa-panel-border-width) var(--wa-color-surface-border) var(--wa-panel-border-style);
background-color: var(--wa-color-surface-default);
border-radius: var(--wa-panel-border-radius);
color: var(--wa-color-text-normal);
/* Print styles */
@media print {
background: none;
border: solid var(--wa-border-width-s) var(--wa-color-surface-border);
summary {
list-style: none;
}
}
}
/* Appearance modifiers */
:host([appearance='plain']) details {
background-color: transparent;
border-color: transparent;
border-radius: 0;
}
:host([appearance='outlined']) details {
background-color: var(--wa-color-surface-default);
border-color: var(--wa-color-surface-border);
}
:host([appearance='filled']) details {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: transparent;
}
:host([appearance='filled-outlined']) details {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: var(--wa-color-neutral-border-quiet);
}
:host([disabled]) details {
opacity: 0.5;
cursor: not-allowed;
}
summary {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing);
padding: var(--spacing); /* Add padding here */
border-radius: calc(var(--wa-panel-border-radius) - var(--wa-panel-border-width));
user-select: none;
-webkit-user-select: none;
cursor: pointer;
&::marker,
&::-webkit-details-marker {
display: none;
}
&:focus {
outline: none;
}
&:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: calc(var(--wa-panel-border-width) + var(--wa-focus-ring-offset));
}
}
:host([open]) summary {
border-end-start-radius: 0;
border-end-end-radius: 0;
}
/* 'Start' icon placement */
:host([icon-placement='start']) summary {
flex-direction: row-reverse;
justify-content: start;
}
[part~='icon'] {
flex: 0 0 auto;
display: flex;
align-items: center;
color: var(--wa-color-text-quiet);
transition: rotate var(--wa-transition-normal) var(--wa-transition-easing);
}
:host([open]) [part~='icon'] {
rotate: 90deg;
}
:host([open]:dir(rtl)) [part~='icon'] {
rotate: -90deg;
}
:host([open]) slot[name='expand-icon'],
:host(:not([open])) slot[name='collapse-icon'] {
display: none;
}
.body.animating {
overflow: hidden;
}
.content {
display: block;
padding-block-start: var(--spacing);
padding-inline: var(--spacing); /* Add horizontal padding */
padding-block-end: var(--spacing); /* Add bottom padding */
}
`;

View File

@@ -13,7 +13,7 @@ import WebAwesomeElement from '../../internal/webawesome-element.js';
import { WebAwesomeFormAssociatedElement } from '../../internal/webawesome-form-associated-element.js';
import { LocalizeController } from '../../utilities/localize.js';
import '../icon/icon.js';
import styles from './details.css';
import styles from './details.styles.js';
/**
* @summary Details show a brief summary and expand to show additional content.

View File

@@ -1,183 +0,0 @@
:host {
--width: 31rem;
--spacing: var(--wa-space-l);
--show-duration: 200ms;
--hide-duration: 200ms;
display: none;
}
:host([open]) {
display: block;
}
.dialog {
display: flex;
flex-direction: column;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: var(--width);
max-width: calc(100% - var(--wa-space-2xl));
max-height: calc(100% - var(--wa-space-2xl));
background-color: var(--wa-color-surface-raised);
border-radius: var(--wa-panel-border-radius);
border: none;
box-shadow: var(--wa-shadow-l);
padding: 0;
margin: auto;
&.show {
animation: show-dialog var(--show-duration) ease;
&::backdrop {
animation: show-backdrop var(--show-duration, 200ms) ease;
}
}
&.hide {
animation: show-dialog var(--hide-duration) ease reverse;
&::backdrop {
animation: show-backdrop var(--hide-duration, 200ms) ease reverse;
}
}
&.pulse {
animation: pulse 250ms ease;
}
}
.dialog:focus {
outline: none;
}
/* Ensure there's enough vertical padding for phones that don't update vh when chrome appears (e.g. iPhone) */
@media screen and (max-width: 420px) {
.dialog {
max-height: 80vh;
}
}
.open {
display: flex;
opacity: 1;
}
.header {
flex: 0 0 auto;
display: flex;
flex-wrap: nowrap;
padding-inline-start: var(--spacing);
padding-block-end: 0;
/* Subtract the close button's padding so that the X is visually aligned with the edges of the dialog content */
padding-inline-end: calc(var(--spacing) - var(--wa-form-control-padding-block));
padding-block-start: calc(var(--spacing) - var(--wa-form-control-padding-block));
}
.title {
align-self: center;
flex: 1 1 auto;
font-family: inherit;
font-size: var(--wa-font-size-l);
font-weight: var(--wa-font-weight-heading);
line-height: var(--wa-line-height-condensed);
margin: 0;
}
.header-actions {
align-self: start;
display: flex;
flex-shrink: 0;
flex-wrap: wrap;
justify-content: end;
gap: var(--wa-space-2xs);
padding-inline-start: var(--spacing);
}
.header-actions wa-button,
.header-actions ::slotted(wa-button) {
flex: 0 0 auto;
display: flex;
align-items: center;
}
.body {
flex: 1 1 auto;
display: block;
padding: var(--spacing);
overflow: auto;
-webkit-overflow-scrolling: touch;
&:focus {
outline: none;
}
&:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
}
.footer {
flex: 0 0 auto;
display: flex;
flex-wrap: wrap;
gap: var(--wa-space-xs);
justify-content: end;
padding: var(--spacing);
padding-block-start: 0;
}
.footer ::slotted(wa-button:not(:first-of-type)) {
margin-inline-start: var(--wa-spacing-xs);
}
.dialog::backdrop {
/*
NOTE: the ::backdrop element doesn't inherit properly in Safari yet, but it will in 17.4! At that time, we can
remove the fallback values here.
*/
background-color: var(--wa-color-overlay-modal, rgb(0 0 0 / 0.25));
}
@keyframes pulse {
0% {
scale: 1;
}
50% {
scale: 1.02;
}
100% {
scale: 1;
}
}
@keyframes show-dialog {
from {
opacity: 0;
scale: 0.8;
}
to {
opacity: 1;
scale: 1;
}
}
@keyframes show-backdrop {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@media (forced-colors: active) {
.dialog {
border: solid 1px white;
}
}

View File

@@ -0,0 +1,187 @@
import { css } from 'lit';
export default css`
:host {
--width: 31rem;
--spacing: var(--wa-space-l);
--show-duration: 200ms;
--hide-duration: 200ms;
display: none;
}
:host([open]) {
display: block;
}
.dialog {
display: flex;
flex-direction: column;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: var(--width);
max-width: calc(100% - var(--wa-space-2xl));
max-height: calc(100% - var(--wa-space-2xl));
background-color: var(--wa-color-surface-raised);
border-radius: var(--wa-panel-border-radius);
border: none;
box-shadow: var(--wa-shadow-l);
padding: 0;
margin: auto;
&.show {
animation: show-dialog var(--show-duration) ease;
&::backdrop {
animation: show-backdrop var(--show-duration, 200ms) ease;
}
}
&.hide {
animation: show-dialog var(--hide-duration) ease reverse;
&::backdrop {
animation: show-backdrop var(--hide-duration, 200ms) ease reverse;
}
}
&.pulse {
animation: pulse 250ms ease;
}
}
.dialog:focus {
outline: none;
}
/* Ensure there's enough vertical padding for phones that don't update vh when chrome appears (e.g. iPhone) */
@media screen and (max-width: 420px) {
.dialog {
max-height: 80vh;
}
}
.open {
display: flex;
opacity: 1;
}
.header {
flex: 0 0 auto;
display: flex;
flex-wrap: nowrap;
padding-inline-start: var(--spacing);
padding-block-end: 0;
/* Subtract the close button's padding so that the X is visually aligned with the edges of the dialog content */
padding-inline-end: calc(var(--spacing) - var(--wa-form-control-padding-block));
padding-block-start: calc(var(--spacing) - var(--wa-form-control-padding-block));
}
.title {
align-self: center;
flex: 1 1 auto;
font-family: inherit;
font-size: var(--wa-font-size-l);
font-weight: var(--wa-font-weight-heading);
line-height: var(--wa-line-height-condensed);
margin: 0;
}
.header-actions {
align-self: start;
display: flex;
flex-shrink: 0;
flex-wrap: wrap;
justify-content: end;
gap: var(--wa-space-2xs);
padding-inline-start: var(--spacing);
}
.header-actions wa-button,
.header-actions ::slotted(wa-button) {
flex: 0 0 auto;
display: flex;
align-items: center;
}
.body {
flex: 1 1 auto;
display: block;
padding: var(--spacing);
overflow: auto;
-webkit-overflow-scrolling: touch;
&:focus {
outline: none;
}
&:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
}
.footer {
flex: 0 0 auto;
display: flex;
flex-wrap: wrap;
gap: var(--wa-space-xs);
justify-content: end;
padding: var(--spacing);
padding-block-start: 0;
}
.footer ::slotted(wa-button:not(:first-of-type)) {
margin-inline-start: var(--wa-spacing-xs);
}
.dialog::backdrop {
/*
NOTE: the ::backdrop element doesn't inherit properly in Safari yet, but it will in 17.4! At that time, we can
remove the fallback values here.
*/
background-color: var(--wa-color-overlay-modal, rgb(0 0 0 / 0.25));
}
@keyframes pulse {
0% {
scale: 1;
}
50% {
scale: 1.02;
}
100% {
scale: 1;
}
}
@keyframes show-dialog {
from {
opacity: 0;
scale: 0.8;
}
to {
opacity: 1;
scale: 1;
}
}
@keyframes show-backdrop {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@media (forced-colors: active) {
.dialog {
border: solid 1px white;
}
}
`;

View File

@@ -13,7 +13,7 @@ import { watch } from '../../internal/watch.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import { LocalizeController } from '../../utilities/localize.js';
import '../button/button.js';
import styles from './dialog.css';
import styles from './dialog.styles.js';
/**
* @summary Dialogs, sometimes called "modals", appear above the page and require the user's immediate attention.

View File

@@ -1,19 +0,0 @@
:host {
--color: var(--wa-color-surface-border);
--width: var(--wa-border-width-s);
--spacing: var(--wa-space-m);
}
:host(:not([orientation='vertical'])) {
display: block;
border-top: solid var(--width) var(--color);
margin: var(--spacing) 0;
}
:host([orientation='vertical']) {
display: inline-block;
height: 100%;
border-inline-start: solid var(--width) var(--color);
margin: 0 var(--spacing);
min-block-size: 1lh;
}

View File

@@ -0,0 +1,23 @@
import { css } from 'lit';
export default css`
:host {
--color: var(--wa-color-surface-border);
--width: var(--wa-border-width-s);
--spacing: var(--wa-space-m);
}
:host(:not([orientation='vertical'])) {
display: block;
border-top: solid var(--width) var(--color);
margin: var(--spacing) 0;
}
:host([orientation='vertical']) {
display: inline-block;
height: 100%;
border-inline-start: solid var(--width) var(--color);
margin: 0 var(--spacing);
min-block-size: 1lh;
}
`;

View File

@@ -1,7 +1,7 @@
import { customElement, property } from 'lit/decorators.js';
import { watch } from '../../internal/watch.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import styles from './divider.css';
import styles from './divider.styles.js';
/**
* @summary Dividers are used to visually separate or group elements.

View File

@@ -1,290 +0,0 @@
:host {
--size: 25rem;
--spacing: var(--wa-space-l);
--show-duration: 200ms;
--hide-duration: 200ms;
display: none;
}
:host([open]) {
display: block;
}
.drawer {
display: flex;
flex-direction: column;
top: 0;
inset-inline-start: 0;
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
overflow: hidden;
background-color: var(--wa-color-surface-raised);
border: none;
box-shadow: var(--wa-shadow-l);
overflow: auto;
padding: 0;
margin: 0;
animation-duration: var(--show-duration);
animation-timing-function: ease;
&.show::backdrop {
animation: show-backdrop var(--show-duration, 200ms) ease;
}
&.hide::backdrop {
animation: show-backdrop var(--hide-duration, 200ms) ease reverse;
}
&.show.top {
animation: show-drawer-from-top var(--show-duration) ease;
}
&.hide.top {
animation: show-drawer-from-top var(--hide-duration) ease reverse;
}
&.show.end {
animation: show-drawer-from-end var(--show-duration) ease;
&:dir(rtl) {
animation-name: show-drawer-from-start;
}
}
&.hide.end {
animation: show-drawer-from-end var(--hide-duration) ease reverse;
&:dir(rtl) {
animation-name: show-drawer-from-start;
}
}
&.show.bottom {
animation: show-drawer-from-bottom var(--show-duration) ease;
}
&.hide.bottom {
animation: show-drawer-from-bottom var(--hide-duration) ease reverse;
}
&.show.start {
animation: show-drawer-from-start var(--show-duration) ease;
&:dir(rtl) {
animation-name: show-drawer-from-end;
}
}
&.hide.start {
animation: show-drawer-from-start var(--hide-duration) ease reverse;
&:dir(rtl) {
animation-name: show-drawer-from-end;
}
}
&.pulse {
animation: pulse 250ms ease;
}
}
.drawer:focus {
outline: none;
}
.top {
top: 0;
inset-inline-end: auto;
bottom: auto;
inset-inline-start: 0;
width: 100%;
height: var(--size);
}
.end {
top: 0;
inset-inline-end: 0;
bottom: auto;
inset-inline-start: auto;
width: var(--size);
height: 100%;
}
.bottom {
top: auto;
inset-inline-end: auto;
bottom: 0;
inset-inline-start: 0;
width: 100%;
height: var(--size);
}
.start {
top: 0;
inset-inline-end: auto;
bottom: auto;
inset-inline-start: 0;
width: var(--size);
height: 100%;
}
.header {
display: flex;
flex-wrap: nowrap;
padding-inline-start: var(--spacing);
padding-block-end: 0;
/* Subtract the close button's padding so that the X is visually aligned with the edges of the dialog content */
padding-inline-end: calc(var(--spacing) - var(--wa-form-control-padding-block));
padding-block-start: calc(var(--spacing) - var(--wa-form-control-padding-block));
}
.title {
align-self: center;
flex: 1 1 auto;
font: inherit;
font-size: var(--wa-font-size-l);
font-weight: var(--wa-font-weight-heading);
line-height: var(--wa-line-height-condensed);
margin: 0;
}
.header-actions {
align-self: start;
display: flex;
flex-shrink: 0;
flex-wrap: wrap;
justify-content: end;
gap: var(--wa-space-2xs);
padding-inline-start: var(--spacing);
}
.header-actions wa-button,
.header-actions ::slotted(wa-button) {
flex: 0 0 auto;
display: flex;
align-items: center;
}
.body {
flex: 1 1 auto;
display: block;
padding: var(--spacing);
overflow: auto;
-webkit-overflow-scrolling: touch;
&:focus {
outline: none;
}
&:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
}
.footer {
display: flex;
flex-wrap: wrap;
gap: var(--wa-space-xs);
justify-content: end;
padding: var(--spacing);
padding-block-start: 0;
}
.footer ::slotted(wa-button:not(:last-of-type)) {
margin-inline-end: var(--wa-spacing-xs);
}
.drawer::backdrop {
/*
NOTE: the ::backdrop element doesn't inherit properly in Safari yet, but it will in 17.4! At that time, we can
remove the fallback values here.
*/
background-color: var(--wa-color-overlay-modal, rgb(0 0 0 / 0.25));
}
@keyframes pulse {
0% {
scale: 1;
}
50% {
scale: 1.01;
}
100% {
scale: 1;
}
}
@keyframes show-drawer {
from {
opacity: 0;
scale: 0.8;
}
to {
opacity: 1;
scale: 1;
}
}
@keyframes show-drawer-from-top {
from {
opacity: 0;
translate: 0 -100%;
}
to {
opacity: 1;
translate: 0 0;
}
}
@keyframes show-drawer-from-end {
from {
opacity: 0;
translate: 100%;
}
to {
opacity: 1;
translate: 0 0;
}
}
@keyframes show-drawer-from-bottom {
from {
opacity: 0;
translate: 0 100%;
}
to {
opacity: 1;
translate: 0 0;
}
}
@keyframes show-drawer-from-start {
from {
opacity: 0;
translate: -100% 0;
}
to {
opacity: 1;
translate: 0 0;
}
}
@keyframes show-backdrop {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@media (forced-colors: active) {
.drawer {
border: solid 1px white;
}
}

View File

@@ -0,0 +1,294 @@
import { css } from 'lit';
export default css`
:host {
--size: 25rem;
--spacing: var(--wa-space-l);
--show-duration: 200ms;
--hide-duration: 200ms;
display: none;
}
:host([open]) {
display: block;
}
.drawer {
display: flex;
flex-direction: column;
top: 0;
inset-inline-start: 0;
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
overflow: hidden;
background-color: var(--wa-color-surface-raised);
border: none;
box-shadow: var(--wa-shadow-l);
overflow: auto;
padding: 0;
margin: 0;
animation-duration: var(--show-duration);
animation-timing-function: ease;
&.show::backdrop {
animation: show-backdrop var(--show-duration, 200ms) ease;
}
&.hide::backdrop {
animation: show-backdrop var(--hide-duration, 200ms) ease reverse;
}
&.show.top {
animation: show-drawer-from-top var(--show-duration) ease;
}
&.hide.top {
animation: show-drawer-from-top var(--hide-duration) ease reverse;
}
&.show.end {
animation: show-drawer-from-end var(--show-duration) ease;
&:dir(rtl) {
animation-name: show-drawer-from-start;
}
}
&.hide.end {
animation: show-drawer-from-end var(--hide-duration) ease reverse;
&:dir(rtl) {
animation-name: show-drawer-from-start;
}
}
&.show.bottom {
animation: show-drawer-from-bottom var(--show-duration) ease;
}
&.hide.bottom {
animation: show-drawer-from-bottom var(--hide-duration) ease reverse;
}
&.show.start {
animation: show-drawer-from-start var(--show-duration) ease;
&:dir(rtl) {
animation-name: show-drawer-from-end;
}
}
&.hide.start {
animation: show-drawer-from-start var(--hide-duration) ease reverse;
&:dir(rtl) {
animation-name: show-drawer-from-end;
}
}
&.pulse {
animation: pulse 250ms ease;
}
}
.drawer:focus {
outline: none;
}
.top {
top: 0;
inset-inline-end: auto;
bottom: auto;
inset-inline-start: 0;
width: 100%;
height: var(--size);
}
.end {
top: 0;
inset-inline-end: 0;
bottom: auto;
inset-inline-start: auto;
width: var(--size);
height: 100%;
}
.bottom {
top: auto;
inset-inline-end: auto;
bottom: 0;
inset-inline-start: 0;
width: 100%;
height: var(--size);
}
.start {
top: 0;
inset-inline-end: auto;
bottom: auto;
inset-inline-start: 0;
width: var(--size);
height: 100%;
}
.header {
display: flex;
flex-wrap: nowrap;
padding-inline-start: var(--spacing);
padding-block-end: 0;
/* Subtract the close button's padding so that the X is visually aligned with the edges of the dialog content */
padding-inline-end: calc(var(--spacing) - var(--wa-form-control-padding-block));
padding-block-start: calc(var(--spacing) - var(--wa-form-control-padding-block));
}
.title {
align-self: center;
flex: 1 1 auto;
font: inherit;
font-size: var(--wa-font-size-l);
font-weight: var(--wa-font-weight-heading);
line-height: var(--wa-line-height-condensed);
margin: 0;
}
.header-actions {
align-self: start;
display: flex;
flex-shrink: 0;
flex-wrap: wrap;
justify-content: end;
gap: var(--wa-space-2xs);
padding-inline-start: var(--spacing);
}
.header-actions wa-button,
.header-actions ::slotted(wa-button) {
flex: 0 0 auto;
display: flex;
align-items: center;
}
.body {
flex: 1 1 auto;
display: block;
padding: var(--spacing);
overflow: auto;
-webkit-overflow-scrolling: touch;
&:focus {
outline: none;
}
&:focus-visible {
outline: var(--wa-focus-ring);
outline-offset: var(--wa-focus-ring-offset);
}
}
.footer {
display: flex;
flex-wrap: wrap;
gap: var(--wa-space-xs);
justify-content: end;
padding: var(--spacing);
padding-block-start: 0;
}
.footer ::slotted(wa-button:not(:last-of-type)) {
margin-inline-end: var(--wa-spacing-xs);
}
.drawer::backdrop {
/*
NOTE: the ::backdrop element doesn't inherit properly in Safari yet, but it will in 17.4! At that time, we can
remove the fallback values here.
*/
background-color: var(--wa-color-overlay-modal, rgb(0 0 0 / 0.25));
}
@keyframes pulse {
0% {
scale: 1;
}
50% {
scale: 1.01;
}
100% {
scale: 1;
}
}
@keyframes show-drawer {
from {
opacity: 0;
scale: 0.8;
}
to {
opacity: 1;
scale: 1;
}
}
@keyframes show-drawer-from-top {
from {
opacity: 0;
translate: 0 -100%;
}
to {
opacity: 1;
translate: 0 0;
}
}
@keyframes show-drawer-from-end {
from {
opacity: 0;
translate: 100%;
}
to {
opacity: 1;
translate: 0 0;
}
}
@keyframes show-drawer-from-bottom {
from {
opacity: 0;
translate: 0 100%;
}
to {
opacity: 1;
translate: 0 0;
}
}
@keyframes show-drawer-from-start {
from {
opacity: 0;
translate: -100% 0;
}
to {
opacity: 1;
translate: 0 0;
}
}
@keyframes show-backdrop {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@media (forced-colors: active) {
.drawer {
border: solid 1px white;
}
}
`;

View File

@@ -13,7 +13,7 @@ import { watch } from '../../internal/watch.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import { LocalizeController } from '../../utilities/localize.js';
import '../button/button.js';
import styles from './drawer.css';
import styles from './drawer.styles.js';
/**
* @summary Drawers slide in from a container to expose additional options and information.

View File

@@ -1,227 +0,0 @@
:host {
display: flex;
position: relative;
align-items: center;
padding: 0.5em 1em;
border-radius: var(--wa-border-radius-s);
isolation: isolate;
color: var(--wa-color-text-normal);
line-height: var(--wa-line-height-condensed);
cursor: pointer;
transition:
100ms background-color ease,
100ms color ease;
}
@media (hover: hover) {
:host(:hover:not(:state(disabled))) {
background-color: var(--wa-color-neutral-fill-normal);
}
}
:host(:focus-visible) {
z-index: 1;
outline: var(--wa-focus-ring);
background-color: var(--wa-color-neutral-fill-normal);
}
:host(:state(disabled)) {
opacity: 0.5;
cursor: not-allowed;
}
/* Danger variant */
:host([variant='danger']),
:host([variant='danger']) #details {
color: var(--wa-color-danger-on-quiet);
}
@media (hover: hover) {
:host([variant='danger']:hover) {
background-color: var(--wa-color-danger-fill-normal);
color: var(--wa-color-danger-on-normal);
}
}
:host([variant='danger']:focus-visible) {
background-color: var(--wa-color-danger-fill-normal);
color: var(--wa-color-danger-on-normal);
}
:host([checkbox-adjacent]) {
padding-inline-start: 2em;
}
/* Only add padding when item actually has a submenu */
:host([submenu-adjacent]:not(:state(has-submenu))) #details {
padding-inline-end: 0;
}
:host(:state(has-submenu)[submenu-adjacent]) #details {
padding-inline-end: 1.75em;
}
#check {
visibility: hidden;
margin-inline-start: -1.5em;
margin-inline-end: 0.5em;
font-size: var(--wa-font-size-smaller);
}
:host(:state(checked)) #check {
visibility: visible;
}
#icon ::slotted(*) {
display: flex;
flex: 0 0 auto;
align-items: center;
margin-inline-end: 0.75em !important;
font-size: var(--wa-font-size-smaller);
}
#label {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#details {
display: flex;
flex: 0 0 auto;
align-items: center;
justify-content: end;
color: var(--wa-color-text-quiet);
font-size: var(--wa-font-size-smaller) !important;
}
#details ::slotted(*) {
margin-inline-start: 2em !important;
}
/* Submenu indicator icon */
#submenu-indicator {
position: absolute;
inset-inline-end: 1em;
color: var(--wa-color-neutral-on-quiet);
font-size: var(--wa-font-size-smaller);
}
/* Flip chevron icon when RTL */
:host(:dir(rtl)) #submenu-indicator {
transform: scaleX(-1);
}
/* Submenu styles */
#submenu {
display: flex;
z-index: 10;
position: absolute;
top: 0;
left: 0;
flex-direction: column;
width: max-content;
margin: 0;
padding: 0.25em;
border: var(--wa-border-style) var(--wa-border-width-s) var(--wa-color-surface-border);
border-radius: var(--wa-border-radius-m);
background-color: var(--wa-color-surface-raised);
box-shadow: var(--wa-shadow-m);
color: var(--wa-color-text-normal);
text-align: start;
user-select: none;
/* Override default popover styles */
&[popover] {
margin: 0;
inset: auto;
padding: 0.25em;
overflow: visible;
border-radius: var(--wa-border-radius-m);
}
&.show {
animation: submenu-show var(--show-duration, 50ms) ease;
}
&.hide {
animation: submenu-show var(--show-duration, 50ms) ease reverse;
}
/* Submenu placement transform origins */
&[data-placement^='top'] {
transform-origin: bottom;
}
&[data-placement^='bottom'] {
transform-origin: top;
}
&[data-placement^='left'] {
transform-origin: right;
}
&[data-placement^='right'] {
transform-origin: left;
}
&[data-placement='left-start'] {
transform-origin: right top;
}
&[data-placement='left-end'] {
transform-origin: right bottom;
}
&[data-placement='right-start'] {
transform-origin: left top;
}
&[data-placement='right-end'] {
transform-origin: left bottom;
}
/* Safe triangle styling */
&::before {
display: none;
z-index: 9;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: transparent;
content: '';
clip-path: polygon(
var(--safe-triangle-cursor-x, 0) var(--safe-triangle-cursor-y, 0),
var(--safe-triangle-submenu-start-x, 0) var(--safe-triangle-submenu-start-y, 0),
var(--safe-triangle-submenu-end-x, 0) var(--safe-triangle-submenu-end-y, 0)
);
pointer-events: auto; /* Enable mouse events on the triangle */
}
&[data-visible]::before {
display: block;
}
}
::slotted(wa-dropdown-item) {
font-size: inherit;
}
::slotted(wa-divider) {
--spacing: 0.25em;
}
@keyframes submenu-show {
from {
scale: 0.9;
opacity: 0;
}
to {
scale: 1;
opacity: 1;
}
}

View File

@@ -0,0 +1,231 @@
import { css } from 'lit';
export default css`
:host {
display: flex;
position: relative;
align-items: center;
padding: 0.5em 1em;
border-radius: var(--wa-border-radius-s);
isolation: isolate;
color: var(--wa-color-text-normal);
line-height: var(--wa-line-height-condensed);
cursor: pointer;
transition:
var(--wa-transition-fast) background-color var(--wa-transition-easing),
var(--wa-transition-fast) color var(--wa-transition-easing);
}
@media (hover: hover) {
:host(:hover:not(:state(disabled))) {
background-color: var(--wa-color-neutral-fill-normal);
}
}
:host(:focus-visible) {
z-index: 1;
outline: var(--wa-focus-ring);
background-color: var(--wa-color-neutral-fill-normal);
}
:host(:state(disabled)) {
opacity: 0.5;
cursor: not-allowed;
}
/* Danger variant */
:host([variant='danger']),
:host([variant='danger']) #details {
color: var(--wa-color-danger-on-quiet);
}
@media (hover: hover) {
:host([variant='danger']:hover) {
background-color: var(--wa-color-danger-fill-normal);
color: var(--wa-color-danger-on-normal);
}
}
:host([variant='danger']:focus-visible) {
background-color: var(--wa-color-danger-fill-normal);
color: var(--wa-color-danger-on-normal);
}
:host([checkbox-adjacent]) {
padding-inline-start: 2em;
}
/* Only add padding when item actually has a submenu */
:host([submenu-adjacent]:not(:state(has-submenu))) #details {
padding-inline-end: 0;
}
:host(:state(has-submenu)[submenu-adjacent]) #details {
padding-inline-end: 1.75em;
}
#check {
visibility: hidden;
margin-inline-start: -1.5em;
margin-inline-end: 0.5em;
font-size: var(--wa-font-size-smaller);
}
:host(:state(checked)) #check {
visibility: visible;
}
#icon ::slotted(*) {
display: flex;
flex: 0 0 auto;
align-items: center;
margin-inline-end: 0.75em !important;
font-size: var(--wa-font-size-smaller);
}
#label {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#details {
display: flex;
flex: 0 0 auto;
align-items: center;
justify-content: end;
color: var(--wa-color-text-quiet);
font-size: var(--wa-font-size-smaller) !important;
}
#details ::slotted(*) {
margin-inline-start: 2em !important;
}
/* Submenu indicator icon */
#submenu-indicator {
position: absolute;
inset-inline-end: 1em;
color: var(--wa-color-neutral-on-quiet);
font-size: var(--wa-font-size-smaller);
}
/* Flip chevron icon when RTL */
:host(:dir(rtl)) #submenu-indicator {
transform: scaleX(-1);
}
/* Submenu styles */
#submenu {
display: flex;
z-index: 10;
position: absolute;
top: 0;
left: 0;
flex-direction: column;
width: max-content;
margin: 0;
padding: 0.25em;
border: var(--wa-border-style) var(--wa-border-width-s) var(--wa-color-surface-border);
border-radius: var(--wa-border-radius-m);
background-color: var(--wa-color-surface-raised);
box-shadow: var(--wa-shadow-m);
color: var(--wa-color-text-normal);
text-align: start;
user-select: none;
/* Override default popover styles */
&[popover] {
margin: 0;
inset: auto;
padding: 0.25em;
overflow: visible;
border-radius: var(--wa-border-radius-m);
}
&.show {
animation: submenu-show var(--show-duration, 50ms) ease;
}
&.hide {
animation: submenu-show var(--show-duration, 50ms) ease reverse;
}
/* Submenu placement transform origins */
&[data-placement^='top'] {
transform-origin: bottom;
}
&[data-placement^='bottom'] {
transform-origin: top;
}
&[data-placement^='left'] {
transform-origin: right;
}
&[data-placement^='right'] {
transform-origin: left;
}
&[data-placement='left-start'] {
transform-origin: right top;
}
&[data-placement='left-end'] {
transform-origin: right bottom;
}
&[data-placement='right-start'] {
transform-origin: left top;
}
&[data-placement='right-end'] {
transform-origin: left bottom;
}
/* Safe triangle styling */
&::before {
display: none;
z-index: 9;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: transparent;
content: '';
clip-path: polygon(
var(--safe-triangle-cursor-x, 0) var(--safe-triangle-cursor-y, 0),
var(--safe-triangle-submenu-start-x, 0) var(--safe-triangle-submenu-start-y, 0),
var(--safe-triangle-submenu-end-x, 0) var(--safe-triangle-submenu-end-y, 0)
);
pointer-events: auto; /* Enable mouse events on the triangle */
}
&[data-visible]::before {
display: block;
}
}
::slotted(wa-dropdown-item) {
font-size: inherit;
}
::slotted(wa-divider) {
--spacing: 0.25em;
}
@keyframes submenu-show {
from {
scale: 0.9;
opacity: 0;
}
to {
scale: 1;
opacity: 1;
}
}
`;

Some files were not shown because too many files have changed in this diff Show More