diff --git a/packages/webawesome/docs/assets/styles/utils.css b/packages/webawesome/docs/assets/styles/utils.css
index 52655e13d..b395fed00 100644
--- a/packages/webawesome/docs/assets/styles/utils.css
+++ b/packages/webawesome/docs/assets/styles/utils.css
@@ -111,7 +111,49 @@
}
/* #endregion */
- /* #region funsies */
+ /* #region funsies + cosmetics */
+
+ /* grid background */
+ .background-grid {
+ --grid-spacing: var(--wa-space-2xl);
+ --grid-line-color: color-mix(in oklab, var(--wa-color-text-normal), transparent 90%);
+ --grid-line-width: var(--wa-border-width-s);
+ --subgrid-spacing: calc(var(--grid-spacing) / 2);
+ --subgrid-line-color: color-mix(in oklab, var(--wa-color-text-normal), transparent 95%);
+ --subgrid-line-width: var(--wa-border-width-s);
+
+ background-image:
+ /* main grid - vertical lines */
+ linear-gradient(to right, var(--grid-line-color) var(--grid-line-width), transparent var(--grid-line-width)),
+ /* main grid - horizontal lines */
+ linear-gradient(to bottom, var(--grid-line-color) var(--grid-line-width), transparent var(--grid-line-width)),
+ /* sub-grid - vertical lines (offset by half the main grid spacing) */
+ linear-gradient(
+ to right,
+ var(--subgrid-line-color) var(--subgrid-line-width),
+ transparent var(--subgrid-line-width)
+ ),
+ /* sub-grid - horizontal lines (offset by half the main grid spacing) */
+ linear-gradient(
+ to bottom,
+ var(--subgrid-line-color) var(--subgrid-line-width),
+ transparent var(--subgrid-line-width)
+ );
+
+ background-size:
+ var(--grid-spacing) var(--grid-spacing),
+ var(--grid-spacing) var(--grid-spacing),
+ var(--subgrid-spacing) var(--subgrid-spacing),
+ var(--subgrid-spacing) var(--subgrid-spacing);
+
+ background-position:
+ 0 0,
+ 0 0,
+ calc(var(--grid-spacing) / 2) calc(var(--grid-spacing) / 2),
+ calc(var(--grid-spacing) / 2) calc(var(--grid-spacing) / 2);
+ }
+ /* #endregion */
+
/* buttons with icon toggle on hover */
wa-button .icon-hover {
display: none;
diff --git a/packages/webawesome/docs/docs/form-controls.md b/packages/webawesome/docs/docs/form-controls.md
index 0670b6582..dbc4320ba 100644
--- a/packages/webawesome/docs/docs/form-controls.md
+++ b/packages/webawesome/docs/docs/form-controls.md
@@ -52,7 +52,7 @@ To make a field required, use the `required` attribute. Required fields will aut
customElements.whenDefined('wa-input'),
customElements.whenDefined('wa-option'),
customElements.whenDefined('wa-select'),
- customElements.whenDefined('wa-textarea')
+ customElements.whenDefined('wa-textarea'),
]).then(() => {
form.addEventListener('submit', event => {
event.preventDefault();
@@ -78,10 +78,7 @@ To restrict a value to a specific [pattern](https://developer.mozilla.org/en-US/
const form = document.querySelector('.input-validation-pattern');
// Wait for controls to be defined before attaching form listeners
- await Promise.all([
- customElements.whenDefined('wa-button'),
- customElements.whenDefined('wa-input')
- ]).then(() => {
+ await Promise.all([customElements.whenDefined('wa-button'), customElements.whenDefined('wa-input')]).then(() => {
form.addEventListener('submit', event => {
event.preventDefault();
alert('All fields are valid!');
@@ -108,10 +105,7 @@ Some input types will automatically trigger constraints, such as `email` and `ur
const form = document.querySelector('.input-validation-type');
// Wait for controls to be defined before attaching form listeners
- await Promise.all([
- customElements.whenDefined('wa-button'),
- customElements.whenDefined('wa-input')
- ]).then(() => {
+ await Promise.all([customElements.whenDefined('wa-button'), customElements.whenDefined('wa-input')]).then(() => {
form.addEventListener('submit', event => {
event.preventDefault();
alert('All fields are valid!');
@@ -137,10 +131,7 @@ To create a custom validation error, pass a non-empty string to the `setCustomVa
const input = form.querySelector('wa-input');
// Wait for controls to be defined before attaching form listeners
- await Promise.all([
- customElements.whenDefined('wa-button'),
- customElements.whenDefined('wa-input')
- ]).then(() => {
+ await Promise.all([customElements.whenDefined('wa-button'), customElements.whenDefined('wa-input')]).then(() => {
form.addEventListener('submit', event => {
event.preventDefault();
alert('All fields are valid!');
@@ -163,17 +154,15 @@ Custom validation can be applied to any form control that supports the `setCusto
## Custom Validation Styles
-Due to the many ways form controls are used, Web Awesome doesn't provide out of the box validation styles for form controls as part of its default theme. Instead, the following attributes will be applied to reflect a control's validity as users interact with it. You can use them to create custom styles for any of the validation states you're interested in.
+Due to the many ways form controls are used, Web Awesome doesn't provide out of the box validation styles for form controls as part of its default theme.
-- `required` - the form control is required
-- `optional` - the form control is optional
-- `invalid` - the form control is invalid
-- `valid` - the form control is valid
-- `user-invalid` - the form control is invalid and the user has interacted with it
-- `user-valid` - the form control is valid and the user has interacted with it
+Instead, the following [custom states](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/states) will be applied to reflect a control's validity as users interact with it. You can use them to create custom styles for any of the validation states you're interested in.
-These attributes map to the browser's built-in pseudo classes for validation: [`:required`](https://developer.mozilla.org/en-US/docs/Web/CSS/:required), [`:optional`](https://developer.mozilla.org/en-US/docs/Web/CSS/:optional), [`:invalid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:invalid), [`:valid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:valid), [`:user-invalid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:user-invalid), and [`:user-valid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:user-valid).
+- `:state(required)` - the form control is required
+- `:state(optional)` - the form control is optional
+- `:state(invalid)` - the form control is invalid
+- `:state(valid)` - the form control is valid
+- `:state(user-invalid)` - the form control is invalid and the user has interacted with it
+- `:state(user-valid)` - the form control is valid and the user has interacted with it
-:::info
-In the future, data attribute selectors will be replaced with custom states such as `:state(valid)` and `:state(invalid)`. Web Awesome is using data attributes as a workaround until browsers fully support [custom states](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/states).
-:::
\ No newline at end of file
+These custom states work alongside the browser's built-in pseudo classes for validation: [`:required`](https://developer.mozilla.org/en-US/docs/Web/CSS/:required), [`:optional`](https://developer.mozilla.org/en-US/docs/Web/CSS/:optional), [`:invalid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:invalid), [`:valid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:valid), [`:user-invalid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:user-invalid), and [`:user-valid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:user-valid).
diff --git a/packages/webawesome/docs/docs/resources/changelog.md b/packages/webawesome/docs/docs/resources/changelog.md
index 63c1a5a7a..c5ae7264e 100644
--- a/packages/webawesome/docs/docs/resources/changelog.md
+++ b/packages/webawesome/docs/docs/resources/changelog.md
@@ -13,10 +13,14 @@ Components with the Experimental badge sh
## Next
- Added the Kazakh translation [pr:1496]
+- Added docs for code completion for VS Code and JetBrains [pr:1550]
+- Added back the missing `form-control-label` part to `` for consistency with other form controls [pr:1533]
- Fixed a bug in `` where slotted badges weren't properly positioned in buttons with an `href` [issue:1377]
- Fixed focus outline styles in `` and native `` [issue:1456]
- Fixed focus outline styles in ``, ``, and `` [issue:1484]
- Fixed a bug in `` where its value would revert to `""` when checked / unchecked [pr:1547]
+- Fixed a bug that caused icon button labels to not render in frameworks [issue:1542]
+- Fixed a bug in `` that caused the `name` property not to reflect [pr:1538]
## 3.0.0-beta.6
diff --git a/packages/webawesome/docs/docs/usage.md b/packages/webawesome/docs/docs/usage.md
index c7b96681f..b21fcc455 100644
--- a/packages/webawesome/docs/docs/usage.md
+++ b/packages/webawesome/docs/docs/usage.md
@@ -174,3 +174,54 @@ This time we see an empty string, which means the boolean attribute is now prese
:::info
To wait for multiple components to update, you can use `requestAnimationFrame()` instead of awaiting each element.
:::
+
+## Code Completion
+
+### VS Code
+
+Web Awesome ships with a file called `vscode.html-custom-data.json` that can be used to describe its custom elements to [Visual Studio Code](https://code.visualstudio.com/). This enables code completion for Web Awesome components (also known as “code hinting” or “IntelliSense”). To enable it, you need to tell VS Code where the file is.
+
+1. [Install Web Awesome locally](/docs/#installing-via-npm)
+2. If it doesn’t already exist, create a folder called `.vscode` at the root of your project
+3. If it doesn’t already exist, create a file inside that folder called `settings.json`
+4. Add the following to the file
+
+```json
+{
+ "html.customData": ["./node_modules/@awesome.me/webawesome/dist/vscode.html-custom-data.json"]
+}
+```
+
+If `settings.json` already exists, simply add the above line to the root of the object. Note that you may need to restart VS Code for the changes to take effect.
+
+If you are using WebAwesome through the [CDN](/docs/#quick-start-autoloading-via-cdn) you can manually [download the file]({% cdnUrl 'vscode.html-custom-data.json' %}]({% cdnUrl 'vscode.html-custom-data.json' %}) instead.
+
+### JetBrains IDEs
+If you are using a [JetBrains IDE](https://www.jetbrains.com/) and you are installing Web Awesome from NPM, the editor will automatically detect the web-types.json file from the package and you should immediately see component information in your editor.
+
+If you are installing from the CDN, you can [download a local copy]({% cdnUrl 'web-types.json' %}) and add it to the root of your project. Be sure to add a reference to the web-types.json file in your package.json in order for your editor to properly detect it.
+
+```json
+{
+ ...
+ "web-types": "./web-types.json"
+ ...
+}
+```
+
+If you are using types from multiple projects, you can add an array of references.
+
+```json
+{
+ ...
+ "web-types": [
+ ...,
+ "./web-types.json"
+ ]
+ ...
+}
+```
+
+### Other Editors
+
+Most popular editors support custom code completion with a bit of configuration. Please [submit a feature request](https://github.com/shoelace-style/webawesome/issues/new/choose) for your editor of choice. PRs are also welcome!
diff --git a/packages/webawesome/scripts/build.js b/packages/webawesome/scripts/build.js
index 8add5c444..f9c6112ef 100644
--- a/packages/webawesome/scripts/build.js
+++ b/packages/webawesome/scripts/build.js
@@ -18,6 +18,7 @@ import { getCdnDir, getDistDir, getDocsDir, getRootDir, getSiteDir } from './uti
const __dirname = dirname(fileURLToPath(import.meta.url));
+const currentYear = new Date().getFullYear();
const spinner = ora({ text: 'Web Awesome', color: 'cyan' }).start();
const getPackageData = async () => JSON.parse(await readFile(join(getRootDir(), 'package.json'), 'utf-8'));
const getVersion = async () => JSON.stringify((await getPackageData()).version.toString());
@@ -225,6 +226,9 @@ export async function build(options = {}) {
bundle: true,
splitting: true,
minify: false,
+ banner: {
+ js: `/*! Copyright ${currentYear} Fonticons, Inc. - https://webawesome.com/license */`,
+ },
plugins: [replace({ __WEBAWESOME_VERSION__: await getVersion() })],
loader: {
'.css': 'text',
diff --git a/packages/webawesome/src/components/button/button.ts b/packages/webawesome/src/components/button/button.ts
index 4923d12db..4fa26436b 100644
--- a/packages/webawesome/src/components/button/button.ts
+++ b/packages/webawesome/src/components/button/button.ts
@@ -11,6 +11,7 @@ import sizeStyles from '../../styles/utilities/size.css';
import variantStyles from '../../styles/utilities/variants.css';
import { LocalizeController } from '../../utilities/localize.js';
import '../icon/icon.js';
+import type WaIcon from '../icon/icon.js';
import '../spinner/spinner.js';
import styles from './button.css';
@@ -179,9 +180,9 @@ export default class WaButton extends WebAwesomeFormAssociatedElement {
// If there's only an icon and no text, it's an icon button
[...nodes].forEach(node => {
- if (node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).localName === 'wa-icon') {
+ if (node.nodeType === Node.ELEMENT_NODE && (node as WaIcon).localName === 'wa-icon') {
hasIcon = true;
- if (!hasIconLabel) hasIconLabel = (node as HTMLElement).hasAttribute('label');
+ if (!hasIconLabel) hasIconLabel = (node as WaIcon).label !== undefined;
}
// Concatenate text nodes
diff --git a/packages/webawesome/src/components/details/details.test.ts b/packages/webawesome/src/components/details/details.test.ts
index 75bba1a17..45b9f058f 100644
--- a/packages/webawesome/src/components/details/details.test.ts
+++ b/packages/webawesome/src/components/details/details.test.ts
@@ -24,6 +24,13 @@ describe('', () => {
});
});
+ it('should reflect the name property', async () => {
+ const el = await fixture(html``);
+ el.name = 'test';
+ await el.updateComplete;
+ expect(el.getAttribute('name')).to.equal('test');
+ });
+
it('should be visible with the open attribute', async () => {
const el = await fixture(html`
diff --git a/packages/webawesome/src/components/details/details.ts b/packages/webawesome/src/components/details/details.ts
index 13ad982cf..3b1799d82 100644
--- a/packages/webawesome/src/components/details/details.ts
+++ b/packages/webawesome/src/components/details/details.ts
@@ -70,7 +70,7 @@ export default class WaDetails extends WebAwesomeElement {
@property() summary: string;
/** Groups related details elements. When one opens, others with the same name will close. */
- @property() name: string;
+ @property({ reflect: true }) name: string;
/** Disables the details so it can't be toggled. */
@property({ type: Boolean, reflect: true }) disabled = false;
diff --git a/packages/webawesome/src/components/radio/radio.ts b/packages/webawesome/src/components/radio/radio.ts
index 6b79faa21..3898b3b20 100644
--- a/packages/webawesome/src/components/radio/radio.ts
+++ b/packages/webawesome/src/components/radio/radio.ts
@@ -47,7 +47,7 @@ export default class WaRadio extends WebAwesomeFormAssociatedElement {
/** The radio's value. When selected, the radio group will receive this value. */
@property({ reflect: true }) value: string;
- /** The radio's value. When selected, the radio group will receive this value. */
+ /** The radio's visual appearance. */
@property({ reflect: true }) appearance: 'default' | 'button' = 'default';
/**
diff --git a/packages/webawesome/src/components/textarea/textarea.ts b/packages/webawesome/src/components/textarea/textarea.ts
index 61b6e856b..1b3626bac 100644
--- a/packages/webawesome/src/components/textarea/textarea.ts
+++ b/packages/webawesome/src/components/textarea/textarea.ts
@@ -338,7 +338,7 @@ export default class WaTextarea extends WebAwesomeFormAssociatedElement {
const hasHint = this.hint ? true : !!hasHintSlot;
return html`
-