Compare commits

..

135 Commits

Author SHA1 Message Date
Cory LaViska
03da8e9b56 make event cancelable 2025-09-11 11:23:42 -04:00
konnorrogers
6dce88429a Bump changelog
Bump package.json version

update lockfile
2025-09-10 12:45:43 -04:00
Kelsey Jackson
04497cfd13 Add horizontal orientation to <wa-card> (#874)
* started horizontal card logic

* a little more work

* remove SSR attributes

These are no longer used since we're not serving up an SSR version of the website anymore.

* more work

* looking for old code

* added actions slot to horizontal card

* troubleshooting linter issue

* fixed liniting error

* responded to feedback

* added jsDoc and updated example

---------

Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
2025-09-10 10:27:15 -05:00
randomguy-2650
75116a5b0c Replace invisible BOM marker in Dialog/Drawer with a zero‐width space (#1410)
* replace BOM marker with a zero‐width space

* replace BOM marker with a zero‐width space
2025-09-10 11:06:15 -04:00
Cory LaViska
5e192023b4 reword (#1427) 2025-09-10 11:05:53 -04:00
Brian Talbot
26b29189db fixing GitHub discussion links to point to webawesome project (#1425) 2025-09-10 10:53:38 -04:00
trent
ac20e495d9 allow bundlers access to package.json (#1415) 2025-09-10 10:53:17 -04:00
Cory LaViska
4ac31e06f3 remove whitespace; closes #1417 (#1418) 2025-09-10 10:38:06 -04:00
Konnor Rogers
4993b1034f add notes about skips (#1419)
* add notes about skips

* prettier

* re-add support for 'unpublished: true'

* prettier
2025-09-10 10:32:48 -04:00
Cory LaViska
b3b93091f7 Add intersection observer component (#1406)
* add intersection observer component

* remove prefix

* update description
2025-09-08 17:22:45 -04:00
Brian Talbot
8cf20d9938 Docs: Fix Color Swatch Hover States (#1407)
* removing unused `--background-color-hover` from `docs.css`
* fixing `.swatch` hover-based `background-color`
* linting + formatting `docs/tokens/color.md`
2025-09-05 16:30:15 -04:00
randomguy-2650
63296b7ed5 update FA version from 7.0.0 to 7.0.1 (#1399) 2025-09-03 15:01:35 -04:00
Brian Talbot
0e56ed0cbb Prep for Pro + Product Marketing (#1390)
* adding conditional header + footer includes to `base.njk`

- support for custom headers via `header` front matter variable
- support for custom footers via `footer` front matter variable
- backward compatibility with default header

* revising `base.njk`'s body classes

* adding fileSlug-based class to body
* adding pageType-based class (default `docs`) to body

* adding conditional CSS asset logic to `base.njk`

* to load marketing-based CSS based on pageType
* to load docs-based CSS by default

* disabling wa-page's sticky header for marketing pageType
2025-09-03 12:37:28 -04:00
Cory LaViska
e70cb5c66d add changelog entry (#1398) 2025-09-03 08:13:55 -04:00
Michael Romer
913abd0db1 Reflect icon properties to its attributes (#1395) 2025-09-03 08:12:11 -04:00
Cory LaViska
d2798a96da flip color picker to keep it in the viewport (#1391) 2025-09-02 18:02:48 -04:00
Konnor Rogers
42729153db update vercel sh clone (#1392) 2025-09-02 17:52:25 -04:00
Cory LaViska
c2df5ca1ea fix typo (#1381) 2025-08-29 11:34:48 -04:00
Cory LaViska
c49813c7c1 Update themer to use bunny fonts instead of google fonts (#1378)
* use fonts.bunny.net for web fonts

* use bunny
2025-08-27 19:24:44 +00:00
Cory LaViska
f63dfbfff0 fix var name (#1372) 2025-08-25 16:17:58 -04:00
Cory LaViska
9a7947debd fix radio group styles; closes #1178 (#1360) 2025-08-25 14:30:59 -04:00
Cory LaViska
d2e1653519 fix value assignment; closes #1323 (#1368) 2025-08-25 12:35:34 -04:00
Cory LaViska
5b7004e72d Fix edge case where interactive elements inside <wa-details> would cause it to open/close (#1350)
* fixes #1252

* fixes #1250

* update changelog
2025-08-25 11:08:36 -04:00
Lindsay M
7ccfed9e93 Use FA7 icons in native styles (#1362)
* replace icons with FA7 paths

* replace details icon
2025-08-22 10:47:12 -04:00
Lindsay M
4f1de3918b Fix button positioning for real (#1361) 2025-08-21 18:00:09 -04:00
Konnor Rogers
adaea2fa5f fix wa-page fallback loading in free repo (#1359) 2025-08-21 14:12:39 -04:00
Lindsay M
e016e4bd48 Fix home page icons (#1358) 2025-08-21 13:29:09 -04:00
Cory LaViska
5e0b5f3fe6 update system icon view boxes (#1357) 2025-08-21 11:46:09 -04:00
Cory LaViska
493e1c06b9 Fixes spacing between clear and password toggle icons in <wa-input> (#1351)
* fixes spacing between icons; closes #1325

* use form control padding token

---------

Co-authored-by: lindsaym-fa <dev@lindsaym.design>
2025-08-21 11:35:05 -04:00
Konnor Rogers
8b763d0392 remove page (#1352) 2025-08-20 17:45:28 -04:00
Brian Talbot
9d82749abb 💅 Docs: Sidebar Visual + UI Polish (#1341)
* using layout utilities for sidebar heading link styling
* syncing up sidebar heading + general link styles
* updating sidebar heading text + icon alignment
* updating layout of experimental + pro badge decoratives
* increasing visual padding of `#search-trigger`'s `<kbd>`
* fixing `<li>` indentations
2025-08-20 17:24:36 -04:00
Lindsay M
3e3e5276a6 Apply position: relative only to buttons that contain badges (#1346)
* make relative positioning conditional

* add changelog
2025-08-20 17:07:29 -04:00
Cory LaViska
a0a47b1bdf remove outdated wa-change info (#1348) 2025-08-20 15:38:26 -04:00
Cory LaViska
fa51cff947 Fix icon sizes for FA7 (#1345)
* fix icon sizes for FA7

* update test to reflect new size

* fix icons for real

* update tests
2025-08-20 15:14:07 -04:00
Cory LaViska
fd08d4f227 add --show-duration and --hide-duration to select (#1344) 2025-08-20 14:34:21 -04:00
Cory LaViska
7008c0cef7 Add z-index to scroller's content and shadows (#1338)
* add z-index to content and shadows; fixes #1326

* remove unused property
2025-08-20 14:20:33 -04:00
Cory LaViska
e9ce8659f6 rename icon-position to icon-placement (#1343) 2025-08-20 12:31:55 -04:00
Cory LaViska
325d6f211b Remove the unsupported button group size attribute (#1334)
* remove unsupported example

* remove old/incorrect example

* remove unsupported attribute
2025-08-20 12:20:18 -04:00
Cory LaViska
bd1570ec76 fix paths and imports; closes #1303 (#1336) 2025-08-19 17:10:49 -04:00
Cory LaViska
406f3a0e81 Allow the slider's thumb to receive focus when tapping or dragging (#1337)
* fix paths and imports; closes #1303

* allow slider thumb to receive focus on tap; fixes #1312
2025-08-19 17:10:15 -04:00
Lindsay M
08babbce6d fix search trigger label alignment (#1315) 2025-08-19 16:18:49 -04:00
Cory LaViska
293b86705a update changelog (#1333) 2025-08-19 15:51:35 -04:00
Alan Chambers
fe5ab48c06 Add jsx types to package.json exports (#1295) 2025-08-19 15:50:12 -04:00
Cory LaViska
35e9dfe88d Update <wa-icon> to support Font Awesome 7 (#1301)
* Add FA 7 support

* Add FA 7 support

* Add FA 7 support

* Update the system library to use FA 7 icons

* fix: fix type issues

* Update the SVGs in the system library to be minified/compressed

* add suggestions and more features

* feat: add `swap-opacity` attribute

* fix: remove unrelated stuff in `swap-opacity` attribute styling

* Only scale paths for fixed width icons

* fix: fix Prettier lint issues

* fix: fix more syntax errors

* lint: Fix CSS linting, batch 1 of 3

* lint: fix TS linting issues, batch 2 of 3

* lint: Fix JS linting issues, batch 3 of 3

* lint: fix hopefully last linting issue, batch 3.5 of 3

* lint: fix final linting issues, 3.75 of 3

* lint: the actual last lint fix, batch 3.875 of 3

* chore: centre SVG paths within the SVG for fixed‐width icons

* fix iconoir example

* add comment to clarify

* use a constant for fa version

* remove unsupported features

* update for FA7; improve duotone support

* update changelog

* remove redundant fixed-width attributes

* update kit code

* notdog!

* add support for pro+ icons

* clean up example layouts, use consistent icon sizes

---------

Co-authored-by: randomguy-2650 <150704902+randomguy-2650@users.noreply.github.com>
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
2025-08-19 15:44:22 -04:00
Curtis Keller
44567ec967 remove unimplemented appearance typing (#1319) 2025-08-19 15:37:08 -04:00
Cory LaViska
bfdd0bd6d0 update list (#1309) 2025-08-14 11:37:18 -04:00
Cory LaViska
f3f5d40b7b Update changelog for new translation (#1308)
* prettier

* update changelog
2025-08-14 11:34:05 -04:00
Pratik sharma
3d75d6b59c added translation for Hindi(hi) (#1307) 2025-08-14 11:32:24 -04:00
whjvenyl
f30801ab66 Do not crush labels with nested tags (#1274)
* Adjust label styles for button and checkbox components to not crush space of nested tags

* Adjust label styles for button and checkbox components to not crush space of nested tags

* Update packages/webawesome/src/components/checkbox/checkbox.css

---------

Co-authored-by: Tobias Bannwart <tobias.bannwart@bison-group.com>
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
2025-08-12 11:38:06 -04:00
Cory LaViska
f92ef1f74e Fix dropdown bugs (#1293)
* fix dropdown auto-size; closes #1268

* fix slotted dropdown items; fixes #1271

* fix keyboard selection in dropdowns in shadow roots; fixes #1270
2025-08-12 11:31:40 -04:00
Lindsay M
da27a8dc74 Add native <input type="file"> styles (#1279)
* add `input type="file"` styles

* add `max-inline-size`

* refactor button styles to include `::file-selector-button`

* improve docs

* add changelog

* add region marker
2025-08-11 10:39:47 -04:00
Kelsey Jackson
437e0d9aec updated icon docs (#1283) 2025-08-07 13:35:27 -05:00
Cory LaViska
583d9c0616 add changelog; #1277 (#1282) 2025-08-07 13:40:47 -04:00
LX
cb29033eaf Fix exportparts of tooltip inside wa-slider component (#1277) 2025-08-07 13:33:59 -04:00
Konnor Rogers
c02ac306af Add extra build logging (#1259)
* fix build reloading

* prettier
2025-08-06 16:25:30 -04:00
konnorrogers
56d678b504 Bump package.json version 2025-08-05 12:59:29 -04:00
konnorrogers
b1864eb93d Bump package.json version 2025-08-05 12:58:54 -04:00
konnorrogers
d2b5613e85 bump changelog 2025-08-05 12:58:07 -04:00
konnorrogers
f7ca634822 Bump changelog 2025-08-05 12:57:53 -04:00
Kelsey Jackson
35d33c89b9 updated templates (#1265)
* updated templates

* added conditional

* updated layouts again
2025-08-05 12:32:09 -04:00
randomguy-2650
094bd478ff fix: remove non‐existent Plain appearance in the Badge visual tests (#1260) 2025-08-05 10:58:15 -04:00
Kelsey Jackson
0b619a99f1 Kj/honeyhive patterns sidebar updates (#1258)
* adding to sidebar

* updated sidebar

* updated sidebar navigation

* add header to sidebar nav
2025-08-01 12:57:14 -04:00
Cory LaViska
89cf48c865 Add JSX types for React (#1256)
* add JSX types for React et al

* update changelog
2025-07-31 13:10:07 -04:00
Cory LaViska
b7a6ebd228 add without-arrow to hide arrows without artifacts (#1253) 2025-07-30 14:08:26 -04:00
Cory LaViska
6c8bbd51d1 Add missing dependency for React wrappers (#1242)
* add dep

* remove dev dep
2025-07-28 13:55:12 -04:00
Lindsay M
6085b9698c Add tokens to style tooltip borders (#1234)
* add tooltip border tokens

* target the correct part

* target the correct part (for real)
2025-07-28 12:30:42 -04:00
Tu Nguyen
17ee36175b fixed a typo in dropdown doc (#1235) 2025-07-28 12:29:56 -04:00
Cory LaViska
3c7bb71a59 scope styles to #content (#1217) 2025-07-23 17:10:32 -04:00
randomguy-2650
d66b552962 fix: fix a German translation to make it sound more natural (#1223) 2025-07-23 14:43:13 -04:00
Cory LaViska
6f6e23c78c Fix details animation by preventing overflow during animation (#1214)
* don't overflow content; fixes #1149

* fix details overflow; closes #1149
2025-07-22 18:00:21 +00:00
Cory LaViska
310f7a8c5d fix dialog and drawer header; fixes #1209 (#1213) 2025-07-22 13:57:07 -04:00
Cory LaViska
9a7b258108 remove links to the old alpha repo (#1216) 2025-07-22 13:54:19 -04:00
Lindsay M
e10aba0ed1 Add icon-position to <wa-details> (#1210)
* add `icon-position` to `<wa-details>`

* fix attribute name
2025-07-22 13:38:42 -04:00
Konnor Rogers
1ea5dae9ad fix build reloading (#1211)
* fix build reloading

* prettier

* fix build reloading
2025-07-22 10:51:17 -04:00
Cory LaViska
21310bd367 Link fix and typo (#1208)
* fix typo

* fix broken discord link
2025-07-21 14:20:54 -04:00
Doug Stevenson
c1478e5865 Fix hash link for "cherry picking" (#1207) 2025-07-21 14:14:49 -04:00
randomguy-2650
9b8433c996 Update outdated docs related to A+O appearance (#1204) 2025-07-21 11:37:47 -04:00
konnorrogers
57dac67aab update package-lock 2025-07-18 14:24:04 -04:00
konnorrogers
441bfd7b72 Bump package.json version 2025-07-18 14:02:10 -04:00
konnorrogers
7150c59334 Bump changelog 2025-07-18 14:01:31 -04:00
Konnor Rogers
bd2a3c3b64 add pro setup (#1201) 2025-07-18 13:41:03 -04:00
Lindsay M
11519625ed Use margin for <wa-icon> spacing in native buttons (#1197) 2025-07-18 09:47:24 -04:00
Konnor Rogers
f19848c11e prevent infinite loop in build watcher (#1200)
* prevent infinite loop in build watcher

* prettier
2025-07-18 00:43:29 -04:00
Konnor Rogers
36b21b0be7 introduce before watch and after watch events (#1199)
* add before / after watch events so pro can properly incrementally build

* add events for pro / app

* add extra hooks for non-wa dev

* add old new line

* use package-lock.json from next

* npm install

* prettier
2025-07-18 00:09:47 -04:00
Cory LaViska
fe2c2ab7af improve accessibility; fixes #1177 (#1190) 2025-07-17 11:56:41 -04:00
Cory LaViska
b98b9baba4 add back id="hint" (#1192) 2025-07-17 11:55:53 -04:00
Cory LaViska
7b18be876b fix media rounding; closes #1107 (#1193) 2025-07-17 11:55:26 -04:00
Cory LaViska
c9e6895ef7 fix pill buttons in groups; closes #1165 (#1191) 2025-07-17 11:28:57 -04:00
Konnor Rogers
64c8647dee build speed improvements and add optional incremental builds (#1183)
* build speed improvments

* fix button

* prettier

* move things to plugins / transformers

* final fixes

* build fixes

* fix build issues

* add comment

* build sstuf

* prettier

* fix badge.css

* fix build stuff

* fix eleventy stuff

* prettier
2025-07-16 17:37:47 -04:00
randomguy-2650
9e9a00547a fix: fix incorrect documentation link used in @documentation JSDoc (#1187) 2025-07-16 12:02:35 -04:00
Lindsay M
f747483e32 Add --track-height to <wa-progress-bar> (#1159)
* add `--track-height` to `<wa-progress-bar>`

* fix custom `<wa-progress-bar>` height instances

* add changelog
2025-07-14 18:16:19 -04:00
Lindsay M
8719bbc88b Fix extra whitespace in <wa-textarea> with resize="auto" (#1175)
* fix extra whitespace

* fix the fix

* add changelog
2025-07-14 17:56:53 -04:00
Cory LaViska
0ff5e7fb7a Fix domain in documentation links (#1180)
* fix domain in doc links

* unprettier
2025-07-14 17:19:28 -04:00
Konnor Rogers
2a52b2766f fix badge pulsing (#1173)
* fix badge pulsing

* use and document `--pulse-color`

* Add changelog entry

---------

Co-authored-by: lindsaym-fa <dev@lindsaym.design>
2025-07-14 17:00:35 -04:00
Cory LaViska
1e8bbc3b06 fix domain (#1179) 2025-07-14 16:57:44 -04:00
Cory LaViska
1ef9cb9601 add missing dependency (#1176) 2025-07-14 16:55:43 -04:00
Lindsay M
5b54410212 Revise native styles documentation (#1153) 2025-07-14 16:21:15 -04:00
Joe Marquardt
f621fbb224 fix the build on windows (#1148)
- make-react importPath variable
 - esbuild entryPoints globby usage requires forward slashes
2025-07-14 16:13:11 -04:00
Cory LaViska
f5624fbf4a Slider hint (#1174)
* update example

* show hint in correct position when present

* update example

* update example
2025-07-14 16:05:02 -04:00
randomguy-2650
f65bc3918e fix: fix the language name in it.ts (#1171) 2025-07-14 15:48:18 -04:00
Lindsay M
f49c10b05b Replace old --wa-flow-spacing with --wa-content-spacing (#1157)
* remove old `--wa-flow-spacing`

* add changelog
2025-07-11 15:03:18 -04:00
Konnor Rogers
3b6c018fed Fix react imports to include a class name (#1158) 2025-07-10 15:40:45 -04:00
Lindsay M
c10e1e77c9 Update <wa-select> "Sizes" documentation (#1162) 2025-07-10 15:37:37 -04:00
Lindsay M
a1e879035c Fix code example styles (#1156) 2025-07-10 15:36:03 -04:00
Lindsay M
d2625fccab Remove extra stylesheets from CodePen editing (#1161) 2025-07-10 14:09:50 -04:00
randomguy-2650
29c8ad08bb Fix links pointing to / instead of the current page (#1145) 2025-07-09 13:11:24 -04:00
Mischa
0f68e6f0dd Refactor copy button documentation layout for improved alignment with input (#1141) 2025-07-09 13:09:53 -04:00
Tu Nguyen
4dca2b9541 Fixed a minor doc typo (#1137) 2025-07-09 12:17:20 -04:00
konnorrogers
36ccaa4aaa bump package.json 2025-07-03 18:32:12 -04:00
konnorrogers
c86d7635aa Bump package.json version 2025-07-03 18:31:59 -04:00
Konnor Rogers
d84e842a4e fixing select + tests (#1136)
* fixing select + tests

* fix TS

* prettier

* prettier

* fix CI test

* fix changelog
2025-07-03 18:29:02 -04:00
Lindsay M
fb8c06235f Fix link hover styles (#1135) 2025-07-03 14:20:51 -04:00
Cory LaViska
f6a10e9dda update changelog (#1134) 2025-07-03 12:06:38 -04:00
Lindsay M
5ce34677ed Add GitHub repository links (#1128)
* add repository links

* fix mobile navigation drawer
2025-07-03 11:26:35 -04:00
Lindsay M
8ebc839dfd Fix text colors on accent backgrounds (#1130) 2025-07-03 11:26:28 -04:00
Lindsay M
2779eb1753 Fix :active Awesome button text colors (#1129) 2025-07-03 09:24:47 -04:00
Cory LaViska
341ca809e9 Themes page fix (#1125)
* fix themes + palettes

* fix copy button color

* unimprove code links
2025-07-02 21:39:50 +00:00
Cory LaViska
7232ddee5d Dropdown fix (#1122)
* _blank

* fix dropdown flip/shift/ behavior when the viewport doesn't have space
2025-07-02 15:06:50 -04:00
whjvenyl
f63001f18e remove duplicate property (#1119)
Co-authored-by: Tobias Bannwart <tobias.bannwart@bison-group.com>
2025-07-02 14:10:15 -04:00
Lindsay M
8b831f6ece Improve organization of essential and optional styles (#1113)
* include all essential styles in `styles/themes/default.css` + cleanup

* tweak installation quick start description

* more docs updates
2025-07-02 13:58:55 -04:00
Lindsay M
4dee3d0f2d Add opt-in class to highlight table rows on hover (#1111)
* add `.wa-hover-rows`

* update docs

* update changelog
2025-07-02 09:20:17 -04:00
Cory LaViska
10a78d99af add missing items (#1117) 2025-07-02 08:21:52 -04:00
Lindsay M
99d9024339 Fix filled + outlined appearances (#1112)
* fix filled + outlined appearances

* docs consistency
2025-07-01 16:50:28 -04:00
Alan Chambers
313e31a3f2 Adjust package.json styles exports (#1104) 2025-07-01 16:45:55 -04:00
Konnor Rogers
4eeabc57e5 fix component paths....again (#1098) 2025-06-30 18:52:49 -04:00
Konnor Rogers
c8c0d0f848 disable runaway popup example (#1097) 2025-06-30 18:37:36 -04:00
Konnor Rogers
e8687b895d fix component paths (#1096) 2025-06-30 17:50:59 -04:00
Konnor Rogers
7743b670ed update docs (#1095)
* update docs

* add publish access config

* update package-lock
2025-06-30 15:32:08 -04:00
Konnor Rogers
88e99d7cd3 add placeholder readme.md (#1093) 2025-06-30 13:57:19 -04:00
Konnor Rogers
c0d18ab9f0 add dist-cdn to files (#1092) 2025-06-30 13:40:52 -04:00
Konnor Rogers
6576f67cfa center cta (#1091) 2025-06-30 13:37:22 -04:00
Konnor Rogers
057ff5fb31 change to webawesome (#1089)
* change to webawesome

* change to webawesome

* update index.md

* whitespace

* add thanks for being a webawesome pro subscriber

* add stub for currentUser

* add source code link

* add source code link

* prettier

* fix raw call
2025-06-30 13:29:56 -04:00
Cory LaViska
1dac76a35e fix blurb (#1090) 2025-06-30 13:03:28 -04:00
Konnor Rogers
e7f2962984 Pro fixes (#1088)
* add pro badge to themer

* add isPro flag to palettes

* show based on currentUser.hasPro

* fix logged out user stuff

---------

Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
2025-06-30 12:13:21 -04:00
Lindsay M
956dc9bdd9 Fix avatar colors in theme showcase (#1087) 2025-06-30 10:53:23 -04:00
205 changed files with 4318 additions and 3062 deletions

View File

@@ -92,6 +92,7 @@
"heroicons",
"hexa",
"Hotwire",
"hrefs",
"Iconoir",
"Iframes",
"iife",
@@ -135,6 +136,7 @@
"noopener",
"noreferrer",
"noscript",
"Notdog",
"novalidate",
"nowrap",
"Numberish",

83
package-lock.json generated
View File

@@ -16,7 +16,7 @@
"@custom-elements-manifest/analyzer": "^0.10.4",
"@lit-labs/eleventy-plugin-lit": "^1.0.3",
"@lit-labs/testing": "^0.2.5",
"@lit/react": "^1.0.6",
"@lit/react": "^1.0.8",
"@open-wc/testing": "^3.2.0",
"@types/mocha": "^10.0.10",
"@types/react": "^18.2.28",
@@ -589,6 +589,10 @@
"node": ">=12.17"
}
},
"node_modules/@awesome.me/webawesome": {
"resolved": "packages/webawesome",
"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",
@@ -2025,10 +2029,9 @@
}
},
"node_modules/@lit/react": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@lit/react/-/react-1.0.7.tgz",
"integrity": "sha512-cencnwwLXQKiKxjfFzSgZRngcWJzUDZi/04E0fSaF86wZgchMdvTyu+lE36DrUfvuus3bH8+xLPrhM1cTjwpzw==",
"dev": true,
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@lit/react/-/react-1.0.8.tgz",
"integrity": "sha512-p2+YcF+JE67SRX3mMlJ1TKCSTsgyOVdAwd/nxp3NuV1+Cb6MWALbN6nT7Ld4tpmYofcE5kcaSY1YBB9erY+6fw==",
"peerDependencies": {
"@types/react": "17 || 18 || 19"
}
@@ -2484,10 +2487,6 @@
"resolved": "https://registry.npmjs.org/@shoelace-style/localize/-/localize-3.2.1.tgz",
"integrity": "sha512-r4C9C/5kSfMBIr0D9imvpRdCNXtUNgyYThc4YlS6K5Hchv1UyxNQ9mxwj+BTRH2i1Neits260sR3OjKMnplsFA=="
},
"node_modules/@shoelace-style/webawesome": {
"resolved": "packages/webawesome",
"link": true
},
"node_modules/@shoelace-style/webawesome-pro": {
"resolved": "packages/webawesome-pro",
"link": true
@@ -2876,8 +2875,7 @@
"node_modules/@types/prop-types": {
"version": "15.7.14",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
"integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==",
"dev": true
"integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ=="
},
"node_modules/@types/qs": {
"version": "6.9.11",
@@ -2895,7 +2893,6 @@
"version": "18.3.23",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz",
"integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
@@ -2986,6 +2983,12 @@
"@types/node": "*"
}
},
"node_modules/@wc-toolkit/jsx-types": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@wc-toolkit/jsx-types/-/jsx-types-1.3.0.tgz",
"integrity": "sha512-2rcRyPNEAdesFlokSSFBuCjpPPrMySk4NqyVJsqCs/WczcAUnIGwjnJk2fd/SNmzSjxGFRIFLAhXOgFOHLPvxQ==",
"dev": true
},
"node_modules/@web/browser-logs": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@web/browser-logs/-/browser-logs-0.4.0.tgz",
@@ -5799,8 +5802,7 @@
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/custom-element-jet-brains-integration": {
"version": "1.7.0",
@@ -13974,42 +13976,83 @@
}
},
"packages/webawesome": {
"name": "@shoelace-style/webawesome",
"version": "3.0.0-beta.1",
"name": "@awesome.me/webawesome",
"version": "3.0.0-beta.5",
"license": "MIT",
"dependencies": {
"@ctrl/tinycolor": "^4.1.0",
"@floating-ui/dom": "^1.6.13",
"@lit/react": "^1.0.8",
"@shoelace-style/animations": "^1.2.0",
"@shoelace-style/localize": "^3.2.1",
"composed-offset-position": "^0.0.6",
"lit": "^3.2.1",
"nanoid": "^5.1.5",
"qr-creator": "^1.0.0",
"style-observer": "^0.0.7"
},
"devDependencies": {},
"devDependencies": {
"@wc-toolkit/jsx-types": "^1.3.0"
},
"engines": {
"node": ">=14.17.0"
}
},
"packages/webawesome-pro": {
"name": "@shoelace-style/webawesome-pro",
"version": "3.0.0-beta.1",
"license": "TODO",
"version": "3.0.0-beta.4",
"dependencies": {
"@ctrl/tinycolor": "^4.1.0",
"@floating-ui/dom": "^1.6.13",
"@lit/react": "^1.0.8",
"@shoelace-style/animations": "^1.2.0",
"@shoelace-style/localize": "^3.2.1",
"composed-offset-position": "^0.0.6",
"lit": "^3.2.1",
"nanoid": "^5.1.5",
"qr-creator": "^1.0.0",
"style-observer": "^0.0.7"
},
"devDependencies": {},
"devDependencies": {
"@wc-toolkit/jsx-types": "^1.3.0"
},
"engines": {
"node": ">=14.17.0"
}
},
"packages/webawesome-pro/node_modules/nanoid": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz",
"integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^18 || >=20"
}
},
"packages/webawesome/node_modules/nanoid": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz",
"integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^18 || >=20"
}
}
}
}

View File

@@ -18,13 +18,12 @@
"engines": {
"node": ">=14.17.0"
},
"dependencies": {},
"devDependencies": {
"@11ty/eleventy": "3.0.0",
"@custom-elements-manifest/analyzer": "^0.10.4",
"@lit-labs/eleventy-plugin-lit": "^1.0.3",
"@lit-labs/testing": "^0.2.5",
"@lit/react": "^1.0.6",
"@lit/react": "^1.0.8",
"@open-wc/testing": "^3.2.0",
"@types/mocha": "^10.0.10",
"@types/react": "^18.2.28",
@@ -87,4 +86,3 @@
]
}
}

View File

@@ -0,0 +1 @@
Visit our documentation! <https://webawesome.com>

View File

@@ -1,3 +1,4 @@
import { jsxTypesPlugin } from '@wc-toolkit/jsx-types';
import { customElementJetBrainsPlugin } from 'custom-element-jet-brains-integration';
import { customElementVsCodePlugin } from 'custom-element-vs-code-integration';
// import { customElementVuejsPlugin } from 'custom-element-vuejs-integration';
@@ -164,6 +165,7 @@ export default {
],
}),
// Generate custom JetBrains data
customElementJetBrainsPlugin({
outdir: './dist-cdn',
excludeCss: true,
@@ -176,6 +178,16 @@ export default {
},
}),
// Generate JSX types (see https://wc-toolkit.com/integrations/jsx/)
jsxTypesPlugin({
fileName: 'custom-elements-jsx.d.ts',
outdir,
defaultExport: true,
componentTypePath: (_name, _tag, modulePath) => {
return `./${modulePath}`;
},
}),
//
// TODO - figure out why this broke when events were updated
//

View File

@@ -1,30 +1,63 @@
import { parse as HTMLParse } from 'node-html-parser';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { parse } from 'path';
import { anchorHeadingsPlugin } from './_utils/anchor-headings.js';
import { codeExamplesPlugin } from './_utils/code-examples.js';
import { copyCodePlugin } from './_utils/copy-code.js';
import { currentLink } from './_utils/current-link.js';
import { highlightCodePlugin } from './_utils/highlight-code.js';
import { anchorHeadingsTransformer } from './_transformers/anchor-headings.js';
import { codeExamplesTransformer } from './_transformers/code-examples.js';
import { copyCodeTransformer } from './_transformers/copy-code.js';
import { currentLinkTransformer } from './_transformers/current-link.js';
import { highlightCodeTransformer } from './_transformers/highlight-code.js';
import { outlineTransformer } from './_transformers/outline.js';
import { getComponents } from './_utils/manifest.js';
import { markdown } from './_utils/markdown.js';
// import { formatCodePlugin } from './_utils/format-code.js';
import { SimulateWebAwesomeApp } from './_utils/simulate-webawesome-app.js';
// import { formatCodePlugin } from './_plugins/format-code.js';
// import litPlugin from '@lit-labs/eleventy-plugin-lit';
import { readFile } from 'fs/promises';
import nunjucks from 'nunjucks';
import process from 'process';
import * as url from 'url';
import { outlinePlugin } from './_utils/outline.js';
import { replaceTextPlugin } from './_utils/replace-text.js';
import { searchPlugin } from './_utils/search.js';
import { replaceTextPlugin } from './_plugins/replace-text.js';
import { searchPlugin } from './_plugins/search.js';
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const isDev = process.argv.includes('--develop');
const passThroughExtensions = ['js', 'css', 'png', 'svg', 'jpg', 'mp4'];
async function getPackageData() {
return JSON.parse(await readFile(path.join(__dirname, '..', 'package.json'), 'utf-8'));
}
export default async function (eleventyConfig) {
const packageData = JSON.parse(await readFile(path.join(__dirname, '..', 'package.json'), 'utf-8'));
const docsDir = path.join(process.env.BASE_DIR || '.', 'docs');
const allComponents = getComponents();
let packageData = await getPackageData();
let allComponents = getComponents();
const distDir = process.env.UNBUNDLED_DIST_DIRECTORY || path.resolve(__dirname, '../dist');
const customElementsManifest = path.join(distDir, 'custom-elements.json');
const stylesheets = path.join(distDir, 'styles');
eleventyConfig.addWatchTarget(customElementsManifest);
eleventyConfig.setWatchThrottleWaitTime(10); // in milliseconds
eleventyConfig.on('eleventy.beforeWatch', async function (changedFiles) {
let updatePackageData = false;
let updateComponentData = false;
changedFiles.forEach(file => {
if (file.includes('package.json')) {
updatePackageData = true;
}
if (file.includes('custom-elements.json')) {
updateComponentData = true;
}
});
if (updatePackageData) {
packageData = await getPackageData();
}
if (updateComponentData) {
allComponents = getComponents();
}
});
/**
* If you plan to add or remove any of these extensions, make sure to let either Konnor or Cory know as these
@@ -43,6 +76,7 @@ export default async function (eleventyConfig) {
//
eleventyConfig.addGlobalData('package', packageData);
eleventyConfig.addGlobalData('layout', 'page.njk');
eleventyConfig.addGlobalData('pageType', 'docs'); // Default page type
eleventyConfig.addGlobalData('server', {
head: '',
loginOrAvatar: '',
@@ -52,7 +86,7 @@ export default async function (eleventyConfig) {
// Template filters - {{ content | filter }}
eleventyConfig.addFilter('inlineMarkdown', content => markdown.renderInline(content || ''));
eleventyConfig.addFilter('markdown', content => markdown.render(content || ''));
eleventyConfig.addFilter('stripExtension', string => parse(string + '').name);
eleventyConfig.addFilter('stripExtension', string => path.parse(string + '').name);
eleventyConfig.addFilter('stripPrefix', content => content.replace(/^wa-/, ''));
// Trims whitespace and pipes from the start and end of a string. Useful for CEM types, which can be pipe-delimited.
// With Prettier 3, this means a leading pipe will exist be present when the line wraps.
@@ -109,28 +143,6 @@ export default async function (eleventyConfig) {
return '';
});
eleventyConfig.addTransform('second-nunjucks-transform', function NunjucksTransform(content) {
// For a server build, we expect a server to run the second transform.
if (serverBuild) {
return content;
}
// Only run the transform on files nunjucks would transform.
if (!this.page.inputPath.match(/.(md|html|njk)$/)) {
return content;
}
/** This largely mimics what an app would do and just stubs out what we don't care about. */
return nunjucks.renderString(content, {
// Stub the server EJS shortcodes.
server: {
head: '',
loginOrAvatar: '',
flashes: '',
},
});
});
// Paired shortcodes - {% shortCode %}content{% endShortCode %}
eleventyConfig.addPairedShortcode('markdown', content => markdown.render(content || ''));
@@ -148,34 +160,43 @@ export default async function (eleventyConfig) {
// Use our own markdown instance
eleventyConfig.setLibrary('md', markdown);
// for files with `unpublished: true`, it will make sure they do not make it into the final build at all, but will be usable in development.
eleventyConfig.addPreprocessor('unpublished', '*', (data, content) => {
if (data.unpublished && process.env.ELEVENTY_RUN_MODE === 'build') {
return false;
}
return content;
});
// Add anchors to headings
eleventyConfig.addPlugin(anchorHeadingsPlugin({ container: '#content' }));
eleventyConfig.addTransform('doc-transforms', function (content) {
let doc = HTMLParse(content, { blockTextElements: { code: true } });
// Add an outline to the page
eleventyConfig.addPlugin(
outlinePlugin({
container: '#content',
target: '.outline-links',
selector: 'h2, h3',
ifEmpty: doc => {
doc.querySelector('#outline')?.remove();
},
}),
);
const transformers = [
anchorHeadingsTransformer({ container: '#content' }),
outlineTransformer({
container: '#content',
target: '.outline-links',
selector: 'h2, h3',
ifEmpty: doc => {
doc.querySelector('#outline')?.remove();
},
}),
// Add current link classes
currentLinkTransformer(),
codeExamplesTransformer(),
highlightCodeTransformer(),
copyCodeTransformer(),
];
// Add current link classes
eleventyConfig.addPlugin(currentLink());
for (const transformer of transformers) {
transformer.call(this, doc);
}
// Add code examples for `<code class="example">` blocks
eleventyConfig.addPlugin(codeExamplesPlugin());
return doc.toString();
});
// Highlight code blocks with Prism
eleventyConfig.addPlugin(highlightCodePlugin());
// Add copy code buttons to code blocks
eleventyConfig.addPlugin(copyCodePlugin);
// Various text replacements
eleventyConfig.addPlugin(
replaceTextPlugin([
{
@@ -185,17 +206,17 @@ export default async function (eleventyConfig) {
// Replace [issue:1234] with a link to the issue on GitHub
{
replace: /\[pr:([0-9]+)\]/gs,
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/pull/$1">#$1</a>',
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/pull/$1" target="_blank">#$1</a>',
},
// Replace [pr:1234] with a link to the pull request on GitHub
{
replace: /\[issue:([0-9]+)\]/gs,
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/issues/$1">#$1</a>',
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/issues/$1" target="_blank">#$1</a>',
},
// Replace [discuss:1234] with a link to the discussion on GitHub
{
replace: /\[discuss:([0-9]+)\]/gs,
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/discussions/$1">#$1</a>',
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/discussions/$1" target="_blank">#$1</a>',
},
]),
);
@@ -218,16 +239,18 @@ export default async function (eleventyConfig) {
// eleventyConfig.addPlugin(formatCodePlugin());
// }
let assetsDir = path.join(process.env.BASE_DIR || 'docs', 'assets');
fs.cpSync(assetsDir, path.join(eleventyConfig.directories.output, 'assets'), { recursive: true });
// This needs to happen in "eleventy.after" otherwise incremental builds never update.
eleventyConfig.on('eleventy.after', function () {
let assetsDir = path.join(process.env.BASE_DIR || 'docs', 'assets');
const siteAssetsDir = path.join(eleventyConfig.directories.output, 'assets');
fs.cpSync(assetsDir, siteAssetsDir, { recursive: true });
});
for (let glob of passThrough) {
eleventyConfig.addPassthroughCopy(glob);
}
// // SSR plugin
// // Make sure this is the last thing, we don't want to run the risk of accidentally transforming shadow roots with
// // the nunjucks 2nd transform.
// if (!isDev) {
// //
// // Problematic components in SSR land:
@@ -250,6 +273,20 @@ export default async function (eleventyConfig) {
// componentModules,
// });
// }
// For a server build, we expect a server to run the second transform.
// For dev builds, we run the second transform in a middleware.
if (!isDev && !serverBuild) {
eleventyConfig.addTransform('simulate-webawesome-app', function (content) {
// Only run the transform on files nunjucks would transform.
if (!this.page.inputPath.match(/.(md|html|njk)$/)) {
return content;
}
/** This largely mimics what an app would do and just stubs out what we don't care about. */
return SimulateWebAwesomeApp(content);
});
}
}
export const config = {

View File

@@ -74,12 +74,12 @@ export const themes = [
body: {
name: 'Quicksand',
css: 'Quicksand, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Quicksand:wght@300..700&display=swap',
href: 'https://fonts.bunny.net/css2?family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Quicksand:wght@300..700&display=swap',
},
heading: {
name: 'Quicksand',
css: 'Quicksand, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Quicksand:wght@300..700&display=swap',
href: 'https://fonts.bunny.net/css2?family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Quicksand:wght@300..700&display=swap',
},
code: {
name: 'OS Default',
@@ -89,7 +89,7 @@ export const themes = [
longform: {
name: 'Crimson Pro',
css: '"Crimson Pro", serif',
href: 'https://fonts.googleapis.com/css2?family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Quicksand:wght@300..700&display=swap',
href: 'https://fonts.bunny.net/css2?family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Quicksand:wght@300..700&display=swap',
},
},
icons: {
@@ -194,22 +194,22 @@ export const themes = [
body: {
name: 'Inter',
css: 'Inter, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Aleo:ital,wght@0,100..900;1,100..900&family=Geist+Mono:wght@100..900&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Aleo:ital,wght@0,100..900;1,100..900&family=Geist+Mono:wght@100..900&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
},
heading: {
name: 'Inter',
css: 'Inter, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Aleo:ital,wght@0,100..900;1,100..900&family=Geist+Mono:wght@100..900&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Aleo:ital,wght@0,100..900;1,100..900&family=Geist+Mono:wght@100..900&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
},
code: {
name: 'Geist Mono',
css: '"Geist Mono", monospace',
href: 'https://fonts.googleapis.com/css2?family=Aleo:ital,wght@0,100..900;1,100..900&family=Geist+Mono:wght@100..900&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Aleo:ital,wght@0,100..900;1,100..900&family=Geist+Mono:wght@100..900&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
},
longform: {
name: 'Aleo',
css: 'Aleo, serif',
href: 'https://fonts.googleapis.com/css2?family=Aleo:ital,wght@0,100..900;1,100..900&family=Geist+Mono:wght@100..900&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Aleo:ital,wght@0,100..900;1,100..900&family=Geist+Mono:wght@100..900&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
},
},
icons: {
@@ -254,22 +254,22 @@ export const themes = [
body: {
name: 'Space Grotesk',
css: '"Space Grotesk", sans-serif',
href: 'https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Podkova:wght@400..800&family=Space+Grotesk:wght@300..700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap',
href: 'https://fonts.bunny.net/css2?family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Podkova:wght@400..800&family=Space+Grotesk:wght@300..700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap',
},
heading: {
name: 'IBM Plex Sans Condensed',
css: '"IBM Plex Sans Condensed", sans-serif',
href: 'https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Podkova:wght@400..800&family=Space+Grotesk:wght@300..700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap',
href: 'https://fonts.bunny.net/css2?family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Podkova:wght@400..800&family=Space+Grotesk:wght@300..700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap',
},
code: {
name: 'Space Mono',
css: '"Space Mono", monospace',
href: 'https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Podkova:wght@400..800&family=Space+Grotesk:wght@300..700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap',
href: 'https://fonts.bunny.net/css2?family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Podkova:wght@400..800&family=Space+Grotesk:wght@300..700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap',
},
longform: {
name: 'Podkova',
css: 'Podkova, serif',
href: 'https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Podkova:wght@400..800&family=Space+Grotesk:wght@300..700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap',
href: 'https://fonts.bunny.net/css2?family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Podkova:wght@400..800&family=Space+Grotesk:wght@300..700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap',
},
},
icons: {
@@ -314,22 +314,22 @@ export const themes = [
body: {
name: 'Figtree',
css: 'Figtree, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Chivo+Mono:ital,wght@0,100..900;1,100..900&family=Figtree:ital,wght@0,300..900;1,300..900&family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Chivo+Mono:ital,wght@0,100..900;1,100..900&family=Figtree:ital,wght@0,300..900;1,300..900&family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=swap',
},
heading: {
name: 'Figtree',
css: 'Figtree, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Chivo+Mono:ital,wght@0,100..900;1,100..900&family=Figtree:ital,wght@0,300..900;1,300..900&family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Chivo+Mono:ital,wght@0,100..900;1,100..900&family=Figtree:ital,wght@0,300..900;1,300..900&family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=swap',
},
code: {
name: 'Chivo Mono',
css: '"Chivo Mono", monospace',
href: 'https://fonts.googleapis.com/css2?family=Chivo+Mono:ital,wght@0,100..900;1,100..900&family=Figtree:ital,wght@0,300..900;1,300..900&family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Chivo+Mono:ital,wght@0,100..900;1,100..900&family=Figtree:ital,wght@0,300..900;1,300..900&family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=swap',
},
longform: {
name: 'Fraunces',
css: 'Fraunces, serif',
href: 'https://fonts.googleapis.com/css2?family=Chivo+Mono:ital,wght@0,100..900;1,100..900&family=Figtree:ital,wght@0,300..900;1,300..900&family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Chivo+Mono:ital,wght@0,100..900;1,100..900&family=Figtree:ital,wght@0,300..900;1,300..900&family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=swap',
},
},
icons: {
@@ -374,22 +374,22 @@ export const themes = [
body: {
name: 'Wix Madefor Text',
css: '"Wix Madefor Text", sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto+Serif:ital,opsz,wght@0,8..144,100..900;1,8..144,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Wix+Madefor+Text:ital,wght@0,400..800;1,400..800&display=swap',
href: 'https://fonts.bunny.net/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto+Serif:ital,opsz,wght@0,8..144,100..900;1,8..144,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Wix+Madefor+Text:ital,wght@0,400..800;1,400..800&display=swap',
},
heading: {
name: 'Wix Madefor Text',
css: '"Wix Madefor Text", sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto+Serif:ital,opsz,wght@0,8..144,100..900;1,8..144,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Wix+Madefor+Text:ital,wght@0,400..800;1,400..800&display=swap',
href: 'https://fonts.bunny.net/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto+Serif:ital,opsz,wght@0,8..144,100..900;1,8..144,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Wix+Madefor+Text:ital,wght@0,400..800;1,400..800&display=swap',
},
code: {
name: 'Roboto Mono',
css: '"Roboto Mono", monospace',
href: 'https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto+Serif:ital,opsz,wght@0,8..144,100..900;1,8..144,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Wix+Madefor+Text:ital,wght@0,400..800;1,400..800&display=swap',
href: 'https://fonts.bunny.net/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto+Serif:ital,opsz,wght@0,8..144,100..900;1,8..144,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Wix+Madefor+Text:ital,wght@0,400..800;1,400..800&display=swap',
},
longform: {
name: 'Roboto Serif',
css: '"Roboto Serif", serif',
href: 'https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto+Serif:ital,opsz,wght@0,8..144,100..900;1,8..144,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Wix+Madefor+Text:ital,wght@0,400..800;1,400..800&display=swap',
href: 'https://fonts.bunny.net/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto+Serif:ital,opsz,wght@0,8..144,100..900;1,8..144,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Wix+Madefor+Text:ital,wght@0,400..800;1,400..800&display=swap',
},
},
icons: {
@@ -434,12 +434,12 @@ export const themes = [
body: {
name: 'Mulish',
css: 'Mulish, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400..700;1,400..700&family=Mulish:ital,wght@0,200..1000;1,200..1000&display=swap',
href: 'https://fonts.bunny.net/css2?family=Lora:ital,wght@0,400..700;1,400..700&family=Mulish:ital,wght@0,200..1000;1,200..1000&display=swap',
},
heading: {
name: 'Lora',
css: 'Lora, serif',
href: 'https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400..700;1,400..700&family=Mulish:ital,wght@0,200..1000;1,200..1000&display=swap',
href: 'https://fonts.bunny.net/css2?family=Lora:ital,wght@0,400..700;1,400..700&family=Mulish:ital,wght@0,200..1000;1,200..1000&display=swap',
},
code: {
name: 'OS Default',
@@ -449,7 +449,7 @@ export const themes = [
longform: {
name: 'Lora',
css: 'Lora, serif',
href: 'https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400..700;1,400..700&family=Mulish:ital,wght@0,200..1000;1,200..1000&display=swap',
href: 'https://fonts.bunny.net/css2?family=Lora:ital,wght@0,400..700;1,400..700&family=Mulish:ital,wght@0,200..1000;1,200..1000&display=swap',
},
},
icons: {
@@ -494,22 +494,22 @@ export const themes = [
body: {
name: 'Nunito',
css: 'Nunito, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Azeret+Mono:ital,wght@0,100..900;1,100..900&family=BioRhyme:wght@200..800&family=Fredoka:wght@300..700&family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap',
href: 'https://fonts.bunny.net/css2?family=Azeret+Mono:ital,wght@0,100..900;1,100..900&family=BioRhyme:wght@200..800&family=Fredoka:wght@300..700&family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap',
},
heading: {
name: 'Fredoka',
css: 'Fredoka, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Azeret+Mono:ital,wght@0,100..900;1,100..900&family=BioRhyme:wght@200..800&family=Fredoka:wght@300..700&family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap',
href: 'https://fonts.bunny.net/css2?family=Azeret+Mono:ital,wght@0,100..900;1,100..900&family=BioRhyme:wght@200..800&family=Fredoka:wght@300..700&family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap',
},
code: {
name: 'Azeret Mono',
css: '"Azeret Mono", monospace',
href: 'https://fonts.googleapis.com/css2?family=Azeret+Mono:ital,wght@0,100..900;1,100..900&family=BioRhyme:wght@200..800&family=Fredoka:wght@300..700&family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap',
href: 'https://fonts.bunny.net/css2?family=Azeret+Mono:ital,wght@0,100..900;1,100..900&family=BioRhyme:wght@200..800&family=Fredoka:wght@300..700&family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap',
},
longform: {
name: 'BioRhyme',
css: 'BioRhyme, serif',
href: 'https://fonts.googleapis.com/css2?family=Azeret+Mono:ital,wght@0,100..900;1,100..900&family=BioRhyme:wght@200..800&family=Fredoka:wght@300..700&family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap',
href: 'https://fonts.bunny.net/css2?family=Azeret+Mono:ital,wght@0,100..900;1,100..900&family=BioRhyme:wght@200..800&family=Fredoka:wght@300..700&family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap',
},
},
icons: {
@@ -554,12 +554,12 @@ export const themes = [
body: {
name: 'DM Sans',
css: '"DM Sans", sans-serif',
href: 'https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Playfair:ital,opsz,wght@0,5..1200,300..900;1,5..1200,300..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Playfair:ital,opsz,wght@0,5..1200,300..900;1,5..1200,300..900&display=swap',
},
heading: {
name: 'Playfair Display',
css: '"Playfair Display", serif',
href: 'https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Playfair:ital,opsz,wght@0,5..1200,300..900;1,5..1200,300..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Playfair:ital,opsz,wght@0,5..1200,300..900;1,5..1200,300..900&display=swap',
},
code: {
name: 'OS Default',
@@ -569,7 +569,7 @@ export const themes = [
longform: {
name: 'Playfair',
css: 'Playfair, serif',
href: 'https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Playfair:ital,opsz,wght@0,5..1200,300..900;1,5..1200,300..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Playfair:ital,opsz,wght@0,5..1200,300..900;1,5..1200,300..900&display=swap',
},
},
icons: {
@@ -614,12 +614,12 @@ export const themes = [
body: {
name: 'Inter',
css: 'Inter, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
},
heading: {
name: 'Inter',
css: 'Inter, sans-serif',
href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
href: 'https://fonts.bunny.net/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
},
code: {
name: 'OS Default',

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" data-fa-kit-code="b10bfbde90" data-cdn-url="{% cdnUrl %}" class="wa-cloak">
<html lang="en" data-fa-kit-code="38c11e3f20" data-cdn-url="{% cdnUrl %}" class="wa-cloak">
<head>
{% include 'head.njk' %}
<meta name="theme-color" content="#f36944">
@@ -13,10 +13,16 @@
<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="backers.webawesome.com" src="https://plausible.io/js/script.js"></script>
<script defer data-domain="webawesome.com" src="https://plausible.io/js/script.js"></script>
{% if pageType == 'marketing' %}
{# Marketing styles #}
<link rel="stylesheet" href="/assets/styles/marketing.css" />
{% else %}
{# Docs styles (default) #}
<link rel="stylesheet" href="/assets/styles/docs.css" />
{% endif %}
{# Docs styles #}
<link rel="stylesheet" href="/assets/styles/docs.css" />
{% block head %}{% endblock %}
@@ -42,49 +48,61 @@
}
</script>
</head>
<body class="layout-{{ layout | stripExtension }}{{ ' page-wide' if wide }}">
<body class="layout-{{ layout | stripExtension }} page-{{ page.fileSlug or 'home' }}{{ ' page-wide' if wide }} page-{{ pageType or 'docs' }}">
<!-- use view="desktop" as default to reduce layout jank on desktop site. -->
<wa-page view="desktop" disable-navigation-toggle="" mobile-breakpoint="1180">
<header slot="header" class="wa-split">
{# Logo #}
<div id="docs-branding">
{# Nav toggle #}
<wa-button appearance="plain" size="small" data-toggle-nav>
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
</wa-button>
<wa-page view="desktop" disable-navigation-toggle {% if pageType == 'marketing' %}disable-sticky="header"{% endif %} mobile-breakpoint="1180">
{% if pageHeader %}
{% include pageHeader %}
{% else %}
<header slot="header" class="wa-split">
{# Logo #}
<div id="docs-branding">
{# Nav toggle #}
<wa-button appearance="plain" size="small" data-toggle-nav>
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
</wa-button>
<a href="/" aria-label="Web Awesome">
<span class="wa-desktop-only">{% include "logo.njk" %}</span>
<span class="wa-mobile-only">{% include "logo-simple.njk" %}</span>
</a>
<small id="version-number" class="wa-desktop-only">{{ package.version }}</small>
<wa-badge variant="brand" appearance="filled" class="wa-desktop-only">Beta</wa-badge>
</div>
<div id="docs-toolbar" class="wa-cluster wa-gap-xs">
{# Desktop selectors #}
<div class="wa-desktop-only wa-cluster wa-gap-xs">
{% include "theme-selector.njk" %}
{% include "color-scheme-selector.njk" %}
<a href="/" aria-label="Web Awesome">
<span class="wa-desktop-only">{% include "logo.njk" %}</span>
<span class="wa-mobile-only">{% include "logo-simple.njk" %}</span>
</a>
<small id="version-number" class="wa-desktop-only">{{ package.version }}</small>
<wa-badge variant="brand" appearance="filled" class="wa-desktop-only">Beta</wa-badge>
</div>
{# Search #}
<wa-button id="search-trigger" appearance="outlined" size="small" data-search>
<wa-icon slot="start" name="magnifying-glass"></wa-icon>
Search
<kbd slot="end" class="wa-desktop-only">/</kbd>
</wa-button>
<div id="docs-toolbar" class="wa-cluster">
{# Desktop selectors #}
<div class="wa-desktop-only wa-cluster wa-gap-xs">
{% include "theme-selector.njk" %}
{% include "color-scheme-selector.njk" %}
</div>
{# Login #}
{% server "loginOrAvatar" %}
</div>
</header>
<wa-divider orientation="vertical" class="wa-desktop-only"></wa-divider>
<div id="github-buttons" class="wa-cluster wa-gap-xs">
<wa-button id="github-repo-button" href="https://github.com/shoelace-style/webawesome" rel="noopener noreferrer" target="_blank" appearance="filled" size="small">
<wa-icon family="brands" name="github" label="GitHub"></wa-icon>
</wa-button>
<wa-tooltip for="github-repo-button" distance="2">GitHub</wa-tooltip>
<wa-button id="github-star-button" href="https://github.com/shoelace-style/webawesome/stargazers" rel="noopener noreferrer" target="_blank" appearance="filled" size="small">
<wa-icon name="star" variant="regular" label="Star this repository"></wa-icon>
</wa-button>
<wa-tooltip for="github-star-button" distance="2">Star this repository</wa-tooltip>
</div>
<wa-divider orientation="vertical"></wa-divider>
{# Login #}
{% server "loginOrAvatar" %}
</div>
</header>
{% endif %}
{# Sidebar #}
{% if hasSidebar %}
{# Mobile selectors #}
<div class="wa-mobile-only" slot="navigation-header">
<div class="wa-cluster wa-gap-xs">
<div class="wa-cluster wa-gap-xs" style="flex-wrap: nowrap;">
{% include "theme-selector.njk" %}
{% include "color-scheme-selector.njk" %}
</div>
@@ -130,6 +148,11 @@
</main>
{% include 'search.njk' %}
{# Footer #}
{% if pageFooter %}
{% include pageFooter %}
{% endif %}
</wa-page>
</body>

View File

@@ -1,4 +1,4 @@
<wa-select class="color-scheme-selector" appearance="filled" size="small" value="auto" pill title="Press \ to toggle">
<wa-select class="color-scheme-selector" appearance="filled" size="small" value="auto" title="Press \ to toggle">
<wa-icon class="only-light" slot="start" name="sun" variant="regular"></wa-icon>
<wa-icon class="only-dark" slot="start" name="moon" variant="regular"></wa-icon>
<wa-option value="light">

View File

@@ -26,5 +26,17 @@
{% endfor %}
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
<script type="module">
document.addEventListener("wa-discovery-complete", loadLayout)
function loadLayout () {
if (!customElements.get("wa-layout")) {
import("{% cdnUrl 'components/page/page.js' %}")
.catch((e) => {
// known errors with dual registration. This is only a thing in the free repo.
})
}
}
</script>
{# Used by Web Awesome App to inject other assets into the head. #}
{% server "head" %}

View File

@@ -1,3 +1,10 @@
{# Search #}
<wa-button id="search-trigger" appearance="outlined" size="small" data-search>
<wa-icon slot="start" name="magnifying-glass"></wa-icon>
Search
<kbd slot="end" class="wa-desktop-only">/</kbd>
</wa-button>
{# Getting started #}
<h2>Getting Started</h2>
<ul>
@@ -12,6 +19,7 @@
<h2>Resources</h2>
<ul>
<li><a href="https://github.com/shoelace-style/webawesome/discussions" target="_blank">Help &amp; Support</a></li>
<li><a href="https://github.com/shoelace-style/webawesome/">Source Code</a></li>
<li><a href="/docs/resources/community">Community</a></li>
<li><a href="/docs/resources/accessibility">Accessibility</a></li>
<li><a href="/docs/resources/browser-support">Browser Support</a></li>
@@ -23,16 +31,19 @@
<!-- Components -->
<wa-details appearance="outlined">
<h2 slot="summary">
<a href="/docs/components/" title="Overview">
Components
<a class="wa-cluster wa-gap-xs" href="/docs/components/" title="Overview">
<wa-icon name="grid-2" aria-hidden="true"></wa-icon>
Components
</a>
</h2>
<ul>
<li>
<a href="/docs/components/page/">Page</a>
<wa-icon name="flask" aria-hidden="true"></wa-icon>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
<span class="wa-split">
<a class="wa-cluster wa-gap-xs" href="/docs/components/page/">
Page <wa-icon name="flask" aria-hidden="true"></wa-icon>
</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
</span>
</li>
<li><a href="/docs/components/animated-image/">Animated Image</a></li>
<li><a href="/docs/components/animation/">Animation</a></li>
@@ -49,12 +60,16 @@
<li><a href="/docs/components/callout/">Callout</a></li>
<li><a href="/docs/components/card/">Card</a></li>
<li>
<a href="/docs/components/carousel/">Carousel</a>
<wa-icon name="flask" aria-hidden="true"></wa-icon>
<a class="wa-cluster wa-gap-xs" href="/docs/components/carousel/">
Carousel
<wa-icon name="flask" aria-hidden="true"></wa-icon>
</a>
<ul>
<li>
<a href="/docs/components/carousel-item/">Carousel Item</a>
<wa-icon name="flask" aria-hidden="true"></wa-icon>
<a class="wa-cluster wa-gap-xs" href="/docs/components/carousel-item/">
Carousel Item
<wa-icon name="flask" aria-hidden="true"></wa-icon>
</a>
</li>
</ul>
</li>
@@ -62,8 +77,10 @@
<li><a href="/docs/components/color-picker/">Color Picker</a></li>
<li><a href="/docs/components/comparison/">Comparison</a></li>
<li>
<a href="/docs/components/copy-button/">Copy Button</a>
<wa-icon name="flask" aria-hidden="true"></wa-icon>
<a class="wa-cluster wa-gap-xs" href="/docs/components/copy-button/">
Copy Button
<wa-icon name="flask" aria-hidden="true"></wa-icon>
</a>
</li>
<li><a href="/docs/components/details/">Details</a></li>
<li><a href="/docs/components/dialog/">Dialog</a></li>
@@ -81,6 +98,7 @@
<li><a href="/docs/components/icon/">Icon</a></li>
<li><a href="/docs/components/include/">Include</a></li>
<li><a href="/docs/components/input/">Input</a></li>
<li><a href="/docs/components/intersection-observer">Intersection Observer</a></li>
<li><a href="/docs/components/mutation-observer/">Mutation Observer</a></li>
<li><a href="/docs/components/popover/">Popover</a></li>
<li><a href="/docs/components/popup/">Popup</a></li>
@@ -128,9 +146,9 @@
<!-- Style utilities -->
<wa-details appearance="outlined">
<h2 slot="summary">
<a href="/docs/utilities/" title="Overview">
Style Utilities
<a class="wa-cluster wa-gap-xs" href="/docs/utilities/" title="Overview">
<wa-icon name="grid-2" aria-hidden="true"></wa-icon>
Style Utilities
</a>
</h2>
<ul>
@@ -146,9 +164,9 @@
<!-- Layout -->
<wa-details appearance="outlined">
<h2 slot="summary">
<a href="/docs/layout/" title="Overview">
Layout
<a class="wa-cluster wa-gap-xs" href="/docs/layout/" title="Overview">
<wa-icon name="grid-2" aria-hidden="true"></wa-icon>
Layout
</a>
</h2>
<ul>
@@ -161,9 +179,12 @@
<li><a href="/docs/utilities/split/">Split</a></li>
<li><a href="/docs/utilities/stack/">Stack</a></li>
<li>
<a href="/docs/components/page/">Page</a>
<wa-icon name="flask" aria-hidden="true"></wa-icon>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
<span class="wa-split">
<a class="wa-cluster wa-gap-xs" href="/docs/components/page/">
Page <wa-icon name="flask" aria-hidden="true"></wa-icon>
</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
</span>
</li>
</ul>
</wa-details>
@@ -171,15 +192,17 @@
<!-- Patterns -->
<wa-details appearance="outlined">
<h2 slot="summary">
<a href="/docs/patterns/" title="Overview">
Patterns
<a class="wa-cluster wa-gap-xs" href="/docs/patterns/" title="Overview">
<wa-icon name="grid-2" aria-hidden="true"></wa-icon>
Patterns
</a>
</h2>
<ul>
<li>
<a href="/docs/patterns/app/">App</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
<span class="wa-split">
<a href="/docs/patterns/app/">App</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
</span>
<ul>
<li>
<a href="/docs/patterns/app/action-panel/">Action Panel</a>
@@ -210,6 +233,8 @@
</li>
<li>
<a href="/docs/patterns/app/pagination/">Pagination</a>
</li><li>
<a href="/docs/patterns/app/password/">Password</a>
</li>
<li>
<a href="/docs/patterns/app/permissions/">Permissions</a>
@@ -220,21 +245,35 @@
</ul>
</li>
<li>
<a href="/docs/patterns/blog-news/">Blog &amp; News</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
<span class="wa-split">
<a href="/docs/patterns/blog-news/">Blog &amp; News</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
</span>
<ul>
<li>
<a href="/docs/patterns/blog-news/banners/">Banners</a>
</li>
<li>
<a href="/docs/patterns/blog-news/call-to-action/">Call To Action</a>
</li>
<li>
<a href="/docs/patterns/blog-news/category-list/">Category List</a>
</li>
<li>
<a href="/docs/patterns/blog-news/contact/">Contact</a>
</li>
<li>
<a href="/docs/patterns/blog-news/featured-post/">Featured Post</a>
</li>
<li>
<a href="/docs/patterns/blog-news/footer/">Footer</a>
</li>
<li>
<a href="/docs/patterns/blog-news/grid-section/">Grid Section</a>
</li>
<li>
<a href="/docs/patterns/blog-news/header/">Header</a>
</li>
<li>
<a href="/docs/patterns/blog-news/newsletter/">Newsletter</a>
</li>
@@ -253,14 +292,25 @@
<li>
<a href="/docs/patterns/blog-news/login/">Sign Up &amp; Login</a>
</li>
<li>
<a href="/docs/patterns/blog-news/numbers/">Numbers</a>
</li>
<li>
<a href="/docs/patterns/blog-news/social-share/">Social Share</a>
</li>
<li>
<a href="/docs/patterns/blog-news/teams/">Teams</a>
</li>
<li>
<a href="/docs/patterns/blog-news/testimonials/">Testimonials</a>
</li>
</ul>
</li>
<li>
<a href="/docs/patterns/ecommerce/">Ecommerce</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
<span class="wa-split">
<a href="/docs/patterns/ecommerce/">Ecommerce</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
</span>
<ul>
<li>
<a href="/docs/patterns/ecommerce/category-filter/">Category Filter</a>
@@ -298,8 +348,10 @@
</ul>
</li>
<li>
<a href="/docs/patterns/layouts/">Layouts</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
<span class="wa-split">
<a href="/docs/patterns/layouts/">Layouts</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
</span>
<ul>
<li>
<a href="/docs/patterns/layouts/ecommerce/">Ecommerce</a>
@@ -321,17 +373,19 @@
<li><a href="/docs/color-palettes">Color Palettes</a></li>
<li><a href="/docs/themes">Themes</a></li>
<li>
<a href="/themer" data-turbo="false">Theme Builder</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
<span class="wa-split">
<a href="/themer" data-turbo="false">Theme Builder</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
</span>
</li>
</ul>
<!-- Design tokens -->
<wa-details appearance="outlined">
<h2 slot="summary">
<a href="/docs/tokens/" title="Overview">
Design Tokens
<a class="wa-cluster wa-gap-xs" href="/docs/tokens/" title="Overview">
<wa-icon name="grid-2" aria-hidden="true"></wa-icon>
Design Tokens
</a>
</h2>
<ul>

View File

@@ -1,4 +1,4 @@
<wa-select appearance="filled" size="small" value="default" pill class="theme-selector">
<wa-select appearance="filled" size="small" value="default" class="theme-selector">
<wa-icon slot="start" name="paintbrush" variant="regular"></wa-icon>
{# Free themes #}

View File

@@ -12,22 +12,18 @@
<th><code>brand</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge variant="brand" appearance="accent outlined">A+O</wa-badge>
<wa-badge variant="brand" appearance="accent">Accent</wa-badge>
<wa-badge variant="brand" appearance="filled outlined">F+O</wa-badge>
<wa-badge variant="brand" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge variant="brand" appearance="filled">Filled</wa-badge>
<wa-badge variant="brand" appearance="outlined">Outlined</wa-badge>
<wa-badge variant="brand" appearance="plain">Plain</wa-badge>
</div>
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge class="wa-brand" appearance="accent outlined">A+O</wa-badge>
<wa-badge class="wa-brand" appearance="accent">Accent</wa-badge>
<wa-badge class="wa-brand" appearance="filled outlined">F+O</wa-badge>
<wa-badge class="wa-brand" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge class="wa-brand" appearance="filled">Filled</wa-badge>
<wa-badge class="wa-brand" appearance="outlined">Outlined</wa-badge>
<wa-badge class="wa-brand" appearance="plain">Plain</wa-badge>
</div>
</td>
</tr>
@@ -35,22 +31,18 @@
<th><code>neutral</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge variant="neutral" appearance="accent outlined">A+O</wa-badge>
<wa-badge variant="neutral" appearance="accent">Accent</wa-badge>
<wa-badge variant="neutral" appearance="filled outlined">F+O</wa-badge>
<wa-badge variant="neutral" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge variant="neutral" appearance="filled">Filled</wa-badge>
<wa-badge variant="neutral" appearance="outlined">Outlined</wa-badge>
<wa-badge variant="neutral" appearance="plain">Plain</wa-badge>
</div>
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge class="wa-neutral" appearance="accent outlined">A+O</wa-badge>
<wa-badge class="wa-neutral" appearance="accent">Accent</wa-badge>
<wa-badge class="wa-neutral" appearance="filled outlined">F+O</wa-badge>
<wa-badge class="wa-neutral" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge class="wa-neutral" appearance="filled">Filled</wa-badge>
<wa-badge class="wa-neutral" appearance="outlined">Outlined</wa-badge>
<wa-badge class="wa-neutral" appearance="plain">Plain</wa-badge>
</div>
</td>
</tr>
@@ -58,22 +50,18 @@
<th><code>success</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge variant="success" appearance="accent outlined">A+O</wa-badge>
<wa-badge variant="success" appearance="accent">Accent</wa-badge>
<wa-badge variant="success" appearance="filled outlined">F+O</wa-badge>
<wa-badge variant="success" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge variant="success" appearance="filled">Filled</wa-badge>
<wa-badge variant="success" appearance="outlined">Outlined</wa-badge>
<wa-badge variant="success" appearance="plain">Plain</wa-badge>
</div>
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge class="wa-success" appearance="accent outlined">A+O</wa-badge>
<wa-badge class="wa-success" appearance="accent">Accent</wa-badge>
<wa-badge class="wa-success" appearance="filled outlined">F+O</wa-badge>
<wa-badge class="wa-success" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge class="wa-success" appearance="filled">Filled</wa-badge>
<wa-badge class="wa-success" appearance="outlined">Outlined</wa-badge>
<wa-badge class="wa-success" appearance="plain">Plain</wa-badge>
</div>
</td>
</tr>
@@ -81,22 +69,18 @@
<th><code>warning</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge variant="warning" appearance="accent outlined">A+O</wa-badge>
<wa-badge variant="warning" appearance="accent">Accent</wa-badge>
<wa-badge variant="warning" appearance="filled outlined">F+O</wa-badge>
<wa-badge variant="warning" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge variant="warning" appearance="filled">Filled</wa-badge>
<wa-badge variant="warning" appearance="outlined">Outlined</wa-badge>
<wa-badge variant="warning" appearance="plain">Plain</wa-badge>
</div>
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge class="wa-warning" appearance="accent outlined">A+O</wa-badge>
<wa-badge class="wa-warning" appearance="accent">Accent</wa-badge>
<wa-badge class="wa-warning" appearance="filled outlined">F+O</wa-badge>
<wa-badge class="wa-warning" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge class="wa-warning" appearance="filled">Filled</wa-badge>
<wa-badge class="wa-warning" appearance="outlined">Outlined</wa-badge>
<wa-badge class="wa-warning" appearance="plain">Plain</wa-badge>
</div>
</td>
</tr>
@@ -104,22 +88,18 @@
<th><code>danger</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge variant="danger" appearance="accent outlined">A+O</wa-badge>
<wa-badge variant="danger" appearance="accent">Accent</wa-badge>
<wa-badge variant="danger" appearance="filled outlined">F+O</wa-badge>
<wa-badge variant="danger" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge variant="danger" appearance="filled">Filled</wa-badge>
<wa-badge variant="danger" appearance="outlined">Outlined</wa-badge>
<wa-badge variant="danger" appearance="plain">Plain</wa-badge>
</div>
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-badge class="wa-danger" appearance="accent outlined">A+O</wa-badge>
<wa-badge class="wa-danger" appearance="accent">Accent</wa-badge>
<wa-badge class="wa-danger" appearance="filled outlined">F+O</wa-badge>
<wa-badge class="wa-danger" appearance="filled outlined">Filled + Outlined</wa-badge>
<wa-badge class="wa-danger" appearance="filled">Filled</wa-badge>
<wa-badge class="wa-danger" appearance="outlined">Outlined</wa-badge>
<wa-badge class="wa-danger" appearance="plain">Plain</wa-badge>
</div>
</td>
</tr>
@@ -142,9 +122,8 @@
<th><code>brand</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button variant="brand" appearance="accent outlined">A+O</wa-button>
<wa-button variant="brand" appearance="accent">Accent</wa-button>
<wa-button variant="brand" appearance="filled outlined">F+O</wa-button>
<wa-button variant="brand" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button variant="brand" appearance="filled">Filled</wa-button>
<wa-button variant="brand" appearance="outlined">Outlined</wa-button>
<wa-button variant="brand" appearance="plain">Plain</wa-button>
@@ -152,9 +131,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button class="wa-brand" appearance="accent outlined">A+O</wa-button>
<wa-button class="wa-brand" appearance="accent">Accent</wa-button>
<wa-button class="wa-brand" appearance="filled outlined">F+O</wa-button>
<wa-button class="wa-brand" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button class="wa-brand" appearance="filled">Filled</wa-button>
<wa-button class="wa-brand" appearance="outlined">Outlined</wa-button>
<wa-button class="wa-brand" appearance="plain">Plain</wa-button>
@@ -165,9 +143,8 @@
<th><code>neutral</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button variant="neutral" appearance="accent outlined">A+O</wa-button>
<wa-button variant="neutral" appearance="accent">Accent</wa-button>
<wa-button variant="neutral" appearance="filled outlined">F+O</wa-button>
<wa-button variant="neutral" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button variant="neutral" appearance="filled">Filled</wa-button>
<wa-button variant="neutral" appearance="outlined">Outlined</wa-button>
<wa-button variant="neutral" appearance="plain">Plain</wa-button>
@@ -175,9 +152,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button class="wa-neutral" appearance="accent outlined">A+O</wa-button>
<wa-button class="wa-neutral" appearance="accent">Accent</wa-button>
<wa-button class="wa-neutral" appearance="filled outlined">F+O</wa-button>
<wa-button class="wa-neutral" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button class="wa-neutral" appearance="filled">Filled</wa-button>
<wa-button class="wa-neutral" appearance="outlined">Outlined</wa-button>
<wa-button class="wa-neutral" appearance="plain">Plain</wa-button>
@@ -188,9 +164,8 @@
<th><code>success</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button variant="success" appearance="accent outlined">A+O</wa-button>
<wa-button variant="success" appearance="accent">Accent</wa-button>
<wa-button variant="success" appearance="filled outlined">F+O</wa-button>
<wa-button variant="success" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button variant="success" appearance="filled">Filled</wa-button>
<wa-button variant="success" appearance="outlined">Outlined</wa-button>
<wa-button variant="success" appearance="plain">Plain</wa-button>
@@ -198,9 +173,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button class="wa-success" appearance="accent outlined">A+O</wa-button>
<wa-button class="wa-success" appearance="accent">Accent</wa-button>
<wa-button class="wa-success" appearance="filled outlined">F+O</wa-button>
<wa-button class="wa-success" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button class="wa-success" appearance="filled">Filled</wa-button>
<wa-button class="wa-success" appearance="outlined">Outlined</wa-button>
<wa-button class="wa-success" appearance="plain">Plain</wa-button>
@@ -211,9 +185,8 @@
<th><code>warning</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button variant="warning" appearance="accent outlined">A+O</wa-button>
<wa-button variant="warning" appearance="accent">Accent</wa-button>
<wa-button variant="warning" appearance="filled outlined">F+O</wa-button>
<wa-button variant="warning" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button variant="warning" appearance="filled">Filled</wa-button>
<wa-button variant="warning" appearance="outlined">Outlined</wa-button>
<wa-button variant="warning" appearance="plain">Plain</wa-button>
@@ -221,9 +194,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button class="wa-warning" appearance="accent outlined">A+O</wa-button>
<wa-button class="wa-warning" appearance="accent">Accent</wa-button>
<wa-button class="wa-warning" appearance="filled outlined">F+O</wa-button>
<wa-button class="wa-warning" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button class="wa-warning" appearance="filled">Filled</wa-button>
<wa-button class="wa-warning" appearance="outlined">Outlined</wa-button>
<wa-button class="wa-warning" appearance="plain">Plain</wa-button>
@@ -234,9 +206,8 @@
<th><code>danger</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button variant="danger" appearance="accent outlined">A+O</wa-button>
<wa-button variant="danger" appearance="accent">Accent</wa-button>
<wa-button variant="danger" appearance="filled outlined">F+O</wa-button>
<wa-button variant="danger" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button variant="danger" appearance="filled">Filled</wa-button>
<wa-button variant="danger" appearance="outlined">Outlined</wa-button>
<wa-button variant="danger" appearance="plain">Plain</wa-button>
@@ -244,9 +215,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-button class="wa-danger" appearance="accent outlined">A+O</wa-button>
<wa-button class="wa-danger" appearance="accent">Accent</wa-button>
<wa-button class="wa-danger" appearance="filled outlined">F+O</wa-button>
<wa-button class="wa-danger" appearance="filled outlined">Filled + Outlined</wa-button>
<wa-button class="wa-danger" appearance="filled">Filled</wa-button>
<wa-button class="wa-danger" appearance="outlined">Outlined</wa-button>
<wa-button class="wa-danger" appearance="plain">Plain</wa-button>
@@ -272,17 +242,13 @@
<th><code>brand</code></th>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout variant="brand" appearance="accent outlined">
<wa-icon slot="icon" name="circle-star"></wa-icon>
A+O
</wa-callout>
<wa-callout variant="brand" appearance="accent">
<wa-icon slot="icon" name="circle-star"></wa-icon>
Accent
</wa-callout>
<wa-callout variant="brand" appearance="filled outlined">
<wa-icon slot="icon" name="circle-star"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout variant="brand" appearance="filled">
<wa-icon slot="icon" name="circle-star"></wa-icon>
@@ -300,17 +266,13 @@
</td>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout class="wa-brand" appearance="accent outlined">
<wa-icon slot="icon" name="circle-star"></wa-icon>
A+O
</wa-callout>
<wa-callout class="wa-brand" appearance="accent">
<wa-icon slot="icon" name="circle-star"></wa-icon>
Accent
</wa-callout>
<wa-callout class="wa-brand" appearance="filled outlined">
<wa-icon slot="icon" name="circle-star"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout class="wa-brand" appearance="filled">
<wa-icon slot="icon" name="circle-star"></wa-icon>
@@ -331,17 +293,13 @@
<th><code>neutral</code></th>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout variant="neutral" appearance="accent outlined">
<wa-icon slot="icon" name="circle-info"></wa-icon>
A+O
</wa-callout>
<wa-callout variant="neutral" appearance="accent">
<wa-icon slot="icon" name="circle-info"></wa-icon>
Accent
</wa-callout>
<wa-callout variant="neutral" appearance="filled outlined">
<wa-icon slot="icon" name="circle-info"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout variant="neutral" appearance="filled">
<wa-icon slot="icon" name="circle-info"></wa-icon>
@@ -359,17 +317,13 @@
</td>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout class="wa-neutral" appearance="accent outlined">
<wa-icon slot="icon" name="circle-info"></wa-icon>
A+O
</wa-callout>
<wa-callout class="wa-neutral" appearance="accent">
<wa-icon slot="icon" name="circle-info"></wa-icon>
Accent
</wa-callout>
<wa-callout class="wa-neutral" appearance="filled outlined">
<wa-icon slot="icon" name="circle-info"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout class="wa-neutral" appearance="filled">
<wa-icon slot="icon" name="circle-info"></wa-icon>
@@ -390,17 +344,13 @@
<th><code>success</code></th>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout variant="success" appearance="accent outlined">
<wa-icon slot="icon" name="circle-check"></wa-icon>
A+O
</wa-callout>
<wa-callout variant="success" appearance="accent">
<wa-icon slot="icon" name="circle-check"></wa-icon>
Accent
</wa-callout>
<wa-callout variant="success" appearance="filled outlined">
<wa-icon slot="icon" name="circle-check"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout variant="success" appearance="filled">
<wa-icon slot="icon" name="circle-check"></wa-icon>
@@ -418,17 +368,13 @@
</td>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout class="wa-success" appearance="accent outlined">
<wa-icon slot="icon" name="circle-check"></wa-icon>
A+O
</wa-callout>
<wa-callout class="wa-success" appearance="accent">
<wa-icon slot="icon" name="circle-check"></wa-icon>
Accent
</wa-callout>
<wa-callout class="wa-success" appearance="filled outlined">
<wa-icon slot="icon" name="circle-check"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout class="wa-success" appearance="filled">
<wa-icon slot="icon" name="circle-check"></wa-icon>
@@ -449,17 +395,13 @@
<th><code>warning</code></th>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout variant="warning" appearance="accent outlined">
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
A+O
</wa-callout>
<wa-callout variant="warning" appearance="accent">
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
Accent
</wa-callout>
<wa-callout variant="warning" appearance="filled outlined">
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout variant="warning" appearance="filled">
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
@@ -477,17 +419,13 @@
</td>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout class="wa-warning" appearance="accent outlined">
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
A+O
</wa-callout>
<wa-callout class="wa-warning" appearance="accent">
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
Accent
</wa-callout>
<wa-callout class="wa-warning" appearance="filled outlined">
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout class="wa-warning" appearance="filled">
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
@@ -508,17 +446,13 @@
<th><code>danger</code></th>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout variant="danger" appearance="accent outlined">
<wa-icon slot="icon" name="circle-xmark"></wa-icon>
A+O
</wa-callout>
<wa-callout variant="danger" appearance="accent">
<wa-icon slot="icon" name="circle-xmark"></wa-icon>
Accent
</wa-callout>
<wa-callout variant="danger" appearance="filled outlined">
<wa-icon slot="icon" name="circle-xmark"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout variant="danger" appearance="filled">
<wa-icon slot="icon" name="circle-xmark"></wa-icon>
@@ -536,17 +470,13 @@
</td>
<td>
<div class="wa-grid wa-gap-2xs">
<wa-callout class="wa-danger" appearance="accent outlined">
<wa-icon slot="icon" name="circle-xmark"></wa-icon>
A+O
</wa-callout>
<wa-callout class="wa-danger" appearance="accent">
<wa-icon slot="icon" name="circle-xmark"></wa-icon>
Accent
</wa-callout>
<wa-callout class="wa-danger" appearance="filled outlined">
<wa-icon slot="icon" name="circle-xmark"></wa-icon>
F+O
Filled + Outlined
</wa-callout>
<wa-callout class="wa-danger" appearance="filled">
<wa-icon slot="icon" name="circle-xmark"></wa-icon>
@@ -582,9 +512,8 @@
<th><code>brand</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag variant="brand" appearance="accent outlined">A+O</wa-tag>
<wa-tag variant="brand" appearance="accent">Accent</wa-tag>
<wa-tag variant="brand" appearance="filled outlined">F+O</wa-tag>
<wa-tag variant="brand" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="brand" appearance="filled">Filled</wa-tag>
<wa-tag variant="brand" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="brand" appearance="plain">Plain</wa-tag>
@@ -592,9 +521,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag class="wa-brand" appearance="accent outlined">A+O</wa-tag>
<wa-tag class="wa-brand" appearance="accent">Accent</wa-tag>
<wa-tag class="wa-brand" appearance="filled outlined">F+O</wa-tag>
<wa-tag class="wa-brand" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag class="wa-brand" appearance="filled">Filled</wa-tag>
<wa-tag class="wa-brand" appearance="outlined">Outlined</wa-tag>
<wa-tag class="wa-brand" appearance="plain">Plain</wa-tag>
@@ -605,9 +533,8 @@
<th><code>neutral</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag variant="neutral" appearance="accent outlined">A+O</wa-tag>
<wa-tag variant="neutral" appearance="accent">Accent</wa-tag>
<wa-tag variant="neutral" appearance="filled outlined">F+O</wa-tag>
<wa-tag variant="neutral" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="neutral" appearance="filled">Filled</wa-tag>
<wa-tag variant="neutral" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="neutral" appearance="plain">Plain</wa-tag>
@@ -615,9 +542,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag class="wa-neutral" appearance="accent outlined">A+O</wa-tag>
<wa-tag class="wa-neutral" appearance="accent">Accent</wa-tag>
<wa-tag class="wa-neutral" appearance="filled outlined">F+O</wa-tag>
<wa-tag class="wa-neutral" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag class="wa-neutral" appearance="filled">Filled</wa-tag>
<wa-tag class="wa-neutral" appearance="outlined">Outlined</wa-tag>
<wa-tag class="wa-neutral" appearance="plain">Plain</wa-tag>
@@ -628,9 +554,8 @@
<th><code>success</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag variant="success" appearance="accent outlined">A+O</wa-tag>
<wa-tag variant="success" appearance="accent">Accent</wa-tag>
<wa-tag variant="success" appearance="filled outlined">F+O</wa-tag>
<wa-tag variant="success" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="success" appearance="filled">Filled</wa-tag>
<wa-tag variant="success" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="success" appearance="plain">Plain</wa-tag>
@@ -638,9 +563,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag class="wa-success" appearance="accent outlined">A+O</wa-tag>
<wa-tag class="wa-success" appearance="accent">Accent</wa-tag>
<wa-tag class="wa-success" appearance="filled outlined">F+O</wa-tag>
<wa-tag class="wa-success" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag class="wa-success" appearance="filled">Filled</wa-tag>
<wa-tag class="wa-success" appearance="outlined">Outlined</wa-tag>
<wa-tag class="wa-success" appearance="plain">Plain</wa-tag>
@@ -651,9 +575,8 @@
<th><code>warning</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag variant="warning" appearance="accent outlined">A+O</wa-tag>
<wa-tag variant="warning" appearance="accent">Accent</wa-tag>
<wa-tag variant="warning" appearance="filled outlined">F+O</wa-tag>
<wa-tag variant="warning" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="warning" appearance="filled">Filled</wa-tag>
<wa-tag variant="warning" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="warning" appearance="plain">Plain</wa-tag>
@@ -661,9 +584,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag class="wa-warning" appearance="accent outlined">A+O</wa-tag>
<wa-tag class="wa-warning" appearance="accent">Accent</wa-tag>
<wa-tag class="wa-warning" appearance="filled outlined">F+O</wa-tag>
<wa-tag class="wa-warning" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag class="wa-warning" appearance="filled">Filled</wa-tag>
<wa-tag class="wa-warning" appearance="outlined">Outlined</wa-tag>
<wa-tag class="wa-warning" appearance="plain">Plain</wa-tag>
@@ -674,9 +596,8 @@
<th><code>danger</code></th>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag variant="danger" appearance="accent outlined">A+O</wa-tag>
<wa-tag variant="danger" appearance="accent">Accent</wa-tag>
<wa-tag variant="danger" appearance="filled outlined">F+O</wa-tag>
<wa-tag variant="danger" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="danger" appearance="filled">Filled</wa-tag>
<wa-tag variant="danger" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="danger" appearance="plain">Plain</wa-tag>
@@ -684,9 +605,8 @@
</td>
<td>
<div class="wa-cluster wa-gap-2xs">
<wa-tag class="wa-danger" appearance="accent outlined">A+O</wa-tag>
<wa-tag class="wa-danger" appearance="accent">Accent</wa-tag>
<wa-tag class="wa-danger" appearance="filled outlined">F+O</wa-tag>
<wa-tag class="wa-danger" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag class="wa-danger" appearance="filled">Filled</wa-tag>
<wa-tag class="wa-danger" appearance="outlined">Outlined</wa-tag>
<wa-tag class="wa-danger" appearance="plain">Plain</wa-tag>
@@ -695,4 +615,4 @@
</tr>
</tbody>
</table>
</div>
</div>

View File

@@ -40,66 +40,6 @@
</div>
<wa-divider></wa-divider>
<h3>Button Group</h3>
<div class="table-scroll">
<table>
<thead>
<th></th>
<th><code>size=""</code></th>
<th><code>.wa-size-[s|m|l]</code></th>
</thead>
<tbody>
<tr>
<th><code>small</code>/<code>s</code></th>
<td>
<wa-button-group orientation="horizontal" size="small">
<wa-button value="1">Button L</wa-button>
<wa-button value="2">Button R</wa-button>
</wa-button-group>
</td>
<td>
<wa-button-group orientation="horizontal" class="wa-size-s">
<wa-button value="1">Button L</wa-button>
<wa-button value="2">Button R</wa-button>
</wa-button-group>
</td>
</tr>
<tr>
<th><code>medium</code>/<code>m</code></th>
<td>
<wa-button-group orientation="horizontal" size="medium">
<wa-button value="1">Button L</wa-button>
<wa-button value="2">Button R</wa-button>
</wa-button-group>
</td>
<td>
<wa-button-group orientation="horizontal" class="wa-size-m">
<wa-button value="1">Button L</wa-button>
<wa-button value="2">Button R</wa-button>
</wa-button-group>
</td>
</tr>
<tr>
<th><code>large</code>/<code>l</code></th>
<td>
<wa-button-group orientation="horizontal" size="large">
<wa-button value="1">Button L</wa-button>
<wa-button value="2">Button R</wa-button>
</wa-button-group>
</td>
<td>
<wa-button-group orientation="horizontal" class="wa-size-l">
<wa-button value="1">Button L</wa-button>
<wa-button value="2">Button R</wa-button>
</wa-button-group>
</td>
</tr>
</tbody>
</table>
</div>
<wa-divider></wa-divider>
<h3>Callout</h3>
<div class="table-scroll">

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" data-fa-kit-code="b10bfbde90" data-cdn-url="{% cdnUrl %}">
<html lang="en" data-fa-kit-code="38c11e3f20" data-cdn-url="{% cdnUrl %}">
<head>
{% include 'head.njk' %}
{% block head %}{% endblock %}

View File

@@ -26,7 +26,7 @@
<p>Learn more about <a href="/docs/usage/#slots">using slots</a>.</p>
<wa-scroller>
<table class="component-table">
<table class="component-table wa-hover-rows">
<thead>
<tr>
<th class="table-name">Name</th>
@@ -57,7 +57,7 @@
<p>Learn more about <a href="/docs/usage/#attributes-and-properties">attributes and properties</a>.</p>
<wa-scroller>
<table class="component-table">
<table class="component-table wa-hover-rows">
<thead>
<tr>
<th class="table-name">Name</th>
@@ -104,7 +104,7 @@
<p>Learn more about <a href="/docs/usage/#methods">methods</a>.</p>
<wa-scroller>
<table class="component-table">
<table class="component-table wa-hover-rows">
<thead>
<tr>
<th class="table-name">Name</th>
@@ -139,7 +139,7 @@
<p>Learn more about <a href="/docs/usage/#events">events</a>.</p>
<wa-scroller>
<table class="component-table">
<table class="component-table wa-hover-rows">
<thead>
<tr>
<th class="table-name">Name</th>
@@ -166,7 +166,7 @@
<p>Learn more about <a href="/docs/customizing/#custom-properties">CSS custom properties</a>.</p>
<wa-scroller>
<table class="component-table">
<table class="component-table wa-hover-rows">
<thead>
<tr>
<th class="table-name">Name</th>
@@ -198,7 +198,7 @@
<p>Learn more about <a href="/docs/customizing/#custom-states">custom states</a>.</p>
<wa-scroller>
<table class="component-table">
<table class="component-table wa-hover-rows">
<thead>
<tr>
<th class="table-name">Name</th>
@@ -225,7 +225,7 @@
<p>Learn more about <a href="/docs/customizing/#css-parts">CSS parts</a>.</p>
<wa-scroller>
<table class="component-table">
<table class="component-table wa-hover-rows">
<thead>
<tr>
<th class="table-name">Name</th>
@@ -264,6 +264,9 @@
The <a href="/docs/#quick-start-autoloading-via-cdn">autoloader</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>
@@ -272,19 +275,20 @@
<p>
To manually import this component from the CDN, use the following code.
</p>
<pre><code class="language-js">import '{% cdnUrl component.path %}';</code></pre>
<pre><code class="language-js">import '{% cdnUrl componentPath %}';</code></pre>
</wa-tab-panel>
<wa-tab-panel name="npm">
Coming soon!
<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">
Coming soon!
{# NOTE - disabled for alpha/beta
<p>
To manually import this component from React, use the following code.
</p>
<pre><code class="language-js">import '@shoelace-style/webawesome/react/{{ component.tagName | stripPrefix }}';</code></pre>
#}
<pre><code class="language-js">import {{ component.name }} from '@awesome.me/webawesome/dist/react/{{ componentName }}';</code></pre>
</wa-tab-panel>
</wa-tab-group>

View File

@@ -0,0 +1,8 @@
{% set hasSidebar = true %}
{% set hasOutline = true %}
{% set section = 'docs' %}
{% block beforeContent %}
<p>{{ description }}</p>
{% endblock %}
{% extends "../_includes/base.njk" %}

View File

@@ -1,4 +1,5 @@
/* eslint-disable no-invalid-this */
import { readFileSync } from 'fs';
import { mkdir, writeFile } from 'fs/promises';
import lunr from 'lunr';
import { parse } from 'node-html-parser';
@@ -23,19 +24,22 @@ export function searchPlugin(options = {}) {
...options,
};
// Hoist above so that it can "cache" properly for incremental builds.
return function (eleventyConfig) {
const pagesToIndex = new Map();
let pagesToIndex = new Map();
eleventyConfig.addPreprocessor('exclude-unlisted-from-search', '*', function (data, content) {
if (data.unlisted) {
// no-op
pagesToIndex.delete(data.page.inputPath);
} else {
pagesToIndex.set(data.page.inputPath, {});
pagesToIndex.set(data.page.inputPath, true);
}
return content;
});
// With incremental builds we need this to be last in case stuff was added from metadata. _BUT_ in incremental builds, not every page is added to the "transform".
eleventyConfig.addTransform('search', function (content) {
if (!pagesToIndex.has(this.page.inputPath)) {
return content;
@@ -67,11 +71,30 @@ export function searchPlugin(options = {}) {
return content;
});
eleventyConfig.on('eleventy.after', ({ directories }) => {
eleventyConfig.on('eleventy.after', async ({ directories }) => {
const { output } = directories;
const outputFilename = path.resolve(join(output, 'search.json'));
const cachedPages = path.resolve(join(output, 'cached_pages.json'));
function getCachedPages() {
let content = { pages: [] };
try {
content = JSON.parse(readFileSync(cachedPages));
} catch (e) {}
const cachedPagesMap = new Map(content.pages);
for (const [key, value] of cachedPagesMap.entries()) {
// A page uses a cached value if `true` and it didnt get its value set in the "transform" hook. This is to get around the limitation of incremental builds not going over every file in transform.
if (pagesToIndex.get(key) === true) {
pagesToIndex.set(key, value);
}
}
}
const map = [];
const searchIndex = lunr(async function () {
getCachedPages();
const searchIndex = lunr(function () {
let index = 0;
this.ref('id');
@@ -84,9 +107,11 @@ export function searchPlugin(options = {}) {
map[index] = { title: page.title, description: page.description, url: page.url };
index++;
}
await mkdir(dirname(outputFilename), { recursive: true });
await writeFile(outputFilename, JSON.stringify({ searchIndex, map }), 'utf-8');
});
await mkdir(dirname(outputFilename), { recursive: true });
await writeFile(outputFilename, JSON.stringify({ searchIndex, map }), 'utf-8');
await writeFile(cachedPages, JSON.stringify({ pages: [...pagesToIndex.entries()] }, null, 2));
});
};
}

View File

@@ -0,0 +1,81 @@
import { parse } from 'node-html-parser';
import slugify from 'slugify';
import { v4 as uuid } from 'uuid';
function createId(text) {
let slug = slugify(String(text), {
remove: /[^\w|\s]/g,
lower: true,
});
// ids must start with a letter
if (!/^[a-z]/i.test(slug)) {
slug = `wa_${slug}`;
}
return slug;
}
/**
* Eleventy plugin to add anchors to headings to content.
*/
export function anchorHeadingsTransformer(options = {}) {
options = {
container: 'body',
headingSelector: 'h2, h3, h4, h5, h6',
anchorLabel: 'Jump to heading',
...options,
};
/** doc is a parsed HTML document */
return function (doc) {
const container = doc.querySelector(options.container);
if (!container) {
return doc;
}
// Look for headings
let selector = `:is(${options.headingSelector}):not([data-no-anchor], [data-no-anchor] *)`;
container.querySelectorAll(selector).forEach(heading => {
const hasAnchor = heading.querySelector('a');
const existingId = heading.getAttribute('id');
const clone = parse(heading.outerHTML);
// Create a clone of the heading so we can remove [data-no-anchor] elements from the text content
clone.querySelectorAll('[data-no-anchor]').forEach(el => el.remove());
if (hasAnchor) {
return;
}
let id = existingId;
if (!id) {
const slug = createId(clone.textContent ?? '') ?? uuid().slice(-12);
id = slug;
let suffix = 1;
// Make sure the slug is unique in the document
while (doc.getElementById(id) !== null) {
id = `${slug}-${++suffix}`;
}
}
// Create the anchor
const anchor = parse(`
<a href="#${encodeURIComponent(id)}">
<span class="wa-visually-hidden"></span>
<span aria-hidden="true">#</span>
</a>
`);
anchor.querySelector('.wa-visually-hidden').textContent = options.anchorLabel;
// Update the heading
if (!existingId) {
heading.setAttribute('id', id);
}
heading.classList.add('anchor-heading');
heading.appendChild(anchor);
});
};
}

View File

@@ -1,43 +1,51 @@
import { parse } from 'node-html-parser';
import { v4 as uuid } from 'uuid';
import { markdown } from '../_utils/markdown.js';
import { copyCode } from './copy-code.js';
import { highlightCode } from './highlight-code.js';
/**
* Eleventy plugin to turn `<code class="example">` blocks into live examples.
*/
export function codeExamplesPlugin(options = {}) {
export function codeExamplesTransformer(options = {}) {
options = {
container: 'body',
...options,
};
return function (eleventyConfig) {
eleventyConfig.addTransform('code-examples', content => {
const doc = parse(content, { blockTextElements: { code: true } });
const container = doc.querySelector(options.container);
return function (doc) {
const container = doc.querySelector(options.container);
if (!container) {
return content;
}
if (!container) {
return;
}
// Look for external links
container.querySelectorAll('code.example').forEach(code => {
const pre = code.closest('pre');
const hasButtons = !code.classList.contains('no-buttons');
const isOpen = code.classList.contains('open') || !hasButtons;
const noEdit = code.classList.contains('no-edit');
const id = `code-example-${uuid().slice(-12)}`;
let preview = pre.textContent;
// Look for external links
container.querySelectorAll('code.example').forEach(code => {
let pre = code.closest('pre');
const hasButtons = !code.classList.contains('no-buttons');
const isOpen = code.classList.contains('open') || !hasButtons;
const noEdit = code.classList.contains('no-edit');
const id = `code-example-${uuid().slice(-12)}`;
let preview = pre.textContent;
// Run preview scripts as modules to prevent collisions
const root = parse(preview, { blockTextElements: { script: true } });
root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module'));
preview = root.toString();
const langClass = [...code.classList.values()].find(val => val.startsWith('language-'));
const lang = langClass ? langClass.replace(/^language-/, '') : 'plain';
const codeExample = parse(`
code.innerHTML = highlightCode(code.textContent ?? '', lang);
// Run preview scripts as modules to prevent collisions
const root = parse(preview, { blockTextElements: { script: true } });
root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module'));
preview = root.toString();
copyCode(code);
const codeExample = parse(`
<div class="code-example ${isOpen ? 'open' : ''}">
<div class="code-example-preview">
${preview}
<div>
${preview}
</div>
<div class="code-example-resizer" aria-hidden="true">
<wa-icon name="grip-lines-vertical"></wa-icon>
</div>
@@ -77,10 +85,7 @@ export function codeExamplesPlugin(options = {}) {
</div>
`);
pre.replaceWith(codeExample);
});
return doc.toString();
pre.replaceWith(codeExample);
});
};
}

View File

@@ -0,0 +1,38 @@
export function copyCode(code) {
const pre = code.closest('pre');
let preId = pre.getAttribute('id') || `code-block-${crypto.randomUUID()}`;
let codeId = code.getAttribute('id') || `${preId}-inner`;
if (!code.getAttribute('id')) {
code.setAttribute('id', codeId);
}
if (!pre.getAttribute('id')) {
pre.setAttribute('id', preId);
}
// Add a copy button
pre.innerHTML += `<wa-copy-button from="${codeId}" class="copy-button wa-dark"></wa-copy-button>`;
}
/**
* Eleventy plugin to add copy buttons to code blocks.
*/
export function copyCodeTransformer(options = {}) {
options = {
container: 'body',
...options,
};
return function (doc) {
const container = doc.querySelector(options.container);
if (!container) {
return;
}
// Look for code blocks
container.querySelectorAll('pre > code').forEach(code => {
copyCode(code);
});
};
}

View File

@@ -24,30 +24,25 @@ function normalize(pathname) {
/**
* Eleventy plugin to decorate current links with a custom class.
*/
export function currentLink(options = {}) {
export function currentLinkTransformer(options = {}) {
options = {
container: 'body',
className: 'current',
...options,
};
return function (eleventyConfig) {
eleventyConfig.addTransform('current-link', function (content) {
const doc = parse(content);
const container = doc.querySelector(options.container);
return function (doc) {
const container = doc.querySelector(options.container);
if (!container) {
return content;
if (!container) {
return;
}
// Compare the href attribute to 11ty's page URL
container.querySelectorAll('a[href]').forEach(a => {
if (normalize(a.getAttribute('href')) === normalize(this.page.url)) {
a.classList.add(options.className);
}
// Compare the href attribute to 11ty's page URL
container.querySelectorAll('a[href]').forEach(a => {
if (normalize(a.getAttribute('href')) === normalize(this.page.url)) {
a.classList.add(options.className);
}
});
return doc.toString();
});
};
}

View File

@@ -37,36 +37,31 @@ export function highlightCode(code, language = 'plain') {
* Eleventy plugin to highlight code blocks with the `language-*` attribute using Prism.js. Unlike most plugins, this
* works on the entire document not just markdown content.
*/
export function highlightCodePlugin(options = {}) {
export function highlightCodeTransformer(options = {}) {
options = {
container: 'body',
...options,
};
return function (eleventyConfig) {
eleventyConfig.addTransform('highlight-code', content => {
const doc = parse(content, { blockTextElements: { code: true } });
const container = doc.querySelector(options.container);
return function (doc) {
const container = doc.querySelector(options.container);
if (!container) {
return content;
}
if (!container) {
return;
}
// Look for <code class="language-*"> and highlight each one
container.querySelectorAll('code[class*="language-"]').forEach(code => {
const langClass = [...code.classList.values()].find(val => val.startsWith('language-'));
const lang = langClass ? langClass.replace(/^language-/, '') : 'plain';
// Look for <code class="language-*"> and highlight each one
container.querySelectorAll('code[class*="language-"]').forEach(code => {
const langClass = [...code.classList.values()].find(val => val.startsWith('language-'));
const lang = langClass ? langClass.replace(/^language-/, '') : 'plain';
try {
code.innerHTML = highlightCode(code.textContent ?? '', lang);
} catch (err) {
if (!options.ignoreMissingLangs) {
throw new Error(err.message);
}
try {
code.innerHTML = highlightCode(code.textContent ?? '', lang);
} catch (err) {
if (!options.ignoreMissingLangs) {
throw new Error(err.message);
}
});
return doc.toString();
}
});
};
}

View File

@@ -0,0 +1,64 @@
import { parse } from 'node-html-parser';
/**
* Eleventy plugin to add an outline (table of contents) to the page. Headings must have an id, otherwise they won't be
* included in the outline. An unordered list containing links will be appended to the target element.
*
* If no headings are found for the outline, the `ifEmpty()` function will be called with a `node-html-parser` object as
* the first argument. This can be used to toggle classes or remove elements when the outline is empty.
*
* See the `node-html-parser` docs for more details: https://www.npmjs.com/package/node-html-parser
*/
export function outlineTransformer(options = {}) {
options = {
container: 'body',
target: '.outline',
selector: 'h2,h3',
ifEmpty: () => null,
...options,
};
return function (doc) {
const container = doc.querySelector(options.container);
const ul = parse('<ul></ul>');
let numLinks = 0;
if (!container) {
return;
}
container.querySelectorAll(options.selector).forEach(heading => {
const id = heading.getAttribute('id');
const level = heading.tagName.slice(1);
const clone = parse(heading.outerHTML);
if (heading.closest('[data-no-outline]')) {
return;
}
// Create a clone of the heading so we can remove links and [data-no-outline] elements from the text content
clone.querySelectorAll('.wa-visually-hidden, [hidden], [aria-hidden="true"]').forEach(el => el.remove());
clone.querySelectorAll('[data-no-outline]').forEach(el => el.remove());
// Generate the link
const li = parse(`<li data-level="${level}"><a></a></li>`);
const a = li.querySelector('a');
a.setAttribute('href', `#${encodeURIComponent(id)}`);
a.textContent = clone.textContent.trim().replace(/#$/, '');
// Add it to the list
ul.firstChild.appendChild(li);
numLinks++;
});
if (numLinks > 0) {
// Append the list to all matching targets
doc.querySelectorAll(options.target).forEach(target => {
target.appendChild(parse(ul.outerHTML));
});
} else {
// Remove if empty
options.ifEmpty(doc);
}
};
}

View File

@@ -1,85 +0,0 @@
import { parse } from 'node-html-parser';
import slugify from 'slugify';
import { v4 as uuid } from 'uuid';
function createId(text) {
let slug = slugify(String(text), {
remove: /[^\w|\s]/g,
lower: true,
});
// ids must start with a letter
if (!/^[a-z]/i.test(slug)) {
slug = `wa_${slug}`;
}
return slug;
}
/**
* Eleventy plugin to add anchors to headings to content.
*/
export function anchorHeadingsPlugin(options = {}) {
options = {
container: 'body',
headingSelector: 'h2, h3, h4, h5, h6',
anchorLabel: 'Jump to heading',
...options,
};
return function (eleventyConfig) {
eleventyConfig.addTransform('anchor-headings', content => {
const doc = parse(content);
const container = doc.querySelector(options.container);
if (!container) {
return content;
}
// Look for headings
let selector = `:is(${options.headingSelector}):not([data-no-anchor], [data-no-anchor] *)`;
container.querySelectorAll(selector).forEach(heading => {
const hasAnchor = heading.querySelector('a');
const existingId = heading.getAttribute('id');
const clone = parse(heading.outerHTML);
// Create a clone of the heading so we can remove [data-no-anchor] elements from the text content
clone.querySelectorAll('[data-no-anchor]').forEach(el => el.remove());
if (hasAnchor) {
return;
}
let id = existingId;
if (!id) {
const slug = createId(clone.textContent ?? '') ?? uuid().slice(-12);
id = slug;
let suffix = 1;
// Make sure the slug is unique in the document
while (doc.getElementById(id) !== null) {
id = `${slug}-${++suffix}`;
}
}
// Create the anchor
const anchor = parse(`
<a href="#${encodeURIComponent(id)}">
<span class="wa-visually-hidden"></span>
<span aria-hidden="true">#</span>
</a>
`);
anchor.querySelector('.wa-visually-hidden').textContent = options.anchorLabel;
// Update the heading
if (!existingId) {
heading.setAttribute('id', id);
}
heading.classList.add('anchor-heading');
heading.appendChild(anchor);
});
return doc.toString();
});
};
}

View File

@@ -1,41 +0,0 @@
import { parse } from 'node-html-parser';
/**
* Eleventy plugin to add copy buttons to code blocks.
*/
export function copyCodePlugin(eleventyConfig, options = {}) {
options = {
container: 'body',
...options,
};
let codeCount = 0;
eleventyConfig.addTransform('copy-code', content => {
const doc = parse(content, { blockTextElements: { code: true } });
const container = doc.querySelector(options.container);
if (!container) {
return content;
}
// Look for code blocks
container.querySelectorAll('pre > code').forEach(code => {
const pre = code.closest('pre');
let preId = pre.getAttribute('id') || `code-block-${++codeCount}`;
let codeId = code.getAttribute('id') || `${preId}-inner`;
if (!code.getAttribute('id')) {
code.setAttribute('id', codeId);
}
if (!pre.getAttribute('id')) {
pre.setAttribute('id', preId);
}
// Add a copy button
pre.innerHTML += `<wa-button href="#${preId}" class="block-link-icon" appearance="plain" size="small"><wa-icon name="link" label="Copy link"></wa-icon></wa-button>
<wa-copy-button from="${codeId}" class="copy-button"></wa-copy-button>`;
});
return doc.toString();
});
}

View File

@@ -1,69 +0,0 @@
import { parse } from 'node-html-parser';
/**
* Eleventy plugin to add an outline (table of contents) to the page. Headings must have an id, otherwise they won't be
* included in the outline. An unordered list containing links will be appended to the target element.
*
* If no headings are found for the outline, the `ifEmpty()` function will be called with a `node-html-parser` object as
* the first argument. This can be used to toggle classes or remove elements when the outline is empty.
*
* See the `node-html-parser` docs for more details: https://www.npmjs.com/package/node-html-parser
*/
export function outlinePlugin(options = {}) {
options = {
container: 'body',
target: '.outline',
selector: 'h2,h3',
ifEmpty: () => null,
...options,
};
return function (eleventyConfig) {
eleventyConfig.addTransform('outline', content => {
const doc = parse(content);
const container = doc.querySelector(options.container);
const ul = parse('<ul></ul>');
let numLinks = 0;
if (!container) {
return content;
}
container.querySelectorAll(options.selector).forEach(heading => {
const id = heading.getAttribute('id');
const level = heading.tagName.slice(1);
const clone = parse(heading.outerHTML);
if (heading.closest('[data-no-outline]')) {
return;
}
// Create a clone of the heading so we can remove links and [data-no-outline] elements from the text content
clone.querySelectorAll('.wa-visually-hidden, [hidden], [aria-hidden="true"]').forEach(el => el.remove());
clone.querySelectorAll('[data-no-outline]').forEach(el => el.remove());
// Generate the link
const li = parse(`<li data-level="${level}"><a></a></li>`);
const a = li.querySelector('a');
a.setAttribute('href', `#${encodeURIComponent(id)}`);
a.textContent = clone.textContent.trim().replace(/#$/, '');
// Add it to the list
ul.firstChild.appendChild(li);
numLinks++;
});
if (numLinks > 0) {
// Append the list to all matching targets
doc.querySelectorAll(options.target).forEach(target => {
target.appendChild(parse(ul.outerHTML));
});
} else {
// Remove if empty
options.ifEmpty(doc);
}
return doc.toString();
});
};
}

View File

@@ -0,0 +1,18 @@
import nunjucks from 'nunjucks';
/**
* This function simulates what a server would do running "on top" of eleventy.
*/
export function SimulateWebAwesomeApp(str) {
return nunjucks.renderString(str, {
// Stub the server EJS shortcodes.
currentUser: {
hasPro: false,
},
server: {
head: '',
loginOrAvatar: '',
flashes: '',
},
});
}

View File

@@ -56,10 +56,8 @@ document.addEventListener('click', event => {
const code = codeExample.querySelector('code');
const cdnUrl = document.documentElement.dataset.cdnUrl;
const html =
`<script data-fa-kit-code="b10bfbde90" type="module" src="${cdnUrl}webawesome.loader.js"></script>\n` +
`<link rel="stylesheet" href="${cdnUrl}styles/themes/default.css">\n` +
`<link rel="stylesheet" href="${cdnUrl}styles/webawesome.css">\n` +
`<link rel="stylesheet" href="${cdnUrl}styles/utilities.css">\n\n` +
`<script data-fa-kit-code="38c11e3f20" type="module" src="${cdnUrl}webawesome.loader.js"></script>\n` +
`<link rel="stylesheet" href="${cdnUrl}styles/webawesome.css">\n\n` +
`${code.textContent}`;
const css = 'html > body {\n padding: 2rem !important;\n}';
const js = '';

View File

@@ -3,7 +3,7 @@
border: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
border-radius: var(--wa-border-radius-l);
color: var(--wa-color-text-normal);
margin-block-end: var(--wa-flow-spacing);
margin-block-end: var(--wa-content-spacing);
isolation: isolate;
}
@@ -100,8 +100,8 @@
.code-example-buttons {
display: flex;
align-items: stretch;
background: var(--wa-color-surface-default) !important; /* TODO - remove after native styles refactor */
color: var(--wa-color-text-quiet) !important; /* TODO - remove after native styles refactor */
background: var(--wa-color-surface-default);
color: var(--wa-color-text-quiet);
border-bottom-left-radius: inherit;
border-bottom-right-radius: inherit;
@@ -116,14 +116,6 @@
padding: 0.5rem;
cursor: pointer;
@media (hover: hover) {
&:hover {
border-left: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet) !important; /* TODO - remove after native styles refactor */
background: var(--wa-color-surface-default) !important; /* TODO - remove after native styles refactor */
color: var(--wa-color-text-quiet) !important; /* TODO - remove after native styles refactor */
}
}
&:first-of-type {
border-left: none;
border-bottom-left-radius: var(--wa-border-radius-l);

View File

@@ -1,7 +1,8 @@
/* Only code blocks generated by our docs get these styles */
pre[id*='code-block-'] {
background-color: var(--wa-color-gray-20);
color-scheme: dark;
color: white;
background-color: var(--wa-color-neutral-20);
/* Ensures a discernible background color in dark mode
* Useful for themes that use gray-20 as --wa-color-surface-default */

View File

@@ -25,6 +25,11 @@ wa-copy-button.copy-button {
border-radius: var(--wa-border-radius-m);
padding: 0.25rem;
&::part(button) {
background: transparent;
cursor: copy;
}
@media (hover: hover) {
&:hover {
color: white;
@@ -45,19 +50,3 @@ wa-copy-button.copy-button {
opacity: 1;
}
}
.block-link-icon {
position: absolute;
inset-block-start: 0;
inset-inline-end: calc(100% + var(--wa-space-s));
transition: var(--wa-transition-slow);
&:not(:hover, :focus) {
opacity: 50%;
}
:not(:hover, :focus-within) > & {
opacity: 0;
}
}

View File

@@ -26,10 +26,6 @@ body.theme-transitioning {
transition: opacity 200ms ease-out;
}
wa-page {
--wa-flow-spacing: var(--wa-space-xl);
}
/* Header */
wa-page::part(header) {
background-color: var(--wa-color-surface-default);
@@ -73,7 +69,33 @@ wa-page > header {
#docs-toolbar {
display: flex;
align-items: center;
gap: var(--wa-space-xs);
gap: var(--wa-space-s);
.color-scheme-selector,
.theme-selector {
max-inline-size: 20ch;
}
wa-divider:last-child {
display: none;
}
}
#github-buttons {
> wa-button {
&::part(base) {
color: var(--wa-color-on-quiet);
background-color: var(--wa-color-fill-quiet);
}
> wa-icon {
font-size: round(1.25em, 1px);
}
}
> wa-tooltip {
--wa-tooltip-arrow-size: 0;
font-size: var(--wa-font-size-xs);
}
}
#version-number {
@@ -86,14 +108,6 @@ wa-page > header {
font-size: var(--wa-font-size-2xs);
text-transform: uppercase;
}
wa-button#search-trigger {
--background-color: var(--wa-form-control-background-color);
--border-color: var(--wa-form-control-border-color);
}
#search-trigger kbd {
font-size: var(--wa-font-size-2xs);
line-height: var(--wa-form-control-value-line-height);
}
}
#sidebar,
@@ -130,8 +144,8 @@ wa-page > header {
border-inline-start: var(--wa-border-width-s) solid var(--wa-color-surface-border);
font-size: var(--wa-font-size-s);
line-height: var(--wa-line-height-condensed);
margin: 0;
padding-inline-start: var(--wa-space-m);
margin: 0;
}
ul ul {
@@ -144,6 +158,7 @@ wa-page > header {
li {
list-style: none;
margin: 0;
+ li {
margin-block-start: var(--wa-space-m);
@@ -166,11 +181,6 @@ wa-page > header {
li wa-icon {
color: var(--wa-color-text-quiet);
vertical-align: middle;
&[name='flask'] {
margin-inline: 0.125em;
}
}
}
@@ -190,25 +200,16 @@ wa-badge.pro {
color: var(--wa-color-text-quiet);
a {
display: flex;
align-items: center;
gap: 0.4em;
color: var(--wa-color-text-normal);
text-decoration: none;
wa-icon {
margin-block-end: -0.15em;
font-size: var(--wa-font-size-s);
font-weight: var(--wa-font-weight-action);
color: var(--wa-color-gray-70);
}
&:hover {
color: var(--wa-color-brand-on-normal);
wa-icon {
color: var(--wa-color-brand-on-quiet);
}
text-decoration: underline;
}
}
}
@@ -242,6 +243,12 @@ wa-button.delete {
}
}
[slot='navigation-header'] {
wa-select::part(listbox) {
font-weight: var(--wa-font-weight-normal);
}
}
#sidebar-close-button {
display: none;
}
@@ -290,7 +297,7 @@ h1.title {
gap: var(--wa-space-xs);
flex-wrap: wrap;
align-items: center;
margin-block-end: var(--wa-flow-spacing);
margin-block-end: var(--wa-content-spacing);
code {
line-height: var(--wa-line-height-condensed);
@@ -333,7 +340,7 @@ h1.title {
border: var(--wa-border-style) var(--wa-border-width-s);
border-radius: var(--wa-border-radius-l);
padding: 1rem;
margin-block-end: var(--wa-flow-spacing);
margin-block-end: var(--wa-content-spacing);
:first-child {
margin-block-start: 0;
@@ -379,6 +386,24 @@ h1.title {
}
}
/* Search trigger */
wa-button#search-trigger {
&::part(base) {
background-color: var(--wa-form-control-background-color);
border: var(--wa-form-control-border-width) var(--wa-form-control-border-style) var(--wa-form-control-border-color);
box-shadow: none;
}
&::part(label) {
text-align: start;
width: 100%;
}
}
#search-trigger kbd {
font-size: var(--wa-font-size-2xs);
line-height: var(--wa-form-control-value-line-height);
padding-inline: 0.33em;
}
/* Search list pages */
wa-page > main:has(> .search-list) {
max-width: 120ch;
@@ -479,7 +504,6 @@ wa-card .page-name {
width: 100%;
height: 100%;
display: block;
--background-color-hover: transparent;
font-family: var(--wa-font-family-code);
&::part(button) {
@@ -489,6 +513,7 @@ wa-card .page-name {
}
&::part(button):hover {
background-color: transparent;
cursor: copy;
}
@@ -584,12 +609,6 @@ table.colors {
min-inline-size: 8rem;
}
/* Utilities */
.two-columns {
columns: 2;
gap: 1rem;
}
/* Component API tables */
wa-scroller:has(.component-table) {
margin-block-end: var(--wa-space-xl);
@@ -630,7 +649,7 @@ wa-scroller:has(.component-table) {
}
/** desktop */
@media screen and not (max-width: 768px) {
@media screen and not (max-width: 1180px) {
/* Navigation sidebar */
wa-page::part(navigation) {
border-right: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-surface-border);

View File

@@ -15,47 +15,12 @@ category: Actions
## Examples
### Button Sizes
Unless otherwise specified,
the size of [buttons](/docs/components/button) will be determined by the Button Group's `size` attribute.
```html {.example}
<wa-button-group size="small" 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 size="medium" 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 size="large" label="Alignment">
<wa-button>Left</wa-button>
<wa-button>Center</wa-button>
<wa-button>Right</wa-button>
</wa-button-group>
```
:::info
While you can still set the size of [buttons](/docs/components/button) individually,
and it will override the inherited size,
it is rarely a good idea to mix sizes within the same button group.
:::
### Vertical Button Groups
Set the `orientation` attribute to `vertical` to make a vertical button group.
```html {.example}
<wa-button-group orientation="vertical" label="Options" style="max-width: 120px;">
<wa-button-group orientation="vertical" label="Options">
<wa-button>
<wa-icon slot="start" name="plus"></wa-icon>
New

View File

@@ -251,4 +251,4 @@ This example demonstrates how to style buttons using a custom class. This is the
outline-offset: 4px;
}
</style>
```
```

View File

@@ -17,10 +17,8 @@ category: Organization
This kitten is as cute as he is playful. Bring him home today!<br />
<small class="wa-caption-m">6 weeks old</small>
<div slot="footer" class="wa-split">
<wa-button variant="brand" pill>More Info</wa-button>
<wa-rating label="Rating"></wa-rating>
</div>
<wa-button slot="footer" variant="brand" pill>More Info</wa-button>
<wa-rating slot="footer-actions" label="Rating"></wa-rating>
</wa-card>
<style>
@@ -55,14 +53,11 @@ If using SSR, you need to also use the `with-header` attribute to add a header t
```html {.example}
<wa-card class="card-header">
<div slot="header" class="wa-split">
Header Title
<wa-button appearance="plain">
<wa-icon name="gear" variant="solid" label="Settings"></wa-icon>
</wa-button>
</div>
<h3 slot="header">Header Title</h3>
This card has a header. You can put all sorts of things in it!
<wa-button appearance="plain" slot="header-actions">
<wa-icon name="gear" variant="solid" label="Settings"></wa-icon>
</wa-button>
</wa-card>
<style>
@@ -85,10 +80,9 @@ If using SSR, you need to also use the `with-footer` attribute to add a footer t
<wa-card class="card-footer">
This card has a footer. You can put all sorts of things in it!
<div slot="footer" class="wa-split">
<wa-rating></wa-rating>
<wa-button variant="brand">Preview</wa-button>
</div>
<wa-rating slot="footer"></wa-rating>
<wa-button slot="footer-actions" variant="brand">Preview</wa-button>
</wa-card>
<style>
@@ -155,3 +149,35 @@ Use the `appearance` attribute to change the card's visual appearance.
{%- endfor %}
</div>
```
### Orientation
Set the `orientation` attribute to `horizontal` to create a card with a horizontal, side-by-side layout. Make sure to set a width or maximum width for the media slot. Horizontal cards do not currently contain the header and footer slots.
<wa-callout>
<wa-icon slot="icon" name="circle-info" variant="regular"></wa-icon>
The `actions` slot is only available for the horizontal orientation
</wa-callout>
```html {.example}
<div class="wa-grid">
<wa-card orientation="horizontal" class="horizontal-card">
<img
slot="media"
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
alt="A kitten sits patiently between a terracotta pot and decorative grasses."
/>
This is a kitten, but not just any kitten. This kitten likes walking along pallets.
<wa-button slot="actions" variant="neutral" appearance="plain"
><wa-icon name="ellipsis" label="actions"></wa-icon
></wa-button>
</wa-card>
</div>
<style>
.horizontal-card {
img[slot='media'] {
max-width: 300px;
}
}
</style>
```

View File

@@ -56,10 +56,12 @@ To copy data from an attribute, use `from="id[attr]"` where `id` is the id of th
<br /><br />
<!-- Copies the input's "value" property -->
<wa-input id="my-input" type="text" value="User input" style="display: inline-block; max-width: 300px;"></wa-input>
<wa-copy-button from="my-input.value"></wa-copy-button>
<span class="wa-align-items-center wa-gap-2xs">
<wa-input id="my-input" type="text" value="User input" style="display: inline-block; max-width: 300px;"></wa-input>
<wa-copy-button from="my-input.value"></wa-copy-button>
</span>
<br /><br />
<br />
<!-- Copies the link's "href" attribute -->
<a id="my-link" href="https://shoelace.style/">Web Awesome Website</a>
@@ -88,6 +90,7 @@ Copy buttons can be disabled by adding the `disabled` attribute.
A success indicator is briefly shown after copying. You can customize the length of time the indicator is shown using the `feedback-duration` attribute.
```html {.example}
<wa-copy-button value="Web Awesome rocks!" feedback-duration="250"></wa-copy-button>
```
@@ -132,4 +135,4 @@ You can customize the button to your liking with CSS.
outline-offset: 4px;
}
</style>
```
```

View File

@@ -48,6 +48,23 @@ Use the `expand-icon` and `collapse-icon` slots to change the expand and collaps
</style>
```
### Icon Position
The default position for the expand and collapse icons is at the end of the summary. Set the `icon-placement` attribute to `start` to place the icon at the start of the summary.
```html {.example}
<div class="wa-stack">
<wa-details summary="Start" icon-placement="start">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</wa-details>
<wa-details summary="End" icon-placement="end">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</wa-details>
</div>
```
### HTML in Summary
To use HTML in the summary, use the `summary` slot.
@@ -68,12 +85,17 @@ Links and other interactive elements will still retain their behavior:
### Right-to-Left Languages
The details component automatically adapts to right-to-left languages:
The details component, including its `icon-placement`, automatically adapts to right-to-left languages:
```html {.example}
<wa-details summary="تبديلني" lang="ar" dir="rtl">
استخدام طريقة لوريم إيبسوم لأنها تعطي توزيعاَ طبيعياَ -إلى حد ما- للأحرف عوضاً عن
</wa-details>
<div class="wa-stack">
<wa-details summary="تبديلني" lang="ar" dir="rtl">
استخدام طريقة لوريم إيبسوم لأنها تعطي توزيعاَ طبيعياَ -إلى حد ما- للأحرف عوضاً عن
</wa-details>
<wa-details summary="تبديلني" lang="ar" dir="rtl" icon-placement="start">
استخدام طريقة لوريم إيبسوم لأنها تعطي توزيعاَ طبيعياَ -إلى حد ما- للأحرف عوضاً عن
</wa-details>
</div>
```
### Appearance
@@ -86,11 +108,11 @@ Use the `appearance` attribute to change the elements visual appearance.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</wa-details>
<wa-details summary="Filled" appearance="filled">
<wa-details summary="Filled + Outlined" appearance="filled outlined">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</wa-details>
<wa-details summary="Filled + Outlined" appearance="filled outlined">
<wa-details summary="Filled" appearance="filled">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</wa-details>

View File

@@ -32,7 +32,7 @@ Dropdowns are designed to work well with [dropdown items](/docs/components/dropd
<wa-dropdown-item slot="submenu" value="show-thumbnails">Show Thumbnails</wa-dropdown-item>
</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item type="checkbox" checked>Emoji Shortcuts<wa-dropdown-item>
<wa-dropdown-item type="checkbox" checked>Emoji Shortcuts</wa-dropdown-item>
<wa-dropdown-item type="checkbox" checked>Word Wrap</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item variant="danger">
@@ -273,10 +273,10 @@ The distance from the panel to the trigger can be customized using the `distance
### Offset
The offset of the panel along the trigger can be customized using the `offset` attribute. This value is specified in pixels.
The offset of the panel along the trigger can be customized using the `skidding` attribute. This value is specified in pixels.
```html {.example}
<wa-dropdown offset="30">
<wa-dropdown skidding="30">
<wa-button slot="trigger" with-caret>Edit</wa-button>
<wa-dropdown-item>Cut</wa-dropdown-item>

View File

@@ -7,6 +7,10 @@ category: Imagery
Web Awesome comes bundled with over 2,000 free icons courtesy of [Font Awesome](https://fontawesome.com/). These icons are part of the `default` icon library. Font Awesome Pro users can unlock additional icon families. Or, if you prefer, you can register your own [custom icon library](#icon-library).
```html {.example}
<wa-icon name="face-awesome" variant="light" label="Awesome" style="font-size: 2em;"></wa-icon>
```
:::info
Not sure which icon to use? [Find the perfect icon over at Font Awesome!](https://fontawesome.com/search?o=r&m=free&f=brands%2Cclassic)
:::
@@ -17,73 +21,58 @@ Not sure which icon to use? [Find the perfect icon over at Font Awesome!](https:
The default icon library is Font Awesome Free, which comes with two icon families: `classic` and `brands`. Use the `family` attribute to set the icon family.
Many Font Awesome Pro icon families have variants such as `thin`, `light`, `regular`, and `solid`. Font Awesome Pro users can [provide their kit code](/docs/#using-font-awesome-kit-codes) to unlock additional families, including `sharp`, `duotone`, and `sharp-duotone`. For these icon families, use the `variant` attribute to set the variant.
Many Font Awesome Pro icon families have variants such as `thin`, `light`, `regular`, and `solid`. Font Awesome Pro users can [provide their kit code](/docs/#using-font-awesome-kit-codes) to unlock additional premium icon families, including `sharp`, `duotone`, `sharp-duotone`, and additional Pro+ icon packs.
For supportive icon families, use the `variant` attribute to set the variant.
```html {.example}
<wa-icon name="eyedropper"></wa-icon>
<wa-icon name="grip-vertical"></wa-icon>
<wa-icon name="play"></wa-icon>
<wa-icon name="star"></wa-icon>
<wa-icon name="user"></wa-icon>
```
### Colors
Icons inherit their color from the current text color. Thus, you can set the `color` property on the `<wa-icon>` element or an ancestor to change the color.
```html {.example}
<div style="color: #4a90e2;">
<wa-icon name="exclamation-triangle"></wa-icon>
<wa-icon name="archive"></wa-icon>
<wa-icon name="battery-three-quarters"></wa-icon>
<wa-icon name="bell"></wa-icon>
<div class="wa-stack wa-gap-xl">
<div class="wa-flank" style="--flank-size: 12ch;">
<span>Classic</span>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon name="eyedropper"></wa-icon>
<wa-icon variant="regular" name="grip-vertical"></wa-icon>
<wa-icon variant="light" name="play"></wa-icon>
<wa-icon variant="thin" name="star"></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 12ch;">
<span>Duotone</span>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="duotone" name="eyedropper"></wa-icon>
<wa-icon family="duotone" variant="regular" name="grip-vertical"></wa-icon>
<wa-icon family="duotone" variant="light" name="play"></wa-icon>
<wa-icon family="duotone" variant="thin" name="star"></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 12ch;">
<span>Sharp</span>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="sharp" name="eyedropper"></wa-icon>
<wa-icon family="sharp" variant="regular" name="grip-vertical"></wa-icon>
<wa-icon family="sharp" variant="light" name="play"></wa-icon>
<wa-icon family="sharp" variant="thin" name="star"></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 12ch;">
<span>Sharp Duotone</span>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="sharp-duotone" name="eyedropper"></wa-icon>
<wa-icon family="sharp-duotone" variant="regular" name="grip-vertical"></wa-icon>
<wa-icon family="sharp-duotone" variant="light" name="play"></wa-icon>
<wa-icon family="sharp-duotone" variant="thin" name="star"></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 12ch;">
<span>Brands</span>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="brands" name="font-awesome"></wa-icon>
<wa-icon family="brands" name="web-awesome"></wa-icon>
<wa-icon family="brands" name="github"></wa-icon>
<wa-icon family="brands" name="discord"></wa-icon>
</div>
</div>
</div>
<div style="color: #9013fe;">
<wa-icon name="clock"></wa-icon>
<wa-icon name="cloud"></wa-icon>
<wa-icon name="download"></wa-icon>
<wa-icon name="file"></wa-icon>
</div>
<div style="color: #417505;">
<wa-icon name="flag"></wa-icon>
<wa-icon name="heart"></wa-icon>
<wa-icon name="image"></wa-icon>
<wa-icon name="bolt-lightning"></wa-icon>
</div>
<div style="color: #f5a623;">
<wa-icon name="microphone"></wa-icon>
<wa-icon name="search"></wa-icon>
<wa-icon name="star"></wa-icon>
<wa-icon name="trash"></wa-icon>
</div>
```
### Sizing
Icons are sized relative to the current font size. To change their size, set the `font-size` property on the icon itself or on a parent element as shown below.
```html {.example}
<div style="font-size: 32px;">
<wa-icon name="bell"></wa-icon>
<wa-icon name="heart"></wa-icon>
<wa-icon name="image"></wa-icon>
<wa-icon name="microphone"></wa-icon>
<wa-icon name="search"></wa-icon>
<wa-icon name="star"></wa-icon>
</div>
```
### Fixed Width Icons
By default, icons have a 1em height and a variable width. Use the `fixed-width` attribute to render the host element in a 1em by 1em box.
```html {.example}
<wa-icon fixed-width name="cloud"></wa-icon>
<wa-icon fixed-width name="user"></wa-icon>
<wa-icon fixed-width name="truck"></wa-icon>
<wa-icon fixed-width name="file"></wa-icon>
<wa-icon fixed-width name="skating"></wa-icon>
<wa-icon fixed-width name="snowplow"></wa-icon>
```
### Labels
@@ -91,9 +80,335 @@ By default, icons have a 1em height and a variable width. Use the `fixed-width`
For non-decorative icons, use the `label` attribute to announce it to assistive devices.
```html {.example}
<wa-icon name="star" label="Add to favorites"></wa-icon>
<wa-icon name="star" label="Favorite" style="font-size: 1.5em;"></wa-icon>
```
### Sizing
Icons are sized relative to the current font size. To change their size, set the `font-size` property on the icon itself or on a parent element as shown below.
```html {.example}
<div class="wa-cluster" style="font-size: 44px;">
<wa-icon name="bell"></wa-icon>
<wa-icon name="heart"></wa-icon>
<wa-icon name="image"></wa-icon>
<wa-icon name="microphone"></wa-icon>
<wa-icon name="search"></wa-icon>
<wa-icon name="star"></wa-icon>
</div>
```
### Auto Width
By default, icons have a 1em height and a fixed 1em width. Use the `auto-width` attribute to allow the icon to use its natural variable width.
```html {.example}
Without auto-width<br />
<div style="font-size: 1.5em; color: #193154;">
<wa-icon family="solid" name="exclamation" style="background: lightsalmon;"></wa-icon>
<wa-icon family="solid" name="circle-check" style="background: lightsalmon;"></wa-icon>
<wa-icon family="solid" name="input-numeric" style="background: lightsalmon;"></wa-icon>
<wa-icon family="solid" name="ruler-vertical" style="background: lightsalmon;"></wa-icon>
<wa-icon family="solid" name="ruler-horizontal" style="background: lightsalmon;"></wa-icon>
<wa-icon family="solid" name="airplay" style="background: lightsalmon;"></wa-icon>
</div>
<br />
With auto-width<br />
<div style="font-size: 1.5em; color: #193154;">
<wa-icon auto-width family="solid" name="exclamation" style="background: lightsalmon;"></wa-icon>
<wa-icon auto-width family="solid" name="circle-check" style="background: lightsalmon;"></wa-icon>
<wa-icon auto-width family="solid" name="input-numeric" style="background: lightsalmon;"></wa-icon>
<wa-icon auto-width family="solid" name="ruler-vertical" style="background: lightsalmon;"></wa-icon>
<wa-icon auto-width family="solid" name="ruler-horizontal" style="background: lightsalmon;"></wa-icon>
<wa-icon auto-width family="solid" name="airplay" style="background: lightsalmon;"></wa-icon>
</div>
```
### Colors
Icons inherit their color from the current text color. Thus, you can set the `color` property on the `<wa-icon>` element or an ancestor to change the color.
```html {.example}
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon name="strawberry" style="color: salmon;"></wa-icon>
<wa-icon name="crab" style="color: coral;"></wa-icon>
<wa-icon name="sun" style="color: gold;"></wa-icon>
<wa-icon name="leaf" style="color: mediumseagreen;"></wa-icon>
<wa-icon name="cloud-showers-heavy" style="color: steelblue;"></wa-icon>
<wa-icon name="cat-space" style="color: mediumpurple;"></wa-icon>
</div>
```
### Duotone
Font Awesome's [Duotone icons](https://docs.fontawesome.com/web/style/duotone) change with the `color` property as well, but you can customize the primary and secondary colors independently using the `--primary-color` and `--secondary-color` custom properties. To change the opacity of either, use `--primary-opacity` and `--secondary-opacity`.
Note that these custom properties will not inherit and _must be applied directly to the icon_.
```html {.example}
<div class="wa-stack">
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon
family="duotone"
name="crow"
style="--primary-color: dodgerblue; --secondary-color: gold; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
name="campfire"
style="--primary-color: sienna; --secondary-color: red; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
name="birthday-cake"
style="--primary-color: pink; --secondary-color: palevioletred; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
name="ear"
style="--primary-color: sandybrown; --secondary-color: bisque; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
name="corn"
style="--primary-color: mediumseagreen; --secondary-color: gold; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
name="cookie-bite"
style="--primary-color: saddlebrown; --secondary-color: burlywood; --secondary-opacity: 1.0;"
></wa-icon>
</div>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon
family="duotone"
variant="regular"
name="crow"
style="--primary-color: dodgerblue; --secondary-color: gold; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="regular"
name="campfire"
style="--primary-color: sienna; --secondary-color: red; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="regular"
name="birthday-cake"
style="--primary-color: pink; --secondary-color: palevioletred; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="regular"
name="ear"
style="--primary-color: sandybrown; --secondary-color: bisque; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="regular"
name="corn"
style="--primary-color: mediumseagreen; --secondary-color: gold; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="regular"
name="cookie-bite"
style="--primary-color: saddlebrown; --secondary-color: burlywood; --secondary-opacity: 1.0;"
></wa-icon>
</div>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon
family="duotone"
variant="light"
name="crow"
style="--primary-color: dodgerblue; --secondary-color: gold; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="light"
name="campfire"
style="--primary-color: sienna; --secondary-color: red; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="light"
name="birthday-cake"
style="--primary-color: pink; --secondary-color: palevioletred; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="light"
name="ear"
style="--primary-color: sandybrown; --secondary-color: bisque; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="light"
name="corn"
style="--primary-color: mediumseagreen; --secondary-color: gold; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="light"
name="cookie-bite"
style="--primary-color: saddlebrown; --secondary-color: burlywood; --secondary-opacity: 1.0;"
></wa-icon>
</div>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon
family="duotone"
variant="thin"
name="crow"
style="--primary-color: dodgerblue; --secondary-color: gold; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="thin"
name="campfire"
style="--primary-color: sienna; --secondary-color: red; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="thin"
name="birthday-cake"
style="--primary-color: pink; --secondary-color: palevioletred; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="thin"
name="ear"
style="--primary-color: sandybrown; --secondary-color: bisque; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="thin"
name="corn"
style="--primary-color: mediumseagreen; --secondary-color: gold; --secondary-opacity: 1.0;"
></wa-icon>
<wa-icon
family="duotone"
variant="thin"
name="cookie-bite"
style="--primary-color: saddlebrown; --secondary-color: burlywood; --secondary-opacity: 1.0;"
></wa-icon>
</div>
</div>
```
:::info
Duotone icons can be unlocked by [providing a valid Font Awesome kit code](/docs/#using-font-awesome-kit-codes).
:::
### Swap Duotone Opacity
For duotone icons, you can swap the primary and secondary opacity values using the `swap-opacity` attribute. This is useful when you want to emphasize the secondary layer of the icon.
```html {.example}
Normal duotone<br />
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="duotone" name="home"></wa-icon>
<wa-icon family="duotone" name="user"></wa-icon>
<wa-icon family="duotone" name="envelope"></wa-icon>
<wa-icon family="duotone" name="calendar"></wa-icon>
</div>
<br />
Swapped duotone<br />
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="duotone" name="home" swap-opacity></wa-icon>
<wa-icon family="duotone" name="user" swap-opacity></wa-icon>
<wa-icon family="duotone" name="envelope" swap-opacity></wa-icon>
<wa-icon family="duotone" name="calendar" swap-opacity></wa-icon>
</div>
```
### Font Awesome Pro+
If you're a [Font Awesome Pro+ customer](https://fontawesome.com/), you have access to even more premium icons! Just set the appropriate `family`, `variant`, and `name` on the icon.
```html {.example}
<div class="wa-stack wa-gap-xl">
<div class="wa-flank" style="--flank-size: 10ch;">
<a href="https://fontawesome.com/icons/packs/notdog" target="_blank">Notdog</a>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="notdog" variant="solid" name="house"></wa-icon>
<wa-icon
family="notdog"
variant="duo-solid"
name="house"
style="--secondary-color: skyblue; --secondary-opacity: 0.8;"
></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 10ch;">
<a href="https://fontawesome.com/icons/packs/chisel" target="_blank">Chisel</a>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="chisel" variant="regular" name="house"></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 10ch;">
<a href="https://fontawesome.com/icons/packs/etch" target="_blank">Etch</a>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="etch" variant="solid" name="house"></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 10ch;">
<a href="https://fontawesome.com/icons/packs/jelly" target="_blank">Jelly</a>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="jelly" variant="regular" name="house"></wa-icon>
<wa-icon
family="jelly"
variant="duo-regular"
name="house"
style="--secondary-color: skyblue; --secondary-opacity: 0.8;"
></wa-icon>
<wa-icon family="jelly" variant="fill-regular" name="house"></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 10ch;">
<a href="https://fontawesome.com/icons/packs/slab" target="_blank">Slab</a>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon family="slab" variant="regular" name="house"></wa-icon>
<wa-icon family="slab" variant="press-regular" name="house"></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 10ch;">
<a href="https://fontawesome.com/icons/packs/thumbprint" target="_blank">Thumbprint</a>
<div class="wa-cluster" style="font-size: 1.5em;">
<wa-icon
family="thumbprint"
variant="light"
name="house"
style="--secondary-color: skyblue; --secondary-opacity: 0.8;"
></wa-icon>
</div>
</div>
<div class="wa-flank" style="--flank-size: 10ch;">
<a href="https://fontawesome.com/icons/packs/whiteboard" target="_blank">Whiteboard</a>
<div class="wa-cluster" style="font-size: 32px;">
<wa-icon family="whiteboard" variant="semibold" name="house"></wa-icon>
</div>
</div>
</div>
```
:::info
Pro+ icons can be unlocked by [providing a valid Font Awesome kit code](/docs/#using-font-awesome-kit-codes).
:::
### Custom Icons
Custom icons can be loaded individually with the `src` attribute. Only SVGs on a local or CORS-enabled endpoint are supported. If you're using more than one custom icon, it might make sense to register a [custom icon library](#icon-libraries).
@@ -287,7 +602,9 @@ Icons in this library are licensed under the [MIT License](https://github.com/lu
import { registerIconLibrary } from '/dist/webawesome.js';
registerIconLibrary('iconoir', {
resolver: name => `https://cdn.jsdelivr.net/gh/lucaburgio/iconoir@latest/icons/${name}.svg`,
resolver: (name, family) => {
return `https://cdn.jsdelivr.net/npm/iconoir@7.11.0/icons/regular/${name}.svg`;
},
mutator: svg =>
svg.querySelectorAll('path').forEach(path => {
path.setAttribute('fill', 'none');
@@ -297,7 +614,7 @@ Icons in this library are licensed under the [MIT License](https://github.com/lu
</script>
<div style="font-size: 24px;">
<wa-icon library="iconoir" name="check-circled-outline"></wa-icon>
<wa-icon library="iconoir" name="check-circle"></wa-icon>
<wa-icon library="iconoir" name="drawer"></wa-icon>
<wa-icon library="iconoir" name="keyframes"></wa-icon>
<wa-icon library="iconoir" name="headset-help"></wa-icon>

View File

@@ -0,0 +1,297 @@
---
title: Intersection Observer
description: Tracks immediate child elements and fires events as they move in and out of view.
layout: component
---
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.
```html {.example}
<div id="intersection__overview">
<wa-intersection-observer threshold="1" intersect-class="visible">
<div class="box"><wa-icon name="bulb"></wa-icon></div>
</wa-intersection-observer>
</div>
<small>Scroll to see the element intersect at 100% visibility</small>
<style>
/* Container styles */
#intersection__overview {
display: flex;
flex-direction: column;
gap: 2rem;
height: 300px;
border: solid 2px var(--wa-color-surface-border);
padding: 1rem;
overflow-y: auto;
/* Spacers to demonstrate scrolling */
&::before {
content: '';
height: 260px;
flex-shrink: 0;
}
&::after {
content: '';
height: 260px;
flex-shrink: 0;
}
/* Box styles */
.box {
flex-shrink: 0;
width: 120px;
height: 120px;
background-color: var(--wa-color-neutral-fill-normal);
color: var(--wa-color-neutral-10);
display: flex;
align-items: center;
justify-content: center;
margin-inline: auto;
transition: all 50ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
wa-icon {
font-size: 3rem;
stroke-width: 1px;
}
&.visible {
background-color: var(--wa-color-brand-60);
color: white;
}
}
+ small {
display: block;
text-align: center;
margin-block-start: 1rem;
}
}
</style>
```
:::info
Keep in mind that only direct children of the host element are monitored. Nested elements won't trigger intersection events.
:::
## Usage Examples
### Adding Observable Content
The intersection observer tracks only its direct children. The component uses [`display: contents`](https://developer.mozilla.org/en-US/docs/Web/CSS/display#contents) styling, which makes it seamless to integrate with flex and grid layouts from a parent container.
```html
<div style="display: flex; flex-direction: column;">
<wa-intersection-observer>
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
</wa-intersection-observer>
</div>
```
The component tracks elements as they enter and exit the root element (viewport by default) and emits the `wa-intersect` event on state changes. The event provides `event.detail.entry`, an [`IntersectionObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry) object with intersection details.
You can identify the triggering element through `entry.target`. Check `entry.isIntersecting` to determine if an element is entering or exiting the viewport.
```javascript
observer.addEventListener('wa-intersect', event => {
const entry = event.detail.entry;
if (entry.isIntersecting) {
console.log('Element entered viewport:', entry.target);
} else {
console.log('Element left viewport:', entry.target);
}
});
```
### Setting a Custom Root Element
You can observe intersections within a specific container by assigning the `root` attribute to the [root element's](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/root) ID. Apply [`rootMargin`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin) with the `root-margin` attribute to expand or contract the observation area.
```html
<div id="scroll-container">
<wa-intersection-observer root="scroll-container" root-margin="50px 0px"> ... </wa-intersection-observer>
</div>
```
### Configuring Multiple Thresholds
Track different visibility percentages by providing multiple [`threshold`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#threshold) values as a space-separated list.
```html
<wa-intersection-observer threshold="0 0.25 0.5 0.75 1"> ... </wa-intersection-observer>
```
### Applying Classes on Intersect
The `intersect-class` attribute automatically toggles the specified class on direct children when they become visible. This enables pure CSS styling without JavaScript event handlers.
```html {.example}
<div id="intersection__classes">
<wa-intersection-observer threshold="0.5" intersect-class="visible" root="intersection__classes">
<div class="box fade">Fade In</div>
<div class="box slide">Slide In</div>
<div class="box scale">Scale & Rotate</div>
<div class="box bounce">Bounce</div>
</wa-intersection-observer>
</div>
<small>Scroll to see elements transition at 50% visibility</small>
<style>
/* Container styles */
#intersection__classes {
display: flex;
flex-direction: column;
gap: 2rem;
height: 300px;
border: solid 2px var(--wa-color-surface-border);
padding: 1rem;
overflow-y: auto;
/* Spacers to demonstrate scrolling */
&::before {
content: '';
height: 260px;
flex-shrink: 0;
}
&::after {
content: '';
height: 260px;
flex-shrink: 0;
}
+ small {
display: block;
text-align: center;
margin-block-start: 1rem;
}
/* Shared box styles */
.box {
flex-shrink: 0;
width: 120px;
height: 120px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
color: white;
opacity: 0;
padding: 2rem;
margin-inline: auto;
/* Fade */
&.fade {
background: var(--wa-color-brand-fill-loud);
color: var(--wa-color-brand-on-loud);
transform: translateY(30px);
transition: all 0.6s ease;
&.visible {
opacity: 1;
transform: translateY(0);
}
}
/* Slide */
&.slide {
background: var(--wa-color-brand-fill-loud);
color: var(--wa-color-brand-on-loud);
transform: translateX(-50px);
transition: all 0.5s ease;
&.visible {
opacity: 1;
transform: translateX(0);
}
}
/* Scale */
&.scale {
background: var(--wa-color-brand-fill-loud);
color: var(--wa-color-brand-on-loud);
transform: scale(0.6) rotate(-15deg);
transition: all 0.7s cubic-bezier(0.175, 0.885, 0.32, 1.275);
&.visible {
opacity: 1;
transform: scale(1) rotate(0deg);
}
}
/* Bounce In and Out */
&.bounce {
background: var(--wa-color-brand-fill-loud);
color: var(--wa-color-brand-on-loud);
opacity: 0;
transform: scale(0.8);
transition: none;
&.visible {
opacity: 1;
transform: scale(1);
animation: bounceIn 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55) forwards;
}
&:not(.visible) {
animation: bounceOut 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55) forwards;
}
}
}
}
@keyframes bounceIn {
0% {
transform: scale(0.8);
}
40% {
transform: scale(1.08);
}
65% {
transform: scale(0.98);
}
80% {
transform: scale(1.02);
}
90% {
transform: scale(0.99);
}
100% {
transform: scale(1);
}
}
@keyframes bounceOut {
0% {
transform: scale(1);
opacity: 1;
}
20% {
transform: scale(1.02);
opacity: 1;
}
40% {
transform: scale(0.98);
opacity: 0.8;
}
60% {
transform: scale(1.05);
opacity: 0.6;
}
80% {
transform: scale(0.95);
opacity: 0.3;
}
100% {
transform: scale(0.8);
opacity: 0;
}
}
</style>
```

View File

@@ -91,7 +91,7 @@ Use the `distance` attribute to control how far the popover appears from its anc
### Arrow Size
Use the `--arrow-size` custom property to change the size of the popover's arrow. Set it to `0` to remove the arrow entirely.
Use the `--arrow-size` custom property to change the size of the popover's arrow. To remove it, use the `without-arrow` attribute.
```html {.example}
<div style="display: flex; gap: 1rem; align-items: center;">
@@ -99,7 +99,7 @@ Use the `--arrow-size` custom property to change the size of the popover's arrow
<wa-popover for="popover__big-arrow" style="--arrow-size: 8px;">I have a big arrow</wa-popover>
<wa-button id="popover__no-arrow">No arrow</wa-button>
<wa-popover for="popover__no-arrow" style="--arrow-size: 0;">I don't have an arrow</wa-popover>
<wa-popover for="popover__no-arrow" without-arrow>I don't have an arrow</wa-popover>
</div>
```

View File

@@ -416,6 +416,8 @@ By default, the arrow will be aligned as close to the center of the _anchor_ as
</div>
```
{# TODO: this example totally destroys browsers. Needs investigation.
### Syncing with the Anchor's Dimensions
Use the `sync` attribute to make the popup the same width or height as the anchor element. This is useful for controls that need the popup to stay the same width or height as the trigger.
@@ -467,6 +469,7 @@ Use the `sync` attribute to make the popup the same width or height as the ancho
sync.addEventListener('change', () => (popup.sync = sync.value));
</script>
```
#}
### Flip
@@ -848,4 +851,4 @@ This example anchors a popup to the mouse cursor using a virtual element. As suc
The following classes can be applied to the popup's `popup` part to animate it in or out programmatically. You can control the animation duration with the `--show-duration` and `--hide-duration` custom properties.
- `show` / `hide` - Shows or hides the popover with a fade
- `show-with-scale` / `hide-with-scale` - Shows or hides the popover with a fade and subtle scale effect
- `show-with-scale` / `hide-with-scale` - Shows or hides the popover with a fade and subtle scale effect

View File

@@ -21,10 +21,10 @@ Use the `label` attribute to label the progress bar and tell assistive devices h
### Custom Height
Use the `height` CSS property to set the progress bar's height.
Use the `--track-height` custom property to set the progress bar's height.
```html {.example}
<wa-progress-bar value="50" style="height: 6px;"></wa-progress-bar>
<wa-progress-bar value="50" style="--track-height: 6px;"></wa-progress-bar>
```
### Showing Values

View File

@@ -7,7 +7,7 @@ category: Form Controls
```html {.example}
<wa-select>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
<wa-option value="option-4">Option 4</wa-option>
@@ -173,7 +173,7 @@ Use `<wa-divider>` to group listbox items visually. You can also use `<small>` t
### Sizes
Use the `size` attribute to change a select's size. Note that size does not apply to listbox options.
Use the `size` attribute to change a select's size.
```html {.example}
<wa-select placeholder="Small" size="small">
@@ -366,6 +366,7 @@ Here's a comprehensive example showing different lazy loading scenarios:
const option = document.createElement('wa-option');
option.setAttribute('value', 'foo');
option.selected = true;
option.innerText = 'Foo';
// For the multiple select with existing selected options, make the new option selected

View File

@@ -7,8 +7,8 @@ category: Form Controls
```html {.example}
<wa-slider
label="Number of cats"
hint="Limit six per household"
label="Number of users"
hint="Limit six per team"
name="value"
value="3"
min="0"
@@ -40,7 +40,7 @@ Use the `label` attribute to give the slider an accessible label. For labels tha
Add descriptive hint to a slider with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
```html {.example}
<wa-slider label="Volume" hint="Controls the volume of the current song." min="0" max="100"></wa-slider>
<wa-slider label="Volume" hint="Controls the volume of the current song." min="0" max="100" value="50"></wa-slider>
```
### Showing tooltips
@@ -72,7 +72,15 @@ Use the `with-markers` attribute to display visual indicators at each step incre
Use the `reference` slot to add contextual labels below the slider. References are automatically spaced using `space-between`, making them easy to align with the start, center, and end positions.
```html {.example}
<wa-slider label="Speed" name="speed" min="1" max="5" value="3" with-markers>
<wa-slider
label="Speed"
name="speed"
min="1"
max="5"
value="3"
with-markers
hint="Controls the speed of the thing you're currently doing."
>
<span slot="reference">Slow</span>
<span slot="reference">Medium</span>
<span slot="reference">Fast</span>
@@ -249,8 +257,8 @@ By default, the filled indicator extends from the minimum value to the current p
```html {.example}
<wa-slider
label="Cat playfulness"
hint="Energy level during playtime"
label="User Friendliness"
hint="Did you find our product easy to use?"
name="value"
value="0"
min="-5"
@@ -259,8 +267,9 @@ By default, the filled indicator extends from the minimum value to the current p
with-markers
with-tooltip
>
<span slot="reference">Lazy</span>
<span slot="reference">Zoomies</span>
<span slot="reference">Easy</span>
<span slot="reference">Moderate</span>
<span slot="reference">Difficult</span>
</wa-slider>
```

View File

@@ -23,42 +23,38 @@ The default appearance is `outlined filled`.
```html {.example}
<div class="wa-stack">
<p>
<wa-tag variant="brand" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="brand" appearance="accent">Accent</wa-tag>
<wa-tag variant="brand" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="brand" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="brand" appearance="filled">Filled</wa-tag>
<wa-tag variant="brand" appearance="outlined filled">Outlined Filled</wa-tag>
<wa-tag variant="brand" appearance="outlined">Outlined</wa-tag>
</p>
<p>
<wa-tag variant="success" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="success" appearance="accent">Accent</wa-tag>
<wa-tag variant="success" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="success" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="success" appearance="filled">Filled</wa-tag>
<wa-tag variant="success" appearance="outlined filled">Outlined Filled</wa-tag>
<wa-tag variant="success" appearance="outlined">Outlined</wa-tag>
</p>
<p>
<wa-tag variant="neutral" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="neutral" appearance="accent">Accent</wa-tag>
<wa-tag variant="neutral" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="neutral" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="neutral" appearance="filled">Filled</wa-tag>
<wa-tag variant="neutral" appearance="outlined filled">Outlined Filled</wa-tag>
<wa-tag variant="neutral" appearance="outlined">Outlined</wa-tag>
</p>
<p>
<wa-tag variant="warning" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="warning" appearance="accent">Accent</wa-tag>
<wa-tag variant="warning" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="warning" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="warning" appearance="filled">Filled</wa-tag>
<wa-tag variant="warning" appearance="outlined filled">Outlined Filled</wa-tag>
<wa-tag variant="warning" appearance="outlined">Outlined</wa-tag>
</p>
<p>
<wa-tag variant="danger" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="danger" appearance="accent">Accent</wa-tag>
<wa-tag variant="danger" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="danger" appearance="filled outlined">Filled + Outlined</wa-tag>
<wa-tag variant="danger" appearance="filled">Filled</wa-tag>
<wa-tag variant="danger" appearance="outlined filled">Outlined Filled</wa-tag>
<wa-tag variant="danger" appearance="outlined">Outlined</wa-tag>
</p>
</div>
```

View File

@@ -113,11 +113,11 @@ Tooltips can be controller programmatically by setting the `trigger` attribute t
### Removing Arrows
You can control the size of tooltip arrows by overriding the `--wa-tooltip-arrow-size` design token. To remove them, set the value to `0` as shown below.
You can control the size of tooltip arrows by overriding the `--wa-tooltip-arrow-size` design token. To remove the arrow, use the `without-arrow` attribute.
```html {.example}
<wa-button id="no-arrow">No Arrow</wa-button>
<wa-tooltip for="no-arrow" style="--wa-tooltip-arrow-size: 0;">This is a tooltip with no arrow</wa-tooltip>
<wa-tooltip for="no-arrow" without-arrow>This is a tooltip with no arrow</wa-tooltip>
```
To override it globally, set it in a root block in your stylesheet after the Web Awesome stylesheet is loaded.

View File

@@ -6,7 +6,7 @@ category: Imagery
---
```html {.example}
<wa-zoomable-frame src="https://backers.webawesome.com/" zoom="0.5"> </wa-zoomable-frame>
<wa-zoomable-frame src="https://webawesome.com/" zoom="0.5"> </wa-zoomable-frame>
```
## Examples
@@ -43,7 +43,7 @@ Set the `zoom` attribute to control the frame's zoom level. Use `1` for 100%, `2
Define specific zoom increments with the `zoom-levels` attribute using space-separated percentages and decimal values like `zoom-levels="0.25 0.5 75% 100%"`.
```html {.example}
<wa-zoomable-frame src="https://backers.webawesome.com/" zoom="0.5" zoom-levels="50% 0.75 100%"> </wa-zoomable-frame>
<wa-zoomable-frame src="https://webawesome.com/" zoom="0.5" zoom-levels="50% 0.75 100%"> </wa-zoomable-frame>
```
### Hiding zoom controls
@@ -51,7 +51,7 @@ Define specific zoom increments with the `zoom-levels` attribute using space-sep
Add the `without-controls` attribute to hide the zoom control interface from the frame.
```html {.example}
<wa-zoomable-frame src="https://backers.webawesome.com/" without-controls zoom="0.5"> </wa-zoomable-frame>
<wa-zoomable-frame src="https://webawesome.com/" without-controls zoom="0.5"> </wa-zoomable-frame>
```
### Preventing user interaction
@@ -59,5 +59,5 @@ Add the `without-controls` attribute to hide the zoom control interface from the
Apply the `without-interaction` attribute to make the frame non-interactive. Note that this prevents keyboard navigation into the frame, which may impact accessibility for some users.
```html {.example}
<wa-zoomable-frame src="https://backers.webawesome.com/" zoom="0.5" without-interaction> </wa-zoomable-frame>
<wa-zoomable-frame src="https://webawesome.com/" zoom="0.5" without-interaction> </wa-zoomable-frame>
```

View File

@@ -10,17 +10,16 @@ You can customize the look and feel of Web Awesome at a high level with themes.
Web Awesome uses [themes](/docs/themes) to apply a cohesive look and feel across the entire library. Themes are built with a collection of predefined CSS custom properties, which we call [design tokens](/docs/tokens), and there are many premade themes you can choose from.
To use a theme, simply add a link to the theme's stylesheet to the `<head>` of your page. For example, you can replace the link to `default.css` in the [installation code](/docs/#quick-start-autoloading-via-cdn) with this snippet to use the *Awesome* theme:
To use a theme, simply add a link to the theme's stylesheet to the `<head>` of your page. For example, you can add this snippet alongside th [installation code](/docs/#quick-start-autoloading-via-cdn) to use the *Awesome* theme:
```html
<link rel="stylesheet" href="{% cdnUrl 'styles/themes/awesome.css' %}" />
```
You can [customize any theme](/docs/themes/creating) just with CSS — no preprocessor required. All design tokens are prefixed with `--wa-` to avoid collisions with other libraries or your own custom properties. Simply override any design token in your own stylesheet by scoping your styles to `:where(:root)`, `:host`, the class for the specific theme you want to override (if needed), and the class for the relevant color scheme (if needed). Here's an example that changes the default brand color to purple in light mode:
You can customize any theme just with CSS — no preprocessor required. All design tokens are prefixed with `--wa-` to avoid collisions with other libraries and your own custom properties. Simply override any design token in your own stylesheet by scoping your styles to `:root`, the class for the specific theme you want to override (if needed), and the class for the relevant color scheme (if needed). Here's an example that changes the default brand color to purple in light mode:
```css
:where(:root),
:host,
:root,
.wa-light,
.wa-dark .wa-invert {
--wa-color-brand-fill-quiet: var(--wa-color-purple-95);
@@ -35,10 +34,6 @@ You can [customize any theme](/docs/themes/creating) just with CSS — no prepro
}
```
:::info
Wrapping the `:root` selector in `:where()` gives this selector 0 specificity. This allows us to define our design tokens' default values while ensuring they can be cleanly overridden as needed.
:::
For a complete list of all custom properties used for theming, refer to `src/styles/themes/default.css` in the project's source code.
## Components

View File

@@ -26,8 +26,8 @@ If you're using a bundler, make sure it comes _before_ any components are import
// Make sure this import is first.
import '@lit-labs/ssr-client/lit-element-hydrate-support.js';
import 'webawesome/dist/components/button/button.js';
import 'webawesome/dist/components/input/input.js';
import '@awesome.me/webawesome/dist/components/button/button.js';
import '@awesome.me/webawesome/dist/components/input/input.js';
```
## Enable Server Rendering
@@ -43,7 +43,7 @@ import litPlugin from '@lit-labs/eleventy-plugin-lit';
eleventyConfig.addPlugin(litPlugin, {
mode: 'worker',
componentModules: ['webawesome/dist/components/button/button.js', 'webawesome/dist/components/input/input.js'],
componentModules: ['@awesome.me/webawesome/dist/components/button/button.js', '@awesome.me/webawesome/dist/components/input/input.js'],
});
```
@@ -114,4 +114,4 @@ Here are some known issues and things we're still working on.
- `@shoelace-style/localize` (our localization library) has no way to set a language currently so it always falls back to `en`.
- `<wa-icon>` has no fallback if there's no JS besides a blank `<svg>`. There's perhaps some backend mechanisms we can use to fetch. But requires altering APIs. Should also have a way to set height / widths, but we don't want to increase pain for SSR users.
- `<wa-qr-code>` QR Code will not error on the backend and will render a blank canvas at the appropriate size, but will not render the canvas until the client component connects.
- `setBasePath` and `kit codes` may need reconfiguring to work with SSR.
- `setBasePath` and `kit codes` may need reconfiguring to work with SSR.

View File

@@ -4,20 +4,12 @@ description: Choose the installation method that works best for you.
layout: page-outline
---
Welcome to your exclusive early access to Web Awesome Beta! 👋
At this time, we're offering access to Web Awesome Free and Pro through a temporary CDN while we prepare for a public release. This beta is tried, true, and stable, but please be aware that things may change here and there before our production release to the public.
Thank you so much for backing us!
Welcome to Web Awesome beta! [Learn more](https://webawesome.com/) about this project and [how to contribute to it](https://webawesome.com/docs/resources/contributing).
- [Report a bug](https://github.com/shoelace-style/webawesome/issues)
- [Get help / ask a question](https://github.com/shoelace-style/webawesome/discussions)
- [See what's new since the last version](/docs/resources/changelog)
:::warning
As a Web Awesome backer, this beta release is _just for you_. Please refrain from sharing it for the time being!
:::
---
## Quick Start (Autoloading via CDN)
@@ -25,15 +17,14 @@ As a Web Awesome backer, this beta release is _just for you_. Please refrain fro
To get everything included in Web Awesome, add the following code to the `<head>` of your site:
```html
<link rel="stylesheet" href="{% cdnUrl 'styles/themes/default.css' %}" />
<link rel="stylesheet" href="{% cdnUrl 'styles/webawesome.css' %}" />
<script type="module" src="{% cdnUrl 'webawesome.loader.js' %}"></script>
```
This snippet includes three parts:
1. **The default theme**, a stylesheet that gives a cohesive look to Web Awesome components with both light and dark modes
2. **Web Awesome styles**, an optional stylesheet that [styles native HTML elements](/docs/utilities/native) and includes [utility classes](/docs/utilities) you can use in your project
3. **The autoloader**, a lightweight script watches the DOM for unregistered Web Awesome elements and lazy loads them for you — even if they're added dynamically
This snippet adds:
- **Web Awesome styles**, a collection of stylesheets including essential default theme styles, optional [styles for native elements](/docs/utilities/native) and optional [utility classes](/docs/utilities)
- **The autoloader**, a lightweight script watches the DOM for unregistered Web Awesome elements and lazy loads them for you — even if they're added dynamically
Now you can [start using Web Awesome!](/docs/usage)
@@ -41,7 +32,7 @@ Now you can [start using Web Awesome!](/docs/usage)
## Using Font Awesome Kit Codes
Font Awesome users can set their kit code to unlock Font Awesome Pro icons. You can provide it by adding the `data-fa-kit-code` attribute to any element on the page, or by calling the `setKitCode()` method.
Font Awesome users can provide their kit code to unlock premium icon packs. You can provide yours by adding the `data-fa-kit-code` attribute to any element on the page, or by calling the `setKitCode()` method.
```html
<!-- Option 1: the data-fa-kit-code attribute -->
@@ -54,19 +45,31 @@ Font Awesome users can set their kit code to unlock Font Awesome Pro icons. You
</script>
```
:::info
Not a Font Awesome user yet? [Learn more about premium icon packs](https://fontawesome.com/) and sign up for an account to unlock them!
:::
---
{# This looks weird, but without it, markdownItAttrs flags the raw calls incorrectly. #}
<div>
{%- raw -%}
{% if currentUser.hasPro %}
<div>
{% include "server/pro-setup.njk" ignore missing %}
</div>
{% endif %}
{% endraw %}
</div>
## Advanced Setup
The autoloader is the easiest way to use Web Awesome, but different projects (or your own preferences!) may require different installation methods.
### Installing via npm
### Cherry Picking from CDN
An npm package isn't yet available, but we'll have one soon! For now, please enjoy [Web Awesome from the CDN](#quick-start-autoloading-via-cdn).
### Cherry Picking
Cherry picking will only load the components you need up front, while limiting the number of files the browser has to download. The disadvantage is that you need to import each individual component on each page it's used. You'll still need to include the default theme (`styles/themes/default.css`) or another theme to style any imported components.
Cherry picking will only load the components you need up front, while limiting the number of files the browser has to download. The disadvantage is that you need to import each individual component on each page it's used. Additionally, you must include the default theme (`styles/themes/default.css`) to style any imported components. To use a different theme, include your preferred theme _in addition to_ the default theme.
Here's an example that loads only the button component.
@@ -86,21 +89,47 @@ You can copy and paste the code to import a component from the "Importing" secti
You will see files named `chunk.[hash].js` in the `chunks` directory. Never import these files directly, as they are generated and change from version to version.
:::
### Installing via npm
```bash
npm install @awesome.me/webawesome
```
And then in your JavaScript files, import the components you need.
:::warning
Web Awesome does not a provide a single import with all Web Awesome components. Instead, you must "cherry pick" the components you want to use.
:::
```js
// Option 1: import all Web Awesome styles
import '@awesome.me/webawesome/dist/styles/webawesome.css';
// Option 2: import only the default theme
import '@awesome.me/webawesome/dist/styles/themes/default.css';
// <wa-button>
import '@awesome.me/webawesome/dist/components/button/button.js';
// <wa-input>
import '@awesome.me/webawesome/dist/components/input/input.js';
```
Once they've been imported, you can use them in your HTML normally. Component imports are located in the "Importing" section of each component's documentation.
### Setting the Base Path
Some components rely on assets (icons, images, etc.) and Web Awesome needs to know where they're located. For convenience, Web Awesome will try to auto-detect the correct location based on the script you've loaded it from. This assumes assets are colocated with `webawesome.loader.js` and will "just work" for most users.
==If you're using the CDN, you can skip this section.== However, if you're [cherry picking](#cherry-picking) or bundling Web Awesome, you'll need to set the base path. You can do this one of two ways.
==If you're using the CDN, you can skip this section.== However, if you're [cherry picking](#cherry-picking-from-cdn) or bundling Web Awesome, you'll need to set the base path. You can do this one of two ways.
```html
<!-- Option 1: the data-webawesome attribute -->
<script src="bundle.js" data-webawesome="/path/to/web-awesome/dist"></script>
<script src="bundle.js" data-webawesome="/path/to/webawesome/dist"></script>
<!-- Option 2: the setBasePath() method -->
<script type="module">
import { setBasePath } from '/path/to/web-awesome/dist/webawesome.js';
setBasePath('/path/to/web-awesome/dist');
import { setBasePath } from '/path/to/webawesome/dist/webawesome.js';
setBasePath('/path/to/webawesome/dist');
</script>
```
@@ -110,7 +139,7 @@ Most of the magic behind assets is handled internally by Web Awesome, but if you
```html
<script type="module">
import { getBasePath, setBasePath } from '/path/to/web-awesome/dist/webawesome.js';
import { getBasePath, setBasePath } from '/path/to/webawesome/dist/webawesome.js';
setBasePath('/path/to/assets');
@@ -123,3 +152,64 @@ Most of the magic behind assets is handled internally by Web Awesome, but if you
const assetPath = getBasePath('file.ext');
</script>
```
### The Difference Between `/dist` & `/dist-cdn`
If you have Web Awesome installed locally via npm, you'll notice the following directories in the project's root:
```
dist/
dist-cdn/
```
The `dist-cdn` files come with everything bundled together, so you can use them directly without a build tool. The dist files keep dependencies separate, which lets your bundler optimize and share code more efficiently.
Use `dist-cdn` if you're loading directly in the browser or from a CDN. Use `dist` if you're using a bundler like Webpack or Vite.
## React Users
React 19+ [supports custom elements](https://react.dev/blog/2024/04/25/react-19#support-for-custom-elements), so you can import them and use them as you'd expect. Just make sure you've included your Web Awesome theme into your app first.
```jsx
import '@awesome.me/webawesome/dist/components/button/button.js';
function App() {
return <wa-button variant="brand">Button</wa-button>;
}
export default App;
```
If you're using TypeScript, you can add type safety using the types file located at:
```
node_modules/@awesome.me/webawesome/dist/custom-elements-jsx.d.ts
```
This gives you inline documentation, autocomplete, and type-safe validation for every component. You can add the types to your project by updating your `tsconfig.json` file as shown below.
```json
{
"compilerOptions": {
"types": ["node_modules/@awesome.me/webawesome/dist/custom-elements-jsx.d.ts"]
}
}
```
Another way is to create a declaration file and extend JSX's `IntrinsicElements`:
```ts
import type { CustomElements, CustomCssProperties } from '@awesome.me/webawesome/dist/custom-elements-jsx.d.ts';
declare module 'react' {
namespace JSX {
interface IntrinsicElements extends CustomElements {}
}
interface CSSProperties extends CustomCssProperties {}
}
```
:::details React 18 and below
React 18 and below have [poor support](https://custom-elements-everywhere.com/#react) for custom elements. For legacy versions of React, we provide React wrappers for every component. You can find the import instructions by selecting the _React_ tab from the _Importing_ section of each
component's documentation.
:::

View File

@@ -22,43 +22,7 @@ Through the magic of a mutation observer, changing the `lang` attribute will aut
## Available Translations
Web Awesome ships with a number of translations. The default is English (US), which also serves as the fallback locale. As such, you do not need to import the English translation.
Available translations include:
<div style="columns: 3; gap: 1rem; margin-block-end: 1.5rem;">
- ar
- cs
- da
- de-ch
- de
- en-gb
- en
- es
- fa
- fi
- fr
- he
- hr
- hu
- id
- it
- ja
- nb
- nl
- nn
- pl
- pt
- ru
- sl
- sv
- tr
- uk
- zh-cn
- zh-tw
</div>
Web Awesome ships with [a number of translations](https://github.com/shoelace-style/webawesome/tree/next/packages/webawesome/src/translations). The default is English (US), which also serves as the fallback locale. As such, you do not need to import the English translation.
You can import translations using the following syntax, where `<code>` is replaced with any language code shown above.
@@ -92,7 +56,7 @@ To contribute new translations or improvements to existing translations, please
Regional translations are welcome! For example, if a German translation (`de`) exists it's perfectly acceptable to submit a German (Switzerland) (`de-CH`) translation.
If you have any questions, please start a [discussion](https://github.com/shoelace-style/shoelace/discussions) or ask in the [community chat](https://discord.gg/mg8f26C).
If you have any questions, please start a [discussion](https://github.com/shoelace-style/webawesome/discussions) or ask in the [community chat](https://discord.gg/mg8f26C).
:::info
Web Awesome provides a localization mechanism for component internals. This is not designed to be used as localization tool for your entire application. You should use a more appropriate tool such as [i18next](https://www.i18next.com/) if you need to localize content in your app.

View File

@@ -14,7 +14,7 @@ Furthermore, accessibility doesnt stop at the component level. Using accessib
My commitment to Web Awesome users is this: Everything we develop will be built with accessibility in mind. We will test and improve every component to the best of our ability and knowledge. We will work around upstream issues, such as browser bugs and limitations, to the best of our ability and within reason.
Were fully aware that we may not get it right every time for every user, so we invite the community to participate in this ongoing effort by submitting [issues](https://github.com/shoelace-style/shoelace/issues?q=is%3Aissue+is%3Aopen+label%3Aa11y), [pull requests](https://github.com/shoelace-style/shoelace/pulls?q=is%3Aopen+is%3Apr+label%3Aa11y), and [discussions](https://github.com/shoelace-style/shoelace/discussions). Many accessibility improvements have already been made thanks to contributors submitting code, feedback, and suggestions.
Were fully aware that we may not get it right every time for every user, so we invite the community to participate in this ongoing effort by submitting [issues](https://github.com/shoelace-style/shoelace/issues?q=is%3Aissue+is%3Aopen+label%3Aa11y), [pull requests](https://github.com/shoelace-style/shoelace/pulls?q=is%3Aopen+is%3Apr+label%3Aa11y), and [discussions](https://github.com/shoelace-style/webawesome/discussions). Many accessibility improvements have already been made thanks to contributors submitting code, feedback, and suggestions.
This is the path forward. Together, we will continue to make Web Awesome accessible to as many users as possible.

View File

@@ -8,6 +8,97 @@ Web Awesome follows [Semantic Versioning](https://semver.org/). Breaking changes
Components with the <wa-badge variant="warning">Experimental</wa-badge> badge should not be used in production. They are made available as release candidates for development and testing purposes. As such, changes to experimental components will not be subject to semantic versioning.
## Next
- Fixed a bug in `<wa-dropdown>` that closed the dropdown event when preventing `wa-select` [issue:1432]
## 3.0.0-beta.5
### Bug Fixes and Improvements {data-no-outline}
- 🚨 BREAKING: Updated `<wa-icon>` to use Font Awesome 7 [pr:1222]
- Added the `auto-width` attribute to automatically size icons, since FA7 is fixed-width by default now
- Improved support for duotone icons in `<wa-icon>`, including custom colors, custom opacity, and opacity swapping
- Removed the `fixed-width` attribute as it's now the default behavior
- 🚨 BREAKING: Renamed the `icon-position` attribute to `icon-placement` in `<wa-details>` [discuss:1340]
- 🚨 BREAKING: Removed the `size` attribute from `<wa-button-group>` as it only set the initial size and gets out of sync when buttons are updated (apply a `size` to each button instead)
- Added the `<wa-intersection-observer>` component
- Added the Hindi translation [pr:1307]
- Added `--show-duration` and `--hide-duration` to `<wa-select>` [issue:1281]
- Fixed incorrectly named exported tooltip parts in `<wa-slider>` [pr:1277]
- Fixed a bug in `<wa-dropdown>` that caused menus to overflow the viewport instead of resizing [issue:1267]
- Fixed a bug in `<wa-dropdown>` that prevented keyboard selection of items when nested in shadow roots [issue:1270]
- Fixed a bug in `<wa-dropdown>` that prevented items passed in from slots from being detected [issue:1271]
- Fixed a bug in JSX typings that prevented the types file from being exported [pr:1295]
- Fixed a bug in JSX typings that generated the incorrect component imports [issue:1303]
- Fixed a bug in `<wa-slider>` that prevented the thumb from receiving focus when clicking/tapping [issue:1312]
- Fixed a bug in `<wa-scroller>` that caused the shadow to appear below relatively-positioned elements [issue:1326]
- Fixed a bug in `<wa-details>` that caused it to expand/collapse when clicking on interactive elements in the summary [issue:1252]
- Fixed `<wa-button>` to have `static` positioning by default and `relative` positioning only when used with `<wa-badge>` [pr:1346]
- Fixed spacing in `<wa-input>` when both clear and password toggle icons are present [issue:1325]
- Fixed a bug in `<wa-radio-group>` and `<wa-radio>` where changing appearances dynamically would render incorrectly [issue:1178]
- Fixed a bug in `<wa-input>` that prevented the value from changing when assigning non-string values to `value` [issue:1323]
- Fixed a bug in `<wa-color-picker>` that prevent the picker from staying in the viewport
- Fixed a bug that in `<wa-icon>` that caused `library`, `family`, `variant` and `name` to not reflect [pr:#1395]
- Fixed a bug in `<wa-format-date>` and `<wa-relative-time>` that caused spaces to appear before and after the output [#1417]
- Added horizontal orientation support with `orientation="horizontal"` for `<wa-card>`
## 3.0.0-beta.4
### New Features {data-no-outline}
- Added the `icon-position` attribute to `<wa-details>` [discuss:1099]
- Added the `animating` custom state to `<wa-details>` [pr:1214]
- Added `--wa-tooltip-border-color`, `--wa-tooltip-border-style`, and `--wa-tooltip-border-width` tokens [issue:1224]
- Added the `without-arrow` attribute to `<wa-popover>` and `<wa-tooltip>` to hide arrows without artifacts
- Added JSX types for use with React and others [pr:1256]
- Added `<input type="file">` to native styles [pr:1279]
### Bug Fixes and Improvements {data-no-outline}
- Fixed a bug in `<wa-details>` that caused the content to overflow the container when animating [issue:1149]
- Fixed a bug in `<wa-dialog>` and `<wa-drawer>` that prevented the header from showing when the label was missing [issue:1209]
- Fixed a missing dependency required for React wrappers
- Fixed missing `:hover` and `:active` styles on native buttons without an appearance modifier class
## 3.0.0-beta.3
### New Features {data-no-outline}
- Added `--track-height` custom property to `<wa-progress-bar>` [pr:1154]
- Added `--pulse-color` custom property to `<wa-badge>` [pr:1173]
### Bug Fixes and Improvements {data-no-outline}
- Fixed a bug in `<wa-badge>` where `appearance="pulse"` was not working as expected [pr:1173]
- Fixed a missing TypeScript type for `<wa-badge>` for its `attention` property missing `bounce` value. [pr:1173]
- Fixed the missing `nanoid` dependency in `package.json` [discuss:1139]
- Fixed a bug in `<wa-slider>` that prevented the hint from showing up [discuss:1172]
- Fixed a bug in `<wa-textarea>` where setting `resize="auto"` caused the height of the textarea to double [issue:1155]
- Fixed a bug in `<wa-color-picker>`, `<wa-checkbox>`, `<wa-input>`, `<wa-radio-group>`, `<wa-switch>`, and `<wa-textarea>` that prevented screen readers from announcing hints [issue:1186]
- Fixed a bug in `<wa-card>` that caused slotted media to have incorrectly rounded corners [issue:1107]
- Fixed a bug in `<wa-button-group>` that prevented pill buttons from rendering corners properly [issue:1165]
- Fixed a bug in `<wa-button-group>` that caused some vertical groups to appear horizontal [issue:1152]
- Improved accessibility of `<wa-animated-image>` so keyboard users can focus and toggle the animation [issue:1177]
## 3.0.0-beta.2
### New Features {data-no-outline}
- Added `.wa-hover-rows` to native styles to opt-in to highlighting table rows on hover.
### Bug Fixes and Improvements {data-no-outline}
- Fixed a bug in `<wa-select>` with options that had blank string values. [pr:1136]
- Added `.wa-hover-rows` to native styles to opt-in to highlighting table rows on hover [pr:1111]
- Added missing changelog entries for beta.1 [pr:1117]
- Fixed a bug in `<wa-dropdown>` that prevented the menu from flipping/shifting to keep the menu in the viewport [pr:1122]
- Fixed the themes page so it shows the correct palette and imports [pr:1125]
- Fixed `filled` and `outlined` appearance styles in various components [issue:1102]
- Fixed active state styles in the Awesome theme [pr:1129]
- Fixed native text styles when applied to certain backgrounds [pr:https://github.com/shoelace-style/webawesome/pull/1130]
- Improved the organization of essential and optional styles [pr:1113]
## 3.0.0-beta.1
We're excited to share the first beta release of Web Awesome, which includes some breaking changes that make the library significantly more intuitive and consistent!
@@ -28,7 +119,8 @@ Many of these changes and improvements were the direct result of feedback from u
- Renamed the `classic` theme to `shoelace`
- Removed `:root` selector from all theme, color palette, and semantic color stylesheets except for the default theme and colors. All of these styles are now solely scoped to classes, such as `.wa-theme-awesome`, `.wa-palette-bright`, and `.wa-brand-orange`.
- Removed most custom properties from components that can otherwise be styled with `::part()` selectors and standard CSS properties.
- Renamed `pulse` attribute in `<wa-badge>` to `attention="pulse"` and added `attention="bounce"` [issue:#940]
- `<wa-dropdown>` was reworked and simplified to not use menu, menu item, menu label; use `<wa-dropdown-item>` instead
- Renamed `pulse` attribute in `<wa-badge>` to `attention="pulse"` and added `attention="bounce"` [issue:940]
- Renamed the `vertical` attribute to `orientation="vertical"` in `<wa-split-panel>` and `<wa-divider>` to align with other components and the platform [issue:674]
- Renamed certain boolean attributes to be consistent using the `with-*` and `without-*` pattern:
- `<wa-button caret>` => `<wa-button with-caret>`
@@ -73,6 +165,7 @@ Many of these changes and improvements were the direct result of feedback from u
- Added a new free component: `<wa-zoomable-frame>` (#3 of 14 per stretch goals)
- Added a `min-block-size` to `<wa-divider orientation="vertical">` to ensure the divider is visible regardless of container height
- Added support for `name` in `<wa-details>` for exclusively opening one in a group
- Added `--wa-content-spacing` to themes to set default spacing between HTML elements in Native Styles
- Added `--checked-icon-scale` to `<wa-checkbox>`
- Added `--tag-max-size` to `<wa-select>` when using `multiple`
- Added support for `data-dialog="open <id>"` to `<wa-dialog>`
@@ -96,6 +189,9 @@ Many of these changes and improvements were the direct result of feedback from u
### Removals {data-no-outline}
- Removed the experimental `<wa-code-demo>` component
- `<wa-menu>`, `<wa-menu-item>`, `<wa-menu-label>` were dropped; use `<wa-dropdown-item>` instead
- `<wa-icon-button>` was removed; icon buttons can be added via `<wa-button>` now
- `<wa-radio-button>` was dropped; use `<wa-radio appearance="button">` instead
<details>
<summary>Alpha Changelogs</summary>
@@ -132,7 +228,7 @@ Many of these changes and improvements were the direct result of feedback from u
### Bug fixes {data-no-outline}
- Specifying inherited CSS properties on `<wa-tooltip>` now works as expected ([thanks Dennis!](https://github.com/shoelace-style/webawesome-alpha/discussions/203))
- Specifying inherited CSS properties on `<wa-tooltip>` now works as expected
- Fixed a bug in `<wa-select>` that made it hard to use with VueJS, Svelte, and many other frameworks
- Fixed a bug in `<wa-select multiple>` that sometimes resulted in empty `<div>` elements being output
- Fixed a bug where changing a `<wa-option>` label wouldn't update the display label in `<wa-select>`
@@ -352,4 +448,4 @@ Many of these changes and improvements were the direct result of feedback from u
</details>
Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome-alpha/discussions)
Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome/discussions)

View File

@@ -10,14 +10,14 @@ Please be respectful of other users and remember that Web Awesome is an open sou
## Discussion Forum
The [discussion forum](https://github.com/shoelace-style/shoelace/discussions) is open to anyone with a GitHub account. This is the best place to:
The [discussion forum](https://github.com/shoelace-style/webawesome/discussions) is open to anyone with a GitHub account. This is the best place to:
- Ask for help
- Share ideas and get feedback
- Show the community what you're working on
- Learn more about the project, its values, and its roadmap
<wa-button variant="brand" href="https://github.com/shoelace-style/shoelace/discussions" target="_blank" style="margin-block-end: var(--wa-flow-spacing);">
<wa-button variant="brand" href="https://github.com/shoelace-style/webawesome/discussions" target="_blank" style="margin-block-end: var(--wa-content-spacing);">
<wa-icon name="github" family="brands" slot="start"></wa-icon>
Join the Discussion
</wa-button>
@@ -31,7 +31,7 @@ The [community chat](https://discord.gg/mg8f26C) is open to the public and power
- Show the community what you're working on
- Chat live with other designers, developers, and Web Awesome fans
<wa-button variant="brand" href="https://discord.gg/mg8f26C" target="_blank" style="margin-block-end: var(--wa-flow-spacing);">
<wa-button variant="brand" href="https://discord.gg/mg8f26C" target="_blank" style="margin-block-end: var(--wa-content-spacing);">
<wa-icon name="discord" family="brands" slot="start"></wa-icon>
Join the Chat
</wa-button>
@@ -40,9 +40,9 @@ The [community chat](https://discord.gg/mg8f26C) is open to the public and power
Follow [@webawesomer](https://twitter.com/webawesomer) on Twitter for general updates and announcements about Web Awesome. This is a great place to say "hi" or to share something you're working on.
**Please avoid using Twitter for support questions.** The [discussion forum](https://github.com/shoelace-style/shoelace/discussions) is a much better place to share code snippets, screenshots, and other troubleshooting info. You'll have much better luck there, as more users will have a chance to help you.
**Please avoid using Twitter for support questions.** The [discussion forum](https://github.com/shoelace-style/webawesome/discussions) is a much better place to share code snippets, screenshots, and other troubleshooting info. You'll have much better luck there, as more users will have a chance to help you.
<wa-button variant="brand" href="https://twitter.com/webawesomer" target="_blank" style="margin-block-end: var(--wa-flow-spacing);">
<wa-button variant="brand" href="https://twitter.com/webawesomer" target="_blank" style="margin-block-end: var(--wa-content-spacing);">
<wa-icon name="twitter" family="brands" slot="start"></wa-icon>
Follow on Twitter
</wa-button>

View File

@@ -131,7 +131,7 @@ To link to a GitHub issue, PR, or discussion, use the following syntax.
### Frontmatter
There's a number of frontmatter properties for doing different things in the Web Awesome documention.
There's a number of frontmatter properties for doing different things in the Web Awesome documentation.
For example, to only show a page in development, use the `unpublished: true` key / value pair.
@@ -252,22 +252,16 @@ This creates confusion because the part will be documented, but it won't work wh
### Emitting Events
Components must only emit events that start with `wa-` as a namespace. For compatibility with frameworks that utilize DOM templates, events must have lowercase, kebab-style names. For example, use `wa-change` instead of `waChange`.
Components must only emit events that start with `wa-` as a namespace. For compatibility with frameworks that utilize DOM templates, events must have lowercase, kebab-style names. For example, use `wa-event` instead of `waEvent`.
This convention avoids the problem of browsers lowercasing attributes, causing some frameworks to be unable to listen to them. This problem isn't specific to one framework, but [Vue's documentation](https://vuejs.org/v2/guide/components-custom-events.html#Event-Names) provides a good explanation of the problem.
### Change Events
When change events are emitted by Web Awesome components, they should be named `wa-change` and they should only be emitted as a result of user input. Programmatic changes, such as setting `el.value = '…'` _should not_ result in a change event being emitted. This is consistent with how native form controls work.
### Data Attribute Invokers
Some components can be controlled using [data attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/data-*) that trigger specific behaviors. These controls must use the following convention:
```html
<button data-component="action id">
Button text
</button>
<button data-component="action id">Button text</button>
```
The `data-component` portion corresponds to the component's name without the `wa-` prefix. For example, `data-dialog` must control a `<wa-dialog>` component.
@@ -277,13 +271,9 @@ The `action` parameter is required and must be a concise, descriptive term indic
The `id` parameter must point to the ID of the target component. The ID may be omitted if and only if the target component wraps the element with the `data-` attribute.
```html
<wa-dialog id="my-dialog">
Dialog content
</wa-dialog>
<wa-dialog id="my-dialog"> Dialog content </wa-dialog>
<button data-dialog="open my-dialog">
Open dialog
</button>
<button data-dialog="open my-dialog">Open dialog</button>
```
### CSS Custom Properties
@@ -363,7 +353,7 @@ Form controls should support submission and validation through the following con
- Form Controls should extend from `WebAwesomeFormAssociatedElement`
- All form controls must use `name`, `value`, and `disabled` properties in the same manner as `HTMLInputElement`
- All form controls with the `disabled` property *NOT* reflect the `disabled` attribute.
- All form controls with the `disabled` property _NOT_ reflect the `disabled` attribute.
- All form controls must have an `invalid` property that reflects their validity
- All form controls should mirror their native validation attributes such as `required`, `pattern`, `minlength`, `maxlength`, etc. when possible and use the `MirrorValidator`.
- All form controls must be tested to work with the standard `<form>` element
@@ -416,4 +406,4 @@ or for hydrated rendering only:
```bash
SSR_ONLY="true" npm run test
```
```

View File

@@ -6,26 +6,33 @@ wide: true
---
<style>
p {
max-width: 90ch;
}
tbody {
& .wa-grid {
--min-column-size: 5ch;
#content {
p {
max-width: 90ch;
}
& tr th:first-of-type {
width: 20ch;
tbody {
& .wa-grid {
--min-column-size: 5ch;
}
& tr th:first-of-type {
width: 20ch;
}
& th {
vertical-align: middle;
}
& tr:hover {
background-color: color-mix(in oklch, var(--wa-color-fill-quiet), transparent 60%)
}
}
& th {
vertical-align: middle;
wa-divider {
--width: var(--wa-border-width-m);
--spacing: var(--wa-space-3xl);
}
& tr:hover {
background-color: color-mix(in oklch, var(--wa-color-fill-quiet), transparent 60%)
}
}
wa-divider {
--width: var(--wa-border-width-m);
--spacing: var(--wa-space-3xl);
}
</style>

View File

@@ -4,95 +4,100 @@ description: Themes galore
layout: page
---
<div class="wa-stack wa-gap-3xl">
<div class="wa-split">
<h1>{{ title }}</h1>
<wa-button variant="brand" href="/themer">
<wa-icon slot="start" name="plus" variant="regular"></wa-icon>
Create a Theme
</wa-button>
</div>
<div class="wa-split">
<h1>{{ title }}</h1>
<wa-button variant="brand" href="/themer">
<wa-icon slot="start" name="plus" variant="regular"></wa-icon>
Create a Theme
</wa-button>
</div>
<div id="theme-viewer">
<div id="theme-viewer">
{% raw %}
{% if not currentUser.hasPro %}
<p>
Additional themes are available to pro users. Please <a href="/login">login to view pro themes</a>.
</p>
{% endif %}
{% endraw %}
<wa-radio-group id="theme-picker" label="Theme Selector" value="default" orientation="horizontal">
{% for theme in themer.themes %}
{% if not theme.isPro %}
<wa-radio-group id="theme-picker" label="Theme Selector" value="default" orientation="horizontal">
{% for theme in themer.themes %}
{% if not theme.isPro %}
<wa-radio
class="theme-card"
value="{{ theme.filename | stripExtension }}"
data-description="{{ theme.description }}"
data-title="{{ theme.name }}"
data-palette="{{ theme.palette.filename | stripExtension}}"
data-brand="{{ theme.colorBrand.color }}"
{% if theme.isPro %}data-is-pro{% endif %}
>
{{ theme.name }}
</wa-radio>
{% else %}
{% raw %}
{% if currentUser.hasPro %}
{% endraw %}
<wa-radio
class="theme-card"
value="{{ theme.filename | stripExtension }}"
data-description="{{ theme.description }}"
data-title="{{ theme.name }}"
data-palette="{{ theme.palette.filename | stripExtension}}"
data-brand="{{ theme.colorBrand.color }}"
{% if theme.isPro %}data-is-pro{% endif %}
>
{{ theme.name }}
</wa-radio>
{% else %}
{% raw %}
{% if currentUser.hasPro %}
{% endraw %}
<wa-radio
class="theme-card"
value="{{ theme.filename | stripExtension }}"
data-description="{{ theme.description }}"
data-title="{{ theme.name }}"
{% if theme.isPro %}data-is-pro{% endif %}
>
{{ theme.name }}
</wa-radio>
{% raw %}
{% endif %}
{% endraw %}
{% endif %}
{% endfor %}
</wa-radio-group>
</div>
<div id="theme-preview" class="wa-stack">
<header class="wa-stack">
<div class="wa-cluster">
<h2 data-theme-name="name">Theme</h2>
<wa-badge data-free-badge appearance="outlined" variant="neutral" hidden>FREE</wa-badge>
<wa-badge data-pro-badge appearance="accent" hidden>PRO</wa-badge>
</div>
<p data-theme-description>Description</p>
</header>
<wa-comparison position="80">
<wa-zoomable-frame
src="/examples/themes/showcase?color-scheme=dark"
slot="before"
without-controls
without-interaction
></wa-zoomable-frame>
<wa-zoomable-frame
src="/examples/themes/showcase"
slot="after"
without-controls
without-interaction
></wa-zoomable-frame>
</wa-comparison>
</div>
<h2>Using This Theme</h2>
<div id="import-code">
{% for theme in themer.themes %}
<div class="theme-instructions" data-theme="{{ theme.filename | stripExtension }}" {% if not loop.first %}hidden{% endif %}>
<p>
To import this theme, set <code>&lt;html class=&quot;wa-theme-{{ theme.filename | stripExtension }}&quot;&gt;</code> and import the following stylesheet:
</p>
<pre><code class="language-html">&lt;link rel=&quot;stylesheet&quot; href=&quot;{% cdnUrl %}styles/themes/{{ theme.filename }}&quot; /&gt;</code></pre>
</div>
{% raw %}
{% endif %}
{% endraw %}
{% endif %}
{% endfor %}
</div>
</wa-radio-group>
</div>
<div id="theme-preview" class="wa-stack">
<header class="wa-stack">
<div class="wa-cluster">
<h2 data-theme-name="name">Theme</h2>
<wa-badge data-free-badge appearance="outlined" variant="neutral" hidden>FREE</wa-badge>
<wa-badge data-pro-badge appearance="accent" hidden>PRO</wa-badge>
</div>
<p data-theme-description>Description</p>
</header>
<wa-comparison position="80">
<wa-zoomable-frame
src="/examples/themes/showcase?color-scheme=dark"
slot="before"
without-controls
without-interaction
></wa-zoomable-frame>
<wa-zoomable-frame
src="/examples/themes/showcase"
slot="after"
without-controls
without-interaction
></wa-zoomable-frame>
</wa-comparison>
</div>
<h2>Using This Theme</h2>
<div id="import-code">
{% for theme in themer.themes %}
<div class="theme-instructions" data-theme="{{ theme.filename | stripExtension }}" {% if not loop.first %}hidden{% endif %}>
<p>
To import this theme, apply the following classes to the <code>&lt;html&gt;</code> element and import the theme's stylesheet.
</p>
<pre><code class="language-html">&lt;html class=&quot;wa-theme-{{ theme.filename | stripExtension }} wa-palette-{{ theme.palette.filename | stripExtension }} wa-brand-{{ theme.colorBrand.color}}&quot;&gt;
...
&lt;link rel=&quot;stylesheet&quot; href=&quot;{% cdnUrl %}styles/themes/{{ theme.filename }}&quot; /&gt;</code></pre>
</div>
{% endfor %}
</div>
<script type="module">
import { doViewTransition } from '/assets/scripts/view-transitions.js';
@@ -104,23 +109,25 @@ layout: page
const freeBadge = document.querySelector('[data-free-badge]');
const proBadge = document.querySelector('[data-pro-badge]');
function updateFrames(selectedValue, title, description, isPro) {
function updateFrames(selectedValue, title, description, isPro, palette, brand) {
// Update theme classes on both frames
[afterFrame, beforeFrame].forEach(frame => {
if (frame.contentDocument) {
const html = frame.contentDocument.documentElement;
if (!html) return;
// Remove all existing wa-theme-* classes
html.classList.forEach(className => {
if (className.startsWith('wa-theme-')) {
// Remove all existing wa-theme-*, wa-palette-*, and wa-brand-* classes
[...html.classList].forEach(className => {
if (className.startsWith('wa-theme-') || className.startsWith('wa-palette-') || className.startsWith('wa-brand-')) {
html.classList.remove(className);
}
});
// Add new theme class if not default
// Add new theme, palette, and brand classes
if (selectedValue !== 'default') {
html.classList.add(`wa-theme-${selectedValue}`);
html.classList.add(`wa-palette-${palette}`);
html.classList.add(`wa-brand-${brand}`);
}
}
});
@@ -148,8 +155,10 @@ layout: page
defaultRadio.checked = true;
const title = defaultRadio.getAttribute('data-title');
const description = defaultRadio.getAttribute('data-description');
const palette = defaultRadio.getAttribute('data-palette');
const brand = defaultRadio.getAttribute('data-brand');
const isPro = defaultRadio.hasAttribute('data-is-pro');
updateFrames('default', title, description, isPro);
updateFrames('default', title, description, isPro, palette, brand);
}
// Listen for radio changes
@@ -157,9 +166,11 @@ layout: page
const selectedRadio = event.target.querySelector(':state(checked)');
const title = selectedRadio.getAttribute('data-title');
const description = selectedRadio.getAttribute('data-description');
const palette = selectedRadio.getAttribute('data-palette');
const brand = selectedRadio.getAttribute('data-brand');
const isPro = selectedRadio.hasAttribute('data-is-pro');
doViewTransition(() => {
updateFrames(selectedRadio.value, title, description, isPro);
updateFrames(selectedRadio.value, title, description, isPro, palette, brand);
});
});
</script>
@@ -169,6 +180,11 @@ layout: page
display: none !important;
}
#theme-preview,
#using-this-theme {
margin-block-start: var(--wa-space-3xl);
}
.title {
display: none;
}

View File

@@ -55,10 +55,9 @@ Web Awesome's color system is made up of CSS custom properties to help with cons
Color is organized by three main categories:
- [Color scales](/#color-scales) that gives you a full spectrum of hues to work with
- [Foundational colors](/#foundational-colors) that lay the groundwork for your theme
- [Semantic colors](/#semantic-colors) that draw attention and convey meaning
- [Color scales](#color-scales) that gives you a full spectrum of hues to work with
- [Foundational colors](#foundational-colors) that lay the groundwork for your theme
- [Semantic colors](#semantic-colors) that draw attention and convey meaning
## Color Scales
@@ -73,6 +72,7 @@ You can use these tints to ensure accessible color contrast per [WCAG 2.1 succes
You have several hand-crafted [color palettes](/docs/color-palettes) to choose from. Each palette defines 10 hues each with a scale of 11 tints using the format `--wa-color-{hue}-{tint}`.
{% for hue in ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'indigo', 'purple', 'pink', 'gray'] -%}
<div class="color-name">{{ hue | capitalize }}</div>
<ul class="color-group">
{% for tint in ['95', '90', '80', '70', '60', '50', '40', '30', '20', '10', '05'] -%}
@@ -91,6 +91,7 @@ You have several hand-crafted [color palettes](/docs/color-palettes) to choose f
Any hue can be mapped to `brand`, `neutral`, `success`, `warning`, and `danger` scales. Like the tokens in a color scale, each token is identified by its semantic group and a numerical tint using the format `--wa-color-{group}-{tint}`.
{% for group in ['brand', 'neutral', 'success', 'warning', 'danger'] -%}
<div class="color-name">{{ group | capitalize }}</div>
<ul class="color-group">
{% for tint in ['95', '90', '80', '70', '60', '50', '40', '30', '20', '10', '05'] -%}
@@ -112,19 +113,19 @@ Foundational colors lay the groundwork for the content and structure of your pro
Surfaces are background layers that other content rests on. Surface colors help convey hierarchy through a sense of elevation, where `--wa-color-surface-raised` is the closest to the user (e.g., dialogs and popup menus) and `--wa-color-surface-lowered` is the farthest away (e.g., wells).
| Custom Property | Preview |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `--wa-color-surface-raised` | <div class="swatch" style="background-color: var(--wa-color-surface-raised); box-shadow:var(--wa-shadow-s)"></div> |
| `--wa-color-surface-default` | <div class="swatch" style="background-color: var(--wa-color-surface-default)"></div> |
| `--wa-color-surface-lowered` | <div class="swatch" style="background-color: var(--wa-color-surface-lowered); box-shadow: inset var(--wa-shadow-s)"></div> |
| `--wa-color-surface-border` | <div class="swatch" style="border-color: var(--wa-color-surface-border)"></div> |
| Custom Property | Preview |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `--wa-color-surface-raised` | <div class="swatch" style="background-color: var(--wa-color-surface-raised); box-shadow:var(--wa-shadow-s)"></div> |
| `--wa-color-surface-default` | <div class="swatch" style="background-color: var(--wa-color-surface-default)"></div> |
| `--wa-color-surface-lowered` | <div class="swatch" style="background-color: var(--wa-color-surface-lowered); box-shadow: inset var(--wa-shadow-s)"></div> |
| `--wa-color-surface-border` | <div class="swatch" style="border-color: var(--wa-color-surface-border)"></div> |
### Text
Text colors are used for standard text elements. We recommend a minimum 4.5:1 contrast ratio between text colors and surface colors.
| Custom Property | Preview |
| ------------------------ | ---------------------------------------------------------- |
| Custom Property | Preview |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| `--wa-color-text-normal` | <div class="swatch" value="--wa-color-text-normal" style="color: var(--wa-color-text-normal); display: inline-block;">AaBb</div> |
| `--wa-color-text-quiet` | <div class="swatch" value="--wa-color-text-normal" style="color: var(--wa-color-text-quiet); display: inline-block;">AaBb</div> |
| `--wa-color-text-link` | <div class="swatch" value="--wa-color-text-normal" style="color: var(--wa-color-text-link); display: inline-block;">AaBb</div> |
@@ -153,23 +154,23 @@ This is used alongside other [shadow tokens](/docs/tokens/shadows) to construct
Web Awesome uses a single focus color for predictable keyboard navigation. This is used alongside other [focus tokens](/docs/tokens/focus) to construct `--wa-focus-ring`. We recommend a minimum 3:1 contrast ratio against surface colors and background colors wherever possible.
| Custom Property | Preview |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| Custom Property | Preview |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--wa-color-focus` | <div class="swatch" value="--wa-color-focus" style="outline: var(--wa-focus-ring-style) var(--wa-focus-ring-width) var(--wa-color-focus)"></div> |
#### Hover and Active
Web Awesome leverages `color-mix()` to achieve consistent hover and active states across components without the need for untold numbers of handpicked colors. Through `color-mix()`, these custom properties contextually generate hover and active colors based on the color of the component.
| Custom Property | Preview |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `--wa-color-mix-hover` | <div class="swatch color-mix-example" value="--wa-color-mix-hover" style="--mix-color: var(--wa-color-mix-hover)"><small>mixed</small></div> |
| Custom Property | Preview |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `--wa-color-mix-hover` | <div class="swatch color-mix-example" value="--wa-color-mix-hover" style="--mix-color: var(--wa-color-mix-hover)"><small>mixed</small></div> |
| `--wa-color-mix-active` | <div class="swatch color-mix-example" value="--wa-color-mix-active" style="--mix-color: var(--wa-color-mix-active)"><small>mixed</small></div> |
## Semantic Colors
Semantic colors reinforce a specific message, intended usage, or expected results through familiar, meaningful hues. Each color is identified by its semantic group, role, and attention using the format `--wa-color-{group}-{role}-{attention}`. There are five groups of semantic colors:
- **Brand** to emphasize your brand color
- **Success** for validity or confirmation
- **Neutral** for ordinary or inactive content
@@ -177,16 +178,19 @@ Semantic colors reinforce a specific message, intended usage, or expected result
- **Danger** for errors or risk
Each group defines colors for specific roles so that colors can be easily assembled with predictable results and readable contrast. There are three roles:
- **Fill** for background colors or areas larger than a few pixels
- **Border** for borders, dividers, and other stroke-width elements
- **On** for content displayed on a fill (e.g., pair `--wa-color-danger-on-loud` with `--wa-color-danger-fill-loud`)
Finally, each color is named according to how much attention it draws. Here, we use noise as an analogy: a loud noise draws more attention than a quiet one. There are three levels of attention:
- **Quiet** draws the least attention
- **Normal** draws some attention
- **Loud** draws the most attention
{% set variants = ['brand', 'success', 'neutral', 'warning', 'danger'] %}
<table>
<thead>
<tr>

View File

@@ -2,6 +2,7 @@
title: Component Groups
description: Style groups of components that share similar qualities with these Web Awesome custom properties.
order: 9999
layout: page-outline
---
For components that share similar qualities, Web Awesome includes custom properties to change the appearance of these related components all at once.
@@ -84,16 +85,19 @@ Panels consist of components with larger, contained surface areas like [callout]
## Tooltips
Tooltip styles are shared between the [tooltip](/docs/components/tooltip) component and the tooltip implementation in [range](/docs/components/range).
Tooltip styles are shared between the [tooltip](/docs/components/tooltip) component and the tooltips in [slider](/docs/components/slider) and [copy button](/docs/components/copy-button).
| Custom Property | Default Value |
| ---------------------------- | ----------------------------------- |
| `--wa-tooltip-arrow-size` | `0.375rem` <small>(6px)</small> |
| `--wa-tooltip-background-color` | `var(--wa-color-neutral-fill-loud)` |
| `--wa-tooltip-border-radius` | `var(--wa-border-radius-m)` |
| `--wa-tooltip-content-color` | `var(--wa-color-neutral-on-loud)` |
| `--wa-tooltip-font-size` | `var(--wa-font-size-s)` |
| `--wa-tooltip-line-height` | `var(--wa-line-height-normal)` |
| Custom Property | Default Value |
| ------------------------------- | ------------------------------------ |
| `--wa-tooltip-arrow-size` | `0.375rem` <small>(6px)</small> |
| `--wa-tooltip-background-color` | `var(--wa-color-neutral-fill-loud)` |
| `--wa-tooltip-border-color` | `var(--wa-tooltip-background-color)` |
| `--wa-tooltip-border-style` | `var(--wa-border-style)` |
| `--wa-tooltip-border-width` | `var(--wa-border-width-s)` |
| `--wa-tooltip-border-radius` | `var(--wa-border-radius-s)` |
| `--wa-tooltip-content-color` | `var(--wa-color-neutral-on-loud)` |
| `--wa-tooltip-font-size` | `var(--wa-font-size-s)` |
| `--wa-tooltip-line-height` | `var(--wa-line-height-normal)` |
```html {.example}
<wa-button id="bullseye-example" appearance="plain">

View File

@@ -7,7 +7,7 @@ tags: styleUtilities
Often, components are shown before their logic and styles have had a chance to load, also known as a [Flash of Undefined Custom Elements](https://www.abeautifulsite.net/posts/flash-of-undefined-custom-elements/).
The FOUCE style utility (which is automatically applied if you use our [style utilities](/docs/utilities/)) automatically takes care of hiding custom elements until **both they and their contents** have been registered, up to a maximum of two seconds.
The FOUCE style utility takes care of hiding custom elements until **both they and their contents** have been registered, up to a maximum of two seconds.
In many cases, this is not enough, and you may wish to hide a broader wrapper element or even the entire page until all WA elements within it have loaded.
To do that, you can add the `wa-cloak` class to any element on the page or even apply it to the whole page by placing the class on the `<html>` element:

View File

@@ -5,27 +5,52 @@ layout: page-outline
tags: styleUtilities
---
Web Awesome provides optional Native Styles that make native HTML elements look good so you can continue using what you know and gradually adopt Web Awesome as you see fit.
Native styles use design tokens to spruce up native HTML elements so that they match the look and feel of your theme. While these native styles are completely optional, they're a great starting point for a cohesive design and a huge help when using a combination of native elements and Web Awesome components in your project.
## Installation
## Using native styles
To use all Web Awesome page styles (including [utilities](/docs/utilities/)), include the following stylesheet in your project:
To use all Web Awesome styles (including [utilities](/docs/utilities/)), include the following stylesheet in your project:
```html
<link rel="stylesheet" href="{% cdnUrl 'styles/webawesome.css' %}" />
```
Or, to _only_ include styles for native elements:
Or, if you only want styles for native elements, include the default theme and native styles individually:
```html
<link rel="stylesheet" href="{% cdnUrl 'styles/themes/default.css' %}" />
<link rel="stylesheet" href="{% cdnUrl 'styles/native.css' %}" />
```
## Elements
You can additionally include any pre-made [theme](/docs/themes/) or [color palette](/docs/color-palettes/) to change the look of native elements.
## Content flow
Native styles set default space between many block-level HTML elements using the `--wa-content-spacing` token from your theme. This helps ensure that your content is readable.
```html {.example}
<h3>Curabitur odio ligula</h3>
<p>Fusce mollis quam lorem, et gravida arcu laoreet ut. Pellentesque et malesuada mi. Morbi faucibus nisl nec nulla porta, ac scelerisque elit finibus.</p>
<blockquote>The Road goes ever on and on<br />
Out from the door where it began.</blockquote>
<p>Donec varius, ipsum sit amet lobortis tristique, quam arcu pellentesque turpis, non porta lacus arcu non arcu. Morbi luctus at nisl sit amet faucibus.</p>
<hr />
<ul>
<li>Aenean imperdiet</li>
<li>Vivamus consectetur at est</li>
<li>Quisque vel leo in leo semper</li>
</ul>
```
To remove this default spacing, you can set `--wa-content-spacing: 0` in your styles.
## Typography
Native styles use [typography design tokens](/docs/tokens/typography/) to style text elements. A number of styles — such as `color`, `font-family`, `font-size`, `font-weight`, and `line-height` — are set on the `<body>` element to be inherited by child elements.
### Headings
Semantic heading elements with proper hierarchy and styling.
Create headings with `<h1>` through `<h6>`. Headings use tokens with the `-heading` suffix, condensed line height, and `text-wrap: balance` for a prominent yet compact appearance.
```html {.example}
<h1>Heading 1</h1>
@@ -38,7 +63,7 @@ Semantic heading elements with proper hierarchy and styling.
### Paragraphs
Standard paragraph text with optimal spacing and readability.
Create paragraphs with `<p>`. Paragraphs inherit the default text styles set on the `<body>` element and use `text-wrap: pretty` to prevent orphaned lines in supported browsers.
```html {.example}
<p>
@@ -55,7 +80,7 @@ Standard paragraph text with optimal spacing and readability.
### Blockquotes
Styled quotations that stand out from regular text.
Emphasize longer quotations with `<blockquote>`. Block quotes use your theme's serif font family and a leading border to stand out.
```html {.example}
<blockquote>
@@ -67,51 +92,51 @@ Styled quotations that stand out from regular text.
### Lists
Organized content in bulleted or numbered format with proper nesting support.
Create ordered and unordered lists with `<ol>` and `<ul>`, plus `<li>` for list items within.
```html {.example}
<ul>
<li>List item 1</li>
<li>
List item 2
<ul>
<li>Subitem a</li>
<li>Subitem b</li>
</ul>
</li>
<li>List item 3</li>
</ul>
<div class="wa-grid">
<ol>
<li>First item</li>
<li>
Another item
<ol>
<li>Nested item</li>
<li>Another nested item</li>
</ol>
</li>
<li>Final item</li>
</ol>
<ol>
<li>List item 1</li>
<li>
List item 2
<ol>
<li>Subitem a</li>
<li>Subitem b</li>
</ol>
</li>
<li>List item 3</li>
</ol>
<ul>
<li>First item</li>
<li>
Another item
<ul>
<li>Nested item</li>
<li>Another nested item</li>
</ul>
</li>
<li>Final item</li>
</ul>
</div>
```
### Description Lists
Term and definition pairs for glossaries and descriptions.
Use `<dl>` to create lists of terms (`<dt>`) and definitions (`<dd>`).
```html {.example}
<dl>
<dt>Definition 1</dt>
<dt>First term</dt>
<dd>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</dd>
<dt>Definition 2</dt>
<dt>Second term</dt>
<dd>
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</dd>
<dt>Definition 3</dt>
<dt>Final term</dt>
<dd>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam,
eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
@@ -119,13 +144,153 @@ Term and definition pairs for glossaries and descriptions.
</dl>
```
### Code blocks
Create code blocks or other preformatted text with `<pre>`. Preformatted text uses your theme's monospace font family and a subtle background color.
```html {.example}
<pre>
// do a thing
export function thing() {
return true;
}
</pre>
```
### Inline text
Use any inline text element like `<strong>`, `<em>`, `<a>`, `<kbd>`, and others to stylize or emphasize text.
```html {.example}
<div class="wa-grid">
<div class="wa-stack wa-align-items-start">
<strong>Bold</strong>
<em>Italic</em>
<u>Underline</u>
<s>Strike-through</s>
<del>Deleted</del>
<ins>Inserted</ins>
<small>Small</small>
</div>
<div class="wa-stack wa-align-items-start">
<span>Subscript <sub>Sub</sub></span>
<span>Superscript <sup>Sup</sup></span>
<abbr title="Abbreviation">Abbr.</abbr>
<mark>Highlighted</mark>
<a href="#">Link text</a>
<code>Inline code</code>
<kbd>Keyboard</kbd>
</div>
</div>
```
## Widgets & media
### Media
Add responsive media with `<img>`, `<svg>`, `<video>`, `<iframe>`, and others. Media takes up 100% width by default and scales according to its container's width.
```html {.example}
<img
src="https://images.unsplash.com/photo-1620196244888-d31ff5bbf163?q=80&w=1000&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
alt="A gray kitten lays next to a toy"
/>
```
### Tables
Structure tabular data with `<table>` and related elements like `<caption>`, `<thead>`, `<tbody>`, `<th>`, `<tr>`, and `<td>`.
```html {.example}
<table>
<caption>
This <code>&lt;caption&gt;</code> describes the table
</caption>
<thead>
<tr>
<th>First column</th>
<th>Second column</th>
<th>Third column</th>
<th>Final column</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
</tbody>
</table>
```
Add the `wa-hover-rows` class to highlight table rows on hover and the `wa-zebra-rows` class to add alternating row colors to your table.
```html {.example}
<table class="wa-zebra-rows wa-hover-rows">
<thead>
<tr>
<th>First column</th>
<th>Second column</th>
<th>Third column</th>
<th>Final column</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
</tbody>
</table>
```
### Details
Collapsible content sections with expand/collapse functionality.
Create disclosure widgets with `<details>` and `<summary>`. Details closely match the appearance of [`<wa-details>`](/docs/components/details/).
```html {.example}
<details>
<summary>Tincidunt nunc pulvinar</summary>
<summary>Summary</summary>
<p>
Ut lectus arcu bibendum at varius. Convallis a cras semper auctor neque vitae. Odio pellentesque diam volutpat
commodo sed egestas. Amet dictum sit amet justo donec enim diam vulputate ut.
@@ -135,7 +300,7 @@ Collapsible content sections with expand/collapse functionality.
### Dialog
Modal dialog windows for alerts, confirmations, and overlays.
Create modal and non-modal dialog boxes with `<dialog>`. Dialogs closely match the appearance of [`<wa-dialog>`](/docs/components/dialog/).
```html {.example}
<dialog id="dialog-example">
@@ -155,55 +320,9 @@ Modal dialog windows for alerts, confirmations, and overlays.
</script>
```
### Inline Text
### Progress
Various text formatting elements for emphasis and semantic meaning.
```html {.example}
<div class="two-columns">
<p><strong>Bold</strong></p>
<p><em>Italic</em></p>
<p><u>Underline</u></p>
<p><s>Strike-through</s></p>
<p><del>Deleted</del></p>
<p><ins>Inserted</ins></p>
<p><small>Small</small></p>
<p>
<span>Subscript <sub>Sub</sub></span>
</p>
<p>
<span>Superscript <sup>Sup</sup></span>
</p>
<p><abbr title="Abbreviation">Abbr.</abbr></p>
<p><mark>Highlighted</mark></p>
<p><a href="#">Link text</a></p>
<p><code>Inline code</code></p>
<p><kbd>Keyboard</kbd></p>
</div>
```
### Code Blocks
Formatted code snippets with proper syntax styling.
```html {.example}
<pre>
// do a thing
export function thing() {
return true;
}
</pre>
```
### Images
Responsive images with proper scaling and styling.
![A gray kitten lays next to a toy](https://images.unsplash.com/photo-1620196244888-d31ff5bbf163?q=80&w=1000&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D)
### Progress Bars
Visual indicators for task completion and loading states.
Create progress indicators with `<progress>`. Progress indicators closely match the appearance of [`<wa-progress-bar>`](/docs/components/progress-bar/).
```html {.example}
<progress value="40" max="100"></progress>
@@ -211,156 +330,43 @@ Visual indicators for task completion and loading states.
<progress></progress>
```
### Tables
## Forms
Structured data presentation with clean styling and optional zebra striping.
```html {.example}
<table>
<caption>
I'm just a table
</caption>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
<th>Column 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
</tbody>
</table>
```
You can use the `wa-zebra-rows` class to add alternating row colors to your table:
```html {.example}
<table class="wa-zebra-rows">
<caption>
I'm just a table
</caption>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
<th>Column 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
</tbody>
</table>
```
## Form Controls
Native styles use [form control design tokens](/docs/tokens/component-groups/#form-controls) to style form elements like buttons and inputs. Form elements additionally inherit `font-family` from the `<body>` element.
### Buttons
Use the [variant utility classes](../utilities/color.md) to set the button's semantic variant.
Create buttons with `<button>` or `<input type="button | submit | reset">`. Buttons closely match the appearance of [`<wa-button>`](/docs/components/button/).
```html {.example}
<button class="wa-neutral"><wa-icon name="home"></wa-icon> Neutral</button>
<button>Button</button>
<input type="button" value="Input (button)" />
<input type="submit" value="Input (submit)" />
<input type="reset" value="Input (reset)" />
```
Add the `wa-brand`, `wa-neutral`, `wa-success`, `wa-warning`, or `wa-danger` class to specify the button's [color variant](/docs/utilities/color/).
```html {.example}
<button class="wa-neutral">Neutral</button>
<button class="wa-brand">Brand</button>
<button class="wa-success">Success</button>
<button class="wa-warning">Warning</button>
<button class="wa-danger">Danger</button>
```
Use the [appearance utility classes](/docs/utilities/appearance) to change the button's visual appearance:
Add the `wa-accent`, `wa-filled`, `wa-outlined`, or `wa-plain` class to specify the button's visual appearance.
```html {.example}
<div style="margin-block-end: 1rem;">
<button class="wa-accent wa-outlined wa-neutral">A + O</button>
<button class="wa-accent wa-neutral">Accent</button>
<button class="wa-outlined wa-neutral">Outlined</button>
<button class="wa-filled wa-outlined wa-neutral">F + O</button>
<button class="wa-filled wa-neutral">Filled</button>
<button class="wa-plain wa-neutral">Plain</button>
</div>
<div style="margin-block-end: 1rem;">
<button class="wa-accent wa-outlined wa-brand">A + O</button>
<button class="wa-accent wa-brand">Accent</button>
<button class="wa-outlined wa-brand">Outlined</button>
<button class="wa-filled wa-outlined wa-brand">F + O</button>
<button class="wa-filled wa-brand">Filled</button>
<button class="wa-plain wa-brand">Plain</button>
</div>
<div style="margin-block-end: 1rem;">
<button class="wa-accent wa-outlined wa-success">A + O</button>
<button class="wa-accent wa-success">Accent</button>
<button class="wa-outlined wa-success">Outlined</button>
<button class="wa-filled wa-outlined wa-success">F + O</button>
<button class="wa-filled wa-success">Filled</button>
<button class="wa-plain wa-success">Plain</button>
</div>
<div style="margin-block-end: 1rem;">
<button class="wa-accent wa-outlined wa-warning">A + O</button>
<button class="wa-accent wa-warning">Accent</button>
<button class="wa-outlined wa-warning">Outlined</button>
<button class="wa-filled wa-outlined wa-warning">F + O</button>
<button class="wa-filled wa-warning">Filled</button>
<button class="wa-plain wa-warning">Plain</button>
</div>
<div>
<button class="wa-accent wa-outlined wa-danger">A + O</button>
<button class="wa-accent wa-danger">Accent</button>
<button class="wa-outlined wa-danger">Outlined</button>
<button class="wa-filled wa-outlined wa-danger">F + O</button>
<button class="wa-filled wa-danger">Filled</button>
<button class="wa-plain wa-danger">Plain</button>
</div>
<button class="wa-accent wa-neutral">Accent</button>
<button class="wa-filled wa-outlined wa-neutral">Filled + Outlined</button>
<button class="wa-filled wa-neutral">Filled</button>
<button class="wa-outlined wa-neutral">Outlined</button>
<button class="wa-plain wa-neutral">Plain</button>
```
Use the [size utility classes](../utilities/size.md) to change a button's size.
Add the `wa-size-s`, `wa-size-m`, or `wa-size-l` class to specify the size of the button.
```html {.example}
<button class="wa-size-s">Small</button>
@@ -368,131 +374,154 @@ Use the [size utility classes](../utilities/size.md) to change a button's size.
<button class="wa-size-l">Large</button>
```
Use the `wa-pill` class to give buttons rounded edges.
Add the `wa-pill` class to give buttons rounded edges.
```html {.example}
<button class="wa-size-s wa-pill">Small</button>
<button class="wa-size-m wa-pill">Medium</button>
<button class="wa-size-l wa-pill">Large</button>
<button class="wa-pill">Pill button</button>
```
### Checkboxes
Multi-select form controls with checked, indeterminate, and disabled states.
When using `<wa-icon>` within a button, wrap adjacent label text in `<span>` or similar to automatically add margin between the icon and the label, just like the `start` and `end` slots of `<wa-button>`.
```html {.example}
<label><input type="checkbox" checked /> Checked</label><br />
<label><input type="checkbox" class="indeterminate" /> Indeterminate</label><br />
<label><input type="checkbox" disabled /> Disabled</label>
<button>
<wa-icon name="plane-departure"></wa-icon>
<span>Start Icon</span>
</button>
<button>
<span>End Icon</span>
<wa-icon name="plane-arrival"></wa-icon>
</button>
```
### Form controls
Create a variety of form controls with `<input type="">`, `<select>`, and `<textarea>`. Each control closely matches the appearance of the corresponding Web Awesome component.
```html {.example}
<div class="wa-stack">
<label>Text <input type="text" placeholder="add some text" /></label>
<label>Date <input type="date" /></label>
<label>Time <input type="time" /></label>
<label>Number <input type="number" placeholder="12345" /></label>
<label>Color <input type="color" value="#f36944" /></label>
<label>File <input type="file" multiple /></label>
<label>Range <input type="range" /></label>
<label>Select
<select>
<option value="option-1">Option 1</option>
<option value="option-2">Option 2</option>
<option value="option-3">Option 3</option>
</select>
</label>
<label>Textarea <textarea placeholder="add more text"></textarea></label>
<div class="wa-cluster">
<label><input type="checkbox" checked /> Checked</label>
<label><input type="checkbox" class="indeterminate" /> Indeterminate</label>
<label><input type="checkbox" /> Unchecked</label>
</div>
<div class="wa-cluster">
<label><input type="radio" name="radio-group" value="1" checked /> First radio</label>
<label><input type="radio" name="radio-group" value="2" /> Second radio</label>
<label><input type="radio" name="radio-group" value="3" /> Third radio</label>
</div>
</div>
<script>
document.querySelector('.indeterminate').indeterminate = true;
</script>
```
### Radios
Single-select form controls for mutually exclusive choices.
You can wrap native radios in a flex container to give them a horizontal or vertical orientation with even spacing. The convenience [`wa-cluster`](/docs/utilities/cluster) and [`wa-stack`](/docs/utilities/stack) utilities make this easy.
Add the `wa-size-s`, `wa-size-m`, or `wa-size-l` class to any form control or its parent `<label>` to specify its size.
```html {.example}
<div class="wa-cluster">
<label><input type="radio" name="b" value="1" checked /> Option 1</label>
<label><input type="radio" name="b" value="2" /> Option 2</label>
<label><input type="radio" name="b" value="3" /> Option 3</label>
</div>
<div class="wa-stack" style="margin-block-start: var(--wa-space-2xl);">
<label><input type="radio" name="g" value="1" checked /> Option 1</label>
<label><input type="radio" name="g" value="2" /> Option 2</label>
<label><input type="radio" name="g" value="3" /> Option 3</label>
<div class="wa-stack">
<input type="text" placeholder="Small input" class="wa-size-s" />
<div class="wa-cluster">
<label class="wa-size-s"><input type="checkbox" checked /> Small checkbox</label>
<label class="wa-size-s"><input type="radio" name="radio-small" value="1" checked /> Small radio</label>
</div>
<input type="text" placeholder="Medium input" class="wa-size-m" />
<div class="wa-cluster">
<label class="wa-size-m"><input type="checkbox" checked /> Medium checkbox</label>
<label class="wa-size-m"><input type="radio" name="radio-medium" value="1" checked /> Medium radio</label>
</div>
<input type="text" placeholder="Large input" class="wa-size-l" />
<div class="wa-cluster">
<label class="wa-size-l"><input type="checkbox" checked /> Large checkbox</label>
<label class="wa-size-l"><input type="radio" name="radio-large" value="1" checked /> Large radio</label>
</div>
</div>
```
### Selects
Dropdown menus for choosing from a list of options.
Add the `wa-filled` class to an input to give it a filled background.
```html {.example}
<label
>Select
<select id="select">
<option value="option-1">Option 1</option>
<option value="option-2">Option 2</option>
<option value="option-3">Option 3</option>
<div class="wa-stack">
<input type="text" placeholder="Filled input" class="wa-filled" />
<select class="wa-filled">
<option value="filled">Filled select</option>
</select>
</label>
<textarea placeholder="Filled textarea" class="wa-filled"></textarea>
</div>
```
### Sliders
Range inputs for selecting numeric values within a specified range.
Add the `wa-pill` class to an input or select to give it rounded edges.
```html {.example}
<label>Select a value: <input type="range" /></label>
<div class="wa-stack">
<input type="text" placeholder="Pill input" class="wa-pill" />
<select class="wa-pill">
<option value="pill">Pill select</option>
</select>
</div>
```
### Text Fields
Various input types for collecting user text and data.
Add any [button](#buttons) modifier class to `<input type="file">` to change the file selector button's color variant, appearance, size, and shape.
```html {.example}
<label>Text <input type="text" placeholder="placeholder" /></label>
<label>Number <input type="number" /></label>
<label>Password <input type="password" required /></label>
<label>Email <input type="email" /></label>
<label>Search <input type="search" /></label>
<label>Telephone <input type="tel" /></label>
<label>URL <input type="url" /></label>
```
Add the `wa-pill` class to an `<input>` to make it pill-shaped.
```html {.example}
<label>Input <input type="text" placeholder="placeholder" class="wa-pill" /></label>
```
### Color Pickers
Visual color selection interface with hex value input.
```html {.example}
<label>Input (color) <input type="color" value="#ff0066" /></label>
```
### Date & Time Pickers
Specialized inputs for selecting dates, times, and datetime values.
```html {.example}
<label>Input (datetime-local) <input type="datetime-local" /></label>
<label>Input (date) <input type="date" /></label>
<label>Input (time) <input type="time" /></label>
```
### Textareas
Multi-line text input fields for longer content.
```html {.example}
<label>Textarea <textarea placeholder="Type something"></textarea></label>
<input type="file" class="wa-filled wa-outlined wa-warning wa-size-s wa-pill" />
```
### Fieldsets
Group form controls together with `<fieldset>` and `<legend>`.
```html {.example}
<fieldset>
<fieldset class="wa-stack wa-align-items-start">
<legend>Legend</legend>
Nunc mi ipsum faucibus vitae aliquet nec ullamcorper. Tincidunt id aliquet risus feugiat in ante. Ac turpis egestas
integer eget aliquet nibh praesent tristique magna.
<label><input type="radio" name="legends" value="1" checked /> King Arthur</label>
<label><input type="radio" name="legends" value="2" /> Robin Hood</label>
<label><input type="radio" name="legends" value="3" /> Odysseus</label>
</fieldset>
```
### Form layouts
Wrap form controls in a flex container to arrange them horizontally or vertically with even spacing. Layout utility classes like [`wa-cluster`](/docs/utilities/cluster) and [`wa-stack`](/docs/utilities/stack) can be added directly to a `<fieldset>` or `<form>` to make this especially easy.
```html {.example}
<fieldset class="wa-cluster">
<legend>Ducks in a row</legend>
<label><input type="checkbox" checked /> Mallard</label>
<label><input type="checkbox" /> Common Loon</label>
<label><input type="checkbox" /> Least Grebe</label>
</fieldset>
<br />
<form class="wa-stack">
<label>Number of pancakes <input type="number" value="5" /></label>
<label>Syrup flavor
<select>
<option value="maple">Maple</option>
<option value="strawberry">Strawberry</option>
<option value="blueberry">Blueberry</option>
<option value="pecan">Butter pecan</option>
</select>
</label>
<label><input type="checkbox" checked /> Add whipped butter</label>
<button>
<wa-icon name="pancakes"></wa-icon>
Stack 'em up
</button>
</form>
```

View File

@@ -3,7 +3,7 @@ unlisted: true
layout: false
---
<!doctype html>
<html lang="en" class="wa-cloak" data-fa-kit-code="b10bfbde90">
<html lang="en" class="wa-cloak" data-fa-kit-code="38c11e3f20">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@@ -100,7 +100,7 @@ layout: false
<div class="wa-flank">
<wa-avatar
shape="rounded"
style="--background-color: var(--wa-color-green-60); --text-color: var(--wa-color-green-95)"
style="background-color: var(--wa-color-green-60); color: var(--wa-color-green-95)"
>
<wa-icon slot="icon" name="sword-laser"></wa-icon>
</wa-avatar>
@@ -119,7 +119,7 @@ layout: false
<div class="wa-flank">
<wa-avatar
shape="rounded"
style="--background-color: var(--wa-color-cyan-60); --text-color: var(--wa-color-cyan-95)"
style="background-color: var(--wa-color-cyan-60); color: var(--wa-color-cyan-95)"
>
<wa-icon slot="icon" name="robot-astromech"></wa-icon>
</wa-avatar>
@@ -304,15 +304,15 @@ layout: false
<wa-divider></wa-divider>
<dl class="wa-stack">
<div class="wa-flank wa-align-items-center">
<dt><wa-icon name="user" label="Name" fixed-width></wa-icon></dt>
<dt><wa-icon name="user" label="Name"></wa-icon></dt>
<dd>Tom Bombadil</dd>
</div>
<div class="wa-flank wa-align-items-center">
<dt><wa-icon name="calendar-days" label="Date" fixed-width></wa-icon></dt>
<dt><wa-icon name="calendar-days" label="Date"></wa-icon></dt>
<dd><wa-format-date date="2025-03-15"></wa-format-date></dd>
</div>
<div class="wa-flank wa-align-items-center">
<dt><wa-icon name="coin-vertical" fixed-width></wa-icon></dt>
<dt><wa-icon name="coin-vertical"></wa-icon></dt>
<dd>Paid with copper pennies</dd>
</div>
</dl>
@@ -344,19 +344,19 @@ layout: false
<h4 class="wa-heading-s">What You Get</h4>
<div class="wa-stack">
<div class="wa-flank">
<wa-icon name="user" fixed-width></wa-icon>
<wa-icon name="user"></wa-icon>
<span class="wa-caption-m">9 users</span>
</div>
<div class="wa-flank">
<wa-icon name="ring" fixed-width></wa-icon>
<wa-icon name="ring"></wa-icon>
<span class="wa-caption-m">1 ring</span>
</div>
<div class="wa-flank">
<wa-icon name="chess-rook" fixed-width></wa-icon>
<wa-icon name="chess-rook"></wa-icon>
<span class="wa-caption-m">API access to Isengard</span>
</div>
<div class="wa-flank">
<wa-icon name="feather" fixed-width></wa-icon>
<wa-icon name="feather"></wa-icon>
<span class="wa-caption-m">Priority eagle support</span>
</div>
</div>
@@ -403,7 +403,7 @@ layout: false
<a href="" class="wa-flank wa-link-plain" tabindex="-1">
<wa-avatar
shape="rounded"
style="--background-color: var(--wa-color-yellow-90); --text-color: var(--wa-color-yellow-50)"
style="background-color: var(--wa-color-yellow-90); color: var(--wa-color-yellow-50)"
>
<wa-icon slot="icon" name="egg-fried"></wa-icon>
</wa-avatar>
@@ -435,7 +435,7 @@ layout: false
<a href="" class="wa-flank wa-align-items-start wa-link-plain" tabindex="-1">
<wa-avatar
shape="rounded"
style="--background-color: var(--wa-color-blue-90); color: var(--wa-color-blue-50)"
style="background-color: var(--wa-color-blue-90); color: var(--wa-color-blue-50)"
>
<wa-icon slot="icon" name="shield"></wa-icon>
</wa-avatar>
@@ -449,7 +449,7 @@ layout: false
<a href="" class="wa-flank wa-align-items-start wa-link-plain" tabindex="-1">
<wa-avatar
shape="rounded"
style="--background-color: var(--wa-color-green-90); color: var(--wa-color-green-50)"
style="background-color: var(--wa-color-green-90); color: var(--wa-color-green-50)"
>
<wa-icon slot="icon" name="chevrons-up"></wa-icon>
</wa-avatar>
@@ -463,7 +463,7 @@ layout: false
<a href="" class="wa-flank wa-align-items-start wa-link-plain" tabindex="-1">
<wa-avatar
shape="rounded"
style="--background-color: var(--wa-color-red-90); color: var(--wa-color-red-50)"
style="background-color: var(--wa-color-red-90); color: var(--wa-color-red-50)"
>
<wa-icon slot="icon" name="explosion"></wa-icon>
</wa-avatar>
@@ -477,7 +477,7 @@ layout: false
<a href="" class="wa-flank wa-align-items-start wa-link-plain" tabindex="-1">
<wa-avatar
shape="rounded"
style="--background-color: var(--wa-color-yellow-90); color: var(--wa-color-yellow-50)"
style="background-color: var(--wa-color-yellow-90); color: var(--wa-color-yellow-50)"
>
<wa-icon slot="icon" name="moon-stars"></wa-icon>
</wa-avatar>
@@ -616,8 +616,8 @@ layout: false
}
}
wa-progress-bar::part(base) {
height: 0.5em;
wa-progress-bar {
--track-height: 0.5em;
}
</style>
</body>

View File

@@ -136,35 +136,22 @@ layout: page
margin-block-start: 1rem;
}
}
.link-panel {
background-color: var(--wa-color-neutral-fill-quiet);
border-radius: 0.75rem;
padding: 1.25rem;
& h3 {
font-size: 1rem;
}
& .icon-heading wa-icon {
background-color: var(--wa-color-neutral-fill-loud);
color: var(--wa-color-neutral-on-loud);
}
& p {
font-size: 0.875rem;
}
}
.icon-heading {
display: flex;
align-items: center;
gap: 1rem;
margin-block-end: 1rem;
& wa-icon {
> wa-icon {
display: flex;
align-items: center;
justify-content: center;
background-color: var(--wa-brand-orange);
color: white;
block-size: 2em;
inline-size: 2em;
background-color: var(--wa-color-neutral-fill-loud);
color: var(--wa-color-neutral-on-loud);
border-radius: 0.25rem;
aspect-ratio: 1;
padding: 0.5em;
&.brand-orange {
background-color: var(--wa-brand-orange);
color: white;
}
}
& h3 {
font-size: 1rem;
@@ -224,8 +211,8 @@ layout: page
text-align: left;
white-space: wrap;
}
wa-button.tile::part(end) {
display: none;
wa-button.tile::part(label) {
width: 100%;
}
wa-button.tile {
width: 100%;
@@ -266,11 +253,17 @@ layout: page
</div>
<h1 class="brand-font">Make something <span class="emphasis">awesome</span> with open-source web components</h1>
<div class="hero-cta">
<span><em>Psst!</em> You can pre-order Web Awesome Pro at a low, guaranteed-for-life price &mdash; but not for long. Get in while the gettins good.</span>
<wa-button class="wa-dark" size="small" href="https://www.kickstarter.com/projects/fontawesome/web-awesome">
<wa-icon slot="start" name="person-running"></wa-icon>
Pre-order WA Pro
</wa-button>
{%- raw -%}
{% if currentUser.hasPro %}
<span style="text-align: center; width: 100%; font-size: var(--wa-font-size-l);">Thanks for being a Web Awesome Pro subscriber!</span>
{% else %}
<span><em>Psst!</em> You can pre-order Web Awesome Pro at a low, guaranteed-for-life price &mdash; but not for long. Get in while the gettins good.</span>
<wa-button class="wa-dark" size="small" href="https://www.kickstarter.com/projects/fontawesome/web-awesome">
<wa-icon slot="start" name="person-running"></wa-icon>
Pre-order WA Pro
</wa-button>
{% endif %}
{% endraw %}
</div>
</div>
</div>
@@ -279,23 +272,27 @@ layout: page
<div class="beta-notice">
<div>
<wa-callout variant="brand">
<div class="icon-heading">
<wa-icon name="sparkles" variant="regular" fixed-width></wa-icon>
<h3>Rise and shine, backers!</h3>
<div class="wa-stack">
<div class="wa-cluster icon-heading">
<wa-icon name="sparkles" variant="regular"></wa-icon>
<h3>Bigger and beta than ever</h3>
</div>
<p>This beta is battle-tested and built to last, but if you see something, say something. Please <a href="https://github.com/shoelace-style/webawesome/issues">report bugs</a> or <a href="https://github.com/shoelace-style/webawesome/discussions">ask for help</a>!</p>
</div>
<p>Dig in to your exclusive Web Awesome Beta access. This beta is battle-tested and built to last, but if you see something, say something. Please <a href="https://github.com/shoelace-style/webawesome/issues">report bugs</a> or <a href="https://github.com/shoelace-style/webawesome/discussions">ask for help</a>!</p>
</wa-callout>
</div>
<div>
<wa-button href="/docs/" appearance="outlined" class="tile">
<div style="display: flex; justify-content: space-between; align-items: center; margin-block-end: 1rem;">
<div class="icon-heading" style="margin-block-end: 0;">
<wa-icon name="pen-ruler" fixed-width></wa-icon>
<h3>Get started</h3>
<div class="wa-stack">
<div class="wa-split">
<div class="wa-cluster icon-heading">
<wa-icon name="pen-ruler" class="brand-orange"></wa-icon>
<h3>Get started</h3>
</div>
<wa-icon name="arrow-right"></wa-icon>
</div>
<wa-icon name="arrow-right" fixed-width></wa-icon>
<p>Check out our installation guide to start building with Web Awesome.</p>
</div>
<p>Check out our installation guide to start building with Web Awesome.</p>
</wa-button>
</div>
</div>
@@ -304,30 +301,30 @@ layout: page
<h2 class="brand-font">What's <span class="emphasis">Web</span> Awesome?</h2>
<p>Web Awesome is the biggest open-source library of meticulously designed, highly customizable, and framework-agnostic UI components.</p>
<div class="grid">
<div>
<div class="icon-heading">
<wa-icon name="code" fixed-width></wa-icon>
<div class="wa-stack">
<div class="wa-cluster icon-heading">
<wa-icon name="code" class="brand-orange"></wa-icon>
<h3>Entirely native</h3>
</div>
<p>Built on web standards to last for years to come. No excess tooling. No third-party bloat.</p>
</div>
<div>
<div class="icon-heading">
<wa-icon name="palette" fixed-width></wa-icon>
<div class="wa-stack">
<div class="wa-cluster icon-heading">
<wa-icon name="palette" class="brand-orange"></wa-icon>
<h3>Fully customizable</h3>
</div>
<p>Show off your own style with components that consistently adapt to your theme.</p>
</div>
<div>
<div class="icon-heading">
<wa-icon name="wheelchair-move" fixed-width></wa-icon>
<div class="wa-stack">
<div class="wa-cluster icon-heading">
<wa-icon name="wheelchair-move" class="brand-orange"></wa-icon>
<h3>Accessibility forward</h3>
</div>
<p>Build a website that everyone can use. Designed to be inclusive and usable by everyone.</p>
</div>
<div>
<div class="icon-heading">
<wa-icon name="handshake-simple" fixed-width></wa-icon>
<div class="wa-stack">
<div class="wa-cluster icon-heading">
<wa-icon name="handshake-simple" class="brand-orange"></wa-icon>
<h3>Proudly open source</h3>
</div>
<p>Use Web Awesome Free however you like. Always free, always open source.</p>
@@ -342,24 +339,84 @@ layout: page
<p>Whether youre a developer, designer, or budding tech nerd, we want you a part of the conversation.</p>
</div>
<div>
<div class="link-panel">
<div class="icon-heading">
<wa-icon name="envelope-open" fixed-width></wa-icon>
<h3>Get in touch</h3>
<wa-button href="https://github.com/shoelace-style/webawesome" rel="noopener noreferrer" target="_blank" appearance="filled" class="tile">
<div class="wa-stack">
<div class="wa-split">
<div class="wa-cluster icon-heading">
<wa-icon family="brands" name="github"></wa-icon>
<h3>GitHub</h3>
</div>
<wa-icon name="arrow-up-right"></wa-icon>
</div>
<p>Get involved by opening issues, contributing to discussions, or creating PRs.</p>
</div>
<p>Have a question? Want to share your feedback? Just stopping by to say 'hi'? Email us at <a href="mailto:hello@webawesome.com">hello@webawesome.com</a>.</p>
</div>
<div class="link-panel">
<div class="icon-heading">
<wa-icon name="hashtag" fixed-width></wa-icon>
<h3>Follow us</h3>
</wa-button>
<wa-button href="https://discord.gg/mg8f26C" rel="noopener noreferrer" target="_blank" appearance="filled" class="tile">
<div class="wa-stack">
<div class="wa-split">
<div class="wa-cluster icon-heading">
<wa-icon family="brands" name="discord"></wa-icon>
<h3>Discord</h3>
</div>
<wa-icon name="arrow-up-right"></wa-icon>
</div>
<p>Share your work, ask questions, and explore ideas with other Web Awesome builders.</p>
</div>
<p>Keep up with Web Awesome through updates, announcements, and polls. Find us on <a href="https://bsky.app/profile/webawesome.com">Bluesky</a>, <a href="https://x.com/webawesomer">Twitter (X)</a>, and <a href="https://www.threads.com/@web.awesome">Threads</a>.</p>
</div>
</wa-button>
<wa-button href="mailto:hello@webawesome.com" appearance="filled" class="tile">
<div class="wa-split">
<div class="wa-cluster icon-heading">
<wa-icon name="envelope-open"></wa-icon>
<h3 class="wa-cluster wa-gap-xs">
<span>hello@webawesome.com</span>
<wa-icon name="hand-wave" variant="regular"></wa-icon>
</h3>
</div>
<wa-icon name="arrow-up-right"></wa-icon>
</div>
</wa-button>
</div>
</div>
<wa-divider></wa-divider>
<wa-divider></wa-divider>
<div class="wa-stack wa-gap-xl">
<h2 class="wa-cluster brand-font">
<wa-icon name="hashtag" style="color: var(--wa-brand-orange);"></wa-icon>
<span>Stay in the know</span>
</h2>
<div class="wa-grid">
<wa-button href="https://bsky.app/profile/webawesome.com" rel="noopener noreferrer" target="_blank" appearance="filled" class="tile">
<div class="wa-split">
<div class="wa-cluster icon-heading">
<wa-icon family="brands" name="bluesky"></wa-icon>
<h3>Bluesky</h3>
</div>
<wa-icon name="arrow-up-right"></wa-icon>
</div>
</wa-button>
<wa-button href="https://x.com/webawesomer" rel="noopener noreferrer" target="_blank" appearance="filled" class="tile">
<div class="wa-split">
<div class="wa-cluster icon-heading">
<wa-icon family="brands" name="x-twitter"></wa-icon>
<h3>Twitter (X)</h3>
</div>
<wa-icon name="arrow-up-right"></wa-icon>
</div>
</wa-button>
<wa-button href="https://www.threads.com/@web.awesome" rel="noopener noreferrer" target="_blank" appearance="filled" class="tile">
<div class="wa-split">
<div class="wa-cluster icon-heading">
<wa-icon family="brands" name="threads"></wa-icon>
<h3>Threads</h3>
</div>
<wa-icon name="arrow-up-right"></wa-icon>
</div>
</wa-button>
</div>
</div>
<wa-divider></wa-divider>
<footer>
<div class="wa-crown">
@@ -373,9 +430,9 @@ layout: page
<div class="attribution">
<span>Special thanks</span>
<div class="button-list">
<wa-button appearance="filled" pill href="https://www.11ty.dev/">11ty</wa-button>
<wa-button appearance="filled" pill href="https://lit.dev/">Lit</wa-button>
<wa-button appearance="filled" pill href="https://github.com/open-wc/custom-elements-manifest">Custom Elements Manifest</wa-button>
<wa-button appearance="filled" pill href="https://www.11ty.dev/">11ty</wa-button>
<wa-button appearance="filled" pill href="https://floating-ui.com/">Floating UI</wa-button>
<wa-button appearance="filled" pill href="https://animate.style/">animate.css</wa-button>
<wa-button appearance="filled" pill href="https://lunrjs.com/">Lunr</wa-button>
@@ -386,4 +443,4 @@ layout: page
&copy; Fonticons, Inc.
</div>
</footer>
</div>
</div>

View File

@@ -1,7 +1,10 @@
{
"name": "@shoelace-style/webawesome",
"name": "@awesome.me/webawesome",
"publishConfig": {
"access": "public"
},
"description": "A forward-thinking library of web components.",
"version": "3.0.0-beta.1",
"version": "3.0.0-beta.5",
"homepage": "https://webawesome.com/",
"author": "Web Awesome",
"license": "MIT",
@@ -16,20 +19,23 @@
"import": "./dist/webawesome.js"
},
"./dist/custom-elements.json": "./dist/custom-elements.json",
"./dist/custom-elements-jsx.d.ts": "./dist/custom-elements-jsx.d.ts",
"./dist/webawesome.js": "./dist/webawesome.js",
"./dist/webawesome.loader.js": "./dist/webawesome.loader.js",
"./dist/themes": "./dist/themes",
"./dist/themes/*": "./dist/themes/*",
"./dist/styles": "./dist/styles",
"./dist/styles/*": "./dist/styles/*",
"./dist/components": "./dist/components",
"./dist/components/*": "./dist/components/*",
"./dist/react": "./dist/react/index.js",
"./dist/react/*": "./dist/react/*",
"./dist/translations": "./dist/translations",
"./dist/translations/*": "./dist/translations/*"
"./dist/translations/*": "./dist/translations/*",
"./package.json": "./package.json"
},
"files": [
"README.md",
"dist",
"cdn"
"dist-cdn"
],
"keywords": [
"web components",
@@ -69,17 +75,21 @@
"dependencies": {
"@ctrl/tinycolor": "^4.1.0",
"@floating-ui/dom": "^1.6.13",
"@lit/react": "^1.0.8",
"@shoelace-style/animations": "^1.2.0",
"@shoelace-style/localize": "^3.2.1",
"composed-offset-position": "^0.0.6",
"lit": "^3.2.1",
"nanoid": "^5.1.5",
"qr-creator": "^1.0.0",
"style-observer": "^0.0.7"
},
"devDependencies": {},
"lint-staged": {
"*.{ts,js}": [
"prettier --write"
]
},
"devDependencies": {
"@wc-toolkit/jsx-types": "^1.3.0"
}
}

View File

@@ -4,19 +4,20 @@ import { execSync } from 'child_process';
import { deleteAsync } from 'del';
import esbuild from 'esbuild';
import { replace } from 'esbuild-plugin-replace';
import { mkdir, readFile } from 'fs/promises';
import getPort, { portNumbers } from 'get-port';
import { globby } from 'globby';
import { dirname, join, relative } from 'node:path';
import { dirname, extname, join, posix, relative } from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import ora from 'ora';
import copy from 'recursive-copy';
import { getCdnDir, getDistDir, getDocsDir, getRootDir, getSiteDir, runScript } from './utils.js';
import { SimulateWebAwesomeApp } from '../docs/_utils/simulate-webawesome-app.js';
import { generateDocs } from './docs.js';
import { getCdnDir, getDistDir, getDocsDir, getRootDir, getSiteDir } from './utils.js';
const __dirname = dirname(fileURLToPath(import.meta.url));
const isDeveloping = process.argv.includes('--develop');
const spinner = ora({ text: 'Web Awesome', color: 'cyan' }).start();
const getPackageData = async () => JSON.parse(await readFile(join(getRootDir(), 'package.json'), 'utf-8'));
const getVersion = async () => JSON.stringify((await getPackageData()).version.toString());
@@ -25,11 +26,16 @@ let buildContexts = {
unbundledContext: {},
};
const debugPerf = process.env.DEBUG_PERFORMANCE === '1';
const isDeveloping = process.argv.includes('--develop');
/**
* @typedef {Object} BuildOptions
* @property {Array<string>} [watchedSrcDirectories]
* @property {Array<string>} [watchedDocsDirectories]
* @property {(eventName: "change" | "add" | "unlink", filePath: string) => unknown} [onWatchEvent]
* @property {(eventName: "change" | "add" | "unlink", filePath: string) => unknown} [beforeWatchEvent]
* @property {(eventName: "change" | "add" | "unlink", filePath: string) => unknown} [afterWatchEvent]
*/
/**
@@ -51,17 +57,24 @@ export async function build(options = {}) {
const start = Date.now();
try {
await cleanup();
await generateManifest();
await generateReactWrappers();
await generateTypes();
await generateStyles();
const steps = [cleanup, generateManifest, generateReactWrappers, generateTypes, generateStyles];
for (const step of steps) {
if (debugPerf) {
const stepStart = Date.now();
await step();
const elapsedTime = (Date.now() - stepStart) / 1000 + 's';
spinner.succeed(`${step.name}: ${elapsedTime}`);
} else {
await step();
}
}
// copy everything to unbundled before we generate bundles.
await copy(getCdnDir(), getDistDir(), { overwrite: true });
await generateBundle();
await generateDocs();
await generateDocs({ spinner });
const time = (Date.now() - start) / 1000 + 's';
spinner.succeed(`The build is complete ${chalk.gray(`(finished in ${time})`)}`);
@@ -108,6 +121,12 @@ export async function build(options = {}) {
* Generates React wrappers for all components.
*/
function generateReactWrappers() {
// Used by webawesome-app to make re-rendering not miserable with extra React file generation.
if (process.env.SKIP_SLOW_STEPS === 'true') {
spinner.info('Skipping React Wrapper generation.');
return Promise.resolve();
}
spinner.start('Generating React wrappers');
try {
@@ -142,6 +161,12 @@ export async function build(options = {}) {
* Runs TypeScript to generate types.
*/
async function generateTypes() {
// Used by webawesome-app to make re-rendering not miserable with extra TS compilations.
if (process.env.SKIP_SLOW_STEPS === 'true') {
spinner.info('Skipping TypeScript compiler.');
return Promise.resolve();
}
spinner.start('Running the TypeScript compiler');
const cwd = process.cwd();
@@ -186,11 +211,11 @@ export async function build(options = {}) {
join(rootDir, 'src/webawesome.loader.ts'),
join(rootDir, 'src/webawesome.ssr-loader.ts'),
// Individual components
...(await globby(join(rootDir, 'src/components/**/!(*.(style|test)).ts'))),
...(await globby(posix.join(rootDir, 'src/components/**/!(*.(style|test)).ts'))),
// Translations
...(await globby(join(rootDir, 'src/translations/**/*.ts'))),
...(await globby(posix.join(rootDir, 'src/translations/**/*.ts'))),
// React wrappers
...(await globby(join(rootDir, 'src/react/**/*.ts'))),
...(await globby(posix.join(rootDir, 'src/react/**/*.ts'))),
],
outdir: getCdnDir(),
chunkNames: 'chunks/[name].[hash]',
@@ -258,49 +283,6 @@ export async function build(options = {}) {
spinner.succeed();
}
/**
* Generates the documentation site.
*/
async function generateDocs() {
/**
* Used by the webawesome-app to skip doc generation since it will do its own.
*/
if (process.env.SKIP_ELEVENTY === 'true') {
return;
}
spinner.start('Writing the docs');
const args = [];
if (isDeveloping) args.push('--develop');
let output;
try {
// 11ty
output = (await runScript(join(__dirname, 'docs.js'), args, { env: process.env }))
// Cleanup the output
.replace('[11ty]', '')
.replace(' seconds', 's')
.replace(/\(.*?\)/, '')
.toLowerCase()
.trim();
// Copy dist (production only)
if (!isDeveloping) {
await copy(getCdnDir(), join(getSiteDir(), 'dist'));
}
spinner.succeed(`Writing the docs ${chalk.gray(`(${output}`)})`);
} catch (error) {
console.error('\n\n' + chalk.red(error) + '\n');
spinner.fail(chalk.red(`Error while writing the docs.`));
if (!isDeveloping) {
process.exit(1);
}
}
}
// Initial build
await buildAll();
@@ -338,6 +320,46 @@ export async function build(options = {}) {
'/dist/': './dist-cdn/',
},
},
middleware: [
function simulateWebawesomeApp(req, res, next) {
// Accumulator for strings so we can pass them through nunjucks a second time similar to how the webawesome-app
// will be running nunjucks twice.
const finalString = [];
const encoding = 'utf-8';
if (!next) {
return;
}
if (!req.url) {
next();
return;
}
const extension = extname(req.url);
if (extension !== '' && extension !== '.html') {
// Assume its something like .svg / .png / .css etc. that we don't want to transform.
next();
return;
}
const _write = res.write;
res.write = function (chunk, encoding) {
// Buffer chunks into an array so that we do a single transform.
finalString.push(chunk.toString());
};
const _end = res.end;
res.end = function (...args) {
const transformedStr = SimulateWebAwesomeApp(finalString.join(''));
_write.call(res, transformedStr, encoding);
_end.call(res, ...args);
};
next();
},
],
callbacks: {
ready: (_err, instance) => {
// 404 errors
@@ -366,22 +388,25 @@ export async function build(options = {}) {
},
);
// TODO: Should probably listen for all of these instead of just "change"
const watchEvents = [
'change',
// "unlink",
// "add"
];
const watchEvents = ['change', 'unlink', 'add'];
// Rebuild and reload when source files change
options.watchedSrcDirectories.forEach(dir => {
const watcher = bs.watch(join(dir, '**', '!(*.test).*'));
const watcher = bs.watch(join(dir, '**', '!(*.test).*'), { ignoreInitial: true });
watchEvents.forEach(evt => {
watcher.on(evt, handleWatchEvent(evt));
});
function handleWatchEvent(evt) {
return async filename => {
spinner.info(`File modified ${chalk.gray(`(${relative(getRootDir(), filename)})`)}`);
const changedFile = relative(getRootDir(), filename);
if (evt === 'change') {
spinner.info(`File modified ${chalk.gray(`(${changedFile})`)}`);
} else if (evt === 'unlink') {
spinner.info(`File deleted ${chalk.gray(`(${changedFile})`)}`);
} else if (evt === 'add') {
spinner.info(`File added ${chalk.gray(`(${changedFile})`)}`);
}
try {
const isTestFile = filename.includes('.test.ts');
@@ -394,10 +419,9 @@ export async function build(options = {}) {
return;
}
if (typeof options.onWatchEvent === 'function') {
await options.onWatchEvent(evt, filename);
if (typeof options.beforeWatchEvent === 'function') {
await options.beforeWatchEvent(evt, filename);
}
await regenerateBundle();
// Copy stylesheets when CSS files change
if (isCssStylesheet) {
@@ -409,8 +433,16 @@ export async function build(options = {}) {
await generateManifest();
}
// copy everything to unbundled before we generate bundles.
await copy(getCdnDir(), getDistDir(), { overwrite: true });
await regenerateBundle();
// This needs to be outside of "isComponent" check because SSR needs to run on CSS files too.
await generateDocs();
await generateDocs({ spinner });
if (typeof options.afterWatchEvent === 'function') {
await options.afterWatchEvent(evt, filename);
}
reload();
} catch (err) {
@@ -426,7 +458,7 @@ export async function build(options = {}) {
// Rebuild the docs and reload when the docs change
options.watchedDocsDirectories.forEach(dir => {
const watcher = bs.watch(join(dir, '**', '*.*'));
const watcher = bs.watch(join(dir, '**', '*.*'), { ignoreInitial: true });
watchEvents.forEach(evt => {
watcher.on(evt, handleWatchEvent(evt));
@@ -434,11 +466,33 @@ export async function build(options = {}) {
function handleWatchEvent(evt) {
return async filename => {
spinner.info(`File modified ${chalk.gray(`(${relative(getRootDir(), filename)})`)}`);
if (typeof options.onWatchEvent === 'function') {
await options.onWatchEvent(evt, filename);
const changedFile = relative(getRootDir(), filename);
let message = '';
if (evt === 'change') {
message = chalk.blue(`File modified ${chalk.gray(`(${changedFile})`)}`);
} else if (evt === 'unlink') {
message = chalk.red(`File deleted ${chalk.gray(`(${changedFile})`)}`);
} else if (evt === 'add') {
message = chalk.green(`File added ${chalk.gray(`(${changedFile})`)}`);
}
if (message) {
if (spinner) {
spinner.info(message);
} else {
console.log(message);
}
}
if (typeof options.beforeWatchEvent === 'function') {
await options.beforeWatchEvent(evt, filename);
}
await generateDocs({ spinner });
if (typeof options.afterWatchEvent === 'function') {
await options.afterWatchEvent(evt, filename);
}
await generateDocs();
reload();
};
}

View File

@@ -1,14 +1,268 @@
import Eleventy from '@11ty/eleventy';
import copy from 'recursive-copy';
import chalk from 'chalk';
import { deleteAsync } from 'del';
import { getDocsDir, getEleventyConfigPath, getSiteDir } from './utils.js';
import { join } from 'path';
import { getCdnDir, getDocsDir, getEleventyConfigPath, getSiteDir } from './utils.js';
const elev = new Eleventy(getDocsDir(), getSiteDir(), {
quietMode: true,
configPath: getEleventyConfigPath(),
});
let eleventyBuildResolver;
let eleventyBuildPromise;
// Cleanup
await deleteAsync(getSiteDir());
function queueBuild() {
eleventyBuildPromise = new Promise(resolve => {
eleventyBuildResolver = resolve;
});
}
// Write it
await elev.write();
// 11ty
export async function createEleventy(options = {}) {
let { isIncremental, isDeveloping, rootDir } = options;
isDeveloping ??= process.argv.includes('--develop');
isIncremental ??= isDeveloping && !process.argv.includes('--no-incremental');
const eleventy = new Eleventy(rootDir || getDocsDir(), getSiteDir(), {
quietMode: true,
configPath: getEleventyConfigPath(),
config: eleventyConfig => {
if (isDeveloping || isIncremental) {
eleventyConfig.setUseTemplateCache(false);
eleventyConfig.on('eleventy.before', function () {
queueBuild();
});
eleventyConfig.on('eleventy.beforeWatch', async function () {
queueBuild();
});
eleventyConfig.on('eleventy.after', async function () {
eleventyBuildResolver();
});
}
},
source: 'script',
runMode: isIncremental ? 'watch' : 'build',
});
eleventy.setIncrementalBuild(isIncremental);
await eleventy.init();
eleventy.logger.isChalkEnabled = false;
eleventy.logger.overrideLogger(new CustomLogger());
if (isIncremental) {
await eleventy.watch();
process.on('SIGINT', async () => {
await eleventy.stopWatch();
process.exitCode = 0;
});
}
return eleventy;
}
/**
* Generates the documentation site.
*/
export async function generateDocs(options = {}) {
let { spinner, isIncremental, isDeveloping } = options;
isDeveloping ??= process.argv.includes('--develop');
isIncremental ??= isDeveloping && !process.argv.includes('--no-incremental');
/**
* Used by the webawesome-app to skip doc generation since it will do its own.
*/
if (process.env.SKIP_ELEVENTY === 'true') {
return;
}
let eleventy = globalThis.eleventy;
spinner?.start?.('Writing the docs');
const outputs = {
warn: [],
};
function stubConsole(key) {
const originalFn = console[key];
console[key] = function (...args) {
outputs[key].push(...args);
};
return originalFn;
}
// Works around a bug in 11ty where it still prints warnings despite the logger being overriden and in quietMode.
const originalWarn = stubConsole('warn');
let output = '';
try {
if (isIncremental) {
if (!globalThis.eleventy) {
// First run
globalThis.eleventy = await createEleventy(options);
eleventy = globalThis.eleventy;
output = chalk.gray(`(${eleventy.logFinished()})`);
} else {
// eleventy incremental does its own writing, so we just kinda trust it for right now.
eleventy = globalThis.eleventy;
await eleventyBuildPromise;
let info = eleventy.logger.logger.outputs.log;
// TODO: The first write with incremental seems to be 1 behind. Not sure why. But its good enough for now.
info = info.filter(line => {
return !line.includes('Watching');
});
const lastLine = info[info.length - 1];
output = chalk.gray(`(${info.join('')})`);
eleventy.logger.logger.reset();
}
} else {
// Cleanup
await deleteAsync(getSiteDir());
globalThis.eleventy = await createEleventy(options);
eleventy = globalThis.eleventy;
// Write it
await eleventy.write();
output = chalk.gray(`(${eleventy.logFinished()})`);
}
// Copy dist (production only)
if (!isDeveloping) {
await copy(getCdnDir(), join(getSiteDir(), 'dist'));
}
if (spinner) {
spinner.succeed(`Writing the docs ${output}`);
} else {
console.log(`Writing the docs ${output}`);
}
} catch (error) {
console.warn = originalWarn;
console.error('\n\n' + chalk.red(error) + '\n');
if (spinner) {
spinner.fail(chalk.red(`Error while writing the docs.`));
} else {
console.error(chalk.red(`Error while writing the docs.`));
}
if (!isDeveloping) {
process.exit(1);
}
}
}
/**
* Much of this code is taken from 11ty's ConsoleLogger here:
* https://github.com/11ty/eleventy/blob/main/src/Util/ConsoleLogger.js
*
* Patches 11ty logger so it doesnt log everything, but we can still use its output for our own build.
* @typedef {'error'|'log'|'warn'|'info'} LogType
*/
class CustomLogger {
#outputStream;
constructor() {
this.reset();
}
flush() {
Object.keys(this.outputs).forEach(outputType => {
console[outputType](this.outputs[outputType].join(''));
});
this.reset();
}
reset() {
this.outputs = {
log: [],
info: [],
warn: [],
error: [],
};
}
/** @param {string} msg */
log(msg) {
this.message(msg);
}
/**
* @typedef LogOptions
* @property {string} message
* @property {string=} prefix
* @property {LogType=} type
* @property {string=} color
* @property {boolean=} force
* @param {LogOptions} options
*/
logWithOptions({ message, type, prefix, color, force }) {
this.message(message, type, color, force, prefix);
}
/** @param {string} msg */
forceLog(msg) {
this.message(msg, undefined, undefined, true);
}
/** @param {string} msg */
info(msg) {
this.message(msg, 'info', 'blue');
}
/** @param {string} msg */
warn(msg) {
this.message(msg, 'warn', 'yellow');
}
/** @param {string} msg */
error(msg) {
this.message(msg, 'error', 'red');
}
get outputStream() {
if (!this.#outputStream) {
this.#outputStream = new Readable({
read() {},
});
}
return this.#outputStream;
}
/** @param {string} msg */
toStream(msg) {
this.outputStream.push(msg);
}
closeStream() {
this.outputStream.push(null);
return this.outputStream;
}
/**
* Formats the message to log.
*
* @param {string} message - The raw message to log.
* @param {LogType} [type='log'] - The error level to log.
* @param {string|undefined} [chalkColor=undefined] - Color name or falsy to disable
* @param {boolean} [forceToConsole=false] - Enforce a log on console instead of specified target.
*/
message(message, type = 'log', chalkColor = undefined, _forceToConsole = false, prefix = '') {
// if (chalkColor && this.isChalkEnabled) {
// message = `${chalk.gray(prefix)} ${message.split("\n").join(`\n${chalk.gray(prefix)} `)}`;
// this.outputs[type].push(chalk[chalkColor](message));
// } else {
message = `${prefix}${message.split('\n').join(`\n${prefix}`)}`;
this.outputs[type].push(message);
// }
}
}

View File

@@ -25,7 +25,7 @@ for await (const component of components) {
const tagWithoutPrefix = component.tagName.replace(/^wa-/, '');
const componentDir = path.join(reactDir, tagWithoutPrefix);
const componentFile = path.join(componentDir, 'index.ts');
const importPath = path.relative(srcDir, component.path);
const importPath = path.posix.relative(srcDir, component.path);
// We only want to wrap wa- prefixed events, because the others are native
const eventsToWrap = component.events?.filter(event => event.name.startsWith('wa-')) || [];

View File

@@ -6,7 +6,7 @@ import styles from './{{ tagWithoutPrefix tag }}.css';
/**
* @summary Short summary of the component's intended use.
* @documentation https://backers.webawesome.com/docs/components/{{ tagWithoutPrefix tag }}
* @documentation https://webawesome.com/docs/components/{{ tagWithoutPrefix tag }}
* @status experimental
* @since 3.0
*

View File

@@ -42,7 +42,7 @@ img[aria-hidden='true'] {
}
}
:host([play]:not(:hover)) .control-box {
:where(:host([play]:not(:hover))) .control-box {
opacity: 0;
}
@@ -50,3 +50,16 @@ img[aria-hidden='true'] {
: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

@@ -4,12 +4,13 @@ import { WaErrorEvent } from '../../events/error.js';
import { WaLoadEvent } from '../../events/load.js';
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';
/**
* @summary A component for displaying animated GIFs and WEBPs that play and pause on interaction.
* @documentation https://backers.webawesome.com/docs/components/animated-image
* @documentation https://webawesome.com/docs/components/animated-image
* @status stable
* @since 2.0
*
@@ -30,6 +31,8 @@ import styles from './animated-image.css';
export default class WaAnimatedImage extends WebAwesomeElement {
static css = styles;
private readonly localize = new LocalizeController(this);
@query('.animated') animatedImage: HTMLImageElement;
@state() frozenFrame: string;
@@ -48,6 +51,13 @@ export default class WaAnimatedImage extends WebAwesomeElement {
this.play = !this.play;
}
private handleKeyDown(event: KeyboardEvent) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
this.play = !this.play;
}
}
private handleLoad() {
const canvas = document.createElement('canvas');
const { width, height } = this.animatedImage;
@@ -82,15 +92,26 @@ export default class WaAnimatedImage extends WebAwesomeElement {
}
render() {
const verb = this.localize.term(this.play ? 'pauseAnimation' : 'playAnimation');
const label = `${verb} ${this.alt}`;
return html`
<div class="animated-image">
<div
class="animated-image"
tabindex="0"
role="button"
aria-pressed=${this.play ? 'true' : 'false'}
aria-label=${label}
@click=${this.handleClick}
@keydown=${this.handleKeyDown}
>
<img
class="animated"
src=${this.src}
alt=${this.alt}
crossorigin="anonymous"
aria-hidden=${this.play ? 'false' : 'true'}
@click=${this.handleClick}
role="presentation"
@load=${this.handleLoad}
@error=${this.handleError}
/>
@@ -102,10 +123,10 @@ export default class WaAnimatedImage extends WebAwesomeElement {
src=${this.frozenFrame}
alt=${this.alt}
aria-hidden=${this.play ? 'true' : 'false'}
@click=${this.handleClick}
role="presentation"
/>
<div part="control-box" class="control-box">
<div part="control-box" class="control-box" aria-hidden="true">
<slot name="play-icon">
<wa-icon
name="play"

View File

@@ -10,7 +10,7 @@ import { animations } from './animations.js';
/**
* @summary Animate elements declaratively with nearly 100 baked-in presets, or roll your own with custom keyframes. Powered by the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API).
* @documentation https://backers.webawesome.com/docs/components/animation
* @documentation https://webawesome.com/docs/components/animation
* @status stable
* @since 2.0
*

View File

@@ -8,7 +8,7 @@ import styles from './avatar.css';
/**
* @summary Avatars are used to represent a person or object.
* @documentation https://backers.webawesome.com/docs/components/avatar
* @documentation https://webawesome.com/docs/components/avatar
* @status stable
* @since 2.0
*

View File

@@ -1,4 +1,6 @@
:host {
--pulse-color: var(--wa-color-fill-loud, var(--wa-color-brand-fill-loud));
display: inline-flex;
align-items: center;
justify-content: center;
@@ -19,29 +21,31 @@
}
/* Appearance modifiers */
:host([appearance~='plain']) {
color: var(--wa-color-on-quiet, var(--wa-color-brand-on-quiet));
background-color: transparent;
border-color: transparent;
}
: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~='outlined']) {
border-color: var(--wa-color-border-normal, var(--wa-color-brand-border-normal));
}
:host([appearance~='filled'][appearance~='outlined']) {
--pulse-color: var(--wa-color-border-normal, var(--wa-color-brand-border-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;
@@ -54,8 +58,6 @@
/* Pulse attention */
:host([attention='pulse']) {
--pulse-color: var(--background-color);
animation: pulse 1.5s infinite;
}

View File

@@ -6,7 +6,7 @@ import styles from './badge.css';
/**
* @summary Badges are used to draw attention and display statuses or counts.
* @documentation https://backers.webawesome.com/docs/components/badge
* @documentation https://webawesome.com/docs/components/badge
* @status stable
* @since 2.0
*
@@ -14,6 +14,8 @@ import styles from './badge.css';
*
* @csspart base - The component's base wrapper.
*
* @cssproperty --pulse-color - The color of the badge's pulse effect when using `attention="pulse"`.
*
*/
@customElement('wa-badge')
export default class WaBadge extends WebAwesomeElement {
@@ -28,8 +30,8 @@ export default class WaBadge extends WebAwesomeElement {
/** Draws a pill-style badge with rounded edges. */
@property({ type: Boolean, reflect: true }) pill = false;
/** Makes the badge pulsate to draw attention. */
@property({ reflect: true }) attention: 'none' | 'pulse' = 'none';
/** Adds an animation to draw attention to the badge. */
@property({ reflect: true }) attention: 'none' | 'pulse' | 'bounce' = 'none';
render() {
return html` <slot part="base" role="status"></slot>`;

View File

@@ -7,7 +7,7 @@ import styles from './breadcrumb-item.css';
/**
* @summary Breadcrumb Items are used inside breadcrumbs to represent different links.
* @documentation https://backers.webawesome.com/docs/components/breadcrumb-item
* @documentation https://webawesome.com/docs/components/breadcrumb-item
* @status stable
* @since 2.0
*

View File

@@ -8,7 +8,7 @@ import styles from './breadcrumb.css';
/**
* @summary Breadcrumbs provide a group of links so users can easily navigate a website's hierarchy.
* @documentation https://backers.webawesome.com/docs/components/breadcrumb
* @documentation https://webawesome.com/docs/components/breadcrumb
* @status stable
* @since 2.0
*

View File

@@ -26,8 +26,7 @@
z-index: 2 !important;
}
}
:host([orientation='vertical']) {
:host([orientation='vertical']) .button-group {
flex-direction: column;
}

View File

@@ -3,14 +3,13 @@ import { html } from 'lit';
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 sizeStyles from '../../styles/utilities/size.css';
import variantStyles from '../../styles/utilities/variants.css';
import type WaButton from '../button/button.js';
import styles from './button-group.css';
/**
* @summary Button groups can be used to group related buttons into sections.
* @documentation https://backers.webawesome.com/docs/components/button-group
* @documentation https://webawesome.com/docs/components/button-group
* @status stable
* @since 2.0
*
@@ -20,7 +19,7 @@ import styles from './button-group.css';
*/
@customElement('wa-button-group')
export default class WaButtonGroup extends WebAwesomeElement {
static css = [sizeStyles, variantStyles, styles];
static css = [variantStyles, styles];
@query('slot') defaultSlot: HTMLSlotElement;
@@ -36,9 +35,6 @@ export default class WaButtonGroup extends WebAwesomeElement {
/** The button group's orientation. */
@property({ reflect: true }) orientation: 'horizontal' | 'vertical' = 'horizontal';
/** The component's size. */
@property({ reflect: true }) size: 'small' | 'medium' | 'large'; // unset by default to not override child elements
/** The button group's theme variant. Defaults to `neutral` if not within another element with a variant. */
@property({ reflect: true }) variant: 'neutral' | 'brand' | 'success' | 'warning' | 'danger' = 'neutral';
@@ -85,7 +81,6 @@ export default class WaButtonGroup extends WebAwesomeElement {
if (button) {
if ((button as WaButton).appearance === 'outlined') this.hasOutlined = true;
if (this.size) button.setAttribute('size', this.size);
button.classList.add('wa-button-group__button');
button.classList.toggle('wa-button-group__horizontal', this.orientation === 'horizontal');
button.classList.toggle('wa-button-group__vertical', this.orientation === 'vertical');
@@ -101,7 +96,10 @@ export default class WaButtonGroup extends WebAwesomeElement {
return html`
<slot
part="base"
class=${classMap({ 'button-group': true, 'has-outlined': this.hasOutlined })}
class=${classMap({
'button-group': true,
'has-outlined': this.hasOutlined,
})}
role="${this.disableRole ? 'presentation' : 'group'}"
aria-label=${this.label}
aria-orientation=${this.orientation}

View File

@@ -1,6 +1,18 @@
@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;
}
}
@@ -103,10 +115,10 @@
var(--wa-color-mix-active)
);
}
}
&:host([appearance~='outlined']) .button {
border-color: var(--wa-color-border-normal, var(--wa-color-neutral-border-normal));
}
:host([appearance~='filled'][appearance~='outlined']) .button {
border-color: var(--wa-color-border-normal, var(--wa-color-neutral-border-normal));
}
:host([appearance~='accent']) {
@@ -184,6 +196,10 @@
}
.label {
display: inline-block;
}
.is-icon-button .label {
display: flex;
}
@@ -309,22 +325,22 @@ slot[name='end']::slotted(*),
}
/* Handle pill modifier for button groups */
:host([pill]) .wa-button-group__horizontal.wa-button-group__button-first {
: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 {
: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 {
: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 {
: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

@@ -16,7 +16,7 @@ import styles from './button.css';
/**
* @summary Buttons represent actions that are available to the user.
* @documentation https://backers.webawesome.com/docs/components/button
* @documentation https://webawesome.com/docs/components/button
* @status stable
* @since 2.0
*

View File

@@ -25,10 +25,10 @@
:host([appearance~='filled']) {
background-color: var(--wa-color-fill-quiet, var(--wa-color-brand-fill-quiet));
border-color: transparent;
}
&:host([appearance~='outlined']) {
border-color: var(--wa-color-border-quiet, var(--wa-color-brand-border-quiet));
}
:host([appearance~='filled'][appearance~='outlined']) {
border-color: var(--wa-color-border-quiet, var(--wa-color-brand-border-quiet));
}
:host([appearance~='accent']) {

View File

@@ -7,7 +7,7 @@ import styles from './callout.css';
/**
* @summary Callouts are used to display important messages inline.
* @documentation https://backers.webawesome.com/docs/components/callout
* @documentation https://webawesome.com/docs/components/callout
* @status stable
* @since 2.0
*
@@ -22,16 +22,11 @@ export default class WaCallout extends WebAwesomeElement {
static css = [styles, variantStyles, sizeStyles];
/** The callout's theme variant. Defaults to `brand` if not within another element with a variant. */
@property({ reflect: true }) variant: 'brand' | 'neutral' | 'success' | 'warning' | 'danger' | 'brand' = 'brand';
@property({ reflect: true }) variant: 'brand' | 'neutral' | 'success' | 'warning' | 'danger' = 'brand';
/** The callout's visual appearance. */
@property({ reflect: true }) appearance:
| 'accent'
| 'filled'
| 'outlined'
| 'plain'
| 'outlined filled'
| 'outlined accent' = 'outlined filled';
@property({ reflect: true }) appearance: 'accent' | 'filled' | 'outlined' | 'plain' | 'outlined filled' =
'outlined filled';
/** The callout's size. */
@property({ reflect: true }) size: 'small' | 'medium' | 'large' = 'medium';

View File

@@ -30,10 +30,10 @@
:host([appearance~='filled']) {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: transparent;
}
&:host([appearance~='outlined']) {
border-color: var(--wa-color-neutral-border-quiet);
}
:host([appearance~='filled'][appearance~='outlined']) {
border-color: var(--wa-color-neutral-border-quiet);
}
:host([appearance~='accent']) {
@@ -63,7 +63,7 @@
&::slotted(*) {
display: block;
width: 100%;
border-radius: 0;
border-radius: 0 !important;
}
}
@@ -77,7 +77,9 @@
}
.header {
display: block;
display: flex;
align-items: center;
justify-content: space-between;
border-block-end-style: inherit;
border-block-end-color: var(--wa-color-surface-border);
border-block-end-width: var(--wa-panel-border-width);
@@ -90,7 +92,9 @@
}
.footer {
display: block;
display: flex;
align-items: center;
justify-content: space-between;
border-block-start-style: inherit;
border-block-start-color: var(--wa-color-surface-border);
border-block-start-width: var(--wa-panel-border-width);
@@ -102,3 +106,27 @@
: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;
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

@@ -7,7 +7,7 @@ import styles from './card.css';
/**
* @summary Cards can be used to group related subjects in a container.
* @documentation https://backers.webawesome.com/docs/components/card
* @documentation https://webawesome.com/docs/components/card
* @status stable
* @since 2.0
*
@@ -15,6 +15,9 @@ import styles from './card.css';
* @slot header - An optional header for the card.
* @slot footer - An optional footer for the card.
* @slot media - An optional media section to render at the start of the card.
* @slot actions - An optional actions section to render at the end for the horizontal card.
* @slot header-actions - An optional actions section to render in the header of the vertical card.
* @slot footer-actions - An optional actions section to render in the footer of the vertical card.
*
* @csspart media - The container that wraps the card's media.
* @csspart header - The container that wraps the card's header.
@@ -42,6 +45,10 @@ export default class WaCard extends WebAwesomeElement {
/** Renders the card with a footer. Only needed for SSR, otherwise is automatically added. */
@property({ attribute: 'with-footer', type: Boolean, reflect: true }) withFooter = false;
/** Renders the card's orientation **/
@property({ reflect: true })
orientation: 'horizontal' | 'vertical' = 'vertical';
updated() {
// Enable the respective slots when detected
if (!this.withHeader && this.hasSlotController.test('header')) this.withHeader = true;
@@ -50,11 +57,27 @@ export default class WaCard extends WebAwesomeElement {
}
render() {
// Horizontal Orientation
if (this.orientation === 'horizontal') {
return html`
<slot name="media" part="media" class="media"></slot>
<slot part="body" class="body"></slot>
<slot name="actions" part="actions" class="actions"></slot>
`;
}
// Vertical Orientation
return html`
<slot name="media" part="media" class="media"></slot>
<slot name="header" part="header" class="header"></slot>
<header part="header" class="header">
<slot name="header"></slot>
<slot name="header-actions"></slot>
</header>
<slot part="body" class="body"></slot>
<slot name="footer" part="footer" class="footer"></slot>
<footer part="footer" class="footer">
<slot name="footer"></slot>
<slot name="footer-actions"></slot>
</footer>
`;
}
}

View File

@@ -46,6 +46,10 @@
cursor: pointer;
}
[part~='label'] {
display: inline;
}
/* Checked */
[part~='control']:has(:checked, :indeterminate) {
color: var(--checked-icon-color);

View File

@@ -15,7 +15,7 @@ import styles from './checkbox.css';
/**
* @summary Checkboxes allow the user to toggle an option on or off.
* @documentation https://backers.webawesome.com/docs/components/checkbox
* @documentation https://webawesome.com/docs/components/checkbox
* @status stable
* @since 2.0
*
@@ -234,13 +234,14 @@ export default class WaCheckbox extends WebAwesomeFormAssociatedElement {
</label>
<slot
id="hint"
part="hint"
name="hint"
aria-hidden=${hasHint ? 'false' : 'true'}
class="${classMap({ 'has-slotted': hasHint })}"
id="hint"
part="hint"
>${this.hint}</slot
>
${this.hint}
</slot>
`;
}
}

View File

@@ -39,7 +39,7 @@ declare const EyeDropper: EyeDropperConstructor;
/**
* @summary Color pickers allow the user to select a color.
* @documentation https://backers.webawesome.com/docs/components/color-picker
* @documentation https://webawesome.com/docs/components/color-picker
* @status stable
* @since 2.0
*
@@ -490,7 +490,7 @@ export default class WaColorPicker extends WebAwesomeFormAssociatedElement {
const target = event.target as HTMLInputElement;
const oldValue = this.value;
// Prevent the `<wa-input>` element's `wa-change` event from bubbling up
// Prevent the `<wa-input>` element's `change` event from bubbling up
event.stopPropagation();
if (this.input.value) {
@@ -1310,6 +1310,7 @@ export default class WaColorPicker extends WebAwesomeFormAssociatedElement {
></button>
<slot
id="hint"
name="hint"
part="hint"
class=${classMap({
@@ -1326,6 +1327,10 @@ export default class WaColorPicker extends WebAwesomeFormAssociatedElement {
distance="0"
skidding="0"
sync="width"
flip
flip-fallback-strategy="best-fit"
shift
shift-padding="10"
aria-disabled=${this.disabled ? 'true' : 'false'}
@wa-after-show=${this.handleAfterShow}
@wa-after-hide=${this.handleAfterHide}

View File

@@ -11,7 +11,7 @@ import styles from './comparison.css';
/**
* @summary Compare visual differences between similar content with a sliding panel.
* @documentation https://backers.webawesome.com/docs/components/comparison
* @documentation https://webawesome.com/docs/components/comparison
* @status stable
* @since 2.0
*

View File

@@ -14,7 +14,7 @@ import styles from './copy-button.css';
/**
* @summary Copies text data to the clipboard when the user clicks the trigger.
* @documentation https://backers.webawesome.com/docs/components/copy
* @documentation https://webawesome.com/docs/components/copy
* @status experimental
* @since 2.7
*
@@ -191,13 +191,13 @@ export default class WaCopyButton extends WebAwesomeElement {
<!-- Render a visually hidden label to appease the accessibility checking gods -->
<span class="wa-visually-hidden">${this.currentLabel}</span>
<slot part="copy-icon" name="copy-icon">
<wa-icon library="system" name="copy" variant="regular" fixed-width></wa-icon>
<wa-icon library="system" name="copy" variant="regular"></wa-icon>
</slot>
<slot part="success-icon" name="success-icon" variant="solid" hidden>
<wa-icon library="system" name="check" fixed-width></wa-icon>
<wa-icon library="system" name="check"></wa-icon>
</slot>
<slot part="error-icon" name="error-icon" variant="solid" hidden>
<wa-icon library="system" name="xmark" fixed-width></wa-icon>
<wa-icon library="system" name="xmark"></wa-icon>
</slot>
<wa-tooltip
class=${classMap({

View File

@@ -49,32 +49,26 @@ details {
}
/* Appearance modifiers */
:host([appearance~='plain']) {
details {
background-color: transparent;
border-color: transparent;
}
:host([appearance~='plain']) details {
background-color: transparent;
border-color: transparent;
}
:host([appearance~='outlined']) {
details {
background-color: var(--wa-color-surface-default);
border-color: var(--wa-color-surface-border);
}
: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~='outlined']) details {
border-color: var(--wa-color-neutral-border-quiet);
}
:host([appearance~='filled']) details {
background-color: var(--wa-color-neutral-fill-quiet);
border-color: transparent;
}
:host([appearance='plain']) {
:host([appearance~='filled'][appearance~='outlined']) details {
border-color: var(--wa-color-neutral-border-quiet);
}
:host([appearance='plain']) details {
border-radius: 0;
}
@@ -87,6 +81,7 @@ details {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing);
user-select: none;
-webkit-user-select: none;
cursor: pointer;
@@ -107,6 +102,12 @@ details {
}
}
/* 'Start' icon placement */
:host([icon-placement='start']) summary {
flex-direction: row-reverse;
justify-content: start;
}
[part~='icon'] {
flex: 0 0 auto;
display: flex;
@@ -128,8 +129,7 @@ details {
display: none;
}
/* Overflows get clipped during the closing animation if we don't wait until the close is gone. */
:host(:not([open])) .body {
.body.animating {
overflow: hidden;
}
@@ -139,10 +139,3 @@ details {
padding-inline: var(--spacing); /* Add horizontal padding */
padding-block-end: var(--spacing); /* Add bottom padding */
}
@keyframes show {
from {
}
to {
}
}

View File

@@ -196,8 +196,9 @@ describe('<wa-details>', () => {
await first.show();
await second.show();
expect(firstBody.clientHeight).to.equal(200);
expect(secondBody.clientHeight).to.equal(400);
// height + 32 (padding probably?)
expect(firstBody.clientHeight).to.equal(232);
expect(secondBody.clientHeight).to.equal(432);
});
});
}

View File

@@ -1,20 +1,23 @@
import type { PropertyValues } from 'lit';
import { html } from 'lit';
import { customElement, property, query } from 'lit/decorators.js';
import { customElement, property, query, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { WaAfterHideEvent } from '../../events/after-hide.js';
import { WaAfterShowEvent } from '../../events/after-show.js';
import { WaHideEvent } from '../../events/hide.js';
import { WaShowEvent } from '../../events/show.js';
import { animate, parseDuration } from '../../internal/animate.js';
import { getTargetElement, waitForEvent } from '../../internal/event.js';
import { waitForEvent } from '../../internal/event.js';
import { watch } from '../../internal/watch.js';
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';
/**
* @summary Details show a brief summary and expand to show additional content.
* @documentation https://backers.webawesome.com/docs/components/details
* @documentation https://webawesome.com/docs/components/details
* @status stable
* @since 2.0
*
@@ -40,6 +43,8 @@ import styles from './details.css';
* @cssproperty --spacing - The amount of space around and between the details' content. Expects a single value.
* @cssproperty [--show-duration=200ms] - The show duration to use when applying built-in animation classes.
* @cssproperty [--hide-duration=200ms] - The hide duration to use when applying built-in animation classes.
*
* @cssstate animating - Applied when the details is animating expand/collapse.
*/
@customElement('wa-details')
export default class WaDetails extends WebAwesomeElement {
@@ -53,6 +58,8 @@ export default class WaDetails extends WebAwesomeElement {
@query('.body') body: HTMLElement;
@query('.expand-icon-slot') expandIconSlot: HTMLSlotElement;
@state() isAnimating = false;
/**
* Indicates whether or not the details is open. You can toggle this attribute to show and hide the details, or you
* can use the `show()` and `hide()` methods and this attribute will reflect the details' open state.
@@ -71,6 +78,14 @@ export default class WaDetails extends WebAwesomeElement {
/** The element's visual appearance. */
@property({ reflect: true }) appearance: 'filled' | 'outlined' | 'plain' = 'outlined';
/** The location of the expand/collapse icon. */
@property({ attribute: 'icon-placement', reflect: true }) iconPlacement: 'start' | 'end' = 'end';
disconnectedCallback() {
super.disconnectedCallback();
this.detailsObserver?.disconnect();
}
firstUpdated() {
this.body.style.height = this.open ? 'auto' : '0';
if (this.open) {
@@ -91,15 +106,34 @@ export default class WaDetails extends WebAwesomeElement {
this.detailsObserver.observe(this.details, { attributes: true });
}
disconnectedCallback() {
super.disconnectedCallback();
this.detailsObserver?.disconnect();
updated(changedProperties: PropertyValues<this>) {
if (changedProperties.has('isAnimating')) {
this.customStates.set('animating', this.isAnimating);
}
}
private handleSummaryClick(event: MouseEvent) {
let targetElement = getTargetElement(event);
const eventPath = event.composedPath() as HTMLElement[];
if (targetElement?.closest('a, button, wa-button, input, wa-input, textarea, wa-textarea, select, wa-select')) {
// Check if any element in the path is interactive
const hasInteractiveElement = eventPath.some(element => {
if (!(element instanceof HTMLElement)) return false;
// Check native interactive elements
const tagName = element.tagName?.toLowerCase();
if (['a', 'button', 'input', 'textarea', 'select'].includes(tagName)) {
return true;
}
// Check for Web Awesome form controls
if (element instanceof WebAwesomeFormAssociatedElement) {
return !('disabled' in element) || !element.disabled;
}
return false;
});
if (hasInteractiveElement) {
// Let interactive elements handle their own clicks, fixes #309
return;
}
@@ -168,6 +202,7 @@ export default class WaDetails extends WebAwesomeElement {
// Close other details with the same name
this.closeOthersWithSameName();
this.isAnimating = true;
const duration = parseDuration(getComputedStyle(this.body).getPropertyValue('--show-duration'));
// We can't animate to 'auto', so use the scroll height for now
await animate(
@@ -182,6 +217,7 @@ export default class WaDetails extends WebAwesomeElement {
},
);
this.body.style.height = 'auto';
this.isAnimating = false;
this.dispatchEvent(new WaAfterShowEvent());
} else {
@@ -194,6 +230,7 @@ export default class WaDetails extends WebAwesomeElement {
return;
}
this.isAnimating = true;
const duration = parseDuration(getComputedStyle(this.body).getPropertyValue('--hide-duration'));
// We can't animate from 'auto', so use the scroll height for now
await animate(
@@ -205,7 +242,7 @@ export default class WaDetails extends WebAwesomeElement {
{ duration, easing: 'linear' },
);
this.body.style.height = 'auto';
this.isAnimating = false;
this.details.open = false;
this.dispatchEvent(new WaAfterHideEvent());
}
@@ -250,25 +287,22 @@ export default class WaDetails extends WebAwesomeElement {
<span part="icon">
<slot name="expand-icon">
<wa-icon
library="system"
variant="solid"
name=${isRtl ? 'chevron-left' : 'chevron-right'}
fixed-width
></wa-icon>
<wa-icon library="system" variant="solid" name=${isRtl ? 'chevron-left' : 'chevron-right'}></wa-icon>
</slot>
<slot name="collapse-icon">
<wa-icon
library="system"
variant="solid"
name=${isRtl ? 'chevron-left' : 'chevron-right'}
fixed-width
></wa-icon>
<wa-icon library="system" variant="solid" name=${isRtl ? 'chevron-left' : 'chevron-right'}></wa-icon>
</slot>
</span>
</summary>
<div class="body" role="region" aria-labelledby="header">
<div
class=${classMap({
body: true,
animating: this.isAnimating,
})}
role="region"
aria-labelledby="header"
>
<slot part="content" id="content" class="content"></slot>
</div>
</details>

View File

@@ -17,7 +17,7 @@ import styles from './dialog.css';
/**
* @summary Dialogs, sometimes called "modals", appear above the page and require the user's immediate attention.
* @documentation https://backers.webawesome.com/docs/components/dialog
* @documentation https://webawesome.com/docs/components/dialog
* @status stable
* @since 2.0
*
@@ -205,9 +205,7 @@ export default class WaDialog extends WebAwesomeElement {
}
render() {
const hasHeader =
!this.withoutHeader &&
(this.label.length > 0 || this.hasSlotController.test('label') || this.hasSlotController.test('header-actions'));
const hasHeader = !this.withoutHeader;
const hasFooter = this.hasSlotController.test('footer');
return html`
@@ -226,7 +224,7 @@ export default class WaDialog extends WebAwesomeElement {
<header part="header" class="header">
<h2 part="title" class="title" id="title">
<!-- If there's no label, use an invisible character to prevent the header from collapsing -->
<slot name="label"> ${this.label.length > 0 ? this.label : String.fromCharCode(65279)} </slot>
<slot name="label"> ${this.label.length > 0 ? this.label : String.fromCharCode(8203)} </slot>
</h2>
<div part="header-actions" class="header-actions">
<slot name="header-actions"></slot>

View File

@@ -5,7 +5,7 @@ import styles from './divider.css';
/**
* @summary Dividers are used to visually separate or group elements.
* @documentation https://backers.webawesome.com/docs/components/divider
* @documentation https://webawesome.com/docs/components/divider
* @status stable
* @since 2.0
*

View File

@@ -17,7 +17,7 @@ import styles from './drawer.css';
/**
* @summary Drawers slide in from a container to expose additional options and information.
* @documentation https://backers.webawesome.com/docs/components/drawer
* @documentation https://webawesome.com/docs/components/drawer
* @status stable
* @since 2.0
*
@@ -218,9 +218,7 @@ export default class WaDrawer extends WebAwesomeElement {
}
render() {
const hasHeader =
!this.withoutHeader &&
(this.label.length > 0 || this.hasSlotController.test('label') || this.hasSlotController.test('header-actions'));
const hasHeader = !this.withoutHeader;
const hasFooter = this.hasSlotController.test('footer');
return html`
@@ -243,7 +241,7 @@ export default class WaDrawer extends WebAwesomeElement {
<header part="header" class="header">
<h2 part="title" class="title" id="title">
<!-- If there's no label, use an invisible character to prevent the header from collapsing -->
<slot name="label"> ${this.label.length > 0 ? this.label : String.fromCharCode(65279)} </slot>
<slot name="label"> ${this.label.length > 0 ? this.label : String.fromCharCode(8203)} </slot>
</h2>
<div part="header-actions" class="header-actions">
<slot name="header-actions"></slot>

View File

@@ -8,7 +8,7 @@ import styles from './dropdown-item.css';
/**
* @summary Represents an individual item within a dropdown menu, supporting standard items, checkboxes, and submenus.
* @documentation https://backers.webawesome.com/docs/components/dropdown-item
* @documentation https://webawesome.com/docs/components/dropdown-item
* @status experimental
* @since 3.0
*

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