Compare commits

...

33 Commits

Author SHA1 Message Date
Cory LaViska
f2b05600a5 rename caret => with-caret 2025-06-26 12:18:07 -04:00
Cory LaViska
dc556e5379 add disabled to radio group; remove @watch (#1066) 2025-06-23 14:41:54 -04:00
Konnor Rogers
c11d6129a3 Rework setting initial values in <wa-select> (#1063)
* fix select to use selected options

* fix selected stuff

* remove unused prop

* update tests

* fix default value and form reset

* remove demo

* update changelog

* document value prop

* recommend selected in docs

* document props

---------

Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
2025-06-23 13:46:05 -04:00
Cory LaViska
dd5c32680a remove redundant examples; closes #1041 (#1064) 2025-06-23 10:38:02 -04:00
Lindsay M
81996cbc63 fix tag sizes (#1062) 2025-06-23 10:30:01 -04:00
Konnor Rogers
d20945d78b increase breakpoint on wa-page (#1060) 2025-06-17 11:45:38 -04:00
Konnor Rogers
07327be95e input / change always bubble now (#1057)
* make sure relayNativeEvent is synchronous

* prettier

* changelog entry

* fix event
2025-06-13 13:19:47 -04:00
Cory LaViska
b99d7771dc move pro themes to pro (#1054) 2025-06-11 12:15:52 -04:00
Lindsay M
10cc9bdc68 Change prefix and suffix to start and end (#1047)
* change `prefix` > `start` and `suffix` > `end` (breadcrumb item)

* fix formatting

* change `prefix` > `start` and `suffix` > `end` (button)

* change `prefix` > `start` and `suffix` > `end` (input)

* change `prefix` > `start` and `suffix` > `end` (select)

* replace leftover `prefix` instances with `start`

* replace leftover `suffix` instances with `end`

* update changelog

* remove `slot="start|end"` examples from unsupported components
2025-06-11 11:36:50 -04:00
Lindsay M
bc598dad92 Consolidate theme files (#1053)
* consolidate theme files

* move dimension to its own layer

* touch up

* fix `.wa-invert`

* fix selectors and missing fonts

* fix selectors (for real this time)
2025-06-11 11:24:40 -04:00
Lindsay M
ff61ac002f Remove clamped color tokens (#1050) 2025-06-10 15:44:33 -04:00
Konnor Rogers
63ec9d5bc1 Try with PAT (#1049)
* Try with PAT

* Try with PAT
2025-06-10 13:59:52 -04:00
Kelsey Jackson
555327b2fc Kj/layout patterns (#1013)
* add button for drawer example

* scaffolding

* building initial page

* loading blank

* committing to pull down changes

* committing to merge

* trying to sync with next

* drawer issue

* added content to drawer

* added checkout page

* added checkout page

* committing to merge

* committing to merge

* made changes to sidebar

* syncing with repo

* syncing with repo

* update sidebar again

---------

Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
2025-06-09 12:17:14 -05:00
Cory LaViska
15c6eaec90 Dropdown rework (#1039)
* use wa-popup in color picker

* remove test

* remove old dropdown, menu, menu item, menu label

* remove old dropdown

* rework dropdown + dropdown item

* update examples

* add hide duration

* update jsdoc

* add event

* add size

* add size

* fix docs

* remove old test; fix types

* add submenu to example

* adapt for <wa-popup>

* remove state

* fix dropdown stuff (#1044)

* fix dropdown stuff

* prettier

* get typescript to give a real error

* remove unnecessary checks

* prettier

* remove old tag

* convert old dropdowns to new syntax

* update example

* update styles

---------

Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
2025-06-09 11:19:34 -04:00
Lindsay M
6f856fbd89 Native styles cleanup (#1043)
* tidy and touch up content styles

* finish touching up inline text styles

* move styles for docs code blocks from `native.css` to appropriate files

* tidy and touch up list and table styles

* tidy and touch up details styles

* tidy up dialog styles

* fix bloated spacing in dialog and drawer

* add fieldset, refactor radio and checkbox styles

* refactor input, textarea, and select styles

* refactor range styles to match new `<wa-slider>`

* readability improvements

* touch up theme overrides

* fix Matter checkbox and radio hover styles
2025-06-09 11:18:37 -04:00
Konnor Rogers
df46e1db3b remove public alpha cdn (#1042) 2025-06-06 14:04:44 -04:00
Cory LaViska
d21d829c29 Slider rework (#1034)
* initial rework

* improvements

* add size styles

* update changelog

* update changelog

* fix hint aria

* whitespace

* slider test fixes (#1036)

* prettier

* More slider fixes 2 (#1037)

* more fixes

* more fixes

* prettier

* fix theme slider styles

* only add extra space around slider when label is present

---------

Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
2025-06-06 10:38:18 -04:00
Cory LaViska
2331e88dcf update jsdoc (#1038) 2025-06-06 08:29:19 -04:00
Cory LaViska
c162983ca2 add hover queries (#1035) 2025-06-05 22:03:51 +00:00
Cory LaViska
0d09037916 Zoomable frame (#1029)
* add zoomable frame component; #986

* remove viewport demo component

* update changelog

* fix code demos

* update zoomable iframes with theme changes
2025-06-05 17:34:25 -04:00
Cory LaViska
d2e32a0a53 Support icon buttons directly in <wa-button> (#1030)
* support icon buttons directly in <wa-button>

* [progress] replace `<wa-icon-button>` instances

* change close buttons to `<wa-button>`

* fix formatting

* change scroll buttons to `<wa-button>`

* update tests

* change tag remove button to `<wa-button>`

* fix tag tests

* remove nonexistent parts from tab docs

* change viewport demo controls to `<wa-button>`

* fix leftover icon button dependencies

* fix icon button usage in palettes and themes

* revert mistakenly committed change to theme preview heights

* fix icon button styles in old themer

* replace icon buttons in style utility examples

* fix import

* handle press on button, not icon-button, in select

* fix stray icon button references in docs

* fix broken home page button

* remove icon button overrides from Matter theme

* add generated directories so they're excluded from search results

* add dire

* remove icon-button component

---------

Co-authored-by: lindsaym-fa <dev@lindsaym.design>
2025-06-05 15:16:03 -04:00
Cory LaViska
71d45eabbd Add data- invokers to dialog and drawer (#1032)
* add data- invokers to dialog and drawer

* rename var
2025-06-05 14:47:29 -04:00
Konnor Rogers
eac60a9022 Fixes for app and prettier (#1028)
* fix for app

* prettier

* fix for app

* prettier

* update prettierignore

* prettier

* prettier

* fix prism vendoring
2025-06-04 10:28:38 -04:00
Cory LaViska
f8dca5d1a8 refactor styles and simplify custom states (#1016) 2025-06-04 08:09:14 -04:00
Lindsay M
5980b5f843 Refactor form control sizing (#1005)
* visual test setup

* fix improper class placement in visual tests

* add `wa-form-control-*-font-size` and `-wa-form-control-hint-*` custom properties

* use new custom properties

* dump of component sizing improvements

* fix native color picker styles

* update menu with relative sizes

* tidy up menu, select, and tag sizing

* use relative sizing across components

* touch up custom properties

* update docs and comments

* update changelog

* revert changes to visual tests to simplify PR

* revert leftover change to visual tests

* tidy up space doc markdown

* fix default card spacing

* fix card docs

* wrap up new `--tag-max-size` for `<wa-select>`

* change default `--tag-max-size`

* prettier

* touch up

* clean up leftovers

* fix native form control margins

* set default toggle size relative to font size

* correct toggle size in docs

* Konnorrogers/lm form control sizing (#1025)

* try a second updateComplete??

* try a second updateComplete??

* more timeouts?

* try logging

* more logging
gp

* maybe now

* radio group test

* add todo note'

* add workflow dispatch for client tests

---------

Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
2025-06-03 16:27:24 -04:00
Cory LaViska
9a3ffb04ba remove unused custom props; align styles with wa-slider (#1017) 2025-06-03 15:51:49 -04:00
Cory LaViska
04d37224e0 remove hint from <wa-radio>; fixes #1024 (#1026) 2025-06-03 15:31:53 -04:00
Cory LaViska
f4a63f9e22 Simplify color variants docs (#1023)
* remove

* simplify
2025-06-03 15:28:11 -04:00
Cory LaViska
3ab342ebb6 add support for name attribute (#1022) 2025-06-03 15:10:31 -04:00
Cory LaViska
48fe9389c8 Use outlined appearance for buttons in <wa-color-picker> (#1021)
* use outlined appearance for buttons

* don't override child element's size
2025-06-03 15:10:15 -04:00
Cory LaViska
6b2a081fa0 Improve rating's default a11y (#1019)
* add regular star

* support dual icons; improve default contrast

* support dual icons; improve contrast

* update docs

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

Co-authored-by: Lindsay M <126139086+lindsaym-fa@users.noreply.github.com>

---------

Co-authored-by: Lindsay M <126139086+lindsaym-fa@users.noreply.github.com>
2025-06-03 15:09:34 -04:00
Cory LaViska
afb2082c79 add resize-vertical (#1018) 2025-06-03 15:08:52 -04:00
Cory LaViska
7bdc9a2cc4 Add <wa-popover> (#1012)
* remove redundant styles from template

* rotate arrow based on placement so borders show correctly when applied

* use actual placement, not preferred

* add popover

* update changelog

* update changelog

* use <dialog> for popover

* fix arrow border in FF/Safari

* update content

* add sidebar to plop

* add popover
2025-06-02 16:13:24 -04:00
366 changed files with 8612 additions and 11498 deletions

View File

@@ -4,6 +4,7 @@
name: Client Tests
on:
workflow_dispatch:
push:
branches: [next]
pull_request:

View File

@@ -1,18 +1,23 @@
# Files are relative to .prettierignore at the root of this monorepo.
# <https://github.com/prettier/prettier-vscode/issues/1252>
*.hbs
*.md
!docs/docs/patterns/**/*.md
!packages/webawesome/docs/docs/patterns/**/*.md
docs/docs/patterns/blog-news/post-list.md
.cache
**/*/.cache
.github
cspell.json
dist
docs/search.json
src/components/icon/icons
src/react/index.ts
packages/**/*/dist
packages/**/*/dist-cdn
packages/**/*/docs/search.json
packages/**/*/src/components/icon/icons
packages/**/*/src/react/index.ts
**/*/package.json
**/*/package-lock.json
**/*/tsconfig.json
**/*/tsconfig.prod.json
node_modules
package.json
package-lock.json
tsconfig.json
cdn
_site
docs/assets/scripts/prism-downloaded.js
packages/**/*/_site
packages/webawesome/docs/assets/scripts/prism-downloaded.js

View File

@@ -125,6 +125,7 @@
"noreferrer",
"novalidate",
"Numberish",
"nums",
"oklab",
"oklch",
"onscrollend",
@@ -139,6 +140,7 @@
"progressbar",
"radiogroup",
"Railsbyte",
"referrerpolicy",
"remixicon",
"reregister",
"resizer",
@@ -165,6 +167,7 @@
"slotchange",
"smartquotes",
"spacebar",
"srcdoc",
"stylesheet",
"svgs",
"Tabbable",

23
package-lock.json generated
View File

@@ -2488,6 +2488,10 @@
"resolved": "packages/webawesome",
"link": true
},
"node_modules/@shoelace-style/webawesome-pro": {
"resolved": "packages/webawesome-pro",
"link": true
},
"node_modules/@sindresorhus/is": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
@@ -13987,6 +13991,25 @@
"engines": {
"node": ">=14.17.0"
}
},
"packages/webawesome-pro": {
"name": "@shoelace-style/webawesome-pro",
"version": "3.0.0-alpha.13",
"license": "TODO",
"dependencies": {
"@ctrl/tinycolor": "^4.1.0",
"@floating-ui/dom": "^1.6.13",
"@shoelace-style/animations": "^1.2.0",
"@shoelace-style/localize": "^3.2.1",
"composed-offset-position": "^0.0.6",
"lit": "^3.2.1",
"qr-creator": "^1.0.0",
"style-observer": "^0.0.7"
},
"devDependencies": {},
"engines": {
"node": ">=14.17.0"
}
}
}
}

4
packages/webawesome/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
_site
dist
dist-cdn
src/react

View File

@@ -3,9 +3,9 @@ import { customElementVsCodePlugin } from 'custom-element-vs-code-integration';
// import { customElementVuejsPlugin } from 'custom-element-vuejs-integration';
import { parse } from 'comment-parser';
import fs from 'fs';
import * as path from 'node:path';
import { pascalCase } from 'pascal-case';
import * as url from 'url';
import * as path from "node:path"
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const packageData = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
@@ -186,4 +186,3 @@ export default {
// })
],
};

View File

@@ -1,5 +1,5 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import * as fs from "node:fs"
import { anchorHeadingsPlugin } from './_utils/anchor-headings.js';
import { codeExamplesPlugin } from './_utils/code-examples.js';
import { copyCodePlugin } from './_utils/copy-code.js';
@@ -41,7 +41,7 @@ export default async function (eleventyConfig) {
*/
const passThroughExtensions = ['js', 'css', 'png', 'svg', 'jpg', 'mp4'];
const docsDir = path.join(process.env.BASE_DIR || ".", 'docs');
const docsDir = path.join(process.env.BASE_DIR || '.', 'docs');
const passThrough = [...passThroughExtensions.map(ext => path.join(docsDir, '**/*.' + ext))];
/**
@@ -176,9 +176,8 @@ 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 })
let assetsDir = path.join(process.env.BASE_DIR || 'docs', 'assets');
fs.cpSync(assetsDir, path.join(eleventyConfig.directories.output, 'assets'), { recursive: true });
for (let glob of passThrough) {
eleventyConfig.addPassthroughCopy(glob);
@@ -210,7 +209,6 @@ export default async function (eleventyConfig) {
// }
}
export const config = {
markdownTemplateEngine: 'njk',
dir: {
@@ -219,5 +217,4 @@ export const config = {
layouts: '_layouts',
},
templateFormats: ['njk', 'md'],
}
};

View File

@@ -2,13 +2,13 @@
* @module components Fetches components from custom-elements.json and exposes them in a saner format.
*/
import { readFileSync } from 'fs';
import { join, dirname, resolve } from 'path';
import { dirname, join, resolve } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const customElementsJSON = process.env.DIST_DIR
? join(process.env.DIST_DIR, "custom-elements.json")
: resolve(__dirname, '../../dist/custom-elements.json')
? join(process.env.DIST_DIR, 'custom-elements.json')
: resolve(__dirname, '../../dist/custom-elements.json');
const manifest = JSON.parse(readFileSync(customElementsJSON), 'utf-8');
@@ -76,4 +76,3 @@ components.sort((a, b) => {
});
export default components;

View File

@@ -1,43 +0,0 @@
import components from './components.js';
const by = {
attribute: {},
slot: {},
event: {},
method: {},
cssPart: {},
cssProperty: {},
};
function getAll(component, type) {
let prop = type + 's';
if (type === 'cssProperty') {
prop = 'cssProperties';
}
return component[prop] ?? [];
}
for (const componentName in components) {
const component = components[componentName];
for (const type of ['attribute', 'slot', 'event', 'method', 'cssPart', 'cssProperty']) {
for (const item of getAll(component, type)) {
by[type][item.name] ??= [];
by[type][item.name].push(component);
}
}
}
// Sort by descending number of components
const sortByLengthDesc = (a, b) => b[1].length - a[1].length;
for (const key in by) {
by[key] = sortObject(by[key], sortByLengthDesc);
}
export default by;
function sortObject(obj, sorter) {
return Object.fromEntries(Object.entries(obj).sort(sorter));
}

View File

@@ -20,7 +20,7 @@
</head>
<body class="layout-{{ layout | stripExtension }}{{ ' page-wide' if wide }}">
<!-- use view="desktop" as default to reduce layout jank on desktop site. -->
<wa-page view="desktop" disable-navigation-toggle="" mobile-breakpoint="1140">
<wa-page view="desktop" disable-navigation-toggle="" mobile-breakpoint="1180">
<header slot="header" class="wa-split">
{# Logo #}
<div id="docs-branding">
@@ -46,9 +46,9 @@
{# Search #}
<wa-button id="search-trigger" appearance="outlined" size="small" data-search>
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
<wa-icon slot="start" name="magnifying-glass"></wa-icon>
Search
<kbd slot="suffix" class="wa-desktop-only">/</kbd>
<kbd slot="end" class="wa-desktop-only">/</kbd>
</wa-button>
{# Login #}

View File

@@ -1,19 +1,19 @@
{# Color scheme selector #}
<wa-select class="color-scheme-selector" appearance="filled" size="small" value="auto" pill title="Press \ to toggle">
<wa-icon class="only-light" slot="prefix" name="sun" variant="regular"></wa-icon>
<wa-icon class="only-dark" slot="prefix" name="moon" variant="regular"></wa-icon>
<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">
<wa-icon slot="prefix" name="sun" variant="regular"></wa-icon>
<wa-icon slot="start" name="sun" variant="regular"></wa-icon>
Light
</wa-option>
<wa-option value="dark">
<wa-icon slot="prefix" name="moon" variant="regular"></wa-icon>
<wa-icon slot="start" name="moon" variant="regular"></wa-icon>
Dark
</wa-option>
<wa-divider></wa-divider>
<wa-option value="auto">
<wa-icon class="only-light" slot="prefix" name="sun" variant="regular"></wa-icon>
<wa-icon class="only-dark" slot="prefix" name="moon" variant="regular"></wa-icon>
<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>
System
</wa-option>
</wa-select>

View File

@@ -15,9 +15,8 @@
{% endfor %}
</div>
</fieldset>
<wa-viewport-demo viewport="1000">
<iframe srcdoc="" id="page_slots_iframe"></iframe>
</wa-viewport-demo>
<wa-zoomable-frame srcdoc="" zoom="0.5" id="page_slots_iframe"></wa-zoomable-frame>
</div>
<script type="module">

View File

@@ -1,6 +1,6 @@
{# Preset theme selector #}
<wa-select appearance="filled" size="small" value="default" pill class="preset-theme-selector">
<wa-icon slot="prefix" name="paintbrush" variant="regular"></wa-icon>
<wa-icon slot="start" name="paintbrush" variant="regular"></wa-icon>
{% for theme in collections.theme | sort %}
<wa-option value="{{ theme.page.fileSlug }}">
{{ theme.data.title }}

View File

@@ -24,7 +24,7 @@
aria-haspopup="listbox"
aria-activedescendant
>
<wa-icon slot="prefix" name="search"></wa-icon>
<wa-icon slot="start" name="search"></wa-icon>
</wa-input>
</div>
</header>

View File

@@ -121,22 +121,20 @@
<li><a href="/docs/components/dialog/">Dialog</a></li>
<li><a href="/docs/components/divider/">Divider</a></li>
<li><a href="/docs/components/drawer/">Drawer</a></li>
<li><a href="/docs/components/dropdown/">Dropdown</a></li>
<li>
<a href="/docs/components/dropdown">Dropdown</a>
<ul>
<li><a href="/docs/components/dropdown-item">Dropdown Item</a></li>
</ul>
</li>
<li><a href="/docs/components/format-bytes/">Format Bytes</a></li>
<li><a href="/docs/components/format-date/">Format Date</a></li>
<li><a href="/docs/components/format-number/">Format Number</a></li>
<li><a href="/docs/components/icon/">Icon</a></li>
<li><a href="/docs/components/icon-button/">Icon Button</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/menu/">Menu</a>
<ul>
<li><a href="/docs/components/menu-item/">Menu Item</a></li>
<li><a href="/docs/components/menu-label/">Menu Label</a></li>
</ul>
</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>
<li><a href="/docs/components/progress-bar/">Progress Bar</a></li>
<li><a href="/docs/components/progress-ring/">Progress Ring</a></li>
@@ -174,6 +172,8 @@
<li><a href="/docs/components/tooltip/">Tooltip</a></li>
<li><a href="/docs/components/tree/">Tree</a></li>
<li><a href="/docs/components/tree-item/">Tree Item</a></li>
<li><a href="/docs/components/zoomable-frame">Zoomable Frame</a></li>
{# PLOP_NEW_COMPONENT_PLACEHOLDER #}
</ul>
</wa-details>
@@ -349,6 +349,21 @@
</li>
</ul>
</li>
<li>
<a href="/docs/patterns/layouts/">Layouts</a>
<wa-badge class="pro" appearance="accent" attention="none">PRO</wa-badge>
<ul>
<li>
<a href="/docs/patterns/layouts/ecommerce/">Ecommerce</a>
</li>
<li>
<a href="/docs/patterns/layouts/app/">App</a>
</li>
<li>
<a href="/docs/patterns/layouts/blog/">Blog</a>
</li>
</ul>
</li>
</ul>
</wa-details>

View File

@@ -1,4 +0,0 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 6C0 2.68629 2.68629 0 6 0H26C29.3137 0 32 2.68629 32 6V26C32 29.3137 29.3137 32 26 32H6C2.68629 32 0 29.3137 0 26V6Z" fill="var(--wa-color-neutral-fill-normal)"/>
<path d="M23.4688 13.2188C23.5938 13.5 23.5 13.7812 23.2812 14L21.9375 15.2188C21.9688 15.4688 21.9688 15.75 21.9688 16C21.9688 16.2812 21.9688 16.5625 21.9375 16.8125L23.2812 18.0312C23.5 18.2188 23.5938 18.5312 23.4688 18.8125C23.3438 19.1875 23.1875 19.5312 23 19.875L22.8438 20.125C22.625 20.4688 22.4062 20.8125 22.1562 21.0938C21.9688 21.3438 21.6562 21.4062 21.375 21.3125L19.6562 20.7812C19.2188 21.0938 18.75 21.3438 18.2812 21.5625L17.875 23.3438C17.8125 23.625 17.5938 23.8438 17.3125 23.9062C16.875 23.9688 16.4375 24 15.9688 24C15.5312 24 15.0938 23.9688 14.6562 23.9062C14.375 23.8438 14.1562 23.625 14.0938 23.3438L13.6875 21.5625C13.1875 21.3438 12.75 21.0938 12.3125 20.7812L10.5938 21.3125C10.3125 21.4062 10 21.3438 9.8125 21.125C9.5625 20.8125 9.34375 20.4688 9.125 20.125L8.96875 19.875C8.78125 19.5312 8.625 19.1875 8.5 18.8125C8.375 18.5312 8.46875 18.25 8.6875 18.0312L10.0312 16.8125C10 16.5625 10 16.2812 10 16C10 15.75 10 15.4688 10.0312 15.2188L8.6875 14C8.46875 13.7812 8.375 13.5 8.5 13.2188C8.625 12.8438 8.78125 12.5 8.96875 12.1562L9.125 11.9062C9.34375 11.5625 9.5625 11.2188 9.8125 10.9062C10 10.6875 10.3125 10.625 10.5938 10.7188L12.3125 11.25C12.75 10.9375 13.2188 10.6562 13.6875 10.4688L14.0938 8.6875C14.1562 8.40625 14.375 8.1875 14.6562 8.125C15.0938 8.0625 15.5312 8 16 8C16.4375 8 16.875 8.0625 17.3125 8.125C17.5938 8.15625 17.8125 8.40625 17.875 8.6875L18.2812 10.4688C18.7812 10.6562 19.2188 10.9375 19.6562 11.25L21.375 10.7188C21.6562 10.625 21.9688 10.6875 22.1562 10.9062C22.4062 11.2188 22.625 11.5625 22.8438 11.9062L23 12.1562C23.1875 12.5 23.3438 12.8438 23.5 13.2188H23.4688ZM16 18.5C16.875 18.5 17.6875 18.0312 18.1562 17.25C18.5938 16.5 18.5938 15.5312 18.1562 14.75C17.6875 14 16.875 13.5 16 13.5C15.0938 13.5 14.2812 14 13.8125 14.75C13.375 15.5312 13.375 16.5 13.8125 17.25C14.2812 18.0312 15.0938 18.5 16 18.5Z" fill="var(--wa-color-neutral-on-normal)"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -3,7 +3,9 @@
<wa-card>
<div slot="header" class="wa-split">
<h3 class="wa-heading-m">Your Cart</h3>
<wa-icon-button name="xmark" tabindex="-1"></wa-icon-button>
<wa-button appearance="plain" size="small" tabindex="-1">
<wa-icon name="xmark" label="Close"></wa-icon>
</wa-button>
</div>
<div class="wa-stack wa-gap-xl">
<div class="wa-flank">
@@ -45,7 +47,7 @@
</div>
<span class="wa-caption-m">Shipping and taxes calculated at checkout.</span>
<wa-button tabindex="-1" variant="brand">
<wa-icon slot="prefix" name="shopping-bag"></wa-icon>
<wa-icon slot="start" name="shopping-bag"></wa-icon>
Checkout
</wa-button>
</div>
@@ -60,10 +62,10 @@
<div class="wa-stack">
<h3 class="wa-heading-m">Sign In</h3>
<wa-input tabindex="-1" label="Email" placeholder="ddjarin@mandalore.gov">
<wa-icon slot="prefix" name="envelope" variant="regular"></wa-icon>
<wa-icon slot="start" name="envelope" variant="regular"></wa-icon>
</wa-input>
<wa-input tabindex="-1" label="Password" type="password">
<wa-icon slot="prefix" name="lock" variant="regular"></wa-icon>
<wa-icon slot="start" name="lock" variant="regular"></wa-icon>
</wa-input>
<wa-button tabindex="-1" variant="brand">Sign In</wa-button>
<a href="#" tabindex="-1" class="wa-body-s">I forgot my password</a>
@@ -73,7 +75,9 @@
<div class="wa-stack">
<div class="wa-split">
<h3 class="wa-heading-m">To-Do</h3>
<wa-icon-button tabindex="-1" name="plus" label="Add task"></wa-icon-button>
<wa-button appearance="plain" size="small" tabindex="-1">
<wa-icon name="plus" label="Add task"></wa-icon>
</wa-button>
</div>
<wa-checkbox tabindex="-1" checked>Umbrella for Adelard</wa-checkbox>
<wa-checkbox tabindex="-1" checked>Waste-paper basket for Dora</wa-checkbox>
@@ -98,7 +102,9 @@
</div>
<span class="wa-caption-m">Samwise G</span>
</div>
<wa-icon-button tabindex="-1" name="ellipsis" label="Options"></wa-icon-button>
<wa-button appearance="plain" size="small" tabindex="-1">
<wa-icon name="ellipsis" label="Options"></wa-icon>
</wa-button>
</div>
<div class="wa-stack wa-gap-2xs">
<wa-progress-bar value="34" style="height: 0.5em"></wa-progress-bar>
@@ -108,9 +114,15 @@
</div>
</div>
<div class="wa-grid wa-align-items-center" style="--min-column-size: 1em; justify-items: center;">
<wa-icon-button tabindex="-1" name="backward" label="Skip backward"></wa-icon-button>
<wa-icon-button tabindex="-1" name="pause" style="font-size: var(--wa-font-size-2xl);" label="Pause"></wa-icon-button>
<wa-icon-button tabindex="-1" name="forward" label="Skip forward"></wa-icon-button>
<wa-button appearance="plain" tabindex="-1">
<wa-icon name="backward" label="Skip backward"></wa-icon>
</wa-button>
<wa-button appearance="plain" size="large" tabindex="-1">
<wa-icon name="pause" label="Pause"></wa-icon>
</wa-button>
<wa-button appearance="plain" tabindex="-1">
<wa-icon name="forward" label="Skip forward"></wa-icon>
</wa-button>
</div>
</div>
</wa-card>
@@ -232,11 +244,11 @@
</div>
<div slot="footer" class="wa-grid wa-gap-xs" style="--min-column-size: 10ch;">
<wa-button appearance="outlined" tabindex="-1">
<wa-icon slot="prefix" name="at"></wa-icon>
<wa-icon slot="start" name="at"></wa-icon>
Email
</wa-button>
<wa-button appearance="outlined" tabindex="-1">
<wa-icon slot="prefix" name="phone"></wa-icon>
<wa-icon slot="start" name="phone"></wa-icon>
Phone
</wa-button>
</div>
@@ -253,12 +265,12 @@
</div>
</a>
<wa-dropdown>
<wa-icon-button id="more-actions-2" slot="trigger" name="ellipsis-vertical" label="View menu" tabindex="-1"></wa-icon-button>
<wa-menu>
<wa-menu-item>Copy link</wa-menu-item>
<wa-menu-item>Rename</wa-menu-item>
<wa-menu-item>Move to trash</wa-menu-item>
</wa-menu>
<wa-button id="more-actions-2" slot="trigger" appearance="plain" size="small" tabindex="-1">
<wa-icon name="ellipsis-vertical" label="View menu"></wa-icon>
</wa-button>
<wa-dropdown-item>Copy link</wa-dropdown-item>
<wa-dropdown-item>Rename</wa-dropdown-item>
<wa-dropdown-item>Move to trash</wa-dropdown-item>
</wa-dropdown>
<wa-tooltip for="more-actions-2">View menu</wa-tooltip>
</div>

View File

@@ -70,7 +70,9 @@
<div class="alignment">
<wa-avatar></wa-avatar>
<wa-rating></wa-rating>
<wa-icon-button name="gear" label="Settings"></wa-icon-button>
<wa-button appearance="plain">
<wa-icon name="gear" label="Settings"></wa-icon>
</wa-button>
<wa-spinner></wa-spinner>
</div>
</div>

View File

@@ -258,20 +258,16 @@
<th><code>small</code>/<code>s</code></th>
<td>
<wa-dropdown size="small">
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>Menu Item 1</wa-dropdown-item>
<wa-dropdown-item>Menu Item 2</wa-dropdown-item>
</wa-dropdown>
</td>
<td>
<wa-dropdown class="wa-size-s">
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>Menu Item 1</wa-dropdown-item>
<wa-dropdown-item>Menu Item 2</wa-dropdown-item>
</wa-dropdown>
</td>
</tr>
@@ -279,20 +275,16 @@
<th><code>medium</code>/<code>m</code></th>
<td>
<wa-dropdown size="medium">
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>Menu Item 1</wa-dropdown-item>
<wa-dropdown-item>Menu Item 2</wa-dropdown-item>
</wa-dropdown>
</td>
<td>
<wa-dropdown class="wa-size-m">
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>Menu Item 1</wa-dropdown-item>
<wa-dropdown-item>Menu Item 2</wa-dropdown-item>
</wa-dropdown>
</td>
</tr>
@@ -300,20 +292,16 @@
<th><code>large</code>/<code>l</code></th>
<td>
<wa-dropdown size="large">
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>Menu Item 1</wa-dropdown-item>
<wa-dropdown-item>Menu Item 2</wa-dropdown-item>
</wa-dropdown>
</td>
<td>
<wa-dropdown class="wa-size-l">
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>Menu Item 1</wa-dropdown-item>
<wa-dropdown-item>Menu Item 2</wa-dropdown-item>
</wa-dropdown>
</td>
</tr>
@@ -322,66 +310,6 @@
</div>
<wa-divider></wa-divider>
<h3>Menu</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-menu size="small">
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
</td>
<td>
<wa-menu class="wa-size-s">
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
</td>
</tr>
<tr>
<th><code>medium</code>/<code>m</code></th>
<td>
<wa-menu size="medium">
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
</td>
<td>
<wa-menu class="wa-size-m">
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
</td>
</tr>
<tr>
<th><code>large</code>/<code>l</code></th>
<td>
<wa-menu size="large">
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
</td>
<td>
<wa-menu class="wa-size-l">
<wa-menu-item>Menu Item 1</wa-menu-item>
<wa-menu-item>Menu Item 2</wa-menu-item>
</wa-menu>
</td>
</tr>
</tbody>
</table>
</div>
<wa-divider></wa-divider>
<h3>Input</h3>
<div class="table-scroll">
@@ -799,4 +727,4 @@
</tr>
</tbody>
</table>
</div>
</div>

View File

@@ -8,7 +8,7 @@ layout: page-outline
<div id="block-filter">
<wa-input type="search" placeholder="Search {{ title }}" with-clear autofocus>
<wa-icon slot="prefix" name="search"></wa-icon>
<wa-icon slot="start" name="search"></wa-icon>
</wa-input>
</div>

View File

@@ -33,14 +33,14 @@
<h1 class="title">
<span v-content="title">{{ title }}</span>
<template v-if="saved || tweaked">
<wa-icon-button name="pencil" label="Rename palette" @click="rename"></wa-icon-button>
<wa-icon-button v-if="saved" class="delete" name="trash" label="Delete palette" @click="deleteSaved"></wa-icon-button>
<wa-button appearance="plain" size="small" @click="rename">
<wa-icon name="pencil" label="Rename palette"></wa-icon>
</wa-button>
<wa-button appearance="plain" size="small" v-if="saved" class="delete" @click="deleteSaved">
<wa-icon name="trash" label="Delete palette"></wa-icon>
</wa-button>
<wa-button @click="save()" :disabled="!unsavedChanges"
:variant="unsavedChanges ? 'success' : 'neutral'" size="small" :appearance="unsavedChanges ? 'accent' : 'outlined'">
<span slot="prefix" class="icon-modifier">
<wa-icon name="sidebar" variant="regular"></wa-icon>
<wa-icon name="circle-plus" class="modifier" style="color: light-dark(var(--wa-color-green-70), var(--wa-color-green-60));"></wa-icon>
</span>
<span v-content="unsavedChanges ? 'Save' : 'Saved'">Save</span>
</wa-button>
</template>
@@ -71,10 +71,8 @@
<wa-tag v-for="tweakHumanReadable, param in tweaksHumanReadable" with-remove @wa-remove="reset(param)" v-content="tweakHumanReadable"></wa-tag>
</div>
<wa-button @click="reset()" appearance="outlined" variant="danger">
<span slot="prefix" class="icon-modifier">
<wa-icon name="circle-xmark" variant="regular"></wa-icon>
</span>
<wa-button @click="reset()" appearance="outlined" variant="danger" size="small">
<wa-icon slot="start" name="circle-xmark" variant="regular"></wa-icon>
Reset
</wa-button>
</wa-callout>
@@ -130,7 +128,9 @@
@input="tweaking.grayChroma = true" @change="tweaking.grayChroma = false">
<div slot="label">
Gray colorfulness
<wa-icon-button @click="grayChroma = originalGrayChroma" class="clear-button" name="circle-xmark" library="system" variant="regular" label="Reset"></wa-icon-button>
<wa-button appearance="plain" @click="grayChroma = originalGrayChroma" class="clear-button">
<wa-icon name="circle-xmark" label="Reset" variant="regular"></wa-icon>
</wa-button>
</div>
</wa-slider>
<div class="label-min">Neutral</div>
@@ -149,7 +149,9 @@
@change="tweaking.hue = tweaking.{{ hue }} = false">
<div slot="label">
Tweak {{ hue }} hue
<wa-icon-button @click="hueShifts.{{ hue }} = 0" class="clear-button" name="circle-xmark" library="system" variant="regular" label="Reset"></wa-icon-button>
<wa-button appearance="plain" @click="hueShifts.{{ hue }} = 0" class="clear-button">
<wa-icon name="circle-xmark" label="Reset" variant="regular"></wa-icon>
</wa-button>
</div>
</wa-slider>
<div class="label-min">More {{hueBefore}}</div>
@@ -193,7 +195,9 @@ style="--min: {{ chromaScaleBounds[0] }}; --max: {{ chromaScaleBounds[1] }};">
@change="tweaking.chroma = false">
<div slot="label">
Overall colorfulness
<wa-icon-button @click="chromaScale = 1" class="clear-button" name="circle-xmark" library="system" variant="regular" label="Reset"></wa-icon-button>
<wa-button appearance="plain" @click="chromaScale = 1" class="clear-button">
<wa-icon name="circle-xmark" label="Reset" variant="regular"></wa-icon>
</wa-button>
</div>
</wa-slider>
<div class="label-min">More muted</div>

View File

@@ -24,12 +24,12 @@ if (location.pathname.endsWith('/custom/') && !location.search) {
<h4 slot="summary" data-no-anchor data-no-outline id="remix">
<wa-icon name="arrows-rotate"></wa-icon>
Remix this theme
<wa-icon id="what-is-remixing" href="#remixing" name="circle-question" slot="suffix" variant="regular"></wa-icon>
<wa-icon id="what-is-remixing" href="#remixing" name="circle-question" slot="end" variant="regular"></wa-icon>
<wa-tooltip for="what-is-remixing">Customize this theme by changing its colors and/or remixing it with design elements from other themes!</wa-tooltip>
</h4>
<wa-select name="palette" label="Color palette" with-clear v-model="theme.palette">
<wa-icon name="swatchbook" slot="prefix" variant="regular"></wa-icon>
<wa-icon name="swatchbook" slot="start" variant="regular"></wa-icon>
<wa-option v-for="(palette, paletteId) in palettes" :label="palette.title" :value="paletteId === baseTheme.palette ? '' : paletteId">
<palette-card :palette="paletteId" size="small">
<template #extra>
@@ -43,7 +43,7 @@ if (location.pathname.endsWith('/custom/') && !location.search) {
:values="hues"></color-select>
<wa-select name="colors" class="theme-colors-select" label="Color contrast from…" value="" with-clear v-model="theme.colors">
<wa-icon name="palette" slot="prefix" variant="regular"></wa-icon>
<wa-icon name="palette" slot="start" variant="regular"></wa-icon>
<template v-for="(themeMeta, themeId) in themes">
<wa-option v-if="themeId !== 'custom'" :label="themeMeta.title" :value="themeId === computed.colors ? '' : themeId">
<theme-card :theme="themeId" type="colors" :rest="{base: computed.base, palette: computed.palette, brand: computed.brand}" size="small">
@@ -56,7 +56,7 @@ if (location.pathname.endsWith('/custom/') && !location.search) {
</wa-select>
<wa-select name="typography" label="Typography from…" with-clear v-model="theme.typography">
<wa-icon name="font-case" slot="prefix"></wa-icon>
<wa-icon name="font-case" slot="start"></wa-icon>
<wa-option v-for="(themeMeta, themeId) in themes" :label="themeMeta.title" :value="themeId === theme.base ? '' : themeId">
<fonts-card :theme="themeId" size="small">

View File

@@ -25,7 +25,6 @@ export function codeExamplesPlugin(options = {}) {
const pre = code.closest('pre');
const hasButtons = !code.classList.contains('no-buttons');
const isOpen = code.classList.contains('open') || !hasButtons;
const isViewportDemo = code.classList.contains('viewport');
const noEdit = code.classList.contains('no-edit');
const id = `code-example-${uuid().slice(-12)}`;
let preview = pre.textContent;
@@ -35,29 +34,10 @@ export function codeExamplesPlugin(options = {}) {
root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module'));
preview = root.toString();
const escapedHtml = markdown.utils.escapeHtml(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Awesome Demo</title>
<link rel="stylesheet" href="https://early.webawesome.com/webawesome@[version]/dist/styles/themes/default.css" />
<link rel="stylesheet" href="https://early.webawesome.com/webawesome@[version]/dist/styles/webawesome.css" />
<script type="module" src="https://early.webawesome.com/webawesome@[version]/dist/webawesome.loader.js"></script>
</head>
<body>
${preview}
</body>
</html>
`);
const codeExample = parse(`
<div class="code-example ${isOpen ? 'open' : ''} ${isViewportDemo ? 'is-viewport-demo' : ''}">
<div class="code-example ${isOpen ? 'open' : ''}">
<div class="code-example-preview">
${isViewportDemo ? ` <wa-viewport-demo><iframe srcdoc="${escapedHtml}"></iframe></wa-viewport-demo>` : preview}
${preview}
<div class="code-example-resizer" aria-hidden="true">
<wa-icon name="grip-lines-vertical"></wa-icon>
</div>

View File

@@ -32,7 +32,7 @@ export function copyCodePlugin(eleventyConfig, options = {}) {
}
// Add a copy button
pre.innerHTML += `<wa-icon-button href="#${preId}" class="block-link-icon" name="link"></wa-icon-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>`;
});

View File

@@ -32,7 +32,9 @@
</header>
<nav slot="subheader">
<div class="wa-cluster" style="flex-wrap: nowrap">
<wa-icon-button data-toggle-nav name="bars" label="Menu"></wa-icon-button>
<wa-button data-toggle-nav appearance="plain" size="small">
<wa-icon name="bars" label="Menu"></wa-icon>
</wa-button>
<wa-breadcrumb style="font-size: var(--wa-font-size-s)">
<wa-breadcrumb-item>Field Guides</wa-breadcrumb-item>
<wa-breadcrumb-item>Owls</wa-breadcrumb-item>
@@ -40,7 +42,7 @@
</wa-breadcrumb>
</div>
<wa-input id="search" class="wa-desktop-only" placeholder="Search" size="small" style="max-inline-size: 12rem">
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
<wa-icon slot="start" name="magnifying-glass"></wa-icon>
</wa-input>
</nav>
<nav slot="navigation-header">

View File

@@ -12,12 +12,14 @@
<wa-page class="wa-dark">
<header slot="header">
<div class="wa-cluster">
<wa-icon-button name="bars" label="Menu" data-toggle-nav></wa-icon-button>
<wa-button data-toggle-nav appearance="plain" size="small">
<wa-icon name="bars" label="Menu"></wa-icon>
</wa-button>
<wa-icon name="record-vinyl"></wa-icon>
<span class="wa-heading-m">radiogaga</span>
</div>
<wa-input id="search-header" placeholder="Search" class="wa-desktop-only" style="max-inline-size: 100%">
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
<wa-icon slot="start" name="magnifying-glass"></wa-icon>
</wa-input>
<div class="wa-cluster">
<wa-button appearance="outlined">Log In</wa-button>
@@ -26,11 +28,14 @@
</header>
<div slot="navigation-header" class="wa-split">
<wa-input id="search-nav-drawer" placeholder="Search" style="max-inline-size: 100%" class="wa-mobile-only">
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
<wa-icon slot="start" name="magnifying-glass"></wa-icon>
</wa-input>
<div class="wa-split">
<h2 class="wa-heading-s">For You</h2>
<wa-icon-button id="settings" name="gear" label="Settings"></wa-icon-button>
<wa-button id="settings" appearance="plain" size="small">
<wa-icon name="gear" label="Settings"></wa-icon>
</wa-button>
<wa-tooltip for="settings">Settings</wa-tooltip>
</div>
</div>
<nav slot="navigation">
@@ -120,12 +125,18 @@
</ul>
</nav>
<div slot="main-header">
<wa-icon-button id="back" name="chevron-left" label="Back"></wa-icon-button>
<wa-button id="back" appearance="plain" size="small">
<wa-icon name="chevron-left" label="Back"></wa-icon>
</wa-button>
<wa-tooltip for="back" placement="bottom" distance="2">Back</wa-tooltip>
<div class="wa-cluster">
<wa-icon-button id="favorite" name="heart" variant="regular" label="Favorite"></wa-icon-button>
<wa-button id="favorite" appearance="plain" size="small">
<wa-icon name="heart" label="Favorite" variant="regular"></wa-icon>
</wa-button>
<wa-tooltip for="favorite" placement="bottom" distance="2">Favorite</wa-tooltip>
<wa-icon-button id="options" name="ellipsis" label="Options"></wa-icon-button>
<wa-button id="options" appearance="plain" size="small">
<wa-icon name="ellipsis" label="Options"></wa-icon>
</wa-button>
<wa-tooltip for="options" placement="bottom" distance="2">Options</wa-tooltip>
</div>
</div>
@@ -152,10 +163,16 @@
</div>
<div id="play-controls" class="wa-split wa-gap-xl">
<div class="wa-cluster wa-gap-xl">
<wa-icon-button name="play" label="Play"></wa-icon-button>
<wa-icon-button name="shuffle" label="Shuffle"></wa-icon-button>
<wa-button variant="brand" size="large">
<wa-icon name="play" label="Play"></wa-icon>
</wa-button>
<wa-button appearance="plain">
<wa-icon name="shuffle" label="Shuffle"></wa-icon>
</wa-button>
</div>
<wa-icon-button name="plus" label="Add to Library"></wa-icon-button>
<wa-button appearance="plain">
<wa-icon name="plus" label="Add to Library"></wa-icon>
</wa-button>
</div>
</div>
</div>
@@ -167,7 +184,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">3:27</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -177,7 +196,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">2:36</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -187,7 +208,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">2:51</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -197,7 +220,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">3:05</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -207,7 +232,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">1:56</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -217,7 +244,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">3:32</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -227,7 +256,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">2:46</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -237,7 +268,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">3:27</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -247,7 +280,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">2:13</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -260,7 +295,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">2:55</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -273,7 +310,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">3:10</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
<li class="wa-split">
@@ -286,7 +325,9 @@
</span>
<span class="wa-cluster">
<span class="wa-caption-m">3:22</span>
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="ellipsis" label="Song Options"></wa-icon>
</wa-button>
</span>
</li>
</ol>
@@ -380,8 +421,8 @@
aspect-ratio: 1;
color: var(--wa-color-brand-fill-loud);
display: flex;
height: var(--flank-size);
justify-content: center;
padding-block: 0.5em;
}
#recent wa-icon {
border-radius: var(--wa-border-radius-s);
@@ -420,16 +461,14 @@
[slot='main-header'] {
background-color: var(--wa-color-surface-raised);
}
#play-controls wa-icon-button::part(base) {
#play-controls wa-button::part(base) {
border: var(--wa-border-width-l) var(--wa-border-style) currentColor;
border-radius: var(--wa-border-radius-circle);
font-size: 1.5rem;
}
#play-controls wa-icon-button[name='play']::part(base) {
background-color: var(--wa-color-brand-fill-loud);
#play-controls wa-button:has(wa-icon[name='play'])::part(base) {
border: none;
color: var(--wa-color-brand-on-loud);
font-size: 3rem;
font-size: 2.5rem;
padding: 0.5em 0.45em 0.5em 0.55em;
}
[slot='main-footer'].wa-grid > * {

View File

@@ -1,4 +1,4 @@
import { domChange, nextFrame, ThemeAspect } from './theme-picker.js';
import { domChange, ThemeAspect } from './theme-picker.js';
const presetTheme = new ThemeAspect({
defaultValue: 'default',
@@ -33,7 +33,7 @@ const presetTheme = new ThemeAspect({
if (instant) {
// If no VT, delay by 1 frame to make it smoother
await nextFrame();
await new Promise(requestAnimationFrame);
}
oldStylesheet.remove();

View File

@@ -6,3 +6,4 @@ Prism.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0
Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/};
Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript;
!function(){if("undefined"!=typeof Prism){var n,s,a="";Prism.plugins.customClass={add:function(s){n=s},map:function(n){s="function"==typeof n?n:function(s){return n[s]||s}},prefix:function(n){a=n||""},apply:t},Prism.hooks.add("wrap",(function(e){if(n){var u=n({content:e.content,type:e.type,language:e.language});Array.isArray(u)?e.classes.push.apply(e.classes,u):u&&e.classes.push(u)}(s||a)&&(e.classes=e.classes.map((function(n){return t(n,e.language)})))}))}function t(n,t){return a+(s?s(n,t):n)}}();

View File

@@ -79,10 +79,12 @@ const sidebar = {
let append = [...badges];
if (entity.delete) {
let deleteButton = Object.assign(document.createElement('wa-icon-button'), {
name: 'trash',
label: 'Delete',
let deleteButton = Object.assign(document.createElement('wa-button'), {
appearance: 'plain',
variant: 'danger',
size: 'small',
className: 'delete',
innerHTML: '<wa-icon name="trash" label="Delete"></wa-icon>',
});
deleteButton.addEventListener('click', () => entity.delete());
append.push(deleteButton);

View File

@@ -1,14 +1,11 @@
import { domChange } from './util/dom-change.js';
export { domChange };
export function nextFrame() {
return new Promise(resolve => requestAnimationFrame(resolve));
}
export class ThemeAspect {
constructor(options) {
Object.assign(this, options);
this.set();
this.syncIframes();
// Update when local storage changes.
// That way changes in one window will propagate to others (including iframes).
@@ -67,6 +64,30 @@ export class ThemeAspect {
this.syncUI();
}
async syncIframes() {
await customElements.whenDefined('wa-zoomable-frame');
await new Promise(requestAnimationFrame);
// Sync to wa-zoomable-frame iframes
let dark = this.computedValue === 'dark';
for (let zoomableEl of document.querySelectorAll('wa-zoomable-frame')) {
const iframe = zoomableEl.iframe;
const applyToIframe = () => {
try {
iframe.contentDocument.documentElement.classList.toggle('wa-dark', dark);
} catch (e) {
// Silently handle access issues
}
};
// Try immediately
applyToIframe();
// Also listen for load in case it wasn't ready
iframe.addEventListener('load', applyToIframe, { once: true });
}
}
syncUI(container = document) {
for (let picker of container.querySelectorAll(this.picker)) {
picker.setAttribute('value', this.value);
@@ -87,27 +108,22 @@ const colorScheme = new ThemeAspect({
},
applyChange() {
// Toggle the dark mode class
domChange(() => {
// Toggle the dark mode class with view transition
const updateTheme = () => {
let dark = this.computedValue === 'dark';
document.documentElement.classList.toggle(`wa-dark`, dark);
document.documentElement.dispatchEvent(new CustomEvent('wa-color-scheme-change', { detail: { dark } }));
syncViewportDemoColorSchemes();
});
this.syncIframes();
};
if (document.startViewTransition) {
document.startViewTransition(() => domChange(updateTheme));
} else {
domChange(updateTheme);
}
},
});
function syncViewportDemoColorSchemes() {
const isDark = document.documentElement.classList.contains('wa-dark');
// Update viewport demo color schemes in code examples
document.querySelectorAll('.code-example.is-viewport-demo wa-viewport-demo').forEach(demo => {
demo.querySelectorAll('iframe').forEach(iframe => {
iframe.contentWindow.document.documentElement?.classList?.toggle('wa-dark', isDark);
});
});
}
// Update the color scheme when the preference changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => colorScheme.set());
@@ -121,12 +137,3 @@ document.addEventListener('keydown', event => {
colorScheme.set(colorScheme.get() === 'dark' ? 'light' : 'dark');
}
});
// When rendering a code example with a viewport demo, set the theme to match initially
document.querySelectorAll('.code-example.is-viewport-demo wa-viewport-demo iframe').forEach(iframe => {
const isDark = document.documentElement.classList.contains('wa-dark');
iframe.addEventListener('load', () => {
iframe.contentWindow.document.documentElement?.classList?.toggle('wa-dark', isDark);
});
});

View File

@@ -116,10 +116,12 @@
padding: 0.5rem;
cursor: pointer;
&: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 */
@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 {

View File

@@ -1,4 +1,5 @@
pre {
/* Only code blocks generated by our docs get these styles */
pre[id*='code-block-'] {
background-color: var(--wa-color-gray-20);
color: white;
@@ -8,6 +9,7 @@ pre {
background-color: var(--wa-color-surface-lowered);
}
}
.code-comment,
.code-prolog,
.code-doctype,

View File

@@ -1,3 +1,19 @@
/* Prep our code blocks to host the copy button */
pre[id*='code-block-']:has(code) {
position: relative;
padding: 0;
white-space: normal;
& code {
display: block;
font-size: 1em;
background-color: transparent;
padding: var(--wa-space-m);
white-space: pre;
overflow-x: auto;
}
}
wa-copy-button.copy-button {
--background-color: var(--wa-color-gray-20);
--background-color-hover: color-mix(in oklab, var(--background-color), white 5%);
@@ -9,8 +25,10 @@ wa-copy-button.copy-button {
border-radius: var(--wa-border-radius-m);
padding: 0.25rem;
&:hover {
color: white;
@media (hover: hover) {
&:hover {
color: white;
}
}
&:focus-visible {

View File

@@ -193,10 +193,13 @@ wa-badge.pro {
}
}
wa-icon-button.delete {
vertical-align: -0.2em;
wa-button.delete {
margin-inline-start: var(--wa-space-xs);
&:hover wa-icon {
color: var(--wa-color-danger-on-quiet);
}
&:not(li:hover > *, :focus) {
opacity: 0;
}
@@ -208,12 +211,9 @@ wa-badge.pro {
}
}
wa-icon-button.delete {
&:hover {
color: var(--wa-color-danger-on-quiet);
}
wa-button.delete {
&::part(base):hover {
color: var(--wa-color-danger-on-quiet);
background: var(--wa-color-danger-fill-quiet);
}
@@ -251,12 +251,6 @@ wa-page[view='mobile'] :is([slot='navigation-header'], [slot='navigation']) {
}
}
[slot='navigation-header'] wa-menu {
font-family: var(--wa-font-family-body);
font-size: var(--wa-font-size-m);
font-weight: var(--wa-font-weight-normal);
}
/* Main content */
wa-page > main {
max-width: 80ch;
@@ -495,8 +489,10 @@ table.colors {
tbody {
tr {
border: none;
&:hover {
background: transparent;
@media (hover: hover) {
&:hover {
background: transparent;
}
}
}
@@ -545,27 +541,6 @@ table.colors {
--icon-color: var(--wa-color-success-fill-quiet);
}
.icon-modifier {
position: relative;
display: inline-flex;
.modifier {
position: absolute;
bottom: -0.1em;
right: -0.3em;
font-size: 60%;
&::part(svg) {
stroke: var(--background-color, var(--wa-color-surface-default));
stroke-width: 100px;
paint-order: stroke;
overflow: visible;
stroke-linecap: round;
stroke-linejoin: round;
}
}
}
/* Layout Examples */
.layout-example-boundary {
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);

View File

@@ -124,7 +124,7 @@ html.wa-theme-tailspin .preview-container {
&::part(footer) {
border: none;
}
& wa-icon-button {
& wa-button {
color: var(--wa-color-base-50);
}
}
@@ -185,11 +185,11 @@ html.wa-theme-brutalist .preview-container {
text-align: right;
}
.product-card wa-button::part(prefix) {
.product-card wa-button::part(start) {
padding-inline-start: var(--wa-space-xs);
}
.product-card wa-button::part(suffix) {
.product-card wa-button::part(end) {
padding-inline-end: var(--wa-space-xs);
}
@@ -226,11 +226,11 @@ html.wa-theme-brutalist .preview-container {
--wa-color-neutral-border-quiet: color-mix(in oklab, var(--wa-color-gray-30), white 40%);
}
.message-composer [slot='header'] wa-icon-button::part(base) {
.message-composer [slot='header'] wa-button::part(base) {
color: var(--wa-color-neutral-on-loud);
}
.message-composer .grouped-buttons wa-icon-button::part(base):hover {
.message-composer .grouped-buttons wa-button::part(base):hover {
background-color: var(--wa-color-neutral-fill-normal);
color: var(--wa-color-text-normal);
}
@@ -421,7 +421,7 @@ html.wa-theme-playful .preview-container {
--wa-color-neutral-fill-quiet: var(--wa-color-gray-90);
}
.message-composer wa-icon-button {
.message-composer wa-button {
color: var(--wa-text-color-normal);
font-size: var(--wa-font-size-l);
}
@@ -662,12 +662,12 @@ html.wa-theme-premium .preview-container {
--padding: var(--wa-space-s) var(--wa-space-xl);
}
.message-composer .grouped-buttons wa-icon-button::part(base) {
.message-composer .grouped-buttons wa-button::part(base) {
block-size: var(--wa-form-control-height-s);
inline-size: var(--wa-form-control-height-s);
justify-content: center;
}
.message-composer .grouped-buttons wa-icon-button::part(base):hover {
.message-composer .grouped-buttons wa-button::part(base):hover {
background-color: var(--wa-color-neutral-fill-normal);
color: var(--wa-color-text-normal);
}

View File

@@ -5,10 +5,11 @@
}
.title {
wa-icon-button {
font-size: var(--wa-font-size-l);
color: var(--wa-color-text-quiet);
display: flex;
align-items: center;
gap: var(--wa-space-xs);
wa-button:has(wa-icon) {
&:not(:hover, :focus) {
opacity: 0.5;
}
@@ -127,11 +128,11 @@
> input {
font: inherit;
margin-block: calc(-1 * var(--wa-space-smaller));
margin-block: 0.75em;
field-sizing: content;
}
wa-icon-button {
wa-button {
font-size: 90%;
}
}

View File

@@ -4,11 +4,15 @@ const template = `
<span class="editable-text">
<template v-if="isEditing">
<input ref="input" class="wa-size-s" :aria-label="label" :value="value" @input="handleInput" @keydown.enter="done" @keydown.esc="cancel" @blur="handleBlur" />
<wa-icon-button v-if="blur !== 'done'" name="check" label="Done editing" @click="done"></wa-icon-button>
<wa-button appearance="plain" v-if="blur !== 'done'" @click="done">
<wa-icon name="check" label="Done editing"></wa-icon>
</wa-button>
</template>
<template v-else>
<span class="text" ref="wrapper" @focus="edit" @click="edit" tabindex="0">{{ value }}</span>
<wa-icon-button name="pencil" :label="'Edit ' + label" @click="edit"></wa-icon-button>
<wa-button appearance="plain" @click="edit">
<wa-icon name="pencil" :label="'Edit ' + label"></wa-icon>
</wa-button>
</template>
</span>
`;

View File

@@ -8,7 +8,9 @@ const template = `
<div class="ui-slider-header">
<label :for="sliderId">{{ label }}</label>
<info-tip v-if="clearable && (value !== defaultValue ?? initialValue)" :text="'Reset to ' + valueFormatter(defaultValue ?? initialValue)">
<wa-icon-button @click="value = defaultValue ?? initialValue" class="clear-button" name="circle-xmark" library="system" variant="regular" :label="'Reset to ' + tooltipFormatter(defaultValue ?? initialValue)"></wa-icon-button>
<wa-button @click="value = defaultValue ?? initialValue" class="clear-button">
<wa-icon name="circle-xmark" library="system" variant="regular" :label="'Reset to ' + tooltipFormatter(defaultValue ?? initialValue)"></wa-icon>
</wa-button>
</info-tip>
</div>
<info-tip v-if="$slots.min" :text="'Set to min (' + valueFormatter(min) + ')'">

View File

@@ -141,14 +141,3 @@ One of the most common use cases for badges is attaching them to buttons. To mak
<wa-badge variant="danger" pill>6</wa-badge>
</wa-button>
```
### With Menu Items
When including badges in menu items, use the `suffix` slot to make sure they're aligned correctly.
```html {.example}
<wa-menu style="max-width: 240px;">
<wa-menu-label>Messages</wa-menu-label>
<wa-menu-item>Comments <wa-badge slot="suffix" variant="neutral" pill>4</wa-badge></wa-menu-item>
<wa-menu-item>Replies <wa-badge slot="suffix" variant="neutral" pill>12</wa-badge></wa-menu-item>
</wa-menu>

View File

@@ -5,17 +5,4 @@ tags: component
parent: breadcrumb
---
```html {.example}
<wa-breadcrumb>
<wa-breadcrumb-item>
<wa-icon slot="prefix" name="house" variant="solid"></wa-icon>
Home
</wa-breadcrumb-item>
<wa-breadcrumb-item>Clothing</wa-breadcrumb-item>
<wa-breadcrumb-item>Shirts</wa-breadcrumb-item>
</wa-breadcrumb>
```
:::info
Additional demonstrations can be found in the [breadcrumb examples](/docs/components/breadcrumb).
:::
This component must be used as a child of `<wa-breadcrumb>`. Please see the [Breadcrumb docs](/docs/components/breadcrumb) to see examples of this component in action.

View File

@@ -36,32 +36,20 @@ For websites, you'll probably want to use links instead. You can make any breadc
</wa-breadcrumb>
```
### Prefixes
### Start & End Decorations
Use the `prefix` slot to add content before any breadcrumb item.
Use the `start` and `end` slots to add presentational elements like `<wa-icon>` next to any breadcrumb item.
```html {.example}
<wa-breadcrumb>
<wa-breadcrumb-item>
<wa-icon slot="prefix" name="house" variant="solid"></wa-icon>
<wa-icon slot="start" name="house"></wa-icon>
Home
</wa-breadcrumb-item>
<wa-breadcrumb-item>Articles</wa-breadcrumb-item>
<wa-breadcrumb-item>Traveling</wa-breadcrumb-item>
</wa-breadcrumb>
```
### Suffixes
Use the `suffix` slot to add content after any breadcrumb item.
```html {.example}
<wa-breadcrumb>
<wa-breadcrumb-item>Documents</wa-breadcrumb-item>
<wa-breadcrumb-item>Policies</wa-breadcrumb-item>
<wa-breadcrumb-item>
Security
<wa-icon slot="suffix" name="shield" variant="solid"></wa-icon>
<wa-icon slot="end" name="tree-palm"></wa-icon>
Traveling
</wa-breadcrumb-item>
</wa-breadcrumb>
```
@@ -99,7 +87,7 @@ Use the `separator` slot to change the separator that goes between breadcrumb it
### Custom Colors
Breadcrumb labels match the color set on `<wa-breadcrumb-item>`. Prefixes, suffixes, and separators can be styled using CSS parts.
Breadcrumb labels match the color set on `<wa-breadcrumb-item>`. Content in the `start`, `end`, and `separator` slots can be styled using CSS parts.
```html {.example}
<style>
@@ -112,14 +100,14 @@ Breadcrumb labels match the color set on `<wa-breadcrumb-item>`. Prefixes, suffi
.redcrumbs wa-breadcrumb-item::part(separator) {
color: pink;
}
.redcrumbs wa-breadcrumb-item::part(prefix),
.redcrumbs wa-breadcrumb-item::part(suffix) {
.redcrumbs wa-breadcrumb-item::part(start),
.redcrumbs wa-breadcrumb-item::part(end) {
color: currentColor;
}
</style>
<wa-breadcrumb class="redcrumbs">
<wa-breadcrumb-item>
<wa-icon slot="prefix" name="house" variant="solid"></wa-icon>
<wa-icon slot="start" name="house" variant="solid"></wa-icon>
Home
</wa-breadcrumb-item>
<wa-breadcrumb-item>Articles</wa-breadcrumb-item>
@@ -139,11 +127,9 @@ Dropdown menus can be placed in the default slot to provide additional options.
<wa-button slot="trigger" size="small" appearance="filled" pill>
<wa-icon label="More options" name="ellipsis" variant="solid"></wa-icon>
</wa-button>
<wa-menu>
<wa-menu-item type="checkbox" checked>Web Design</wa-menu-item>
<wa-menu-item type="checkbox">Web Development</wa-menu-item>
<wa-menu-item type="checkbox">Marketing</wa-menu-item>
</wa-menu>
<wa-dropdown-item type="checkbox" checked>Web Design</wa-dropdown-item>
<wa-dropdown-item type="checkbox">Web Development</wa-dropdown-item>
<wa-dropdown-item type="checkbox">Marketing</wa-dropdown-item>
</wa-dropdown>
</wa-breadcrumb-item>
<wa-breadcrumb-item>Our Services</wa-breadcrumb-item>
@@ -151,7 +137,7 @@ Dropdown menus can be placed in the default slot to provide additional options.
</wa-breadcrumb>
```
Alternatively, you can place dropdown menus in a prefix or suffix slot.
Alternatively, you can place dropdown menus in a `start` or `end` slot.
```html {.example}
<wa-breadcrumb>
@@ -160,15 +146,14 @@ Alternatively, you can place dropdown menus in a prefix or suffix slot.
<wa-breadcrumb-item>Digital Media</wa-breadcrumb-item>
<wa-breadcrumb-item>
Web Design
<wa-dropdown slot="suffix">
<wa-dropdown slot="end">
<wa-button slot="trigger" size="small" appearance="filled" pill>
<wa-icon label="More options" name="ellipsis" variant="solid"></wa-icon>
</wa-button>
<wa-menu>
<wa-menu-item type="checkbox" checked>Web Design</wa-menu-item>
<wa-menu-item type="checkbox">Web Development</wa-menu-item>
<wa-menu-item type="checkbox">Marketing</wa-menu-item>
</wa-menu>
<wa-dropdown-item type="checkbox" checked>Web Design</wa-dropdown-item>
<wa-dropdown-item type="checkbox">Web Development</wa-dropdown-item>
<wa-dropdown-item type="checkbox">Marketing</wa-dropdown-item>
</wa-dropdown>
</wa-breadcrumb-item>
</wa-breadcrumb>
```

View File

@@ -50,26 +50,26 @@ and it will override the inherited size,
it is rarely a good idea to mix sizes within the same button group.
:::
### Vertical button groups
### 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>
<wa-icon slot="prefix" name="plus"></wa-icon>
<wa-icon slot="start" name="plus"></wa-icon>
New
</wa-button>
<wa-button>
<wa-icon slot="prefix" name="folder-open"></wa-icon>
<wa-icon slot="start" name="folder-open"></wa-icon>
Open
</wa-button>
<wa-button>
<wa-icon slot="prefix" name="save"></wa-icon>
<wa-icon slot="start" name="save"></wa-icon>
Save
</wa-button>
<wa-button>
<wa-icon slot="prefix" name="print"></wa-icon>
<wa-icon slot="start" name="print"></wa-icon>
Print
</wa-button>
</wa-button-group>
@@ -165,12 +165,10 @@ Dropdowns can be placed into button groups.
<wa-button-group label="Example Button Group">
<wa-button>Button</wa-button>
<wa-dropdown>
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Item 1</wa-menu-item>
<wa-menu-item>Item 2</wa-menu-item>
<wa-menu-item>Item 3</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>Item 1</wa-dropdown-item>
<wa-dropdown-item>Item 2</wa-dropdown-item>
<wa-dropdown-item>Item 3</wa-dropdown-item>
</wa-dropdown>
<wa-button>Button</wa-button>
</wa-button-group>
@@ -187,11 +185,9 @@ Create a split button using a button and a dropdown. Use a [visually hidden](/do
<wa-button slot="trigger" variant="brand">
<wa-icon name="chevron-down" label="More options"></wa-icon>
</wa-button>
<wa-menu>
<wa-menu-item>Save</wa-menu-item>
<wa-menu-item>Save as&hellip;</wa-menu-item>
<wa-menu-item>Save all</wa-menu-item>
</wa-menu>
<wa-dropdown-item>Save</wa-dropdown-item>
<wa-dropdown-item>Save as&hellip;</wa-dropdown-item>
<wa-dropdown-item>Save all</wa-dropdown-item>
</wa-dropdown>
</wa-button-group>
```
@@ -230,9 +226,15 @@ Create interactive toolbars with button groups.
</wa-button-group>
<wa-button-group label="Alignment">
<wa-button id="button-align-left"><wa-icon name="align-left" variant="solid" label="Align Left"></wa-icon></wa-button>
<wa-button id="button-align-center"><wa-icon name="align-center" variant="solid" label="Align Center"></wa-icon></wa-button>
<wa-button id="button-align-right"><wa-icon name="align-right" variant="solid" label="Align Right"></wa-icon></wa-button>
<wa-button id="button-align-left">
<wa-icon name="align-left" variant="solid" label="Align Left"></wa-icon>
</wa-button>
<wa-button id="button-align-center">
<wa-icon name="align-center" variant="solid" label="Align Center"></wa-icon>
</wa-button>
<wa-button id="button-align-right">
<wa-icon name="align-right" variant="solid" label="Align Right"></wa-icon>
</wa-button>
</wa-button-group>
</div>

View File

@@ -103,6 +103,19 @@ It's often helpful to have a button that works like a link. This is possible by
<wa-button href="/assets/images/logo.svg" download="shoelace.svg">Download</wa-button>
```
### Icon Buttons
When only an [icon](/docs/components/icon) is slotted into the `label` slot, the button becomes an icon button. In this case, it's important to give the icon a label for users with assistive devices. Icon buttons can use any appearance or variant.
```html {.example}
<div class="wa-cluster">
<wa-button variant="neutral" appearance="accent"><wa-icon name="house" label="Home"></wa-icon></wa-button>
<wa-button variant="neutral" appearance="outlined"><wa-icon name="house" label="Home"></wa-icon></wa-button>
<wa-button variant="neutral" appearance="filled"><wa-icon name="house" label="Home"></wa-icon></wa-button>
<wa-button variant="neutral" appearance="plain"><wa-icon name="house" label="Home"></wa-icon></wa-button>
</div>
```
### Setting a Custom Width
As expected, buttons can be given a custom width by setting the `width` CSS property. This is useful for making buttons span the full width of their container on smaller screens.
@@ -113,72 +126,72 @@ As expected, buttons can be given a custom width by setting the `width` CSS prop
<wa-button size="large" style="width: 100%;">Large</wa-button>
```
### Prefix and Suffix Icons
### Start & End Decorations
Use the `prefix` and `suffix` slots to add icons.
Use the `start` and `end` slots to add presentational elements like `<wa-icon>` next to the button label.
```html {.example}
<wa-button size="small">
<wa-icon slot="prefix" name="gear" variant="solid"></wa-icon>
<wa-icon slot="start" name="gear"></wa-icon>
Settings
</wa-button>
<wa-button size="small">
<wa-icon slot="suffix" name="undo" variant="solid"></wa-icon>
<wa-icon slot="end" name="undo"></wa-icon>
Refresh
</wa-button>
<wa-button size="small">
<wa-icon slot="prefix" name="link" variant="solid"></wa-icon>
<wa-icon slot="suffix" name="arrow-up-right-from-square" variant="solid"></wa-icon>
<wa-icon slot="start" name="link"></wa-icon>
<wa-icon slot="end" name="arrow-up-right-from-square"></wa-icon>
Open
</wa-button>
<br /><br />
<wa-button>
<wa-icon slot="prefix" name="gear" variant="solid"></wa-icon>
<wa-icon slot="start" name="gear"></wa-icon>
Settings
</wa-button>
<wa-button>
<wa-icon slot="suffix" name="undo" variant="solid"></wa-icon>
<wa-icon slot="end" name="undo"></wa-icon>
Refresh
</wa-button>
<wa-button>
<wa-icon slot="prefix" name="link" variant="solid"></wa-icon>
<wa-icon slot="suffix" name="arrow-up-right-from-square" variant="solid"></wa-icon>
<wa-icon slot="start" name="link"></wa-icon>
<wa-icon slot="end" name="arrow-up-right-from-square"></wa-icon>
Open
</wa-button>
<br /><br />
<wa-button size="large">
<wa-icon slot="prefix" name="gear" variant="solid"></wa-icon>
<wa-icon slot="start" name="gear"></wa-icon>
Settings
</wa-button>
<wa-button size="large">
<wa-icon slot="suffix" name="undo" variant="solid"></wa-icon>
<wa-icon slot="end" name="undo"></wa-icon>
Refresh
</wa-button>
<wa-button size="large">
<wa-icon slot="prefix" name="link" variant="solid"></wa-icon>
<wa-icon slot="suffix" name="arrow-up-right-from-square" variant="solid"></wa-icon>
<wa-icon slot="start" name="link"></wa-icon>
<wa-icon slot="end" name="arrow-up-right-from-square"></wa-icon>
Open
</wa-button>
```
### Caret
Use the `caret` attribute to add a dropdown indicator when a button will trigger a dropdown, menu, or popover.
Use the `with-caret` attribute to add a dropdown indicator when a button will trigger a dropdown, menu, or popover.
```html {.example}
<wa-button size="small" caret>Small</wa-button>
<wa-button size="medium" caret>Medium</wa-button>
<wa-button size="large" caret>Large</wa-button>
<wa-button size="small" with-caret>Small</wa-button>
<wa-button size="medium" with-caret>Medium</wa-button>
<wa-button size="large" with-caret>Large</wa-button>
```
### Loading

View File

@@ -57,7 +57,9 @@ If using SSR, you need to also use the `with-header` attribute to add a header t
<wa-card class="card-header">
<div slot="header" class="wa-split">
Header Title
<wa-icon-button name="gear" variant="solid" label="Settings" class="wa-size-m"></wa-icon-button>
<wa-button appearance="plain">
<wa-icon name="gear" variant="solid" label="Settings"></wa-icon>
</wa-button>
</div>
This card has a header. You can put all sorts of things in it!

View File

@@ -6,41 +6,4 @@ parent: carousel
icon: carousel-item
---
```html {.example}
<wa-carousel pagination>
<wa-carousel-item>
<img
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
src="/assets/examples/carousel/mountains.jpg"
/>
</wa-carousel-item>
<wa-carousel-item>
<img
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
src="/assets/examples/carousel/waterfall.jpg"
/>
</wa-carousel-item>
<wa-carousel-item>
<img
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
src="/assets/examples/carousel/sunset.jpg"
/>
</wa-carousel-item>
<wa-carousel-item>
<img
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
src="/assets/examples/carousel/field.jpg"
/>
</wa-carousel-item>
<wa-carousel-item>
<img
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
src="/assets/examples/carousel/valley.jpg"
/>
</wa-carousel-item>
</wa-carousel>
```
:::info
Additional demonstrations can be found in the [carousel examples](/docs/components/carousel).
:::
This component must be used as a child of `<wa-carousel>`. Please see the [Carousel docs](/docs/components/carousel) to see examples of this component in action.

View File

@@ -1,76 +0,0 @@
let url = new URL(location);
const pushedURL = false;
const matchers = {
default(textContent, query) {
return textContent.includes(query);
},
i(textContent, query) {
return textContent.toLowerCase().includes(query.toLowerCase());
},
regexp(textContent, query) {
query.lastIndex = 0;
return query.test(textContent);
},
};
matchers.iregexp = matchers.regexp; // i is baked into the query
function filterByName(value) {
const previousFilter = url.searchParams.get('name') || '';
url = new URL(location);
if (value) {
const isRegexp = name_search_regexp.checked;
const i = !name_search_i.checked;
const query = isRegexp ? new RegExp(value, 'gmsv' + (i ? 'i' : '')) : value;
const matcherId = (i ? 'i' : '') + (isRegexp ? 'regexp' : '');
const matcher = matchers[matcherId] ?? matchers.default;
for (const th of document.querySelectorAll('table tbody th:first-child')) {
const tr = th.parentNode;
const matches = matcher(th.textContent, query);
tr.toggleAttribute('hidden', !matches);
}
url.searchParams.set('name', value);
if (matcherId) {
url.searchParams.set('match', matcherId);
} else {
url.searchParams.delete('match');
}
} else {
for (const tr of document.querySelectorAll('table tbody tr[hidden]')) {
tr.removeAttribute('hidden');
}
url.searchParams.delete('name');
url.searchParams.delete('match');
}
if (value !== previousFilter) {
history[pushedURL ? 'replaceState' : 'pushState'](null, '', url);
}
// Update heading counts
for (const h2 of document.querySelectorAll('h2:has(+ table)')) {
const count = h2.querySelector('.count');
if (!count) continue;
const table = h2.nextElementSibling;
const visibleRows = table.querySelectorAll('tbody tr:not([hidden])').length;
count.textContent = visibleRows;
const outlineLink = document.querySelector(`#outline-standard a[href="#${h2.id}"]`);
if (outlineLink) {
// Why not just = h2.textContent? To skip the "Jump to heading" link
outlineLink.textContent = '';
outlineLink.append(...[...h2.childNodes].slice(0, 3).map(n => n.cloneNode(true)));
}
}
}
if (name_search.value) {
filterByName(name_search.value);
}
name_search_group.addEventListener('input', e => filterByName(name_search.value));

View File

@@ -1,89 +0,0 @@
---
title: Component Cheatsheet
layout: docs
unlisted: true
---
<style>
table code {
white-space: nowrap;
}
</style>
<p>
This page lists every bit of syntax used by every Web Awesome component and which components share it.
For these times when your memory is failing, or to simply explore the possibilities!
</p>
<fieldset id="name_search_group">
<legend>Filter by name</legend>
<wa-input type="search" with-clear id="name_search"></wa-input>
<wa-checkbox id="name_search_i" checked>Case sensitive</wa-checkbox>
<wa-checkbox id="name_search_regexp">Regular expression</wa-checkbox>
</fieldset>
<script>
{
let url = new URL(location);
if (url.searchParams.get("name")) {
name_search.value = url.searchParams.get("name");
}
if (url.searchParams.get("match")) {
let matcherId = url.searchParams.get("match");
let caseSensitive = !matcherId.startsWith("i");
let isRegexp = matcherId.endsWith("regexp");
customElements.whenDefined("wa-checkbox").then(async () => {
await Promise.all([
name_search_i.updateComplete,
name_search_regexp.updateComplete,
]);
name_search_i.checked = caseSensitive;
name_search_regexp.checked = isRegexp;
});
}
}
</script>
<script type="module" src="/docs/components/cheatsheet.js"></script>
{% for type, all in componentsBy -%}
{% set typeTitle = "CSS custom properties" if type == "cssProperty" else ("CSS parts" if type == "cssPart" else (type | title) + "s") %}
<h2 id="{{ typeTitle | slugify }}">
All <span class="count">{{ (all | keys).length }}</span>
{{ typeTitle }}
</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Components</th>
</tr>
</thead>
{% for name, thingComponents in all -%}
<tr>
<th><code>{{ name }}{{ "()" if type == "method" }}</code></th>
<td>
{% set componentLinks = [] %}
{% for component in thingComponents %}
{%- set link -%}
<a href="../{{ component.slug }}"><code>&lt;{{ component.tagName }}&gt;</code></a>
{%- endset -%}
{# https://giuliachiola.dev/posts/add-items-to-an-array-in-nunjucks/ #}
{% set componentLinks = (componentLinks.push(link), componentLinks) %}
{%- endfor -%}
{% if thingComponents.length > 1 %}
<details open>
<summary><strong>{{ thingComponents.length }}</strong> components</summary>
{{ componentLinks | safe }}
</details>
{% else %}
{{ componentLinks | safe }}
{% endif %}
</td>
</tr>
{%- endfor %}
</table>
{%- endfor %}

View File

@@ -49,7 +49,7 @@ Use the `expand-icon` and `collapse-icon` slots to change the expand and collaps
</style>
```
### HTML in summary
### HTML in Summary
To use HTML in the summary, use the `summary` slot.
Links and other interactive elements will still retain their behavior:
@@ -67,7 +67,7 @@ Links and other interactive elements will still retain their behavior:
</wa-details>
```
### Right-to-Left languages
### Right-to-Left Languages
The details component automatically adapts to right-to-left languages:
@@ -104,40 +104,23 @@ Use the `appearance` attribute to change the elements visual appearance.
### Grouping Details
Details are designed to function independently, but you can simulate a group or "accordion" where only one is shown at a time by listening for the `wa-show` event.
Use the `name` attribute to create accordion-like behavior where only one details element with the same name can be open at a time. This matches the behavior of native `<details>` elements.
```html {.example}
<div class="details-group-example">
<wa-details summary="First" open>
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.
<div class="wa-stack">
<wa-details name="group-1" summary="Section 1" open>
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="Second">
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 name="group-1" summary="Section 2">
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.
</wa-details>
<wa-details summary="Third">
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 name="group-1" summary="Section 3">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque
corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.
</wa-details>
</div>
<script>
const container = document.querySelector('.details-group-example');
// Close all other details when one is shown
container.addEventListener('wa-show', event => {
if (event.target.localName === 'wa-details') {
[...container.querySelectorAll('wa-details')].map(details => (details.open = event.target === details));
}
});
</script>
<style>
.details-group-example wa-details:not(:last-of-type) {
margin-bottom: var(--wa-space-2xs);
}
</style>
```
```

View File

@@ -67,24 +67,28 @@ Footers can be used to display titles and more. Use the `footer` slot to add a f
</script>
```
### Dismissing Dialogs
### Opening and Closing Dialogs Declaratively
You can add the special `data-dialog="close"` attribute to a button inside the dialog to tell it to close without additional JavaScript. Alternatively, you can set the `open` property to `false` to close the dialog programmatically.
You can open and close dialogs with JavaScript by toggling the `open` attribute, but you can also do it declaratively. Add the `data-dialog="open id"` to any button on the page, where `id` is the ID of the dialog you want to open.
```html {.example}
<wa-dialog label="Dialog" class="dialog-dismiss">
<wa-dialog label="Dialog" id="dialog-opening">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
</wa-dialog>
<wa-button>Open Dialog</wa-button>
<wa-button data-dialog="open dialog-opening">Open Dialog</wa-button>
```
<script>
const dialog = document.querySelector('.dialog-dismiss');
const openButton = dialog.nextElementSibling;
Similarly, you can add `data-dialog="close"` to a button _inside_ of a dialog to tell it to close.
openButton.addEventListener('click', () => dialog.open = true);
</script>
```html {.example}
<wa-dialog label="Dialog" id="dialog-dismiss">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
</wa-dialog>
<wa-button data-dialog="open dialog-dismiss">Open Dialog</wa-button>
```
### Custom Width
@@ -131,11 +135,13 @@ By design, a dialog's height will never exceed that of the viewport. As such, di
### Header Actions
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/docs/components/icon-button) if needed.
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [buttons](/docs/components/button) if needed.
```html {.example}
<wa-dialog label="Dialog" class="dialog-header-actions">
<wa-icon-button class="new-window" slot="header-actions" name="arrow-up-right-from-square" variant="solid"></wa-icon-button>
<wa-button class="new-window" slot="header-actions" appearance="plain">
<wa-icon name="arrow-up-right-from-square" variant="solid" label="Open in new window"></wa-icon>
</wa-button>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
</wa-dialog>

View File

@@ -58,13 +58,14 @@ The default orientation for dividers is `horizontal`. Set `orientation` attribut
Use dividers in [menus](/docs/components/menu) to visually group menu items.
```html {.example}
<wa-menu style="max-width: 200px;">
<wa-menu-item value="1">Option 1</wa-menu-item>
<wa-menu-item value="2">Option 2</wa-menu-item>
<wa-menu-item value="3">Option 3</wa-menu-item>
<wa-dropdown style="max-width: 200px;">
<wa-button slot="trigger" with-caret>Menu</wa-button>
<wa-dropdown-item value="1">Option 1</wa-dropdown-item>
<wa-dropdown-item value="2">Option 2</wa-dropdown-item>
<wa-dropdown-item value="3">Option 3</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-menu-item value="4">Option 4</wa-menu-item>
<wa-menu-item value="5">Option 5</wa-menu-item>
<wa-menu-item value="6">Option 6</wa-menu-item>
</wa-menu>
<wa-dropdown-item value="4">Option 4</wa-dropdown-item>
<wa-dropdown-item value="5">Option 5</wa-dropdown-item>
<wa-dropdown-item value="6">Option 6</wa-dropdown-item>
</wa-dropdown>
```

View File

@@ -65,24 +65,28 @@ Footers can be used to display titles and more. Use the `footer` slot to add a f
</script>
```
### Dismissing Drawers
### Opening and Closing Drawers Declaratively
You can add the special `data-drawer="close"` attribute to a button inside the drawer to tell it to close without additional JavaScript. Alternatively, you can set the `open` property to `false` to close the drawer programmatically.
You can open and close drawers with JavaScript by toggling the `open` attribute, but you can also do it declaratively. Add the `data-drawer="open id"` to any button on the page, where `id` is the ID of the drawer you want to open.
```html {.example}
<wa-drawer label="Drawer" class="drawer-dismiss">
<wa-drawer label="Drawer" id="drawer-opening">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
</wa-drawer>
<wa-button>Open Drawer</wa-button>
<wa-button data-drawer="open drawer-opening">Open Drawer</wa-button>
```
<script>
const drawer = document.querySelector('.drawer-dismiss');
const openButton = drawer.nextElementSibling;
Similarly, you can add `data-drawer="close"` to a button _inside_ of a drawer to tell it to close.
openButton.addEventListener('click', () => drawer.open = true);
</script>
```html {.example}
<wa-drawer label="Drawer" id="drawer-dismiss">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
</wa-drawer>
<wa-button data-drawer="open drawer-dismiss">Open Drawer</wa-button>
```
### Slide in From Start
@@ -189,11 +193,13 @@ By design, a drawer's height will never exceed 100% of its container. As such, d
### Header Actions
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/docs/components/icon-button) if needed.
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [buttons](/docs/components/button) if needed.
```html {.example}
<wa-drawer label="Drawer" class="drawer-header-actions">
<wa-icon-button class="new-window" slot="header-actions" name="arrow-up-right-from-square" variant="solid"></wa-icon-button>
<wa-button class="new-window" slot="header-actions" appearance="plain">
<wa-icon name="arrow-up-right-from-square" variant="solid" label="Open in new window"></wa-icon>
</wa-button>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
</wa-drawer>

View File

@@ -0,0 +1,7 @@
---
title: Dropdown Item
description: Description of component.
layout: component
---
This component must be used as a child of `<wa-dropdown>`. Please see the [Dropdown docs](/docs/components/dropdown) to see examples of this component in action.

View File

@@ -7,28 +7,38 @@ icon: dropdown
Dropdowns consist of a trigger and a panel. By default, activating the trigger will expose the panel and interacting outside of the panel will close it.
Dropdowns are designed to work well with [menus](/docs/components/menu) to provide a list of options the user can select from. However, dropdowns can also be used in lower-level applications (e.g. [color picker](/docs/components/color-picker)). The API gives you complete control over showing, hiding, and positioning the panel.
Dropdowns are designed to work well with [dropdown items](/docs/components/dropdown-item) to provide a list of options the user can select from. However, dropdowns can also be used in lower-level applications. The API gives you complete control over showing, hiding, and positioning the panel.
```html {.example}
<wa-dropdown>
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Dropdown Item 1</wa-menu-item>
<wa-menu-item>Dropdown Item 2</wa-menu-item>
<wa-menu-item>Dropdown Item 3</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item type="checkbox" checked>Checkbox</wa-menu-item>
<wa-menu-item disabled>Disabled</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item>
Prefix
<wa-icon slot="prefix" name="gift" variant="solid"></wa-icon>
</wa-menu-item>
<wa-menu-item>
Suffix Icon
<wa-icon slot="suffix" name="heart" variant="solid"></wa-icon>
</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>
<wa-icon slot="icon" name="scissors"></wa-icon>
Cut
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="icon" name="copy"></wa-icon>
Copy
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="icon" name="paste"></wa-icon>
Paste
</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item>
Show images
<wa-dropdown-item slot="submenu" value="show-all-images">Show All Images</wa-dropdown-item>
<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>Word Wrap</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item variant="danger">
<wa-icon slot="icon" name="trash"></wa-icon>
Delete
</wa-dropdown-item>
</wa-dropdown>
```
@@ -36,17 +46,16 @@ Dropdowns are designed to work well with [menus](/docs/components/menu) to provi
### Getting the Selected Item
When dropdowns are used with [menus](/docs/components/menu), you can listen for the [`wa-select`](/docs/components/menu#events) event to determine which menu item was selected. The menu item element will be exposed in `event.detail.item`. You can set `value` props to make it easier to identify commands.
When an item is selected, the `wa-select` event will be emitted by the dropdown. You can inspect `event.detail.item` to get a reference to the selected item. If you've provided a value for each [dropdown item](/docs/components/dropdown-item), it will be available in `event.detail.item.value`.
```html {.example}
<div class="dropdown-selection">
<wa-dropdown>
<wa-button slot="trigger" caret>Edit</wa-button>
<wa-menu>
<wa-menu-item value="cut">Cut</wa-menu-item>
<wa-menu-item value="copy">Copy</wa-menu-item>
<wa-menu-item value="paste">Paste</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>View</wa-button>
<wa-dropdown-item value="full-screen">Enter full screen</wa-dropdown-item>
<wa-dropdown-item value="actual">Actual size</wa-dropdown-item>
<wa-dropdown-item value="zoom-in">Zoom in</wa-dropdown-item>
<wa-dropdown-item value="zoom-out">Zoom out</wa-dropdown-item>
</wa-dropdown>
</div>
@@ -55,53 +64,191 @@ When dropdowns are used with [menus](/docs/components/menu), you can listen for
const dropdown = container.querySelector('wa-dropdown');
dropdown.addEventListener('wa-select', event => {
const selectedItem = event.detail.item;
console.log(selectedItem.value);
console.log(event.detail.item.value);
});
</script>
```
Alternatively, you can listen for the `click` event on individual menu items. Note that, using this approach, disabled menu items will still emit a `click` event.
:::info
To keep the dropdown open after selection, call `event.preventDefault()` in the `wa-select` event's callback.
:::
### Showing Icons
Use the `icon` slot to add icons to [dropdown items](/docs/components/dropdown-item). This works best with [icon](/docs/components/icon) elements.
```html {.example}
<div class="dropdown-selection-alt">
<wa-dropdown>
<wa-button slot="trigger" with-caret>Edit</wa-button>
<wa-dropdown-item value="cut">
<wa-icon slot="icon" name="scissors"></wa-icon>
Cut
</wa-dropdown-item>
<wa-dropdown-item value="copy">
<wa-icon slot="icon" name="copy"></wa-icon>
Copy
</wa-dropdown-item>
<wa-dropdown-item value="paste">
<wa-icon slot="icon" name="paste"></wa-icon>
Paste
</wa-dropdown-item>
<wa-dropdown-item value="delete">
<wa-icon slot="icon" name="trash"></wa-icon>
Delete
</wa-dropdown-item>
</wa-dropdown>
```
### Showing Labels & Dividers
Use any heading, e.g. `<h1>``<h6>` to add labels and the [`<wa-divider>`](/docs/components/divider) element for separators.
```html {.example}
<wa-dropdown>
<wa-button slot="trigger" with-caret>Device</wa-button>
<h3>Type</h3>
<wa-dropdown-item value="phone">Phone</wa-dropdown-item>
<wa-dropdown-item value="tablet">Tablet</wa-dropdown-item>
<wa-dropdown-item value="desktop">Desktop</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item value="more">More options…</wa-dropdown-item>
</wa-dropdown>
```
### Showing Details
Use the `details` slot to display details, such as keyboard shortcuts, inside [dropdown items](/docs/components/dropdown-item).
```html {.example}
<wa-dropdown>
<wa-button slot="trigger" with-caret>Message</wa-button>
<wa-dropdown-item value="reply">
Reply
<span slot="details">⌘R</span>
</wa-dropdown-item>
<wa-dropdown-item value="forward">
Forward
<span slot="details">⌘F</span>
</wa-dropdown-item>
<wa-dropdown-item value="move">
Move
<span slot="details">⌘M</span>
</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item value="archive">
Archive
<span slot="details">⌘A</span>
</wa-dropdown-item>
<wa-dropdown-item value="delete" variant="danger">
Delete
<span slot="details">Del</span>
</wa-dropdown-item>
</wa-dropdown>
```
### Checkable Items
You can turn a [dropdown item](/docs/components/dropdown-item) into a checkable option by setting `type="checkbox"`. Add the `checked` attribute to make it checked initially. When clicked, the item's checked state will toggle and the dropdown will close. You can cancel the `wa-select` event if you want to keep it open instead.
```html {.example}
<div class="dropdown-checkboxes">
<wa-dropdown>
<wa-button slot="trigger" caret>Edit</wa-button>
<wa-menu>
<wa-menu-item value="cut">Cut</wa-menu-item>
<wa-menu-item value="copy">Copy</wa-menu-item>
<wa-menu-item value="paste">Paste</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>View</wa-button>
<wa-dropdown-item type="checkbox" value="canvas" checked>Show canvas</wa-dropdown-item>
<wa-dropdown-item type="checkbox" value="grid" checked>Show grid</wa-dropdown-item>
<wa-dropdown-item type="checkbox" value="source">Show source</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item value="preferences">Preferences…</wa-dropdown-item>
</wa-dropdown>
</div>
<script>
const container = document.querySelector('.dropdown-selection-alt');
const cut = container.querySelector('wa-menu-item[value="cut"]');
const copy = container.querySelector('wa-menu-item[value="copy"]');
const paste = container.querySelector('wa-menu-item[value="paste"]');
const container = document.querySelector('.dropdown-checkboxes');
const dropdown = container.querySelector('wa-dropdown');
cut.addEventListener('click', () => console.log('cut'));
copy.addEventListener('click', () => console.log('copy'));
paste.addEventListener('click', () => console.log('paste'));
dropdown.addEventListener('wa-select', event => {
if (event.detail.item.type === 'checkbox') {
// Checkbox
console.log(event.detail.item.value, event.detail.item.checked ? 'checked' : 'unchecked');
} else {
// Not a checkbox
console.log(event.detail.item.value);
}
});
</script>
```
:::info
When a checkable option exists anywhere in the dropdown, all items will receive additional padding so they align properly.
:::
### Destructive Items
Add `variant="danger"` to any [dropdown item](/docs/components/dropdown-item) to highlight that it's a dangerous action.
```html {.example}
<wa-dropdown>
<wa-button slot="trigger" with-caret>Project</wa-button>
<wa-dropdown-item value="share">
<wa-icon slot="icon" name="share"></wa-icon>
Share
</wa-dropdown-item>
<wa-dropdown-item value="preferences">
<wa-icon slot="icon" name="gear"></wa-icon>
Preferences
</wa-dropdown-item>
<wa-divider></wa-divider>
<h3>Danger zone</h3>
<wa-dropdown-item value="archive">
<wa-icon slot="icon" name="archive"></wa-icon>
Archive
</wa-dropdown-item>
<wa-dropdown-item value="delete" variant="danger">
<wa-icon slot="icon" name="trash"></wa-icon>
Delete
</wa-dropdown-item>
</wa-dropdown>
```
### Placement
The preferred placement of the dropdown can be set with the `placement` attribute. Note that the actual position may vary to ensure the panel remains in the viewport.
```html {.example}
<wa-dropdown placement="top-start">
<wa-button slot="trigger" caret>Edit</wa-button>
<wa-menu>
<wa-menu-item>Cut</wa-menu-item>
<wa-menu-item>Copy</wa-menu-item>
<wa-menu-item>Paste</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item>Find</wa-menu-item>
<wa-menu-item>Replace</wa-menu-item>
</wa-menu>
<wa-dropdown placement="right-start">
<wa-button slot="trigger">
File formats
<wa-icon slot="end" name="chevron-right"></wa-icon>
</wa-button>
<wa-dropdown-item value="pdf">PDF Document</wa-dropdown-item>
<wa-dropdown-item value="docx">Word Document</wa-dropdown-item>
<wa-dropdown-item value="xlsx">Excel Spreadsheet</wa-dropdown-item>
<wa-dropdown-item value="pptx">PowerPoint Presentation</wa-dropdown-item>
<wa-dropdown-item value="txt">Plain Text</wa-dropdown-item>
<wa-dropdown-item value="json">JSON File</wa-dropdown-item>
</wa-dropdown>
```
@@ -111,72 +258,112 @@ The distance from the panel to the trigger can be customized using the `distance
```html {.example}
<wa-dropdown distance="30">
<wa-button slot="trigger" caret>Edit</wa-button>
<wa-menu>
<wa-menu-item>Cut</wa-menu-item>
<wa-menu-item>Copy</wa-menu-item>
<wa-menu-item>Paste</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item>Find</wa-menu-item>
<wa-menu-item>Replace</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret>Edit</wa-button>
<wa-dropdown-item>Cut</wa-dropdown-item>
<wa-dropdown-item>Copy</wa-dropdown-item>
<wa-dropdown-item>Paste</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item>Find</wa-dropdown-item>
<wa-dropdown-item>Replace</wa-dropdown-item>
</wa-dropdown>
```
### Skidding
### Offset
The offset of the panel along the trigger can be customized using the `skidding` attribute. This value is specified in pixels.
The offset of the panel along the trigger can be customized using the `offset` attribute. This value is specified in pixels.
```html {.example}
<wa-dropdown skidding="30">
<wa-button slot="trigger" caret>Edit</wa-button>
<wa-menu>
<wa-menu-item>Cut</wa-menu-item>
<wa-menu-item>Copy</wa-menu-item>
<wa-menu-item>Paste</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item>Find</wa-menu-item>
<wa-menu-item>Replace</wa-menu-item>
</wa-menu>
<wa-dropdown offset="30">
<wa-button slot="trigger" with-caret>Edit</wa-button>
<wa-dropdown-item>Cut</wa-dropdown-item>
<wa-dropdown-item>Copy</wa-dropdown-item>
<wa-dropdown-item>Paste</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item>Find</wa-dropdown-item>
<wa-dropdown-item>Replace</wa-dropdown-item>
</wa-dropdown>
```
### Submenus
To create a submenu, nest an `<wa-menu slot="submenu">` element in a [menu item](/docs/components/menu-item).
To create submenus, nest [dropdown items](/docs/components/dropdown-item) inside of a dropdown item and assign `slot="submenu"` to each one. You can also add [dividers](/docs/components/divider) as needed.
```html {.example}
<wa-dropdown>
<wa-button slot="trigger" caret>Edit</wa-button>
<div class="dropdown-submenus">
<wa-dropdown>
<wa-button slot="trigger" with-caret>Export</wa-button>
<wa-dropdown-item>
Documents
<wa-dropdown-item slot="submenu" value="pdf">PDF</wa-dropdown-item>
<wa-dropdown-item slot="submenu" value="docx">Word Document</wa-dropdown-item>
</wa-dropdown-item>
<wa-dropdown-item>
Spreadsheets
<wa-dropdown-item slot="submenu">
Excel Formats
<wa-dropdown-item slot="submenu" value="xlsx">Excel (.xlsx)</wa-dropdown-item>
<wa-dropdown-item slot="submenu" value="xls">Excel 97-2003 (.xls)</wa-dropdown-item>
<wa-dropdown-item slot="submenu" value="csv">CSV (.csv)</wa-dropdown-item>
</wa-dropdown-item>
<wa-dropdown-item slot="submenu">
Other Formats
<wa-dropdown-item slot="submenu" value="ods">OpenDocument (.ods)</wa-dropdown-item>
<wa-dropdown-item slot="submenu" value="tsv">Tab-separated (.tsv)</wa-dropdown-item>
<wa-dropdown-item slot="submenu" value="json">JSON (.json)</wa-dropdown-item>
</wa-dropdown-item>
<wa-dropdown-item slot="submenu" value="numbers">Apple Numbers</wa-dropdown-item>
</wa-dropdown-item>
<wa-menu style="max-width: 200px;">
<wa-menu-item value="undo">Undo</wa-menu-item>
<wa-menu-item value="redo">Redo</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item value="cut">Cut</wa-menu-item>
<wa-menu-item value="copy">Copy</wa-menu-item>
<wa-menu-item value="paste">Paste</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item>
Find
<wa-menu slot="submenu">
<wa-menu-item value="find">Find…</wa-menu-item>
<wa-menu-item value="find-previous">Find Next</wa-menu-item>
<wa-menu-item value="find-next">Find Previous</wa-menu-item>
</wa-menu>
</wa-menu-item>
<wa-menu-item>
Transformations
<wa-menu slot="submenu">
<wa-menu-item value="uppercase">Make uppercase</wa-menu-item>
<wa-menu-item value="lowercase">Make lowercase</wa-menu-item>
<wa-menu-item value="capitalize">Capitalize</wa-menu-item>
</wa-menu>
</wa-menu-item>
</wa-menu>
</wa-dropdown>
<wa-dropdown-item>
Options
<wa-dropdown-item slot="submenu" type="checkbox" value="compress">Compress files</wa-dropdown-item>
<wa-dropdown-item slot="submenu" type="checkbox" checked value="metadata">Include metadata</wa-dropdown-item>
<wa-dropdown-item slot="submenu" type="checkbox" value="password">Password protect</wa-dropdown-item>
</wa-dropdown-item>
</wa-dropdown>
</div>
<script>
const container = document.querySelector('.dropdown-submenus');
const dropdown = container.querySelector('wa-dropdown');
dropdown.addEventListener('wa-select', event => {
console.log(event.detail.item.value);
});
</script>
```
:::info
Dropdown items that have a submenu will not dispatch the `wa-select` event. However, items inside the submenu will, unless they also have a submenu.
:::
:::warning
As a UX best practice, avoid using more than one level of submenu when possible.
:::
### Disabling Items
Add the `disabled` attribute to any [dropdown item](/docs/components/dropdown-item) to disable it.
```html {.example}
<wa-dropdown>
<wa-button slot="trigger" with-caret>Payment method</wa-button>
<wa-dropdown-item value="cash">Cash</wa-dropdown-item>
<wa-dropdown-item value="check" disabled>Personal check</wa-dropdown-item>
<wa-dropdown-item value="credit">Credit card</wa-dropdown-item>
<wa-dropdown-item value="gift-card">Gift card</wa-dropdown-item>
</wa-dropdown>
```

View File

@@ -1,76 +0,0 @@
---
title: Icon Button
description: Icons buttons are simple, icon-only buttons that can be used for actions and in toolbars.
tags: [actions, apps]
icon: icon-button
---
For a full list of icons that come bundled with Web Awesome, refer to the [icon component](/docs/components/icon).
```html {.example}
<wa-icon-button name="gear" label="Settings"></wa-icon-button>
```
## Examples
### Sizes
Icon buttons inherit their parent element's `font-size`.
```html {.example}
<wa-icon-button name="pen-to-square" variant="solid" label="Edit" style="font-size: 1.5rem;"></wa-icon-button>
<wa-icon-button name="pen-to-square" variant="solid" label="Edit" style="font-size: 2rem;"></wa-icon-button>
<wa-icon-button name="pen-to-square" variant="solid" label="Edit" style="font-size: 2.5rem;"></wa-icon-button>
```
### Colors
Icon buttons are designed to have a uniform appearance, so their color is not inherited. However, you can still customize them by styling the `base` part.
```html {.example}
<div class="icon-button-color">
<wa-icon-button name="bold" variant="solid" label="Bold"></wa-icon-button>
<wa-icon-button name="italic" variant="solid" label="Italic"></wa-icon-button>
<wa-icon-button name="underline" variant="solid" label="Underline"></wa-icon-button>
</div>
<style>
.icon-button-color wa-icon-button::part(base) {
color: #b00091;
}
.icon-button-color wa-icon-button::part(base):hover,
.icon-button-color wa-icon-button::part(base):focus {
color: #c913aa;
}
.icon-button-color wa-icon-button::part(base):active {
color: #960077;
}
</style>
```
### Link Buttons
Use the `href` attribute to convert the button to a link.
```html {.example}
<wa-icon-button name="gear" variant="solid" label="Settings" href="https://example.com" target="_blank"></wa-icon-button>
```
### Icon Button with Tooltip
Add a tooltip that references the `id` of the icon button to provide contextual information.
```html {.example}
<wa-icon-button id="icon-button" name="gear" variant="solid" label="Settings"></wa-icon-button>
<wa-tooltip for="icon-button">Settings</wa-tooltip>
```
### Disabled
Use the `disabled` attribute to disable the icon button.
```html {.example}
<wa-icon-button name="gear" variant="solid" label="Settings" disabled></wa-icon-button>
```

View File

@@ -109,24 +109,24 @@ The `type` attribute controls the type of input the browser renders.
<wa-input type="date" placeholder="Date"></wa-input>
```
### Prefix & Suffix Icons
### Start & End Decorations
Use the `prefix` and `suffix` slots to add icons.
Use the `start` and `end` slots to add presentational elements like `<wa-icon>` within the input.
```html {.example}
<wa-input placeholder="Small" size="small">
<wa-icon name="house" variant="solid" slot="prefix"></wa-icon>
<wa-icon name="comment" variant="solid" slot="suffix"></wa-icon>
<wa-icon name="house" slot="start"></wa-icon>
<wa-icon name="comment" slot="end"></wa-icon>
</wa-input>
<br />
<wa-input placeholder="Medium" size="medium">
<wa-icon name="house" variant="solid" slot="prefix"></wa-icon>
<wa-icon name="comment" variant="solid" slot="suffix"></wa-icon>
<wa-icon name="house" slot="start"></wa-icon>
<wa-icon name="comment" slot="end"></wa-icon>
</wa-input>
<br />
<wa-input placeholder="Large" size="large">
<wa-icon name="house" variant="solid" slot="prefix"></wa-icon>
<wa-icon name="comment" variant="solid" slot="suffix"></wa-icon>
<wa-icon name="house" slot="start"></wa-icon>
<wa-icon name="comment" slot="end"></wa-icon>
</wa-input>
```

View File

@@ -1,125 +0,0 @@
---
title: Menu Item
description: Menu items provide options for the user to pick from in a menu.
tags: component
parent: menu
icon: menu
---
```html {.example}
<wa-menu style="max-width: 200px;">
<wa-menu-item>Option 1</wa-menu-item>
<wa-menu-item>Option 2</wa-menu-item>
<wa-menu-item>Option 3</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item type="checkbox" checked>Checkbox</wa-menu-item>
<wa-menu-item disabled>Disabled</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item>
Prefix Icon
<wa-icon slot="prefix" name="gift" variant="solid"></wa-icon>
</wa-menu-item>
<wa-menu-item>
Suffix Icon
<wa-icon slot="suffix" name="heart" variant="solid"></wa-icon>
</wa-menu-item>
</wa-menu>
```
## Examples
### Prefix & Suffix
Add content to the start and end of menu items using the `prefix` and `suffix` slots.
```html {.example}
<wa-menu style="max-width: 200px;">
<wa-menu-item>
<wa-icon slot="prefix" name="house" variant="solid"></wa-icon>
Home
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="envelope" variant="solid"></wa-icon>
Messages
<wa-badge slot="suffix" variant="brand" pill>12</wa-badge>
</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item>
<wa-icon slot="prefix" name="gear" variant="solid"></wa-icon>
Settings
</wa-menu-item>
</wa-menu>
```
### Disabled
Add the `disabled` attribute to disable the menu item so it cannot be selected.
```html {.example}
<wa-menu style="max-width: 200px;">
<wa-menu-item>Option 1</wa-menu-item>
<wa-menu-item disabled>Option 2</wa-menu-item>
<wa-menu-item>Option 3</wa-menu-item>
</wa-menu>
```
### Loading
Use the `loading` attribute to indicate that a menu item is busy. Like a disabled menu item, clicks will be suppressed until the loading state is removed.
```html {.example}
<wa-menu style="max-width: 200px;">
<wa-menu-item>Option 1</wa-menu-item>
<wa-menu-item loading>Option 2</wa-menu-item>
<wa-menu-item>Option 3</wa-menu-item>
</wa-menu>
```
### Checkbox Menu Items
Set the `type` attribute to `checkbox` to create a menu item that will toggle on and off when selected. You can use the `checked` attribute to set the initial state.
Checkbox menu items are visually indistinguishable from regular menu items. Their ability to be toggled is primarily inferred from context, much like you'd find in the menu of a native app.
```html {.example}
<wa-menu style="max-width: 200px;">
<wa-menu-item type="checkbox">Autosave</wa-menu-item>
<wa-menu-item type="checkbox" checked>Check Spelling</wa-menu-item>
<wa-menu-item type="checkbox">Word Wrap</wa-menu-item>
</wa-menu>
```
### Value & Selection
The `value` attribute can be used to assign a hidden value, such as a unique identifier, to a menu item. When an item is selected, the `wa-select` event will be emitted and a reference to the item will be available at `event.detail.item`. You can use this reference to access the selected item's value, its checked state, and more.
```html {.example}
<wa-menu class="menu-value" style="max-width: 200px;">
<wa-menu-item value="opt-1">Option 1</wa-menu-item>
<wa-menu-item value="opt-2">Option 2</wa-menu-item>
<wa-menu-item value="opt-3">Option 3</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item type="checkbox" value="opt-4">Checkbox 4</wa-menu-item>
<wa-menu-item type="checkbox" value="opt-5">Checkbox 5</wa-menu-item>
<wa-menu-item type="checkbox" value="opt-6">Checkbox 6</wa-menu-item>
</wa-menu>
<script>
const menu = document.querySelector('.menu-value');
menu.addEventListener('wa-select', event => {
const item = event.detail.item;
// Log value
if (item.type === 'checkbox') {
console.log(`Selected value: ${item.value} (${item.checked ? 'checked' : 'unchecked'})`);
} else {
console.log(`Selected value: ${item.value}`);
}
});
</script>
```

View File

@@ -1,21 +0,0 @@
---
title: Menu Label
description: Menu labels are used to describe a group of menu items.
tags: component
parent: menu
icon: menu
---
```html {.example}
<wa-menu style="max-width: 200px;">
<wa-menu-label>Fruits</wa-menu-label>
<wa-menu-item value="apple">Apple</wa-menu-item>
<wa-menu-item value="banana">Banana</wa-menu-item>
<wa-menu-item value="orange">Orange</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-label>Vegetables</wa-menu-label>
<wa-menu-item value="broccoli">Broccoli</wa-menu-item>
<wa-menu-item value="carrot">Carrot</wa-menu-item>
<wa-menu-item value="zucchini">Zucchini</wa-menu-item>
</wa-menu>
```

View File

@@ -1,77 +0,0 @@
---
title: Menu
description: Menus provide a list of options for the user to choose from.
tags: [actions, apps]
icon: menu
---
You can use [menu items](/docs/components/menu-item), [menu labels](/docs/components/menu-label), and [dividers](/docs/components/divider) to compose a menu. Menus support keyboard interactions, including type-to-select an option.
```html {.example}
<wa-menu style="max-width: 200px;">
<wa-menu-item value="undo">Undo</wa-menu-item>
<wa-menu-item value="redo">Redo</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item value="cut">Cut</wa-menu-item>
<wa-menu-item value="copy">Copy</wa-menu-item>
<wa-menu-item value="paste">Paste</wa-menu-item>
<wa-menu-item value="delete">Delete</wa-menu-item>
</wa-menu>
```
:::info
Menus are intended for system menus (dropdown menus, select menus, context menus, etc.). They should not be mistaken for navigation menus which serve a different purpose and have a different semantic meaning. If you're building navigation, use `<nav>` and `<a>` elements instead.
:::
## Examples
### In Dropdowns
Menus work really well when used inside [dropdowns](/docs/components/dropdown).
```html {.example}
<wa-dropdown>
<wa-button slot="trigger" caret>Edit</wa-button>
<wa-menu>
<wa-menu-item value="cut">Cut</wa-menu-item>
<wa-menu-item value="copy">Copy</wa-menu-item>
<wa-menu-item value="paste">Paste</wa-menu-item>
</wa-menu>
</wa-dropdown>
```
### Submenus
To create a submenu, nest an `<wa-menu slot="submenu">` in any [menu item](/docs/components/menu-item).
```html {.example}
<wa-menu style="max-width: 200px;">
<wa-menu-item value="undo">Undo</wa-menu-item>
<wa-menu-item value="redo">Redo</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item value="cut">Cut</wa-menu-item>
<wa-menu-item value="copy">Copy</wa-menu-item>
<wa-menu-item value="paste">Paste</wa-menu-item>
<wa-divider></wa-divider>
<wa-menu-item>
Find
<wa-menu slot="submenu">
<wa-menu-item value="find">Find…</wa-menu-item>
<wa-menu-item value="find-previous">Find Next</wa-menu-item>
<wa-menu-item value="find-next">Find Previous</wa-menu-item>
</wa-menu>
</wa-menu-item>
<wa-menu-item>
Transformations
<wa-menu slot="submenu">
<wa-menu-item value="uppercase">Make uppercase</wa-menu-item>
<wa-menu-item value="lowercase">Make lowercase</wa-menu-item>
<wa-menu-item value="capitalize">Capitalize</wa-menu-item>
</wa-menu>
</wa-menu-item>
</wa-menu>
```
:::warning
As a UX best practice, avoid using more than one level of submenus when possible.
:::

View File

@@ -6,50 +6,4 @@ parent: select
icon: option
---
```html {.example}
<wa-select label="Select one">
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
```
## Examples
### Disabled
Use the `disabled` attribute to disable an option and prevent it from being selected.
```html {.example}
<wa-select label="Select one">
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2" disabled>Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
```
### Prefix & Suffix
Add icons to the start and end of menu items using the `prefix` and `suffix` slots.
```html {.example}
<wa-select label="Select one">
<wa-option value="option-1">
<wa-icon slot="prefix" name="envelope" variant="solid"></wa-icon>
Email
<wa-icon slot="suffix" name="circle-check" variant="solid"></wa-icon>
</wa-option>
<wa-option value="option-2">
<wa-icon slot="prefix" name="phone" variant="solid"></wa-icon>
Phone
<wa-icon slot="suffix" name="circle-check" variant="solid"></wa-icon>
</wa-option>
<wa-option value="option-3">
<wa-icon slot="prefix" name="comment" variant="solid"></wa-icon>
Chat
<wa-icon slot="suffix" name="circle-check" variant="solid"></wa-icon>
</wa-option>
</wa-select>
```
This component must be used as a child of `<wa-select>`. Please see the [Select docs](/docs/components/select) to see examples of this component in action.

View File

@@ -0,0 +1,143 @@
---
title: Popover
layout: component
---
Popovers display interactive content when their anchor element is clicked. Unlike [tooltips](/docs/components/tooltip), popovers can contain links, buttons, and form controls. They appear without an overlay and will close when you click outside or press [[Escape]]. Only one popover can be open at a time.
```html {.example}
<wa-popover for="popover__overview">
<div style="display: flex; flex-direction: column; gap: 1rem;">
<p>This popover contains interactive content that users can engage with directly.</p>
<wa-button variant="primary" size="small">Take Action</wa-button>
</div>
</wa-popover>
<wa-button id="popover__overview">Show popover</wa-button>
```
## Examples
### Assigning an Anchor
Use `<wa-button>` or `<button>` elements as popover anchors. Connect the popover to its anchor by setting the `for` attribute to match the anchor's `id`.
```html {.example}
<wa-button id="popover__anchor-button">Show Popover</wa-button>
<wa-popover for="popover__anchor-button">
I'm anchored to a Web Awesome button.
</wa-popover>
<br><br>
<button id="popover__anchor-native-button">Show Popover</button>
<wa-popover for="popover__anchor-native-button">
I'm anchored to a native button.
</wa-popover>
```
:::warning
Make sure the anchor element exists in the DOM before the popover connects. If it doesn't exist, the popover won't attach and you'll see a console warning.
:::
### Opening and Closing
Popovers show when you click their anchor element. You can also control them programmatically by setting the `open` property to `true` or `false`.
Use `data-popover="close"` on any button inside a popover to close it automatically.
```html {.example}
<wa-popover for="popover__opening">
<p>The button below has <code>data-popover="close"</code> so clicking it will close the popover.</p>
<wa-button data-popover="close" variant="primary">Dismiss</wa-button>
</wa-popover>
<wa-button id="popover__opening">Show popover</wa-button>
```
### Placement
Use the `placement` attribute to set where the popover appears relative to its anchor. The popover will automatically reposition if there isn't enough space in the preferred location. The default placement is `top`.
```html {.example}
<div style="display: flex; gap: 1rem; align-items: center;">
<wa-button id="popover__top">Top</wa-button>
<wa-popover for="popover__top" placement="top">I'm on the top</wa-popover>
<wa-button id="popover__bottom">Bottom</wa-button>
<wa-popover for="popover__bottom" placement="bottom">I'm on the bottom</wa-popover>
<wa-button id="popover__left">Left</wa-button>
<wa-popover for="popover__left" placement="left">I'm on the left</wa-popover>
<wa-button id="popover__right">Right</wa-button>
<wa-popover for="popover__right" placement="right">I'm on the right</wa-popover>
</div>
```
### Distance
Use the `distance` attribute to control how far the popover appears from its anchor.
```html {.example}
<div style="display: flex; gap: 1rem; align-items: center;">
<wa-button id="popover__distance-near">Near</wa-button>
<wa-popover for="popover__distance-near" distance="0">I'm very close</wa-popover>
<wa-button id="popover__distance-far">Far</wa-button>
<wa-popover for="popover__distance-far" distance="30">I'm farther away</wa-popover>
</div>
```
### 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.
```html {.example}
<div style="display: flex; gap: 1rem; align-items: center;">
<wa-button id="popover__big-arrow">Big arrow</wa-button>
<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>
</div>
```
### Setting a Maximum Width
Use the `--max-width` custom property to control the maximum width of the popover.
```html {.example}
<wa-button id="popover__max-width">Toggle me</wa-button>
<wa-popover for="popover__max-width" style="--max-width: 160px;">
Popovers will usually grow to be much wider, but this one has a custom max width that forces text to wrap.
</wa-popover>
```
### Setting Focus
Use the [`autofocus`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) global attribute to move focus to a specific form control when the popover opens.
```html {.example}
<wa-popover for="popover__autofocus">
<div style="display: flex; flex-direction: column; gap: 1rem;">
<wa-textarea
autofocus
placeholder="What's on your mind?"
size="small"
resize="none"
rows="3"
></wa-textarea>
<wa-button variant="primary" size="small" data-popover="close">
Submit
</wa-button>
</div>
</wa-popover>
<wa-button id="popover__autofocus">
<wa-icon name="comment" slot="start"></wa-icon>
Feedback
</wa-button>
```

View File

@@ -7,9 +7,7 @@ icon: progress-bar
---
```html {.example}
<wa-progress-bar value="40">
<wa-icon slot="prefix" name="tasks"></wa-icon>
</wa-progress-bar>
<wa-progress-bar value="40"></wa-progress-bar>
```
## Examples
@@ -38,15 +36,19 @@ Use the default slot to show a value.
<wa-progress-bar value="50" id="progress-bar-demo">50%</wa-progress-bar>
<div>
<wa-icon-button pill name="minus" label="Decrease"></wa-icon-button>
<wa-icon-button pill name="plus" label="Increase"></wa-icon-button>
<wa-button pill appearance="filled">
<wa-icon name="minus" label="Decrease"></wa-icon>
</wa-button>
<wa-button pill appearance="filled">
<wa-icon name="plus" label="Increase"></wa-icon>
</wa-button>
</div>
</div>
<script>
const progressBar = document.querySelector('#progress-bar-demo');
const subtractButton = document.querySelector('wa-icon-button[name="minus"]');
const addButton = document.querySelector('wa-icon-button[name="plus"]');
const subtractButton = document.querySelector('wa-button:has(wa-icon[name="minus"])');
const addButton = document.querySelector('wa-button:has(wa-icon[name="plus"])');
addButton.addEventListener('click', () => {
const value = Math.min(100, progressBar.value + 10);

View File

@@ -6,9 +6,7 @@ icon: progress-ring
---
```html {.example}
<wa-progress-ring value="25">
<wa-icon slot="prefix" name="circle-notch"></wa-icon>
</wa-progress-ring>
<wa-progress-ring value="25"></wa-progress-ring>
```
## Examples
@@ -18,9 +16,7 @@ icon: progress-ring
Use the `--size` custom property to set the diameter of the progress ring.
```html {.example}
<wa-progress-ring value="50" style="--size: 200px;">
<wa-icon slot="prefix" name="expand"></wa-icon>
</wa-progress-ring>
<wa-progress-ring value="50" style="--size: 200px;"></wa-progress-ring>
```
### Track and Indicator Width
@@ -28,9 +24,7 @@ Use the `--size` custom property to set the diameter of the progress ring.
Use the `--track-width` and `--indicator-width` custom properties to set the width of the progress ring's track and indicator.
```html {.example}
<wa-progress-ring value="50" style="--track-width: 6px; --indicator-width: 12px;">
<wa-icon slot="prefix" name="arrows-alt"></wa-icon>
</wa-progress-ring>
<wa-progress-ring value="50" style="--track-width: 6px; --indicator-width: 12px;"></wa-progress-ring>
```
### Colors
@@ -45,7 +39,6 @@ To change the color, use the `--track-color` and `--indicator-color` custom prop
--indicator-color: deeppink;
"
>
<wa-icon slot="prefix" name="palette"></wa-icon>
</wa-progress-ring>
```

View File

@@ -13,7 +13,7 @@ QR codes are useful for providing small pieces of information to users who can q
<br />
<wa-input maxlength="255" with-clear label="Value">
<wa-icon slot="prefix" name="link"></wa-icon>
<wa-icon slot="start" name="link"></wa-icon>
</wa-input>
</div>
@@ -46,9 +46,7 @@ QR codes are useful for providing small pieces of information to users who can q
Use the `fill` and `background` attributes to modify the QR code's colors. You should always ensure good contrast for optimal compatibility with QR code scanners.
```html {.example}
<wa-qr-code value="https://shoelace.style/" fill="deeppink" background="white">
<wa-icon slot="prefix" name="palette"></wa-icon>
</wa-qr-code>
<wa-qr-code value="https://shoelace.style/" fill="deeppink" background="white"></wa-qr-code>
```
### Size
@@ -56,9 +54,7 @@ Use the `fill` and `background` attributes to modify the QR code's colors. You s
Use the `size` attribute to change the size of the QR code.
```html {.example}
<wa-qr-code value="https://shoelace.style/" size="64">
<wa-icon slot="prefix" name="expand"></wa-icon>
</wa-qr-code>
<wa-qr-code value="https://shoelace.style/" size="64"></wa-qr-code>
```
### Radius
@@ -66,9 +62,7 @@ Use the `size` attribute to change the size of the QR code.
Create a rounded effect with the `radius` attribute.
```html {.example}
<wa-qr-code value="https://shoelace.style/" radius="0.5">
<wa-icon slot="prefix" name="circle"></wa-icon>
</wa-qr-code>
<wa-qr-code value="https://shoelace.style/" radius="0.5"></wa-qr-code>
```
### Error Correction
@@ -77,18 +71,10 @@ QR codes can be rendered with various levels of [error correction](https://www.q
```html {.example}
<div class="qr-error-correction">
<wa-qr-code value="https://shoelace.style/" error-correction="L">
<wa-icon slot="prefix" name="shield"></wa-icon>
</wa-qr-code>
<wa-qr-code value="https://shoelace.style/" error-correction="M">
<wa-icon slot="prefix" name="shield"></wa-icon>
</wa-qr-code>
<wa-qr-code value="https://shoelace.style/" error-correction="Q">
<wa-icon slot="prefix" name="shield"></wa-icon>
</wa-qr-code>
<wa-qr-code value="https://shoelace.style/" error-correction="H">
<wa-icon slot="prefix" name="shield"></wa-icon>
</wa-qr-code>
<wa-qr-code value="https://shoelace.style/" error-correction="L"></wa-qr-code>
<wa-qr-code value="https://shoelace.style/" error-correction="M"></wa-qr-code>
<wa-qr-code value="https://shoelace.style/" error-correction="Q"></wa-qr-code>
<wa-qr-code value="https://shoelace.style/" error-correction="H"></wa-qr-code>
</div>
<style>

View File

@@ -44,7 +44,7 @@ Set the `appearance` attribute to `button` on all radios to render a radio butto
<wa-radio appearance="button" value="3">Option 3</wa-radio>
</wa-radio-group>
<br>
<br />
<wa-radio-group
label="Vertical options"
@@ -60,12 +60,22 @@ Set the `appearance` attribute to `button` on all radios to render a radio butto
</wa-radio-group>
```
### Disabling Options
### Disabling
Radios and radio buttons can be disabled by adding the `disabled` attribute to the respective options inside the radio group.
To disable the entire radio group, add the `disabled` attribute to the radio group.
```html {.example}
<wa-radio-group label="Select an option" name="a" value="1">
<wa-radio-group label="Select an option" disabled>
<wa-radio value="1">Option 1</wa-radio>
<wa-radio value="2" disabled>Option 2</wa-radio>
<wa-radio value="3">Option 3</wa-radio>
</wa-radio-group>
```
To disable individual options, add the `disabled` attribute to the respective options.
```html {.example}
<wa-radio-group label="Select an option">
<wa-radio value="1">Option 1</wa-radio>
<wa-radio value="2" disabled>Option 2</wa-radio>
<wa-radio value="3">Option 3</wa-radio>

View File

@@ -7,82 +7,4 @@ native: radio
icon: radio-group
---
Radios are designed to be used with [radio groups](/docs/components/radio-group).
```html {.example}
<wa-radio-group label="Select an option" name="a" value="1">
<wa-radio value="1">Option 1</wa-radio>
<wa-radio value="2">Option 2</wa-radio>
<wa-radio value="3">Option 3</wa-radio>
</wa-radio-group>
```
:::info
This component works with standard `<form>` elements. Please refer to the section on [form controls](/docs/form-controls) to learn more about form submission and client-side validation.
:::
## Examples
### Initial Value
To set the initial value and checked state, use the `value` attribute on the containing radio group.
```html {.example}
<wa-radio-group label="Select an option" name="a" value="3">
<wa-radio value="1">Option 1</wa-radio>
<wa-radio value="2">Option 2</wa-radio>
<wa-radio value="3">Option 3</wa-radio>
</wa-radio-group>
```
### Disabled
Use the `disabled` attribute to disable a radio.
```html {.example}
<wa-radio-group label="Select an option" name="a" value="1">
<wa-radio value="1">Option 1</wa-radio>
<wa-radio value="2" disabled>Option 2</wa-radio>
<wa-radio value="3">Option 3</wa-radio>
</wa-radio-group>
```
### Sizes
Add the `size` attribute to the [Radio Group](/docs/components/radio-group) to change the radios' size.
```html {.example}
<wa-radio-group size="small" value="1">
<wa-radio value="1">Small 1</wa-radio>
<wa-radio value="2">Small 2</wa-radio>
<wa-radio value="3">Small 3</wa-radio>
</wa-radio-group>
<br />
<wa-radio-group size="medium" value="1">
<wa-radio value="1">Medium 1</wa-radio>
<wa-radio value="2">Medium 2</wa-radio>
<wa-radio value="3">Medium 3</wa-radio>
</wa-radio-group>
<br />
<wa-radio-group size="large" value="1">
<wa-radio value="1">Large 1</wa-radio>
<wa-radio value="2">Large 2</wa-radio>
<wa-radio value="3">Large 3</wa-radio>
</wa-radio-group>
```
### Hint
Add descriptive hint to a switch with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
```html {.example}
<wa-radio-group label="Select an option" name="a" value="1">
<wa-radio value="1" hint="What should the user know about radio 1?">Option 1</wa-radio>
<wa-radio value="2" hint="What should the user know about radio 2?">Option 2</wa-radio>
<wa-radio value="3" hint="What should the user know about radio 3?">Option 3</wa-radio>
</wa-radio-group>
```
This component must be used as a child of `<wa-radio-group>`. Please see the [Radio Group docs](/docs/components/radio-group) to see examples of this component in action.

View File

@@ -131,7 +131,7 @@ You can provide custom icons by passing a function to the `getSymbol` property.
### Value-based Icons
You can also use the `getSymbol` property to render different icons based on value.
You can also use the `getSymbol` property to render different icons based on value and/or whether the icon is currently selected.
```html {.example}
<wa-rating label="Rating" class="rating-emojis"></wa-rating>
@@ -142,7 +142,7 @@ You can also use the `getSymbol` property to render different icons based on val
await customElements.whenDefined("wa-rating")
await rating.updateComplete
rating.getSymbol = value => {
rating.getSymbol = (value, isSelected) => {
const icons = ['face-angry', 'face-frown', 'face-meh', 'face-smile', 'face-laugh'];
return `<wa-icon name="${icons[value - 1]}"></wa-icon>`;
};

View File

@@ -109,13 +109,13 @@ Use the `disabled` attribute to disable a select.
### Multiple
To allow multiple options to be selected, use the `multiple` attribute. It's a good practice to use `with-clear` when this option is enabled. To set multiple values at once, set `value` to a space-delimited list of values.
To allow multiple options to be selected, use the `multiple` attribute. It's a good practice to use `with-clear` when this option is enabled. You can select multiple options by adding the `selected` attribute to individual options.
```html {.example}
<wa-select label="Select a Few" value="option-1 option-2 option-3" multiple with-clear>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
<wa-select label="Select a Few" multiple with-clear>
<wa-option value="option-1" selected>Option 1</wa-option>
<wa-option value="option-2" selected>Option 2</wa-option>
<wa-option value="option-3" selected>Option 3</wa-option>
<wa-option value="option-4">Option 4</wa-option>
<wa-option value="option-5">Option 5</wa-option>
<wa-option value="option-6">Option 6</wa-option>
@@ -123,33 +123,37 @@ To allow multiple options to be selected, use the `multiple` attribute. It's a g
```
:::info
Note that multi-select options may wrap, causing the control to expand vertically. You can use the `max-options-visible` attribute to control the maximum number of selected options to show at once.
Selecting multiple options may result in wrapping, causing the control to expand vertically. You can use the `max-options-visible` attribute to control the maximum number of selected options to show at once.
:::
### Setting Initial Values
Use the `value` attribute to set the initial selection.
Use the `selected` attribute on individual options to set the initial selection, similar to native HTML.
```html {.example}
<wa-select value="option-1">
<wa-option value="option-1">Option 1</wa-option>
<wa-select>
<wa-option value="option-1" selected>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>
</wa-select>
```
When using `multiple`, the `value` _attribute_ uses space-delimited values to select more than one option. Because of this, `<wa-option>` values cannot contain spaces. If you're accessing the `value` _property_ through Javascript, it will be an array.
For multiple selections, apply it to all selected options.
```html {.example}
<wa-select value="option-1 option-2" multiple with-clear>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-select multiple with-clear>
<wa-option value="option-1" selected>Option 1</wa-option>
<wa-option value="option-2" selected>Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
<wa-option value="option-4">Option 4</wa-option>
</wa-select>
```
:::info
Framework users can bind directly to the `value` property for reactive data binding and form state management.
:::
### Grouping Options
Use `<wa-divider>` to group listbox items visually. You can also use `<small>` to provide labels, but they won't be announced by most assistive devices.
@@ -208,54 +212,30 @@ The preferred placement of the select's listbox can be set with the `placement`
</wa-select>
```
### Prefix Icons
### Start & End Decorations
Use the `prefix` slot to prepend an icon to the control.
Use the `start` and `end` slots to add presentational elements like `<wa-icon>` within the combobox.
```html {.example}
<wa-select placeholder="Small" size="small" with-clear>
<wa-icon slot="prefix" name="house" variant="solid"></wa-icon>
<wa-icon slot="start" name="house" variant="solid"></wa-icon>
<wa-icon slot="end" name="flag-checkered"></wa-icon>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
<br />
<wa-select placeholder="Medium" size="medium" with-clear>
<wa-icon slot="prefix" name="house" variant="solid"></wa-icon>
<wa-icon slot="start" name="house" variant="solid"></wa-icon>
<wa-icon slot="end" name="flag-checkered"></wa-icon>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
<br />
<wa-select placeholder="Large" size="large" with-clear>
<wa-icon slot="prefix" name="house" variant="solid"></wa-icon>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
```
### Suffix Icons
Use the `suffix` slot to append an icon to the control.
```html {.example}
<wa-select placeholder="Small" size="small" with-clear>
<wa-icon name="house" slot="suffix"></wa-icon>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
<br />
<wa-select placeholder="Medium" size="medium" with-clear>
<wa-icon name="house" slot="suffix"></wa-icon>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
<br />
<wa-select placeholder="Large" size="large" with-clear>
<wa-icon name="house" slot="suffix"></wa-icon>
<wa-icon slot="start" name="house" variant="solid"></wa-icon>
<wa-icon slot="end" name="flag-checkered"></wa-icon>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
@@ -264,40 +244,34 @@ Use the `suffix` slot to append an icon to the control.
### Custom Tags
When multiple options can be selected, you can provide custom tags by passing a function to the `getTag` property. Your function can return a string of HTML, a <a href="https://lit.dev/docs/templates/overview/">Lit Template</a>, or an [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement). The `getTag()` function will be called for each option. The first argument is an `<wa-option>` element and the second argument is the tag's index (its position in the tag list).
When multiple options can be selected, you can provide custom tags by passing a function to the `getTag` property. Your function can return a string of HTML, a [Lit Template](https://lit.dev/docs/templates/overview/), or an [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement). The `getTag()` function will be called for each option. The first argument is an `<wa-option>` element and the second argument is the tag's index (its position in the tag list).
Remember that custom tags are rendered in a shadow root. To style them, you can use the `style` attribute in your template or you can add your own [parts](/docs/customizing/#css-parts) and target them with the [`::part()`](https://developer.mozilla.org/en-US/docs/Web/CSS/::part) selector.
```html {.example}
<wa-select
placeholder="Select one"
value="email phone"
multiple
with-clear
class="custom-tag"
>
<wa-option value="email">
<wa-icon slot="prefix" name="envelope" variant="solid"></wa-icon>
<wa-select placeholder="Select one" multiple with-clear class="custom-tag">
<wa-option value="email" selected>
<wa-icon slot="start" name="envelope" variant="solid"></wa-icon>
Email
</wa-option>
<wa-option value="phone">
<wa-icon slot="prefix" name="phone" variant="solid"></wa-icon>
<wa-option value="phone" selected>
<wa-icon slot="start" name="phone" variant="solid"></wa-icon>
Phone
</wa-option>
<wa-option value="chat">
<wa-icon slot="prefix" name="comment" variant="solid"></wa-icon>
<wa-icon slot="start" name="comment" variant="solid"></wa-icon>
Chat
</wa-option>
</wa-select>
<script type="module">
await customElements.whenDefined("wa-select")
await customElements.whenDefined('wa-select');
const select = document.querySelector('.custom-tag');
await select.updateComplete
await select.updateComplete;
select.getTag = (option, index) => {
// Use the same icon used in wa-option
const name = option.querySelector('wa-icon[slot="prefix"]').name;
const name = option.querySelector('wa-icon[slot="start"]').name;
// You can return a string, a Lit Template, or an HTMLElement here
return `
@@ -316,17 +290,15 @@ Be sure you trust the content you are outputting! Passing unsanitized user input
### Lazy loading options
Lazy loading options is very hard to get right. `<wa-select>` largely follows how a native `<select>` works.
Lazy loading options works similarly to native `<select>` elements. The select component handles various scenarios intelligently:
Here are the following conditions:
#### Basic lazy loading scenarios:
- If a `<wa-select>` is created without any options, but is given a `value` attribute, its `value` will be `""`, and then when options are added, if any of the options have a value equal to the `<wa-select>` value, the value of the `<wa-select>` will equal that of the option.
- **Empty select with value**: If a `<wa-select>` is created without any options but given a `value` attribute, its value will be `""` initially. When options are added later, if any option has a value matching the select's value attribute, the select's value will update to match.
EX: `<wa-select value="foo">` will have a value of `""` until `<wa-option value="foo">Foo</wa-option>` connects, at which point its value will become `"foo"` when submitting.
- **Multiple select with partial options**: If a `<wa-select multiple>` has an initial value with multiple options, but only some options are present in the DOM, it will respect only the available options. When additional selected options are loaded later (and the user hasn't changed the selection), those options will be automatically added to the selection.
- If a `<wa-select multiple>` with an initial value has multiple values, but only some of the options are present, it will only respect the options that are present, and if a selected option is loaded in later, *AND* the value of the select has not changed via user interaction or direct property assignment, it will add the selected option to the form value and to the `.value` of the select.
This can be hard to conceptualize, so heres a fairly large example showing how lazy loaded options work with `<wa-select>` and `<wa-select multiple>` when given initial value attributes. Feel free to play around with it in a codepen.
Here's a comprehensive example showing different lazy loading scenarios:
```html {.example}
<form id="lazy-options-example">
@@ -335,93 +307,100 @@ This can be hard to conceptualize, so heres a fairly large example showing how l
<wa-option value="bar">Bar</wa-option>
<wa-option value="baz">Baz</wa-option>
</wa-select>
<br>
<br />
<wa-button type="button">Add "foo" option</wa-button>
</div>
<br>
<br />
<div>
<wa-select name="select-2" value="foo" label="Single select (with no existing options)">
</wa-select>
<br>
<wa-select name="select-2" value="foo" label="Single select (with no existing options)"> </wa-select>
<br />
<wa-button type="button">Add "foo" option</wa-button>
</div>
<br>
<br />
<div>
<wa-select name="select-3" value="foo bar baz" multiple label="Multiple Select (with existing options)">
<wa-option value="bar">Bar</wa-option>
<wa-option value="baz">Baz</wa-option>
<wa-select name="select-3" multiple label="Multiple Select (with existing selected options)">
<wa-option value="bar" selected>Bar</wa-option>
<wa-option value="baz" selected>Baz</wa-option>
</wa-select>
<br>
<wa-button type="button">Add "foo" option</wa-button>
<br />
<wa-button type="button">Add "foo" option (selected)</wa-button>
</div>
<br>
<br />
<div>
<wa-select name="select-4" value="foo" multiple label="Multiple Select (with no existing options)">
</wa-select>
<br>
<wa-select name="select-4" value="foo" multiple label="Multiple Select (with no existing options)"> </wa-select>
<br />
<wa-button type="button">Add "foo" option</wa-button>
</div>
<br><br>
<br /><br />
<div style="display: flex; gap: 16px;">
<wa-button type="reset">Reset</wa-button>
<wa-button type="submit" variant="brand">Show FormData</wa-button>
</div>
<br>
<br />
<pre hidden><code id="lazy-options-example-form-data"></code></pre>
<br>
<br />
</form>
<script type="module">
function addFooOption(e) {
const addFooButton = e.target.closest("wa-button[type='button']")
const addFooButton = e.target.closest("wa-button[type='button']");
if (!addFooButton) {
return
return;
}
const select = addFooButton.parentElement.querySelector("wa-select")
const select = addFooButton.parentElement.querySelector('wa-select');
if (select.querySelector("wa-option[value='foo']")) {
// Foo already exists. no-op.
return
return;
}
const option = document.createElement("wa-option")
option.setAttribute("value", "foo")
option.innerText = "Foo"
select.append(option)
const option = document.createElement('wa-option');
option.setAttribute('value', 'foo');
option.innerText = 'Foo';
// For the multiple select with existing selected options, make the new option selected
if (select.getAttribute('name') === 'select-3') {
option.selected = true;
}
select.append(option);
}
function handleLazySubmit (event) {
event.preventDefault()
function handleLazySubmit(event) {
event.preventDefault();
const formData = new FormData(event.target)
const codeElement = document.querySelector("#lazy-options-example-form-data")
const formData = new FormData(event.target);
const codeElement = document.querySelector('#lazy-options-example-form-data');
const obj = {}
const obj = {};
for (const key of formData.keys()) {
const val = formData.getAll(key).length > 1 ? formData.getAll(key) : formData.get(key)
obj[key] = val
const val = formData.getAll(key).length > 1 ? formData.getAll(key) : formData.get(key);
obj[key] = val;
}
codeElement.textContent = JSON.stringify(obj, null, 2)
codeElement.textContent = JSON.stringify(obj, null, 2);
const preElement = codeElement.parentElement
preElement.removeAttribute("hidden")
const preElement = codeElement.parentElement;
preElement.removeAttribute('hidden');
}
const container = document.querySelector("#lazy-options-example")
container.addEventListener("click", addFooOption)
container.addEventListener("submit", handleLazySubmit)
const container = document.querySelector('#lazy-options-example');
container.addEventListener('click', addFooOption);
container.addEventListener('submit', handleLazySubmit);
</script>
```
:::info
The key principle is that the select component prioritizes user interactions and explicit selections over programmatic changes, ensuring a predictable user experience even with dynamically loaded content.
:::

View File

@@ -7,7 +7,20 @@ icon: slider
---
```html {.example}
<wa-slider></wa-slider>
<wa-slider
label="Number of cats"
hint="Limit six per household"
name="value"
value="3"
min="0"
max="6"
with-markers
with-tooltip
with-references
>
<span slot="reference">Less</span>
<span slot="reference">More</span>
</wa-slider>
```
:::info
@@ -18,7 +31,7 @@ This component works with standard `<form>` elements. Please refer to the sectio
### Labels
Use the `label` attribute to give the range an accessible label. For labels that contain HTML, use the `label` slot instead.
Use the `label` attribute to give the slider an accessible label. For labels that contain HTML, use the `label` slot instead.
```html {.example}
<wa-slider label="Volume" min="0" max="100"></wa-slider>
@@ -26,18 +39,233 @@ Use the `label` attribute to give the range an accessible label. For labels that
### Hint
Add descriptive hint to a range with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
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>
```
### Min, Max, and Step
### Showing tooltips
Use the `min` and `max` attributes to set the range's minimum and maximum values, respectively. The `step` attribute determines the value's interval when increasing and decreasing.
Use the `with-tooltip` attribute to display a tooltip with the current value when the slider is focused or being dragged.
```html {.example}
<wa-slider min="0" max="10" step="1"></wa-slider>
<wa-slider label="Quality" name="quality" min="0" max="100" value="50" with-tooltip></wa-slider>
```
### Setting min, max, and step
Use the `min` and `max` attributes to define the slider's range, and the `step` attribute to control the increment between values.
```html {.example}
<wa-slider label="Between zero and one" min="0" max="1" step="0.1" value="0.5" with-tooltip></wa-slider>
```
### Showing markers
Use the `with-markers` attribute to display visual indicators at each step increment. This works best with sliders that have a smaller range of values.
```html {.example}
<wa-slider label="Size" name="size" min="0" max="8" value="4" with-markers></wa-slider>
```
### Adding references
Use the `with-references` attribute along with 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 with-references>
<span slot="reference">Slow</span>
<span slot="reference">Medium</span>
<span slot="reference">Fast</span>
</wa-slider>
```
:::info
If you want to show a reference next to a specific marker, you can add `position: absolute` to it and set the `left`, `right`, `top`, or `bottom` property to a percentage that corresponds to the marker's position.
:::
### Formatting the value
Customize how values are displayed in tooltips and announced to screen readers using the `valueFormatter` property. Set it to a function that accepts a number and returns a formatted string. The [`Intl.NumberFormat API`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) is particularly useful for this.
```html {.example}
<!-- Percent -->
<wa-slider
id="slider__percent"
label="Percentage"
name="percentage"
value="0.5"
min="0"
max="1"
step=".01"
with-tooltip
></wa-slider
><br />
<script>
const slider = document.getElementById('slider__percent');
const formatter = new Intl.NumberFormat('en-US', { style: 'percent' });
customElements.whenDefined('wa-slider').then(() => {
slider.valueFormatter = value => formatter.format(value);
});
</script>
<!-- Duration -->
<wa-slider id="slider__duration" label="Duration" name="duration" value="12" min="0" max="24" with-tooltip></wa-slider
><br />
<script>
const slider = document.getElementById('slider__duration');
const formatter = new Intl.NumberFormat('en-US', { style: 'unit', unit: 'hour', unitDisplay: 'long' });
customElements.whenDefined('wa-slider').then(() => {
slider.valueFormatter = value => formatter.format(value);
});
</script>
<!-- Currency -->
<wa-slider id="slider__currency" label="Currency" name="currency" min="0" max="100" value="50" with-tooltip></wa-slider>
<script>
const slider = document.getElementById('slider__currency');
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol',
maximumFractionDigits: 0,
});
customElements.whenDefined('wa-slider').then(() => {
slider.valueFormatter = value => formatter.format(value);
});
</script>
```
### Range selection
Use the `range` attribute to enable dual-thumb selection for choosing a range of values. Set the initial thumb positions with the `min-value` and `max-value` attributes.
```html {.example}
<wa-slider
label="Price Range"
hint="Select minimum and maximum price"
name="price"
range
min="0"
max="100"
min-value="20"
max-value="80"
with-tooltip
with-references
id="slider__range"
>
<span slot="reference">$0</span>
<span slot="reference">$50</span>
<span slot="reference">$100</span>
</wa-slider>
<script>
const slider = document.getElementById('slider__range');
const formatter = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 });
customElements.whenDefined('wa-slider').then(() => {
slider.valueFormatter = value => formatter.format(value);
});
</script>
```
For range sliders, the `minValue` and `maxValue` properties represent the current positions of the thumbs. When the form is submitted, both values will be included as separate entries with the same name.
```ts
const slider = document.querySelector('wa-slider[range]');
// Get the current values
console.log(`Min value: ${slider.minValue}, Max value: ${slider.maxValue}`);
// Set the values programmatically
slider.minValue = 30;
slider.maxValue = 70;
```
### Vertical Sliders
Set the `orientation` attribute to `vertical` to create a vertical slider. Vertical sliders automatically center themselves and fill the available vertical space.
```html {.example}
<div style="display: flex; gap: 1rem;">
<wa-slider orientation="vertical" label="Volume" name="volume" value="65" style="width: 80px"></wa-slider>
<wa-slider orientation="vertical" label="Bass" name="bass" value="50" style="width: 80px"></wa-slider>
<wa-slider orientation="vertical" label="Treble" name="treble" value="40" style="width: 80px"></wa-slider>
</div>
```
Range sliders can also be vertical.
```html {.example}
<div style="height: 300px; display: flex; align-items: center; gap: 2rem;">
<wa-slider
label="Temperature Range"
orientation="vertical"
range
min="0"
max="100"
min-value="30"
max-value="70"
with-tooltip
tooltip-placement="right"
id="slider__vertical-range"
>
</wa-slider>
</div>
<script>
const slider = document.getElementById('slider__vertical-range');
slider.valueFormatter = value => {
return new Intl.NumberFormat('en', {
style: 'unit',
unit: 'fahrenheit',
unitDisplay: 'short',
minimumFractionDigits: 0,
maximumFractionDigits: 1,
}).format(value);
};
</script>
```
### Size
Control the slider's size using the `size` attribute. Valid options include `small`, `medium`, and `large`.
```html {.example}
<wa-slider size="small" value="50" label="Small"></wa-slider><br />
<wa-slider size="medium" value="50" label="Medium"></wa-slider><br />
<wa-slider size="large" value="50" label="Large"></wa-slider>
```
### Indicator Offset
By default, the filled indicator extends from the minimum value to the current position. Use the `indicator-offset` attribute to change the starting point of this visual indicator.
```html {.example}
<wa-slider
label="Cat playfulness"
hint="Energy level during playtime"
name="value"
value="0"
min="-5"
max="5"
indicator-offset="0"
with-markers
with-tooltip
with-references
>
<span slot="reference">Lazy</span>
<span slot="reference">Zoomies</span>
</wa-slider>
```
### Disabled
@@ -45,74 +273,17 @@ Use the `min` and `max` attributes to set the range's minimum and maximum values
Use the `disabled` attribute to disable a slider.
```html {.example}
<wa-slider disabled></wa-slider>
<wa-slider label="Disabled" value="50" disabled></wa-slider>
```
### Tooltip Placement
### Required
By default, the tooltip is shown on top. Set `tooltip` to `bottom` to show it below the slider.
Mark a slider as required using the `required` attribute. Users must interact with required sliders before the form can be submitted.
```html {.example}
<wa-slider tooltip="bottom"></wa-slider>
```
### Disable the Tooltip
To disable the tooltip, set `tooltip` to `none`.
```html {.example}
<wa-slider tooltip="none"></wa-slider>
```
### Custom Track Colors
You can customize the active and inactive portions of the track using the `--track-color-active` and `--track-color-inactive` custom properties.
```html {.example}
<wa-slider
style="
--track-color-active: var(--wa-color-brand-fill-loud);
--track-color-inactive: var(--wa-color-brand-fill-normal);
"
></wa-slider>
```
### Custom Track Offset
You can customize the initial offset of the active track using the `--track-active-offset` custom property.
```html {.example}
<wa-slider
min="-100"
max="100"
style="
--track-color-active: var(--wa-color-brand-fill-loud);
--track-color-inactive: var(--wa-color-brand-fill-normal);
--track-active-offset: 50%;
"
></wa-slider>
```
### Custom Tooltip Formatter
You can change the tooltip's content by setting the `tooltipFormatter` property to a function that accepts the range's value as an argument.
```html {.example}
<wa-slider min="0" max="100" step="1" class="range-with-custom-formatter"></wa-slider>
<script>
const range = document.querySelector('.range-with-custom-formatter');
range.tooltipFormatter = value => `Total - ${value}%`;
</script>
```
### Right-to-Left languages
The component adapts to right-to-left (RTL) languages as you would expect.
```html {.example}
<wa-slider dir="rtl"
label="مقدار"
hint="التحكم في مستوى صوت الأغنية الحالية."
style="--track-color-active: var(--wa-color-brand-fill-loud)" value="10"></wa-slider>
```
<form action="about:blank" target="_blank" method="get">
<wa-slider name="slide" label="Required slider" min="0" max="10" required></wa-slider>
<br />
<button type="submit">Submit</button>
</form>
```

View File

@@ -101,7 +101,9 @@ You can make a tab closable by adding a close button next to the tab and inside
<wa-tab-group class="tabs-closable">
<wa-tab panel="general">General</wa-tab>
<wa-tab panel="closable">Closable</wa-tab>
<wa-icon-button slot="nav" tabindex="-1" name="xmark" label="Close the closable tab"></wa-icon-button>
<wa-button slot="nav" tabindex="-1" appearance="plain" size="small">
<wa-icon name="xmark" label="Close the closable tab"></wa-icon>
</wa-button>
<wa-tab panel="closable-2">Advanced</wa-tab>
<wa-tab-panel name="general">This is the general tab panel.</wa-tab-panel>
@@ -114,17 +116,17 @@ You can make a tab closable by adding a close button next to the tab and inside
<wa-button disabled>Restore tab</wa-button>
<style>
.tabs-closable wa-icon-button {
.tabs-closable wa-button {
position: relative;
left: -1rem;
top: .75rem; }
left: -1.5em;
top: 0.675em; }
</style>
<script>
const tabGroup = document.querySelector('.tabs-closable');
const generalTab = tabGroup.querySelectorAll('wa-tab')[0];
const closableTab = tabGroup.querySelectorAll('wa-tab')[1];
const closeButton = tabGroup.querySelector('wa-icon-button');
const closeButton = tabGroup.querySelector('wa-button');
const restoreButton = tabGroup.nextElementSibling.nextElementSibling;
// Remove the tab when the close button is clicked

View File

@@ -6,20 +6,4 @@ parent: tab-group
icon: tab-panel
---
```html {.example}
<wa-tab-group>
<wa-tab panel="general">General</wa-tab>
<wa-tab panel="custom">Custom</wa-tab>
<wa-tab panel="advanced">Advanced</wa-tab>
<wa-tab panel="disabled" disabled>Disabled</wa-tab>
<wa-tab-panel name="general">This is the general tab panel.</wa-tab-panel>
<wa-tab-panel name="custom">This is the custom tab panel.</wa-tab-panel>
<wa-tab-panel name="advanced">This is the advanced tab panel.</wa-tab-panel>
<wa-tab-panel name="disabled">This is a disabled tab panel.</wa-tab-panel>
</wa-tab-group>
```
:::info
Additional demonstrations can be found in the [tab group examples](/docs/components/tab-group).
:::
This component must be used as a child of `<wa-tab-group>`. Please see the [Tab Group docs](/docs/components/tab-group) to see examples of this component in action.

View File

@@ -6,6 +6,4 @@ parent: tab-group
icon: tab
---
:::info
Additional demonstrations can be found in the [tab group examples](/docs/components/tab-group).
:::
This component must be used as a child of `<wa-tab-group>`. Please see the [Tab Group docs](/docs/components/tab-group) to see examples of this component in action.

View File

@@ -5,78 +5,4 @@ tags: [navigation, disclosure, apps]
icon: tree
---
```html {.example}
<wa-tree>
<wa-tree-item>
Item 1
<wa-tree-item>Item A</wa-tree-item>
<wa-tree-item>Item B</wa-tree-item>
<wa-tree-item>Item C</wa-tree-item>
</wa-tree-item>
<wa-tree-item>Item 2</wa-tree-item>
<wa-tree-item>Item 3</wa-tree-item>
</wa-tree>
```
## Examples
### Nested tree items
A tree item can contain other tree items. This allows the node to be expanded or collapsed by the user.
```html {.example}
<wa-tree>
<wa-tree-item>
Item 1
<wa-tree-item>
Item A
<wa-tree-item>Item Z</wa-tree-item>
<wa-tree-item>Item Y</wa-tree-item>
<wa-tree-item>Item X</wa-tree-item>
</wa-tree-item>
<wa-tree-item>Item B</wa-tree-item>
<wa-tree-item>Item C</wa-tree-item>
</wa-tree-item>
<wa-tree-item>Item 2</wa-tree-item>
<wa-tree-item>Item 3</wa-tree-item>
</wa-tree>
```
### Selected
Use the `selected` attribute to select a tree item initially.
```html {.example}
<wa-tree>
<wa-tree-item selected>
Item 1
<wa-tree-item>Item A</wa-tree-item>
<wa-tree-item>Item B</wa-tree-item>
<wa-tree-item>Item C</wa-tree-item>
</wa-tree-item>
<wa-tree-item>Item 2</wa-tree-item>
<wa-tree-item>Item 3</wa-tree-item>
</wa-tree>
```
### Expanded
Use the `expanded` attribute to expand a tree item initially.
```html {.example}
<wa-tree>
<wa-tree-item expanded>
Item 1
<wa-tree-item expanded>
Item A
<wa-tree-item>Item Z</wa-tree-item>
<wa-tree-item>Item Y</wa-tree-item>
<wa-tree-item>Item X</wa-tree-item>
</wa-tree-item>
<wa-tree-item>Item B</wa-tree-item>
<wa-tree-item>Item C</wa-tree-item>
</wa-tree-item>
<wa-tree-item>Item 2</wa-tree-item>
<wa-tree-item>Item 3</wa-tree-item>
</wa-tree>
```
This component must be used as a child of `<wa-tree>`. Please see the [Tree docs](/docs/components/tree) to see examples of this component in action.

View File

@@ -0,0 +1,79 @@
---
title: Zoomable Frame
layout: component
---
```html {.example}
<wa-zoomable-frame src="https://backers.webawesome.com/" zoom="0.5">
</wa-zoomable-frame>
```
## Examples
### Loading external content
Use the `src` attribute to embed external websites or resources. The URL must be accessible, and cross-origin restrictions may apply due to the Same-Origin Policy, potentially limiting access to the iframe's content.
```html
<wa-zoomable-frame src="https://example.com/">
</wa-zoomable-frame>
```
The zoomable frame fills 100% width by default with a 16:9 aspect ratio. Customize this using the `aspect-ratio` CSS property.
```html
<wa-zoomable-frame src="https://example.com/" style="aspect-ratio: 4/3;">
</wa-zoomable-frame>
```
Use the `srcdoc` attribute or property to display custom HTML content directly within the iframe, perfect for rendering inline content without external resources.
```html
<wa-zoomable-frame srcdoc="<html><body><h1>Hello, World!</h1><p>This is inline content.</p></body></html>">
</wa-zoomable-frame>
```
:::info
When both `src` and `srcdoc` are specified, `srcdoc` takes precedence.
:::
### Controlling zoom behavior
Set the `zoom` attribute to control the frame's zoom level. Use `1` for 100%, `2` for 200%, `0.5` for 50%, and so on.
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>
```
### Hiding zoom controls
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>
```
### Preventing user interaction
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>
```

View File

@@ -1,44 +0,0 @@
---
title: Clamped Color Tokens
layout: block
---
{% set tints = ['max-50', 'max-60', 'max-70', 'min-50', 'min-60', 'min-70'] %}
{% set hues = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'indigo', 'purple', 'pink', 'gray'] %}
<table class="colors">
<thead>
<tr>
<th></th>
<th class="core-column">Core tint</th>
{% for tint in tints -%}
<th>{{ tint }}</th>
{%- endfor %}
</tr>
</thead>
{% for hue in hues -%}
<tr class="wa-color-{{ hue }}">
<th>{{ hue | capitalize }}</th>
<td class="core-column">
<div class="color swatch" style="background-color: var(--wa-color-{{ hue }}); color: var(--wa-color-{{ hue }}-on); --key: var(--wa-color-{{ hue }}-key);">
{{ palettes[paletteId][hue].maxChromaTint }}
<wa-copy-button value="--wa-color-{{ hue }}" copy-label="--wa-color-{{ hue }}"></wa-copy-button>
</div>
</td>
{% for tint in tints -%}
<td>
<div class="color swatch" style="background-color: var(--wa-color-{{ hue }}-{{ tint }})">
<wa-copy-button value="--wa-color-{{ hue }}-{{ tint }}" copy-label="--wa-color-{{ hue }}-{{ tint }}"></wa-copy-button>
</div>
</td>
{%- endfor -%}
</tr>
{%- endfor %}
</table>
<style>
.core-column .color.swatch::before {
counter-reset: key var(--key);
content: counter(key);
}
</style>

View File

@@ -5,71 +5,74 @@ title: Size tests
Button size should default to `medium`:
```html {.example}
<wa-button size=small>Small</wa-button>
<wa-button size="small">Small</wa-button>
<wa-button>Medium</wa-button>
<wa-button size=medium>Medium</wa-button>
<wa-button size=large>Large</wa-button>
<wa-button size="medium">Medium</wa-button>
<wa-button size="large">Large</wa-button>
```
If no button size is specified, it should default to that of its ancestor:
```html {.example}
<wa-button-group size="small">
<wa-button>Small 1</wa-button>
<wa-button>Small 2</wa-button>
<wa-button>Small 3</wa-button>
<wa-button>Small 1</wa-button>
<wa-button>Small 2</wa-button>
<wa-button>Small 3</wa-button>
</wa-button-group>
<br><br>
<br /><br />
<wa-button-group>
<wa-button>Medium 1</wa-button>
<wa-button>Medium 2</wa-button>
<wa-button>Medium 3</wa-button>
<wa-button>Medium 1</wa-button>
<wa-button>Medium 2</wa-button>
<wa-button>Medium 3</wa-button>
</wa-button-group>
<br><br>
<br /><br />
<wa-button-group size="large">
<wa-button>Large 1</wa-button>
<wa-button>Large 2</wa-button>
<wa-button>Large 3</wa-button>
<wa-button>Large 1</wa-button>
<wa-button>Large 2</wa-button>
<wa-button>Large 3</wa-button>
</wa-button-group>
```
Dropdown:
```html {.example}
<p>Small dropdown:
<wa-dropdown size="small">
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Dropdown Item 1</wa-menu-item>
<wa-menu-item>Dropdown Item 2</wa-menu-item>
<wa-menu-item>Dropdown Item 3</wa-menu-item>
</wa-menu>
</wa-dropdown>
<p>Small menu:
<wa-dropdown>
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu size="small">
<wa-menu-item>Dropdown Item 1</wa-menu-item>
<wa-menu-item>Dropdown Item 2</wa-menu-item>
<wa-menu-item>Dropdown Item 3</wa-menu-item>
</wa-menu>
</wa-dropdown>
<p>Small menu item:
<wa-dropdown>
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item size="small">Dropdown Item 1</wa-menu-item>
<wa-menu-item size="small">Dropdown Item 2</wa-menu-item>
<wa-menu-item size="small">Dropdown Item 3</wa-menu-item>
</wa-menu>
</wa-dropdown>
<p>No size:
<wa-dropdown>
<wa-button slot="trigger" caret>Dropdown</wa-button>
<wa-menu>
<wa-menu-item>Dropdown Item 1</wa-menu-item>
<wa-menu-item>Dropdown Item 2</wa-menu-item>
<wa-menu-item>Dropdown Item 3</wa-menu-item>
</wa-menu>
</wa-dropdown>
<p>
Small dropdown:
<wa-dropdown size="small">
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>Dropdown Item 1</wa-dropdown-item>
<wa-dropdown-item>Dropdown Item 2</wa-dropdown-item>
<wa-dropdown-item>Dropdown Item 3</wa-dropdown-item>
</wa-dropdown>
</p>
<p>
Small menu:
<wa-dropdown>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item size="small">Dropdown Item 1</wa-dropdown-item>
<wa-dropdown-item size="small">Dropdown Item 2</wa-dropdown-item>
<wa-dropdown-item size="small">Dropdown Item 3</wa-dropdown-item>
</wa-dropdown>
</p>
<p>
Small menu item:
<wa-dropdown>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item size="small">Dropdown Item 1</wa-dropdown-item>
<wa-dropdown-item size="small">Dropdown Item 2</wa-dropdown-item>
<wa-dropdown-item size="small">Dropdown Item 3</wa-dropdown-item>
</wa-dropdown>
</p>
<p>
No size:
<wa-dropdown>
<wa-button slot="trigger" with-caret>Dropdown</wa-button>
<wa-dropdown-item>Dropdown Item 1</wa-dropdown-item>
<wa-dropdown-item>Dropdown Item 2</wa-dropdown-item>
<wa-dropdown-item>Dropdown Item 3</wa-dropdown-item>
</wa-dropdown>
</p>
```

View File

@@ -671,7 +671,7 @@ hasOutline: false
<div style="display: grid; grid-template-rows: minmax(0, auto) minmax(0, 1fr); height: 100%; gap: 1rem;">
<div style="display: flex; gap: 1.25rem;">
<wa-input name="icon-search" autofocus placeholder="Search Icons" with-clear style="flex: 1 1 auto;">
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
<wa-icon slot="start" name="magnifying-glass"></wa-icon>
</wa-input>
<wa-select name="icon-variant" value="solid" style="flex: 0 1 auto;">
<wa-option value="solid">Solid</wa-option>
@@ -1731,7 +1731,7 @@ hasOutline: false
grid-column-end: col-end;
}
.project-header wa-icon-button {
.project-header wa-button {
color: inherit;
font-size: var(--wa-font-size-l);
@@ -2002,16 +2002,22 @@ hasOutline: false
<span id="project-name" style="margin-inline-start: var(--wa-space-l);">Project Name</span>
</h1>
<div>
<wa-icon-button name="magnifying-glass" label="Search"></wa-icon-button>
<wa-icon-button name="user" label="Account"></wa-icon-button>
<wa-icon-button name="bag-shopping" label="Your Basket"></wa-icon-button>
<wa-button appearance="plain" size="small">
<wa-icon name="magnifying-glass" label="Search"></wa-icon>
</wa-button>
<wa-button appearance="plain" size="small">
<wa-icon name="user" label="Account"></wa-icon>
</wa-button>
<wa-button appearance="plain" size="small">
<wa-icon name="bag-shopping" label="Your Basket"></wa-icon>
</wa-button>
</div>
</header>
<section class="strata hero">
<div class="title">
<h1 class="hero-title">What you know you can't explain, but you feel it.</h1>
<wa-button variant="brand" class="hero-cta">
<wa-icon slot="prefix" name="arrow-down"></wa-icon>
<wa-icon slot="start" name="arrow-down"></wa-icon>
Free Your Mind
</wa-button>
</div>
@@ -2031,11 +2037,11 @@ hasOutline: false
</div>
<div slot="footer">
<wa-button size="small">
<wa-icon slot="prefix" name="plus" variant="regular"></wa-icon>
<wa-icon slot="start" name="plus" variant="regular"></wa-icon>
Add to Cart
</wa-button>
<wa-button size="small" appearance="outline">
<wa-icon slot="prefix" name="bookmark" variant="regular"></wa-icon>
<wa-icon slot="start" name="bookmark" variant="regular"></wa-icon>
Save
</wa-button>
</div>
@@ -2054,11 +2060,11 @@ hasOutline: false
</div>
<div slot="footer">
<wa-button size="small">
<wa-icon slot="prefix" name="plus" variant="regular"></wa-icon>
<wa-icon slot="start" name="plus" variant="regular"></wa-icon>
Add to Cart
</wa-button>
<wa-button size="small" appearance="outline">
<wa-icon slot="prefix" name="bookmark" variant="regular"></wa-icon>
<wa-icon slot="start" name="bookmark" variant="regular"></wa-icon>
Save
</wa-button>
</div>
@@ -2076,11 +2082,11 @@ hasOutline: false
</div>
<div slot="footer">
<wa-button size="small">
<wa-icon slot="prefix" name="plus" variant="regular"></wa-icon>
<wa-icon slot="start" name="plus" variant="regular"></wa-icon>
Add to Cart
</wa-button>
<wa-button size="small" appearance="outline">
<wa-icon slot="prefix" name="bookmark" variant="regular"></wa-icon>
<wa-icon slot="start" name="bookmark" variant="regular"></wa-icon>
Save
</wa-button>
</div>
@@ -2142,31 +2148,49 @@ hasOutline: false
<wa-card class="card-header card-footer">
<div slot="header">
<div class="grouped-buttons">
<wa-icon-button id="bold" name="bold" label="Bold"></wa-icon-button>
<wa-button appearance="plain" size="small" id="bold">
<wa-icon name="bold" label="Bold"></wa-icon>
</wa-button>
<wa-tooltip for="bold">Bold</wa-tooltip>
<wa-icon-button id="italic" name="italic" label="Italic"></wa-icon-button>
<wa-button appearance="plain" size="small" id="italic">
<wa-icon name="italic" label="Italic"></wa-icon>
</wa-button>
<wa-tooltip for="italic">Italic</wa-tooltip>
<wa-icon-button id="strikethrough" name="strikethrough" label="strikethrough"></wa-icon-button>
<wa-button appearance="plain" size="small" id="strikethrough">
<wa-icon name="strikethrough" label="strikethrough"></wa-icon>
</wa-button>
<wa-tooltip for="strikethrough">Strikethrough</wa-tooltip>
</div>
<div class="grouped-buttons">
<wa-icon-button id="link" name="link" label="Link"></wa-icon-button>
<wa-button appearance="plain" size="small" id="link">
<wa-icon name="link" label="Link"></wa-icon>
</wa-button>
<wa-tooltip for="link">Link</wa-tooltip>
</div>
<div class="grouped-buttons">
<wa-icon-button id="list" name="list" label="Unordered List"></wa-icon-button>
<wa-button appearance="plain" size="small" id="list">
<wa-icon name="list" label="Unordered List"></wa-icon>
</wa-button>
<wa-tooltip for="list">Unordered List</wa-tooltip>
<wa-icon-button id="list-ol" name="list-ol" label="Ordered List"></wa-icon-button>
<wa-button appearance="plain" size="small" id="list-ol">
<wa-icon name="list-ol" label="Ordered List"></wa-icon>
</wa-button>
<wa-tooltip for="list-ol">Ordered List</wa-tooltip>
</div>
<div class="grouped-buttons">
<wa-icon-button id="block-quote" name="block-quote" label="Block Quote"></wa-icon-button>
<wa-button appearance="plain" size="small" id="block-quote">
<wa-icon name="block-quote" label="Block Quote"></wa-icon>
</wa-button>
<wa-tooltip for="block-quote">Block Quote</wa-tooltip>
</div>
<div class="grouped-buttons">
<wa-icon-button id="code" name="code" label="Code"></wa-icon-button>
<wa-button appearance="plain" size="small" id="code">
<wa-icon name="code" label="Code"></wa-icon>
</wa-button>
<wa-tooltip for="code">Code</wa-tooltip>
<wa-icon-button id="inline-code" name="terminal" label="Inline Code"></wa-icon-button>
<wa-button appearance="plain" size="small" id="inline-code">
<wa-icon name="terminal" label="Inline Code"></wa-icon>
</wa-button>
<wa-tooltip for="inline-code">Inline Code</wa-tooltip>
</div>
</div>
@@ -2176,29 +2200,43 @@ hasOutline: false
<div slot="footer">
<div class="tools">
<div class="grouped-buttons">
<wa-icon-button id="add-file" name="circle-plus" label="Add File"></wa-icon-button>
<wa-button appearance="plain" size="small" id="add-file">
<wa-icon name="circle-plus" label="Add File"></wa-icon>
</wa-button>
<wa-tooltip for="add-file">Add File</wa-tooltip>
<wa-icon-button id="formatting" name="font-case" label="Open Formatting"></wa-icon-button>
<wa-button appearance="plain" size="small" id="formatting">
<wa-icon name="font-case" label="Open Formatting"></wa-icon>
</wa-button>
<wa-tooltip for="formatting">Formatting</wa-tooltip>
<wa-icon-button id="emojis" name="face-smile" label="Emoji"></wa-icon-button>
<wa-button appearance="plain" size="small" id="emojis">
<wa-icon name="face-smile" label="Emoji"></wa-icon>
</wa-button>
<wa-tooltip for="emojis">Emojis</wa-tooltip>
<wa-icon-button id="mention" name="at" label="Mention"></wa-icon-button>
<wa-button appearance="plain" size="small" id="mention">
<wa-icon name="at" label="Mention"></wa-icon>
</wa-button>
<wa-tooltip for="mention">Mention</wa-tooltip>
</div>
<div class="grouped-buttons">
<wa-icon-button id="record-video" name="video" label="Video"></wa-icon-button>
<wa-button appearance="plain" size="small" id="record-video">
<wa-icon name="video" label="Video"></wa-icon>
</wa-button>
<wa-tooltip for="record-video">Record Video</wa-tooltip>
<wa-icon-button id="record-audio" name="microphone" label="Microphone"></wa-icon-button>
<wa-button appearance="plain" size="small" id="record-audio">
<wa-icon name="microphone" label="Microphone"></wa-icon>
</wa-button>
<wa-tooltip for="record-audio">Record Audio Clip</wa-tooltip>
</div>
<div class="grouped-buttons">
<wa-icon-button id="add-magic" name="sparkles" label="Magic"></wa-icon-button>
<wa-button appearance="plain" size="small" id="add-magic">
<wa-icon name="sparkles" label="Magic"></wa-icon>
</wa-button>
<wa-tooltip for="add-magic">Add Magic</wa-tooltip>
</div>
</div>
<div class="send">
<wa-button variant="brand" size="small">
<wa-icon slot="prefix" name="paper-plane-top" variant="solid" label="Add File"></wa-icon>
<wa-icon slot="start" name="paper-plane-top" variant="solid" label="Add File"></wa-icon>
Send
</wa-button>
</div>
@@ -2248,11 +2286,11 @@ hasOutline: false
<div style="display: flex; align-items: end; gap: 1rem;">
<wa-input type="number" label="How many?"></wa-input>
<wa-button variant="brand">
<wa-icon slot="prefix" name="bag-shopping" variant="solid" label="Add to Basket"></wa-icon>
<wa-icon slot="start" name="bag-shopping" variant="solid" label="Add to Basket"></wa-icon>
Add to Basket
</wa-button>
<wa-button variant="neutral">
<wa-icon slot="prefix" name="bookmark" variant="regular"></wa-icon>
<wa-icon slot="start" name="bookmark" variant="regular"></wa-icon>
Save
</wa-button>
</div>
@@ -2281,25 +2319,23 @@ hasOutline: false
<td style="text-align: center;"><wa-tag variant="warning" size="small">Pending</wa-tag></td>
<td>
<wa-dropdown>
<wa-button slot="trigger" caret size="small">Action</wa-button>
<wa-menu>
<wa-menu-item>
<wa-icon slot="prefix" name="check" variant="regular"></wa-icon>
Resolved
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="clock" variant="regular"></wa-icon>
Pending
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="xmark" variant="regular"></wa-icon>
Delete
</wa-menu-item>
</wa-menu>
<wa-button slot="trigger" with-caret size="small">Action</wa-button>
<wa-dropdown-item>
<wa-icon slot="start" name="check" variant="regular"></wa-icon>
Resolved
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="clock" variant="regular"></wa-icon>
Pending
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="xmark" variant="regular"></wa-icon>
Delete
</wa-dropdown-item>
</wa-dropdown>
</td>
</tr>
@@ -2310,26 +2346,24 @@ hasOutline: false
<td><wa-avatar image="/assets/images/themer/avatar-char.jpg" label="Char" style="margin-right: var(--wa-space-xs)"></wa-avatar> Char McCoy</td>
<td style="text-align: center;"><wa-tag variant="success" size="small">Resolved</wa-tag></td>
<td>
<wa-dropdown>
<wa-button slot="trigger" caret size="small">Action</wa-button>
<wa-menu>
<wa-menu-item>
<wa-icon slot="prefix" name="check" variant="regular"></wa-icon>
Resolved
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="clock" variant="regular"></wa-icon>
Pending
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="xmark" variant="regular"></wa-icon>
Delete
</wa-menu-item>
</wa-menu>
<wa-dropdown>
<wa-button slot="trigger" with-caret size="small">Action</wa-button>
<wa-dropdown-item>
<wa-icon slot="start" name="check" variant="regular"></wa-icon>
Resolved
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="clock" variant="regular"></wa-icon>
Pending
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="xmark" variant="regular"></wa-icon>
Delete
</wa-dropdown-item>
</wa-dropdown>
</td>
</tr>
@@ -2340,26 +2374,24 @@ hasOutline: false
<td><wa-avatar initials="DE" label="Avatar with initials: DE" style="margin-right: var(--wa-space-xs)"></wa-avatar> Debbie Evans</td>
<td style="text-align: center;"><wa-tag variant="warning" size="small">Pending</wa-tag></td>
<td>
<wa-dropdown>
<wa-button slot="trigger" caret size="small">Action</wa-button>
<wa-menu>
<wa-menu-item>
<wa-icon slot="prefix" name="check" variant="regular"></wa-icon>
Resolved
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="clock" variant="regular"></wa-icon>
Pending
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="xmark" variant="regular"></wa-icon>
Delete
</wa-menu-item>
</wa-menu>
<wa-dropdown>
<wa-button slot="trigger" with-caret size="small">Action</wa-button>
<wa-dropdown-item>
<wa-icon slot="start" name="check" variant="regular"></wa-icon>
Resolved
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="clock" variant="regular"></wa-icon>
Pending
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="xmark" variant="regular"></wa-icon>
Delete
</wa-dropdown-item>
</wa-dropdown>
</td>
</tr>
@@ -2370,26 +2402,24 @@ hasOutline: false
<td></td>
<td style="text-align: center;"><wa-tag variant="danger" size="small">Bounced</wa-tag></td>
<td>
<wa-dropdown>
<wa-button slot="trigger" caret size="small">Action</wa-button>
<wa-menu>
<wa-menu-item>
<wa-icon slot="prefix" name="check" variant="regular"></wa-icon>
Resolved
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="clock" variant="regular"></wa-icon>
Pending
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="xmark" variant="regular"></wa-icon>
Delete
</wa-menu-item>
</wa-menu>
<wa-dropdown>
<wa-button slot="trigger" with-caret size="small">Action</wa-button>
<wa-dropdown-item>
<wa-icon slot="start" name="check" variant="regular"></wa-icon>
Resolved
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="clock" variant="regular"></wa-icon>
Pending
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="xmark" variant="regular"></wa-icon>
Delete
</wa-dropdown-item>
</wa-dropdown>
</td>
</tr>
@@ -2400,26 +2430,24 @@ hasOutline: false
<td><wa-avatar image="/assets/images/themer/avatar-dara.jpg" label="Dara" style="margin-right: var(--wa-space-xs)"></wa-avatar> Dara Prescott</td>
<td style="text-align: center;"><wa-tag variant="neutral" size="small">Expired</wa-tag></td>
<td>
<wa-dropdown>
<wa-button slot="trigger" caret size="small">Action</wa-button>
<wa-menu>
<wa-menu-item>
<wa-icon slot="prefix" name="check" variant="regular"></wa-icon>
Resolved
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="clock" variant="regular"></wa-icon>
Pending
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-menu-item>
<wa-menu-item>
<wa-icon slot="prefix" name="xmark" variant="regular"></wa-icon>
Delete
</wa-menu-item>
</wa-menu>
<wa-dropdown>
<wa-button slot="trigger" with-caret size="small">Action</wa-button>
<wa-dropdown-item>
<wa-icon slot="start" name="check" variant="regular"></wa-icon>
Resolved
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="clock" variant="regular"></wa-icon>
Pending
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="arrow-rotate-left" variant="regular"></wa-icon>
Re-open
</wa-dropdown-item>
<wa-dropdown-item>
<wa-icon slot="start" name="xmark" variant="regular"></wa-icon>
Delete
</wa-dropdown-item>
</wa-dropdown>
</td>
</tr>
@@ -2432,30 +2460,30 @@ hasOutline: false
<h2 style="margin-bottom: var(--wa-space-3xl);">Payment</h2>
<form>
<wa-input type="email" placeholder="ex. tanderson@metacortex.com" label="Email">
<wa-icon name="envelope" variant="regular" slot="prefix"></wa-icon>
<wa-icon name="envelope" variant="regular" slot="start"></wa-icon>
</wa-input>
<wa-input placeholder="1234 1234 1234 1234" label="Card Number">
<wa-icon name="credit-card" variant="regular" slot="prefix"></wa-icon>
<wa-icon name="credit-card" variant="regular" slot="start"></wa-icon>
</wa-input>
<div style="display: flex; gap: 1rem;">
<wa-input placeholder="MM / YY" label="Expiration">
<wa-icon name="calendar" variant="regular" slot="prefix"></wa-icon>
<wa-icon name="calendar" variant="regular" slot="start"></wa-icon>
</wa-input>
<wa-input placeholder="CVC" label="CVC">
<wa-icon name="lock" variant="regular" slot="prefix"></wa-icon>
<wa-icon name="lock" variant="regular" slot="start"></wa-icon>
</wa-input>
</div>
<wa-input placeholder="Thomas Anderson" label="Cardholder Name">
<wa-icon name="user" variant="regular" slot="prefix"></wa-icon>
<wa-icon name="user" variant="regular" slot="start"></wa-icon>
</wa-input>
<div style="display: flex; gap: 1rem;">
<wa-select label="Country" value="USA">
<wa-icon slot="prefix" name="globe" variant="regular"></wa-icon>
<wa-icon slot="start" name="globe" variant="regular"></wa-icon>
<wa-option value="USA">United States</wa-option>
<wa-option value="CAN">Canada</wa-option>
</wa-select>
<wa-input placeholder="12345" label="Zip">
<wa-icon name="location-dot" variant="regular" slot="prefix"></wa-icon>
<wa-icon name="location-dot" variant="regular" slot="start"></wa-icon>
</wa-input>
</div>
<wa-switch checked style="margin: var(--wa-space-2xl) 0 var(--wa-space-3xl) 0;">Sign me up for more offers from this store</wa-switch>

View File

@@ -14,6 +14,7 @@ During the alpha period, things might break! We take breaking changes very serio
## Next
- 🚨 BREAKING: `input` and `change` events on form controls like `<wa-input>` now are always set to `bubble` and `compose`.
- 🚨 BREAKING: Greatly simplified how native styles work and removed redundant utilities
- Removed `.wa-button`, `.wa-callout` classes
- Removed `themes/native/*.css` files; use `native.css` to opt into native styles
@@ -22,7 +23,8 @@ During the alpha period, things might break! We take breaking changes very serio
- 🚨 BREAKING: Renamed the `classic` theme to `shoelace`
- 🚨 BREAKING: Renamed `pulse` attribute in `<wa-badge>` to `attention="pulse"` and added `attention="bounce"` [issue:#940]
- 🚨 BREAKING: Renamed the `vertical` attribute to `orientation="vertical"` in `<wa-split-panel>` and `<wa-divider>` to align with other components and the platform [issue:674]
- 🚨 BREAKING: Renamed certain boolean attributes to be more consistent using the `with-*` and `without-*` pattern:
- 🚨 BREAKING: Renamed certain boolean attributes to be consistent using the `with-*` and `without-*` pattern:
- `<wa-button caret>` => `<wa-button with-caret>`
- `<wa-color-picker no-format-toggle>` => `<wa-color-picker without-format-toggle>`
- `<wa-format-number no-grouping>` => `<wa-format-number without-grouping>`
- `<wa-input no-spin-buttons>` => `<wa-input without-spin-buttons>`
@@ -31,20 +33,59 @@ During the alpha period, things might break! We take breaking changes very serio
- `<wa-tab-group no-scroll-controls>` => `<wa-tab-group without-scroll-controls>`
- `<wa-tag removable>` => `<wa-tag with-remove>`
- 🚨 BREAKING: removed the `size` attribute from `<wa-card>`; please set the size of child elements on the children directly
- 🚨 BREAKING: greatly simplified the sizing strategy across components and utilities
- Removed `--wa-size`, `--wa-size-smaller`, `--wa-size-larger`, `--wa-space`, `--wa-space-smaller`, and `--wa-space-larger`
- Added tokens for `--wa-form-control-padding-inline`, `--wa-form-control-padding-block`, and `--wa-form-control-toggle-size`
- Refactored default `--wa-font-size-*` values to use an apparent 1.125 ratio and round rendered values to the nearest whole pixel
- Added convenience tokens for `--wa-font-size-smaller` and `--wa-font-size-larger`
- Updated components to use relative `em` values for internal padding and margin wherever appropriate
- 🚨 BREAKING: removed the `hint` property and slot from `<wa-radio>`; please apply hints directly to `<wa-radio-group>` instead
- 🚨 BREAKING: redesigned `<wa-slider>` with extensive new functionality
- Added support for range sliders with dual thumbs using the `range` attribute
- Added vertical orientation support with `orientation="vertical"`
- Added visual markers at each step with `with-markers`
- Added contextual reference labels with `with-references` and the `reference` slot
- Added tooltips showing current values with `with-tooltip`
- Added customizable indicator offset with `indicator-offset` attribute
- Added value formatting support with the `valueFormatter` property
- Improved the styling API to be consistent and more powerful (no more browser-specific selectors and pseudo elements to style)
- Updated to use consistent `with-*` attribute naming pattern
- 🚨 BREAKING: removed `<wa-icon-button>`; use `<wa-button><wa-icon name="..." label="..."></wa-icon></wa-button>` instead
- 🚨 BREAKING: completely reworked `<wa-dropdown>` to be easier to use
- Added `<wa-dropdown-item>`, greatly simplifying the dropdown's markup structure
- Removed `<wa-menu>`, `<wa-menu-item>`, and `<wa-menu-label>`; use `<wa-dropdown-item>` and native headings instead
- 🚨 BREAKING: renamed all `prefix` and `suffix` slots to `start` and `end`, affecting the following components:
- `<wa-breadcrumb-item>`
- `<wa-button>`
- `<wa-input>`
- `<wa-select>`
- `<wa-option>`
- 🚨 BREAKING: reworked `<wa-select>` to use `<wa-option selected>` to set initially selected options, removing the "no spaces allowed" restrictions for option values
- Added a new free component: `<wa-popover>` (#2 of 14 per stretch goals)
- 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 [issue:675]
- Added support for `name` in `<wa-details>` for exclusively opening one in a group
- 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>`
- Added support for `data-drawer="open <id>"` to `<wa-drawer>`
- Added `@media (hover: hover)` to component hover styles to prevent sticky hover states
- Fixed a bug in `<wa-radio-group>` that caused radios to uncheck when assigning a numeric value [issue:924]
- Fixed `<wa-button-group>` so dividers properly show between buttons
- Fixed the tooltip position in `<wa-slider>` when using RTL
- Fixed a bug in `<wa-details>` and native `<details>` styles that made the summary hard to click [issue:684]
- Fixed a handful of bugs unify form control height across components and native elements
- Improved CSS utilities and Native Styles to use [CSS layers](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) for easier end user customization (no more specificity conflicts  your CSS wins!)
- Improved native `<button>` styles to properly space icons
- Improved button appearances in `<wa-color-picker>`
- Improved `<wa-rating>` to have more accessible icons by default
- Removed the experimental `<wa-code-demo>` component
## 3.0.0-alpha.13
- 🚨 BREAKING: Renamed `<image-comparer>` to `<wa-comparison>` and improved compatibility for non-image content
- 🚨 BREAKING: Added slot detection to `<wa-dialog>` and `<wa-drawer>` so you don't need to specify `with-header` and `with-footer`; headers are on by default now, but you can use the `without-header` attribute to turn them off
- 🚨 BREAKING: Renamed the `image` slot to `media` for a more appropriate naming convention
- 🚨 BREAKING: Added slot detection to `<wa-dialog>` and `<wa-drawer>` so you don't need to specify `with-header` and `with-footer`; headers are on by default now, but you can use the `without-header` attribute to turn them off
- 🚨 BREAKING: Renamed the `image` slot to `media` for a more appropriate naming convention
- Added [a theme builder](/docs/themes/edit/) to create your own themes
- Added a new Blog & News pattern category
- Added a new free component: `<wa-scroller>` (#1 of 14 per stretch goals)
@@ -106,7 +147,7 @@ During the alpha period, things might break! We take breaking changes very serio
### Design Tokens
- Added `--wa-color-[hue]` tokens with the "core" color of each scale, regardless of which tint it lives on.
You can find them in the first column of each color palette.
You can find them in the first column of each color palette.
### Themes
@@ -131,20 +172,21 @@ You can find them in the first column of each color palette.
- Fixed an incorrect CSS value in the expand icon
- Fixed a bug that prevented the description from being read by screen readers
#### `<wa-option>`
#### `<wa-option>`
- `label` attribute to override the generated label (useful for rich content)
- `defaultLabel` property
- Dropped `getTextLabel()` method (if you need dynamic labels, just set the `label` attribute dynamically)
- Dropped `base` part for easier styling. CSS can now be applied directly to the element itself.
#### `<wa-menu-item>`
#### `<wa-menu-item>`
- `label` attribute to override the generated label (useful for rich content)
- `defaultLabel` property
- Dropped `getTextLabel()` method (if you need dynamic labels, just set the `label` attribute dynamically)
#### `<wa-card>`
- Fixed a bug where child elements did not have correct rounding when headers and footers were absent.
- Re-introduced `--border-color` so that the card itself can have a different border color than its inner borders.
- Fixed a bug that prevented slots from showing automatically without `with-` attributes
@@ -330,12 +372,12 @@ Here's a list of some of the things that have changed since Shoelace v2. For que
- Removed `inline` from `<wa-color-picker>`
- Removed `getFormControls()` since we now use Form Associated Custom Elements and can reliably access Web Awesome Elements via `formElement.elements`.
- Removed `valueAsDate` from `<wa-input>`; use the following to mimic native behaviors:
setter: `waInput.value = new Date().toLocaleDateString()`
getter: `new Date(waInput.value)`
setter: `waInput.value = new Date().toLocaleDateString()`
getter: `new Date(waInput.value)`
- Removed `valueAsNumber` from `<wa-input>`; use the following to mimic native behaviors:
setter: `waInput.value = 5.toString()`
getter: `Number(waInput.value)`
setter: `waInput.value = 5.toString()`
getter: `Number(waInput.value)`
Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome-alpha/discussions)
Are you coming from Shoelace? [The 2.x changelog can be found here.](https://shoelace.style/resources/changelog/)
Are you coming from Shoelace? [The 2.x changelog can be found here.](https://shoelace.style/resources/changelog/)

View File

@@ -18,7 +18,7 @@ The [discussion forum](https://github.com/shoelace-style/shoelace/discussions) i
- 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-icon name="github" family="brands" slot="prefix"></wa-icon>
<wa-icon name="github" family="brands" slot="start"></wa-icon>
Join the Discussion
</wa-button>
@@ -32,7 +32,7 @@ The [community chat](https://discord.gg/mg8f26C) is open to the public and power
- 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-icon name="discord" family="brands" slot="prefix"></wa-icon>
<wa-icon name="discord" family="brands" slot="start"></wa-icon>
Join the Chat
</wa-button>
@@ -43,6 +43,6 @@ Follow [@webawesomer](https://twitter.com/webawesomer) on Twitter for general up
**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.
<wa-button variant="brand" href="https://twitter.com/webawesomer" target="_blank" style="margin-block-end: var(--wa-flow-spacing);">
<wa-icon name="twitter" family="brands" slot="prefix"></wa-icon>
<wa-icon name="twitter" family="brands" slot="start"></wa-icon>
Follow on Twitter
</wa-button>

View File

@@ -26,7 +26,7 @@ unlisted: true
{% if theme.fileSlug === 'custom' %}
<p>
<wa-button href="../edit/" class="edit-link" target="_parent" appearance="outlined">
<wa-icon slot="prefix" name="pencil"></wa-icon>
<wa-icon slot="start" name="pencil"></wa-icon>
Edit theme
</wa-button>
</p>

View File

@@ -23,15 +23,13 @@ unlisted: true
<div class="title">
<h1><editable-text :model-value="title" label="theme name" @submit="newTitle => save({title: newTitle})" blur="cancel"></editable-text></h1>
<wa-icon-button v-if="saved" class="delete" name="trash" label="Delete theme" @click="deleteSaved"></wa-icon-button>
<wa-button v-if="saved" class="delete" @click="deleteSaved" appearance="plain" size="small">
<wa-icon name="trash" label="Delete theme"></wa-icon>
</wa-button>
</div>
<wa-button v-if="tweaked || uid" @click="save()" :disabled="!unsavedChanges"
:variant="unsavedChanges ? 'success' : 'neutral'" size="small" :appearance="unsavedChanges ? 'accent' : 'outlined'">
<span slot="prefix" class="icon-modifier">
<wa-icon name="sidebar" variant="regular"></wa-icon>
<wa-icon name="circle-plus" class="modifier" style="color: light-dark(var(--wa-color-green-70), var(--wa-color-green-60));"></wa-icon>
</span>
<span v-content="unsavedChanges ? 'Save' : 'Saved'">Save</span>
</wa-button>
<wa-button size="small" @click="ui.showCode = !showCode" appearance="outlined">
@@ -44,7 +42,7 @@ unlisted: true
<wa-tab-panel name="css">
<p>
<wa-button variant="brand" :href="code.css.blob" :download="cssFilename">
<wa-icon name="arrow-down-to-line" variant="solid" slot="prefix"></wa-icon>
<wa-icon name="arrow-down-to-line" variant="solid" slot="start"></wa-icon>
Download <code v-text="cssFilename"></code>
</wa-button>
</p>
@@ -155,7 +153,7 @@ unlisted: true
</icons-card>
<wa-input label="Font Awesome Pro Kit Code" v-model="theme.icon.kit" placeholder="e.g. f0nta7e50e">
<info-tip slot="suffix"><template #content>You need a Font Awesome Pro license to use certain families and styles.</template></info-tip>
<info-tip slot="end"><template #content>You need a Font Awesome Pro license to use certain families and styles.</template></info-tip>
<a href="https://fontawesome.com/kits" target="_blank" slot="hint" class="wa-caption-m wa-cluster wa-gap-2xs">
<span>Find your kit code here</span>
<wa-icon name="arrow-up-right-from-square" variant="regular" style="font-size: 0.75em"></wa-icon>

View File

@@ -45,11 +45,11 @@ wa-page > header {
margin: 0;
}
wa-icon-button {
wa-button {
transition: var(--wa-transition-slow);
}
&:not(:hover, :focus-within, :has(input)) wa-icon-button {
&:not(:hover, :focus-within, :has(input)) wa-button {
opacity: 0;
}
}

View File

@@ -83,7 +83,7 @@ wa-input::part(input) {
grid-column-end: col-end;
}
.project-header wa-icon-button {
.project-header wa-button {
color: inherit;
font-size: var(--wa-font-size-l);

View File

@@ -21,16 +21,22 @@ noTheme: true
<span id="project-name" style="margin-inline-start: var(--wa-space-l);">Project Name</span>
</h1>
<div>
<wa-icon-button name="magnifying-glass" label="Search"></wa-icon-button>
<wa-icon-button name="user" label="Account"></wa-icon-button>
<wa-icon-button name="bag-shopping" label="Your Basket"></wa-icon-button>
<wa-button appearance="plain">
<wa-icon name="magnifying-glass" label="Search"></wa-icon>
</wa-button>
<wa-button appearance="plain">
<wa-icon name="user" label="Account"></wa-icon>
</wa-button>
<wa-button appearance="plain">
<wa-icon name="bag-shopping" label="Your Basket"></wa-icon>
</wa-button>
</div>
</header>
<section class="strata hero">
<div class="title">
<h1 class="hero-title">What you know you can't explain, but you feel it.</h1>
<wa-button variant="brand" class="hero-cta">
<wa-icon slot="prefix" name="arrow-down"></wa-icon>
<wa-icon slot="start" name="arrow-down"></wa-icon>
Free Your Mind
</wa-button>
</div>
@@ -50,11 +56,11 @@ noTheme: true
</div>
<div slot="footer">
<wa-button size="small">
<wa-icon slot="prefix" name="plus" variant="regular"></wa-icon>
<wa-icon slot="start" name="plus" variant="regular"></wa-icon>
Add to Cart
</wa-button>
<wa-button size="small" appearance="outline">
<wa-icon slot="prefix" name="bookmark" variant="regular"></wa-icon>
<wa-icon slot="start" name="bookmark" variant="regular"></wa-icon>
Save
</wa-button>
</div>
@@ -73,11 +79,11 @@ noTheme: true
</div>
<div slot="footer">
<wa-button size="small">
<wa-icon slot="prefix" name="plus" variant="regular"></wa-icon>
<wa-icon slot="start" name="plus" variant="regular"></wa-icon>
Add to Cart
</wa-button>
<wa-button size="small" appearance="outline">
<wa-icon slot="prefix" name="bookmark" variant="regular"></wa-icon>
<wa-icon slot="start" name="bookmark" variant="regular"></wa-icon>
Save
</wa-button>
</div>
@@ -95,11 +101,11 @@ noTheme: true
</div>
<div slot="footer">
<wa-button size="small">
<wa-icon slot="prefix" name="plus" variant="regular"></wa-icon>
<wa-icon slot="start" name="plus" variant="regular"></wa-icon>
Add to Cart
</wa-button>
<wa-button size="small" appearance="outline">
<wa-icon slot="prefix" name="bookmark" variant="regular"></wa-icon>
<wa-icon slot="start" name="bookmark" variant="regular"></wa-icon>
Save
</wa-button>
</div>

View File

@@ -8,31 +8,38 @@ For components that share similar qualities, Web Awesome includes custom propert
## Form Controls
Components such as [input](/docs/components/input), [select](/docs/components/select), [textarea](/docs/components/textarea), [checkbox](/docs/components/checkbox), etc. share a number of styles to give your forms a cohesive appearance. Web Awesome defines custom properties for these styles using the format `--wa-form-control-{style}`.
Components such as [input](/docs/components/input), [select](/docs/components/select), [textarea](/docs/components/textarea), [checkbox](/docs/components/checkbox), and others share a number of styles to give your forms a cohesive appearance. Web Awesome defines custom properties for these styles using the format `--wa-form-control-{style}`.
Not every form control uses all of these custom properties. For example, `<wa-radio>` defines its own height and border radius to achieve its familiar shape but shares many other styles with other components for a cohesive look and feel. Similarly, `<wa-button>` defines many of its own styles but matches the height and border width of other form controls.
| Custom Property | Default Value |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `--wa-form-control-background-color` | `var(--wa-color-surface-default)` |
| `--wa-form-control-border-color` | `var(--wa-color-neutral-border-loud)` |
| `--wa-form-control-border-style` | `var(--wa-border-style)` |
| `--wa-form-control-border-width` | `var(--wa-border-width-s)` |
| `--wa-form-control-border-radius` | `var(--wa-border-radius-m)` |
| `--wa-form-control-activated-color` | `var(--wa-color-brand-fill-loud)` |
| `--wa-form-control-label-color` | `var(--wa-color-neutral-border-loud)` |
| `--wa-form-control-label-font-weight` | `var(--wa-font-weight-normal)` |
| `--wa-form-control-label-line-height` | `var(--wa-line-height-normal)` |
| `--wa-form-control-value-color` | `var(--wa-color-text-normal)` |
| `--wa-form-control-value-font-weight` | `var(--wa-font-weight-body)` |
| `--wa-form-control-value-line-height` | `var(--wa-line-height-condensed)` |
| `--wa-form-control-placeholder-color` | `var(--wa-color-gray-60)` |
| `--wa-form-control-required-content` | `'*'` |
| `--wa-form-control-required-content-color` | `inherit` |
| `--wa-form-control-required-content-offset` | `-0.1em` |
| Custom Property | Default Value |
| ------------------------------------------- | ------------------------------------- |
| `--wa-form-control-background-color` | `var(--wa-color-surface-default)` |
| `--wa-form-control-border-color` | `var(--wa-color-neutral-border-loud)` |
| `--wa-form-control-border-style` | `var(--wa-border-style)` |
| `--wa-form-control-border-width` | `var(--wa-border-width-s)` |
| `--wa-form-control-border-radius` | `var(--wa-border-radius-m)` |
| `--wa-form-control-activated-color` | `var(--wa-color-brand-fill-loud)` |
| `--wa-form-control-label-color` | `var(--wa-color-neutral-border-loud)` |
| `--wa-form-control-label-font-weight` | `var(--wa-font-weight-normal)` |
| `--wa-form-control-label-line-height` | `var(--wa-line-height-normal)` |
| `--wa-form-control-value-color` | `var(--wa-color-text-normal)` |
| `--wa-form-control-value-font-weight` | `var(--wa-font-weight-body)` |
| `--wa-form-control-value-line-height` | `var(--wa-line-height-condensed)` |
| `--wa-form-control-hint-color` | `var(--wa-color-text-quiet)` |
| `--wa-form-control-hint-font-weight` | `var(--wa-font-weight-body)` |
| `--wa-form-control-hint-line-height` | `var(--wa-line-height-normal)` |
| `--wa-form-control-placeholder-color` | `var(--wa-color-gray-60)` |
| `--wa-form-control-required-content` | `'*'` |
| `--wa-form-control-required-content-color` | `inherit` |
| `--wa-form-control-required-content-offset` | `-0.1em` |
| `--wa-form-control-padding-block` | `0.75em` |
| `--wa-form-control-padding-inline` | `1em` |
| `--wa-form-control-height` | `round(calc(2 * var(--wa-form-control-padding-block) + 1em * var(--wa-form-control-value-line-height)), 1px)` |
| `--wa-form-control-toggle-size` | `round(1.25em, 1px)` |
```html {.example}
<form class="wa-block-spacing-l">
<form class="wa-stack">
<wa-input label="Input" placeholder="Placeholder"></wa-input>
<wa-select label="Select" value="option-1">
<wa-option value="option-1">Option 1</wa-option>
@@ -50,19 +57,6 @@ Not every form control uses all of these custom properties. For example, `<wa-ra
<wa-slider label="Range"></wa-slider>
<wa-button>Button</wa-button>
</form>
<style>
.wa-block-spacing-l > * + *, wa-radio {
display: block;
margin-block-start: var(--wa-space-l);
}
wa-radio {
margin-block-start: var(--wa-space-2xs);
}
wa-radio, wa-checkbox, wa-switch, wa-button {
width: fit-content;
}
</style>
```
## Panels
@@ -76,7 +70,7 @@ Panels consist of components with larger, contained surface areas like [callout]
| `--wa-panel-border-radius` | `var(--wa-border-radius-l)` |
```html {.example}
<div class="wa-block-spacing-l">
<div class="wa-stack">
<wa-callout>
<wa-icon slot="icon" name="circle-info" variant="regular"></wa-icon>
This is a simple callout with an icon.
@@ -86,13 +80,6 @@ Panels consist of components with larger, contained surface areas like [callout]
<code>wa-details</code>, at your service.
</wa-details>
</div>
<style>
.wa-block-spacing-l > * + * {
display: block;
margin-block-start: var(--wa-space-l);
}
</style>
```
## Tooltips
@@ -109,6 +96,8 @@ Tooltip styles are shared between the [tooltip](/docs/components/tooltip) compon
| `--wa-tooltip-line-height` | `var(--wa-line-height-normal)` |
```html {.example}
<wa-icon-button id="bullseye-example" label="Button" name="bullseye"></wa-icon-button>
<wa-button id="bullseye-example" appearance="plain">
<wa-icon label="Target" name="bullseye"></wa-icon>
</wa-button>
<wa-tooltip for="bullseye-example" open trigger="manual">This is a tooltip</wa-tooltip>
```

View File

@@ -35,21 +35,19 @@ description: Lock down consistent spacing Web Awesome's space properties.
Space properties are used intentionally throughout Web Awesome to create predictable rhythm and meaningful proximity. These properties use `rem` units in order to scale proportionately with the root font size.
Each space property uses a `calc()` function with `--wa-space-scale` to scale all spacing at once. By default, this multiplier is `1`. The table below lists the result of the calculation.
You can use `--wa-space-scale` to increase or decrease all spacing at once. By default, this multiplier is `1`.
| Custom Property | Default Value | Preview |
| ---------------- | ------------------------------- | --------------------------------------------------------------------- |
| `--wa-space-3xs` | `0.125rem` <small>(2px)</small> | <div class="spacing-example" style="width: var(--wa-space-3xs)"></div> |
| `--wa-space-2xs` | `0.25rem` <small>(4px)</small> | <div class="spacing-example" style="width: var(--wa-space-2xs)"></div> |
| `--wa-space-xs` | `0.5rem` <small>(8px)</small> | <div class="spacing-example" style="width: var(--wa-space-xs)"></div> |
| `--wa-space-s` | `0.75rem` <small>(12px)</small> | <div class="spacing-example" style="width: var(--wa-space-s)"></div> |
| `--wa-space-m` | `1rem` <small>(16px)</small> | <div class="spacing-example" style="width: var(--wa-space-m)"></div> |
| `--wa-space-l` | `1.25rem` <small>(20px)</small> | <div class="spacing-example" style="width: var(--wa-space-l)"></div> |
| `--wa-space-xl` | `1.5rem` <small>(24px)</small> | <div class="spacing-example" style="width: var(--wa-space-xl)"></div> |
| `--wa-space-2xl` | `2rem` <small>(32px)</small> | <div class="spacing-example" style="width: var(--wa-space-2xl)"></div> |
| `--wa-space-3xl` | `3rem` <small>(48px)</small> | <div class="spacing-example" style="width: var(--wa-space-3xl)"></div> |
The calculations for each size and the resulting pixel value (assuming a 16px root font size) are listed below.
When using space properties, it may be helpful to consider three distinct groups:
- Small-scale space (`3xs`, `2xs`, and `xs`) can be used for gaps between cooperating elements, such as a dropdown button and its menu, and padding within small components, such as badges and tooltips
- Normal space (`s`, `m`, and `l`) can be used for gaps between related elements with distinct touch targets and padding within typical interface elements, such as buttons and inputs
- Large-scale space (`xl`, `2xl`, and `3xl`) can be used for gaps between unrelated elements and padding within larger components, such as cards and dialogs
| Custom Property | Default Value | Preview - |
| ---------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `--wa-space-3xs` | `calc(var(--wa-space-scale) * 0.125rem)` <small>(2px)</small> | <div class="spacing-example" style="width: var(--wa-space-3xs)"></div> |
| `--wa-space-2xs` | `calc(var(--wa-space-scale) * 0.25rem)` <small>(4px)</small> | <div class="spacing-example" style="width: var(--wa-space-2xs)"></div> |
| `--wa-space-xs` | `calc(var(--wa-space-scale) * 0.5rem)` <small>(8px)</small> | <div class="spacing-example" style="width: var(--wa-space-xs)"></div> |
| `--wa-space-s` | `calc(var(--wa-space-scale) * 0.75rem)` <small>(12px)</small> | <div class="spacing-example" style="width: var(--wa-space-s)"></div> |
| `--wa-space-m` | `calc(var(--wa-space-scale) * 1rem)` <small>(16px)</small> | <div class="spacing-example" style="width: var(--wa-space-m)"></div> |
| `--wa-space-l` | `calc(var(--wa-space-scale) * 1.5rem)` <small>(24px)</small> | <div class="spacing-example" style="width: var(--wa-space-l)"></div> |
| `--wa-space-xl` | `calc(var(--wa-space-scale) * 2rem)` <small>(32px)</small> | <div class="spacing-example" style="width: var(--wa-space-xl)"></div> |
| `--wa-space-2xl` | `calc(var(--wa-space-scale) * 2.5rem)` <small>(40px)</small> | <div class="spacing-example" style="width: var(--wa-space-2xl)"></div> |
| `--wa-space-3xl` | `calc(var(--wa-space-scale) * 3rem)` <small>(48px)</small> | <div class="spacing-example" style="width: var(--wa-space-3xl)"></div> |
| `--wa-space-4xl` | `calc(var(--wa-space-scale) * 4rem)` <small>(64px)</small> | <div class="spacing-example" style="width: var(--wa-space-4xl)"></div> |

View File

@@ -17,21 +17,32 @@ Font families are assigned specific roles &mdash; like heading or code &mdash; t
## Font Size
Font sizes use the Major Second type scale, rounded to the nearest whole pixel assuming a 16px root font size. To maximize variation in larger font sizes, every other step on the scale is skipped.
Font sizes use a ratio of 1.125 to scale sizes proportionally. Starting with the medium (`m`) font size, smaller sizes (`s` through `2xs`) are 1.125x smaller as the sizes decrease, and larger sizes (`l` through `4xl`) are _twice_ 1.125x larger as sizes increase — here, the ratio is doubled to maximize impact between sizes.
Each font size uses a `calc()` function with `--wa-font-size-scale` to scale all font sizes at once. By default, this multiplier is `1`. The table below lists the result of the calculation.
Each value uses `rem` units and is rounded to the nearest whole pixel when rendered with [`round()`](https://developer.mozilla.org/en-US/docs/Web/CSS/round).
You can use `--wa-font-size-scale` to increase or decrease all font sizes at once. By default, this multiplier is `1`.
The calculations for each size and the resulting pixel value (assuming a 16px root font size) are listed below.
| Custom Property | Default Value | Preview |
| -------------------- | --------------------------------- | ---------------------------------------------------------- |
| `--wa-font-size-2xs` | `0.6875rem` <small>(11px)</small> | <div style="font-size: var(--wa-font-size-2xs)">AaBb</div> |
| `--wa-font-size-xs` | `0.75rem` <small>(12px)</small> | <div style="font-size: var(--wa-font-size-xs)">AaBb</div> |
| `--wa-font-size-s` | `0.875rem` <small>(14px)</small> | <div style="font-size: var(--wa-font-size-s)">AaBb</div> |
| `--wa-font-size-m` | `1rem` <small>(16px)</small> | <div style="font-size: var(--wa-font-size-m)">AaBb</div> |
| `--wa-font-size-l` | `1.25rem` <small>(20px)</small> | <div style="font-size: var(--wa-font-size-l)">AaBb</div> |
| `--wa-font-size-xl` | `1.625rem` <small>(26px)</small> | <div style="font-size: var(--wa-font-size-xl)">AaBb</div> |
| `--wa-font-size-2xl` | `2rem` <small>(32px)</small> | <div style="font-size: var(--wa-font-size-2xl)">AaBb</div> |
| `--wa-font-size-3xl` | `2.5625rem` <small>(41px)</small> | <div style="font-size: var(--wa-font-size-3xl)">AaBb</div> |
| `--wa-font-size-4xl` | `3.25rem` <small>(52px)</small> | <div style="font-size: var(--wa-font-size-4xl)">AaBb</div> |
| `--wa-font-size-2xs` | `round(calc(var(--wa-font-size-xs) / 1.125), 1px)` <small>(11px)</small> | <div style="font-size: var(--wa-font-size-2xs)">AaBb</div> |
| `--wa-font-size-xs` | `round(calc(var(--wa-font-size-s) / 1.125), 1px)` <small>(12px)</small> | <div style="font-size: var(--wa-font-size-xs)">AaBb</div> |
| `--wa-font-size-s` | `round(calc(var(--wa-font-size-m) / 1.125), 1px)` <small>(14px)</small> | <div style="font-size: var(--wa-font-size-s)">AaBb</div> |
| `--wa-font-size-m` | `calc(1rem * var(--wa-font-size-scale))` <small>(16px)</small> | <div style="font-size: var(--wa-font-size-m)">AaBb</div> |
| `--wa-font-size-l` | `round(calc(var(--wa-font-size-m) * 1.125 * 1.125), 1px)` <small>(20px)</small> | <div style="font-size: var(--wa-font-size-l)">AaBb</div> |
| `--wa-font-size-xl` | `round(calc(var(--wa-font-size-l) * 1.125 * 1.125), 1px)` <small>(25px)</small> | <div style="font-size: var(--wa-font-size-xl)">AaBb</div> |
| `--wa-font-size-2xl` | `round(calc(var(--wa-font-size-xl) * 1.125 * 1.125), 1px)` <small>(32px)</small> | <div style="font-size: var(--wa-font-size-2xl)">AaBb</div> |
| `--wa-font-size-3xl` | `round(calc(var(--wa-font-size-2xl) * 1.125 * 1.125), 1px)` <small>(41px)</small> | <div style="font-size: var(--wa-font-size-3xl)">AaBb</div> |
| `--wa-font-size-4xl` | `round(calc(var(--wa-font-size-3xl) * 1.125 * 1.125)` <small>(52px)</small> | <div style="font-size: var(--wa-font-size-4xl)">AaBb</div> |
You can also use these two custom properties make any font size proportionally smaller or larger to its parent.
| Custom Property | Default Value |
| ------------------------ | --------------------------------------- |
| `--wa-font-size-smaller` | `round(calc(1em / 1.125), 1px)` |
| `--wa-font-size-larger` | `round(calc(1em * 1.125 * 1.125), 1px)` |
## Font Weight

View File

@@ -108,11 +108,11 @@ For example, a button's default slot is used to populate its label.
<wa-button>Click me</wa-button>
```
Some components also have _named_ slots. A named slot can be populated by adding a child element with the appropriate `slot` attribute. Notice how the icon below has the `slot="prefix"` attribute? This tells the component to place the icon into its `prefix` slot.
Some components also have _named_ slots. A named slot can be populated by adding a child element with the appropriate `slot` attribute. Notice how the icon below has the `slot="start"` attribute? This tells the component to place the icon into its `start` slot.
```html
<wa-button>
<wa-icon slot="prefix" name="gear" variant="solid"></wa-icon>
<wa-icon slot="start" name="gear" variant="solid"></wa-icon>
Settings
</wa-button>
```

View File

@@ -7,11 +7,11 @@ file: styles/utilities/variants.css
Some Web Awesome components, like `<wa-button>`, allow you to change the color by using a `variant` attribute:
{% for component in componentsBy.attribute.variant %}
{% if component.fileSlug != "icon" or component.fileSlug != "icon-button" -%}
- <a href="../{{ component.url }}"><code>&lt;{{ component.tagName }}&gt;</code></a>
{%- endif %}
{%- endfor %}
- [`<wa-badge>`](/docs/components/badge)
- [`<wa-button>`](/docs/components/button)
- [`<wa-button-group>`](/docs/components/button-group)
- [`<wa-callout>`](/docs/components/callout)
- [`<wa-tag>`](/docs/components/tag)
You can create the same effect on any element by using the color variant utility classes:

View File

@@ -37,7 +37,7 @@ Flanks work especially well for asides, inputs with adjacent buttons, and rich d
```html {.example}
<div class="wa-flank:end wa-gap-xs">
<wa-input>
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
<wa-icon slot="start" name="magnifying-glass"></wa-icon>
</wa-input>
<wa-button>Search</wa-button>
</div>

View File

@@ -40,7 +40,9 @@ Frames are well-suited for images and image placeholders.
<h3>The Lord of the Rings: The Fellowship of the Ring</h3>
<span>J.R.R. Tolkien</span>
</div>
<wa-icon-button id="options-menu" name="ellipsis"></wa-icon-button>
<wa-button id="options-menu" appearance="plain">
<wa-icon name="ellipsis" label="Options"></wa-icon>
</wa-button>
<wa-tooltip for="options-menu">Options</wa-tooltip>
</div>
</div>
@@ -57,7 +59,9 @@ Frames are well-suited for images and image placeholders.
<span class="wa-body-s">Kitten &bull; Male</span>
<div class="wa-flank:end wa-gap-xs">
<wa-button size="small" appearance="filled" variant="brand">Adopt this pet</wa-button>
<wa-icon-button id="fav-whitesocks" name="heart" variant="regular"></wa-icon-button>
<wa-button id="fav-whitesocks" appearance="plain" size="small">
<wa-icon name="heart" variant="regular" label="Favorite"></wa-icon>
</wa-button>
<wa-tooltip for="fav-whitesocks">Favorite</wa-tooltip>
</div>
</div>
@@ -74,7 +78,9 @@ Frames are well-suited for images and image placeholders.
<span class="wa-body-s">Adult &bull; Male</span>
<div class="wa-flank:end wa-gap-xs">
<wa-button size="small" appearance="filled" variant="brand">Adopt this pet</wa-button>
<wa-icon-button id="fav-bumpkin" name="heart" variant="regular"></wa-icon-button>
<wa-button id="fav-bumpkin" appearance="plain" size="small">
<wa-icon name="heart" variant="regular" label="Favorite"></wa-icon>
</wa-button>
<wa-tooltip for="fav-bumpkin">Favorite</wa-tooltip>
</div>
</div>
@@ -88,7 +94,9 @@ Frames are well-suited for images and image placeholders.
<span class="wa-body-s">Kitten &bull; Female</span>
<div class="wa-flank:end wa-gap-xs">
<wa-button size="small" appearance="filled" variant="brand">Adopt this pet</wa-button>
<wa-icon-button id="fav-swishtail" name="heart" variant="regular"></wa-icon-button>
<wa-button id="fav-swishtail" appearance="plain" size="small">
<wa-icon name="heart" variant="regular" label="Favorite"></wa-icon>
</wa-button>
<wa-tooltip for="fav-swishtail">Favorite</wa-tooltip>
</div>
</div>
@@ -102,7 +110,9 @@ Frames are well-suited for images and image placeholders.
<span class="wa-body-s">Adult &bull; Female</span>
<div class="wa-flank:end wa-gap-xs">
<wa-button size="small" appearance="filled" variant="brand">Adopt this pet</wa-button>
<wa-icon-button id="fav-sharpears" name="heart" variant="regular"></wa-icon-button>
<wa-button id="fav-sharpears" appearance="plain" size="small">
<wa-icon name="heart" variant="regular" label="Favorite"></wa-icon>
</wa-button>
<wa-tooltip for="fav-sharpears">Favorite</wa-tooltip>
</div>
</div>

View File

@@ -77,16 +77,16 @@ Organized content in bulleted or numbered format with proper nesting support.
<ol>
<li>List item 1</li>
<li>List item 2
<ul>
<ol>
<li>Subitem a</li>
<li>Subitem b</li>
</ul>
</ol>
</li>
<li>List item 3</li>
</ol>
```
### Definition Lists
### Description Lists
Term and definition pairs for glossaries and descriptions.
@@ -141,19 +141,19 @@ Various text formatting elements for emphasis and semantic meaning.
```html {.example}
<div class="two-columns">
<p><strong>Bold</strong></p>
<p><em>Italics</em></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><s>Strike-through</s></p>
<p><small>Small</small></p>
<p><span>Text <sub>Sub</sub></span></p>
<p><span>Text <sup>Sup</sup></span></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><kbd>Keyboard</kbd></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>
```
@@ -161,11 +161,13 @@ Various text formatting elements for emphasis and semantic meaning.
Formatted code snippets with proper syntax styling.
```
```html {.example}
<pre>
// do a thing
export function thing() {
return true;
}
</pre>
```
### Images
@@ -454,3 +456,12 @@ Multi-line text input fields for longer content.
```html {.example}
<label>Textarea <textarea placeholder="Type something"></textarea></label>
```
### Fieldsets
```html {.example}
<fieldset>
<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.
</fieldset>
```

View File

@@ -36,13 +36,21 @@ Splits are especially helpful for navigation, header, and footer layouts.
<div class="wa-flank">
<div class="wa-split:column">
<div class="wa-stack">
<wa-icon-button name="house" label="Home"></wa-icon-button>
<wa-icon-button name="calendar" label="Calendar"></wa-icon-button>
<wa-icon-button name="envelope" label="Mail"></wa-icon-button>
<wa-button appearance="plain">
<wa-icon name="house" label="Home"></wa-icon>
</wa-button>
<wa-button appearance="plain">
<wa-icon name="calendar" label="Calendar"></wa-icon>
</wa-button>
<wa-button appearance="plain">
<wa-icon name="envelope" label="Mail"></wa-icon>
</wa-button>
</div>
<div class="wa-stack">
<wa-divider></wa-divider>
<wa-icon-button name="right-from-bracket" label="Sign Out"></wa-icon-button>
<wa-button appearance="plain">
<wa-icon name="right-from-bracket" label="Sign Out"></wa-icon>
</wa-button>
</div>
</div>
<div class="placeholder">

View File

@@ -36,10 +36,10 @@ Stacks are well suited for forms, text, and ensuring consistent spacing between
```html {.example}
<div class="wa-stack">
<wa-input label="Email">
<wa-icon slot="prefix" name="envelope" variant="regular"></wa-icon>
<wa-icon slot="start" name="envelope" variant="regular"></wa-icon>
</wa-input>
<wa-input label="Password" type="password">
<wa-icon slot="prefix" name="lock" variant="regular"></wa-icon>
<wa-icon slot="start" name="lock" variant="regular"></wa-icon>
</wa-input>
<wa-checkbox>Remember me on this device</wa-checkbox>
<wa-button>Log In</wa-button>

View File

@@ -216,14 +216,13 @@ layout: page
border-color: var(--wa-color-surface-border);
border-radius: 0.75rem;
color: var(--wa-color-text-normal);
display: block;
height: 100%;
line-height: var(--wa-line-height-normal);
padding: 1.25rem;
text-align: left;
white-space: wrap;
}
wa-button.tile::part(suffix) {
wa-button.tile::part(end) {
display: none;
}
wa-button.tile {
@@ -240,7 +239,7 @@ layout: page
font-weight: var(--wa-font-weight-normal);
}
&::part(label) {
width: 100%;
flex-direction: column;
}
}
wa-callout {
@@ -267,7 +266,7 @@ layout: page
<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="prefix" name="person-running"></wa-icon>
<wa-icon slot="start" name="person-running"></wa-icon>
Pre-order WA Pro
</wa-button>
</div>

View File

@@ -54,7 +54,7 @@
"test:component": "CSR_ONLY=\"true\" web-test-runner -- --watch --group",
"test:contrast": "cd src/styles/color && node contrast.test.js",
"test:watch": "web-test-runner --watch --group default",
"prettier": "prettier --check --log-level=warn --ignore-path=\"../../.prettierignore\".",
"prettier": "prettier --check --log-level=warn --ignore-path=\"../../.prettierignore\" .",
"prettier:fix": "prettier --write --log-level=warn --ignore-path=\"../../.prettierignore\" .",
"spellcheck": "cspell \"**/*.{js,ts,json,html,css,md}\" --no-progress --config=\"../../cspell.json\"",
"verify": "npm run prettier && npm run build && npm run test",

View File

@@ -1,32 +0,0 @@
#!/bin/bash
version=$1
# Check for a version number
if [ -z "$version" ]; then
echo "A version number must be provided as the first and only argument."
echo
exit 2
fi
echo "This command will build Web Awesome $version and publish it to the the CDN."
echo
read -p "🔥 Are you sure you want to do this? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
# do dangerous stuff
echo
echo "🚀 OK, blasting off..."
# build it
npm run build || { echo >&2 "❌ Something went wrong."; exit 1; }
# copy dist-cdn to the CDN
aws --profile early-webawesome-com --endpoint-url https://c0c64e1b38a89d8ae060d40170ceef46.r2.cloudflarestorage.com s3 cp ./dist-cdn s3://early-webawesome-com/webawesome@$version/dist --recursive || { echo >&2 "❌ Something went wrong."; exit 1; }
echo
echo "✅ All done. Now go make something awesome!"
echo
exit 0
fi

View File

@@ -8,19 +8,12 @@ import { replace } from 'esbuild-plugin-replace';
import { mkdir, readFile } from 'fs/promises';
import getPort, { portNumbers } from 'get-port';
import { globby } from 'globby';
import ora from 'ora';
import { dirname, join, relative } from 'node:path';
import process from 'node:process';
import copy from 'recursive-copy';
import { fileURLToPath } from 'node:url';
import {
getCdnDir,
getDistDir,
getDocsDir,
getRootDir,
getSiteDir,
runScript,
} from './utils.js';
import ora from 'ora';
import copy from 'recursive-copy';
import { getCdnDir, getDistDir, getDocsDir, getRootDir, getSiteDir, runScript } from './utils.js';
const __dirname = dirname(fileURLToPath(import.meta.url));
const isDeveloping = process.argv.includes('--develop');
@@ -42,19 +35,18 @@ let buildContexts = {
/**
* @param {BuildOptions} [options={}]
*/
export async function build (options = {}) {
export async function build(options = {}) {
if (!options.watchedSrcDirectories) {
options.watchedSrcDirectories = ['src']
options.watchedSrcDirectories = ['src'];
}
if (!options.watchedDocsDirectories) {
options.watchedDocsDirectories = [getDocsDir()]
options.watchedDocsDirectories = [getDocsDir()];
}
/**
* Runs the full build.
*/
* Runs the full build.
*/
async function buildAll() {
const start = Date.now();
@@ -92,8 +84,8 @@ export async function build (options = {}) {
}
/**
* Analyzes components and generates the custom elements manifest file.
*/
* Analyzes components and generates the custom elements manifest file.
*/
function generateManifest() {
spinner.start('Generating CEM');
@@ -113,14 +105,14 @@ export async function build (options = {}) {
}
/**
* Generates React wrappers for all components.
*/
* Generates React wrappers for all components.
*/
function generateReactWrappers() {
spinner.start('Generating React wrappers');
try {
// need to run make-react from this directories.
execSync(`node ${join(__dirname, "make-react.js")} --outdir "${getCdnDir()}"`, { stdio: 'inherit' });
execSync(`node ${join(__dirname, 'make-react.js')} --outdir "${getCdnDir()}"`, { stdio: 'inherit' });
} catch (error) {
console.error(`\n\n${error.message}`);
@@ -134,8 +126,8 @@ export async function build (options = {}) {
}
/**
* Copies theme stylesheets to the dist.
*/
* Copies theme stylesheets to the dist.
*/
async function generateStyles() {
spinner.start('Copying stylesheets');
@@ -147,23 +139,24 @@ export async function build (options = {}) {
}
/**
* Runs TypeScript to generate types.
*/
* Runs TypeScript to generate types.
*/
async function generateTypes() {
spinner.start('Running the TypeScript compiler');
const cwd = process.cwd()
const cwd = process.cwd();
try {
if (process.env.ROOT_DIR) {
process.chdir(process.env.ROOT_DIR)
process.chdir(process.env.ROOT_DIR);
}
execSync(`tsc --project ./tsconfig.prod.json --outdir "${getCdnDir()}"`);
process.chdir(cwd)
execSync(`tsc --project ./tsconfig.prod.json --outdir "${getCdnDir()}"`, { stdio: 'inherit' });
process.chdir(cwd);
} catch (error) {
process.chdir(cwd)
process.chdir(cwd);
if (!isDeveloping) {
process.exit(1);
}
return Promise.reject(error.stdout);
}
@@ -173,12 +166,12 @@ export async function build (options = {}) {
}
/**
* Runs esbuild to generate the final dist.
*/
* Runs esbuild to generate the final dist.
*/
async function generateBundle() {
spinner.start('Bundling with esbuild');
const rootDir = process.env.ROOT_DIR || "."
const rootDir = process.env.ROOT_DIR || '.';
// Bundled config
const config = {
format: 'esm',
@@ -246,8 +239,8 @@ export async function build (options = {}) {
}
/**
* Incrementally rebuilds the source files. Must be called only after `generateBundle()` has been called.
*/
* Incrementally rebuilds the source files. Must be called only after `generateBundle()` has been called.
*/
async function regenerateBundle() {
try {
spinner.start('Re-bundling with esbuild');
@@ -266,12 +259,12 @@ export async function build (options = {}) {
}
/**
* Generates the documentation site.
*/
* Generates the documentation site.
*/
async function generateDocs() {
/**
* Used by the webawesome-app to skip doc generation since it will do its own.
*/
* Used by the webawesome-app to skip doc generation since it will do its own.
*/
if (process.env.SKIP_ELEVENTY === 'true') {
return;
}
@@ -375,19 +368,19 @@ export async function build (options = {}) {
// TODO: Should probably listen for all of these instead of just "change"
const watchEvents = [
"change",
'change',
// "unlink",
// "add"
]
];
// Rebuild and reload when source files change
options.watchedSrcDirectories.forEach((dir) => {
const watcher = bs.watch(join(dir, "**", "!(*.test).*"))
options.watchedSrcDirectories.forEach(dir => {
const watcher = bs.watch(join(dir, '**', '!(*.test).*'));
watchEvents.forEach((evt) => {
watcher.on(evt, handleWatchEvent(evt))
})
function handleWatchEvent (evt) {
return async (filename) => {
watchEvents.forEach(evt => {
watcher.on(evt, handleWatchEvent(evt));
});
function handleWatchEvent(evt) {
return async filename => {
spinner.info(`File modified ${chalk.gray(`(${relative(getRootDir(), filename)})`)}`);
try {
@@ -401,8 +394,8 @@ export async function build (options = {}) {
return;
}
if (typeof options.onWatchEvent === "function") {
await options.onWatchEvent(evt, filename)
if (typeof options.onWatchEvent === 'function') {
await options.onWatchEvent(evt, filename);
}
await regenerateBundle();
@@ -427,29 +420,29 @@ export async function build (options = {}) {
process.exit(1);
}
}
}
};
}
})
});
// Rebuild the docs and reload when the docs change
options.watchedDocsDirectories.forEach((dir) => {
const watcher = bs.watch(join(dir, "**", "*.*"))
options.watchedDocsDirectories.forEach(dir => {
const watcher = bs.watch(join(dir, '**', '*.*'));
watchEvents.forEach((evt) => {
watcher.on(evt, handleWatchEvent(evt))
})
watchEvents.forEach(evt => {
watcher.on(evt, handleWatchEvent(evt));
});
function handleWatchEvent (evt) {
return async (filename) => {
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)
if (typeof options.onWatchEvent === 'function') {
await options.onWatchEvent(evt, filename);
}
await generateDocs();
reload();
}
};
}
})
});
}
//
@@ -468,22 +461,23 @@ export async function build (options = {}) {
process.on('SIGINT', terminate);
process.on('SIGTERM', terminate);
}
}
// https://exploringjs.com/nodejs-shell-scripting/ch_nodejs-path.html#detecting-if-module-is-main
// Detects if this was called via node scripts/build.js
function isRunAsMain () {
if (import.meta.url.startsWith('file:')) { // (A)
function isRunAsMain() {
if (import.meta.url.startsWith('file:')) {
// (A)
const modulePath = fileURLToPath(import.meta.url);
if (process.argv[1] === modulePath) { // (B)
return true
if (process.argv[1] === modulePath) {
// (B)
return true;
}
}
return false
return false;
}
if (isRunAsMain()) {
await build()
await build();
}

View File

@@ -1,11 +1,11 @@
import Eleventy from '@11ty/eleventy';
import { deleteAsync } from 'del';
import { join } from 'path';
import { getDocsDir, getSiteDir } from './utils.js';
import { getDocsDir, getEleventyConfigPath, getSiteDir } from './utils.js';
const elev = new Eleventy(getDocsDir(), getSiteDir(), {
quietMode: true,
configPath: join(getDocsDir(), '.eleventy.js'),
configPath: getEleventyConfigPath(),
});
// Cleanup
@@ -13,4 +13,3 @@ await deleteAsync(getSiteDir());
// Write it
await elev.write();

View File

@@ -8,8 +8,8 @@ import { getAllComponents } from './shared.js';
const { outdir } = commandLineArgs({ name: 'outdir', type: String });
const reactDir = path.join(process.env.ROOT_DIR || ".", 'src', 'react');
const srcDir = process.env.ROOT_DIR ? path.join(process.env.ROOT_DIR, "src") : "."
const reactDir = path.join(process.env.ROOT_DIR || '.', 'src', 'react');
const srcDir = process.env.ROOT_DIR ? path.join(process.env.ROOT_DIR, 'src') : '.';
// Clear build directory
deleteSync(reactDir);
@@ -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.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-')) || [];
@@ -81,4 +81,3 @@ for await (const component of components) {
// Generate the index file
fs.writeFileSync(path.join(reactDir, 'index.ts'), index.join('\n'), 'utf8');

View File

@@ -50,6 +50,12 @@ export default function (plop) {
path: '../../docs/docs/components/{{ tagWithoutPrefix tag }}.md',
templateFile: 'templates/component/docs.hbs',
},
{
type: 'modify',
path: '../../docs/_includes/sidebar.njk',
pattern: /\{# PLOP_NEW_COMPONENT_PLACEHOLDER #\}/,
template: `<li><a href="/docs/components/{{ tagWithoutPrefix tag }}">{{ tagToTitle tag }}</a></li>\n {# PLOP_NEW_COMPONENT_PLACEHOLDER #}`,
},
],
});
}

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