Compare commits

..

3 Commits

Author SHA1 Message Date
Lea Verou
4a7fd7964f Update callout.css 2024-12-11 17:35:01 -05:00
Lea Verou
5a683300b2 Convert viewport-demo and callout styles 2024-12-11 16:56:49 -05:00
Lea Verou
20321f84d9 Start integrating esbuild-plugin-lit-css 2024-12-11 16:56:01 -05:00
545 changed files with 16607 additions and 13829 deletions

10
.eslintignore Normal file
View File

@@ -0,0 +1,10 @@
.cache
docs/dist
docs/search.json
docs/**/*.min.js
dist
examples
node_modules
src/react
scripts

213
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,213 @@
/* eslint-env node */
module.exports = {
plugins: [
'@typescript-eslint',
'wc',
'lit',
'lit-a11y',
'chai-expect',
'chai-friendly',
'import',
'sort-imports-es6-autofix'
],
extends: [
'eslint:recommended',
'plugin:wc/recommended',
'plugin:wc/best-practice',
'plugin:lit/recommended',
'plugin:lit-a11y/recommended'
],
env: {
es2021: true,
browser: true
},
parserOptions: {
sourceType: 'module'
},
overrides: [
{
extends: [
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking'
],
parser: '@typescript-eslint/parser',
parserOptions: {
sourceType: 'module',
project: './tsconfig.json',
tsconfigRootDir: __dirname
},
files: ['*.ts'],
rules: {
'default-param-last': 'off',
'@typescript-eslint/default-param-last': 'error',
'no-console': 'warn',
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': 'warn',
'no-implied-eval': 'off',
'no-invalid-this': 'off',
'no-shadow': 'off',
'no-throw-literal': 'off',
'no-unused-expressions': 'off',
'lit-a11y/no-autofocus': 'off',
'@typescript-eslint/no-implied-eval': 'error',
'@typescript-eslint/no-invalid-this': 'error',
'@typescript-eslint/no-throw-literal': 'error',
'@typescript-eslint/no-shadow': 'error',
'@typescript-eslint/prefer-regexp-exec': 'off',
'@typescript-eslint/no-unused-expressions': 'error',
'@typescript-eslint/unbound-method': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': [
'error',
{
checksVoidReturn: false
}
],
'@typescript-eslint/consistent-type-assertions': [
'warn',
{
assertionStyle: 'as',
objectLiteralTypeAssertions: 'never'
}
],
'@typescript-eslint/consistent-type-imports': 'warn',
'@typescript-eslint/no-base-to-string': 'error',
'@typescript-eslint/no-confusing-non-null-assertion': 'error',
'@typescript-eslint/no-invalid-void-type': 'error',
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn',
'@typescript-eslint/no-unnecessary-condition': 'off',
'@typescript-eslint/no-unnecessary-qualifier': 'warn',
'@typescript-eslint/non-nullable-type-assertion-style': 'warn',
'@typescript-eslint/prefer-for-of': 'warn',
'@typescript-eslint/prefer-optional-chain': 'warn',
'@typescript-eslint/prefer-ts-expect-error': 'warn',
'@typescript-eslint/prefer-return-this-type': 'error',
'@typescript-eslint/prefer-string-starts-ends-with': 'warn',
'@typescript-eslint/require-array-sort-compare': 'error',
'@typescript-eslint/unified-signatures': 'warn',
'@typescript-eslint/array-type': 'warn',
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
'@typescript-eslint/member-delimiter-style': 'warn',
'@typescript-eslint/method-signature-style': 'warn',
'@typescript-eslint/no-extraneous-class': 'error',
'@typescript-eslint/no-redundant-type-constituents': 'off',
'@typescript-eslint/parameter-properties': 'error',
'@typescript-eslint/strict-boolean-expressions': 'off'
}
},
{
files: ['**/*.cjs'],
env: {
node: true
}
},
{
extends: ['plugin:chai-expect/recommended', 'plugin:chai-friendly/recommended'],
files: ['*.test.ts'],
rules: {
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unused-expressions': 'off'
}
}
],
rules: {
'no-template-curly-in-string': 'error',
'array-callback-return': 'error',
'comma-dangle': 'off',
'consistent-return': 'error',
curly: 'off',
'default-param-last': 'error',
eqeqeq: 'error',
'lit-a11y/click-events-have-key-events': 'off',
'no-constructor-return': 'error',
'no-empty-function': 'warn',
'no-eval': 'error',
'no-extend-native': 'error',
'no-extra-bind': 'error',
'no-floating-decimal': 'error',
'no-implicit-coercion': 'off',
'no-implicit-globals': 'error',
'no-implied-eval': 'error',
'no-invalid-this': 'off',
'no-labels': 'error',
'no-lone-blocks': 'error',
'no-new': 'error',
'no-new-func': 'error',
'no-new-wrappers': 'error',
'no-octal-escape': 'error',
'no-proto': 'error',
'no-return-assign': 'warn',
'no-script-url': 'error',
'no-self-compare': 'warn',
'no-sequences': 'warn',
'no-throw-literal': 'error',
'no-unmodified-loop-condition': 'error',
'no-unused-expressions': 'warn',
'no-useless-call': 'error',
'no-useless-concat': 'error',
'no-useless-return': 'warn',
'prefer-promise-reject-errors': 'error',
radix: 'off',
'require-await': 'error',
'wrap-iife': ['warn', 'inside'],
'no-shadow': 'error',
'no-array-constructor': 'error',
'no-bitwise': 'error',
'no-multi-assign': 'warn',
'no-new-object': 'error',
'no-useless-computed-key': 'warn',
'no-useless-rename': 'warn',
'no-var': 'error',
'prefer-const': 'warn',
'prefer-numeric-literals': 'warn',
'prefer-object-spread': 'warn',
'prefer-rest-params': 'warn',
'prefer-spread': 'warn',
'prefer-template': 'off',
'no-else-return': 'off',
'func-names': ['warn', 'never'],
'one-var': ['warn', 'never'],
'operator-assignment': 'warn',
'prefer-arrow-callback': 'warn',
'no-restricted-imports': [
'warn',
{
paths: [
{
name: '.',
message: 'Usage of local index imports is not allowed.'
},
{
name: './index',
message: 'Import from the source file instead.'
}
]
}
],
'import/extensions': [
'error',
'always',
{
ignorePackages: true,
pattern: {
js: 'always',
ts: 'never'
}
}
],
'import/no-duplicates': 'warn',
'sort-imports-es6-autofix/sort-imports-es6': [
2,
{
ignoreCase: true,
ignoreMemberSort: false,
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single']
}
],
'wc/guard-super-call': 'off'
}
};

View File

@@ -29,7 +29,7 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run prettier
run: npm run prettier && npm run lint
- name: Build
run: npm run build
- name: Install Playwright

View File

@@ -27,7 +27,7 @@ jobs:
run: npm ci
# Just lint here too. Save some GH Action minutes and not need to use "depends_on" or anything.
- name: Lint
run: npm run prettier
run: npm run prettier && npm run lint
- name: Build
run: npm run build

View File

@@ -3,6 +3,7 @@
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"bierner.lit-html",
"bashmish.es6-string-css",
"streetsidesoftware.code-spell-checker"
]
}

View File

@@ -39,7 +39,6 @@
"crutchcorn",
"csspart",
"cssproperty",
"cssstate",
"datetime",
"describedby",
"Docsify",
@@ -47,7 +46,6 @@
"dropdowns",
"easings",
"ecommerce",
"endfor",
"endraw",
"endregion",
"enterkeyhint",
@@ -105,7 +103,6 @@
"metaframeworks",
"middlewares",
"minlength",
"minmax",
"monospace",
"mousedown",
"mousemove",
@@ -158,19 +155,16 @@
"smartquotes",
"spacebar",
"stylesheet",
"svgs",
"Tabbable",
"tabindex",
"tabler",
"tablist",
"tabpanel",
"tbody",
"templating",
"tera",
"testid",
"textareas",
"textfield",
"thead",
"Themer",
"tinycolor",
"transitionend",

View File

@@ -2,8 +2,8 @@ import { customElementJetBrainsPlugin } from 'custom-element-jet-brains-integrat
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 { pascalCase } from 'pascal-case';
import fs from 'fs';
const packageData = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
const { name, description, version, author, homepage, license } = packageData;
@@ -28,7 +28,7 @@ export default {
name: 'wa-package-data',
packageLinkPhase({ customElementsManifest }) {
customElementsManifest.package = { name, description, version, author, homepage, license };
},
}
},
// Parse custom jsDoc tags
@@ -83,13 +83,13 @@ export default {
classDoc[t.tag].push({
name: t.name,
description: t.description,
type: t.type || undefined,
type: t.type || undefined
});
}
});
}
}
},
}
},
{
@@ -109,7 +109,7 @@ export default {
}
}
}
},
}
},
{
@@ -127,7 +127,7 @@ export default {
//
const terms = [
{ from: /^src\//, to: '' }, // Strip the src/ prefix
{ from: /\.(t|j)sx?$/, to: '.js' }, // Convert .ts to .js
{ from: /\.(t|j)sx?$/, to: '.js' } // Convert .ts to .js
];
mod.path = replace(mod.path, terms);
@@ -146,7 +146,7 @@ export default {
}
}
});
},
}
},
// Generate custom VS Code data
@@ -156,9 +156,9 @@ export default {
referencesTemplate: (_, tag) => [
{
name: 'Documentation',
url: `https://webawesome.com/docs/components/${tag.replace('wa-', '')}`,
},
],
url: `https://webawesome.com/docs/components/${tag.replace('wa-', '')}`
}
]
}),
customElementJetBrainsPlugin({
@@ -168,10 +168,10 @@ export default {
referencesTemplate: (_, tag) => {
return {
name: 'Documentation',
url: `https://webawesome.com/docs/components/${tag.replace('wa-', '')}`,
url: `https://webawesome.com/docs/components/${tag.replace('wa-', '')}`
};
},
}),
}
})
//
// TODO - figure out why this broke when events were updated
@@ -181,5 +181,5 @@ export default {
// fileName: 'index.d.ts',
// componentTypePath: (_, tag) => `../../components/${tag.replace('wa-', '')}/${tag.replace('wa-', '')}.js`
// })
],
]
};

View File

@@ -1,24 +1,24 @@
import { parse } from 'path';
import { markdown } from './_utils/markdown.js';
import { anchorHeadingsPlugin } from './_utils/anchor-headings.js';
import { codeExamplesPlugin } from './_utils/code-examples.js';
import { copyCodePlugin } from './_utils/copy-code.js';
import { removeDataAlphaElements } from './_utils/remove-data-alpha-elements.js';
import { currentLink } from './_utils/current-link.js';
import { highlightCodePlugin } from './_utils/highlight-code.js';
import { markdown } from './_utils/markdown.js';
import { removeDataAlphaElements } from './_utils/remove-data-alpha-elements.js';
// import { formatCodePlugin } from './_utils/format-code.js';
import litPlugin from '@lit-labs/eleventy-plugin-lit';
import { readFile } from 'fs/promises';
import componentList from './_data/componentList.js';
import * as filters from './_utils/filters.js';
import { outlinePlugin } from './_utils/outline.js';
import { replaceTextPlugin } from './_utils/replace-text.js';
import { searchPlugin } from './_utils/search.js';
import { readFile } from 'fs/promises';
import { outlinePlugin } from './_utils/outline.js';
import componentList from './_data/componentList.js';
import litPlugin from '@lit-labs/eleventy-plugin-lit';
import process from 'process';
const packageData = JSON.parse(await readFile('./package.json', 'utf-8'));
const isAlpha = process.argv.includes('--alpha');
const isDev = process.argv.includes('--develop');
// const isDeveloping = process.argv.includes('--develop');
export default function (eleventyConfig) {
// NOTE - alpha setting removes certain pages
@@ -38,10 +38,14 @@ export default function (eleventyConfig) {
// Template filters - {{ content | filter }}
eleventyConfig.addFilter('inlineMarkdown', content => markdown.renderInline(content || ''));
eleventyConfig.addFilter('markdown', content => markdown.render(content || ''));
for (let name in filters) {
eleventyConfig.addFilter(name, filters[name]);
}
eleventyConfig.addFilter('stripExtension', string => parse(string).name);
eleventyConfig.addFilter('stripPrefix', content => content.replace(/^wa-/, ''));
eleventyConfig.addFilter('trimPipes', content => {
// Trims whitespace and pipes from the start and end of a string. Useful for CEM types, which can be pipe-delimited.
// With Prettier 3, this means a leading pipe will exist be present when the line wraps.
return typeof content === 'string' ? content.replace(/^(\s|\|)/g, '').replace(/(\s|\|)$/g, '') : content;
});
eleventyConfig.addFilter('keys', obj => Object.keys(obj));
// Shortcodes - {% shortCode arg1, arg2 %}
eleventyConfig.addShortcode('cdnUrl', location => {
@@ -67,8 +71,8 @@ export default function (eleventyConfig) {
selector: 'h2, h3',
ifEmpty: doc => {
doc.querySelector('#outline')?.remove();
},
}),
}
})
);
// Add current link classes
@@ -89,58 +93,54 @@ export default function (eleventyConfig) {
// Replace [issue:1234] with a link to the issue on GitHub
{
replace: /\[pr:([0-9]+)\]/gs,
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/pull/$1">#$1</a>',
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/pull/$1">#$1</a>'
},
// Replace [pr:1234] with a link to the pull request on GitHub
{
replace: /\[issue:([0-9]+)\]/gs,
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/issues/$1">#$1</a>',
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/issues/$1">#$1</a>'
},
// Replace [discuss:1234] with a link to the discussion on GitHub
{
replace: /\[discuss:([0-9]+)\]/gs,
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/discussions/$1">#$1</a>',
},
]),
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/discussions/$1">#$1</a>'
}
])
);
// SSR plugin
if (!isDev) {
//
// Problematic components in SSR land:
// - animation (breaks on navigation + ssr with Turbo)
// - mutation-observer (why SSR this?)
// - resize-observer (why SSR this?)
// - tooltip (why SSR this?)
//
const omittedModules = [];
const componentModules = componentList
.filter(component => !omittedModules.includes(component.tagName.split(/wa-/)[1]))
.map(component => {
const name = component.tagName.split(/wa-/)[1];
return `./dist/components/${name}/${name}.js`;
});
const omittedModules = [];
eleventyConfig.addPlugin(litPlugin, {
mode: 'worker',
componentModules,
// problematic components:
// animation (breaks on navigation + ssr with Turbo)
// mutation-observer (why SSR this?)
// resize-observer (why SSR this?)
// tooltip (why SSR this?)
const componentModules = componentList
// .filter(component => !omittedModules.includes(component.tagName.split(/wa-/)[1]))
.map(component => {
const name = component.tagName.split(/wa-/)[1];
return `./dist/components/${name}/${name}.js`;
});
}
eleventyConfig.addPlugin(litPlugin, {
mode: 'worker',
componentModules
});
// Build the search index
eleventyConfig.addPlugin(
searchPlugin({
filename: '',
selectorsToIgnore: ['code.example'],
getContent: doc => doc.querySelector('#content')?.textContent ?? '',
}),
getContent: doc => doc.querySelector('#content')?.textContent ?? ''
})
);
// Production-only plugins
//
// TODO - disabled because it takes about a minute to run now
//
// if (!isDev) {
// if (!isDeveloping) {
// // Run Prettier on each file (prod only because it can be slow)
// eleventyConfig.addPlugin(formatCodePlugin());
// }
@@ -149,8 +149,8 @@ export default function (eleventyConfig) {
markdownTemplateEngine: 'njk',
dir: {
includes: '_includes',
layouts: '_layouts',
layouts: '_layouts'
},
templateFormats: ['njk', 'md'],
templateFormats: ['njk', 'md']
};
}

View File

@@ -1,9 +1,9 @@
/**
* @module components Fetches components from custom-elements.json and exposes them in a saner format.
*/
import { readFileSync } from 'fs';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
import { readFileSync } from 'fs';
const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -36,7 +36,7 @@ const components = manifest.modules.flatMap(module => {
slug: declaration.tagName.replace(/^wa-/, ''),
methods,
attributes,
properties,
properties
};
});
});

View File

@@ -6,7 +6,7 @@ const by = {
event: {},
method: {},
cssPart: {},
cssProperty: {},
cssProperty: {}
};
function getAll(component, type) {

View File

@@ -22,10 +22,10 @@
{# Web Awesome #}
<script type="module" src="/dist/webawesome.loader.js"></script>
<link rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/default.css" />
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/color/standard.css" />
<link rel="stylesheet" href="/dist/styles/forms.css" />
<link rel="stylesheet" id="theme-stylesheet" href="/dist/themes/default.css" />
<link rel="stylesheet" href="/dist/themes/applied.css" />
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/color_standard.css" />
<link rel="stylesheet" href="/dist/themes/forms.css" />
{# Docs styles #}
<link rel="stylesheet" href="/assets/styles/docs.css" />
@@ -43,7 +43,7 @@
<wa-page>
<header slot="header">
{# Nav toggle #}
<wa-button appearance="plain" data-toggle-nav>
<wa-button variant="text" data-toggle-nav>
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
</wa-button>

View File

@@ -31,10 +31,11 @@
{# Web Awesome #}
<script type="module" src="/dist/webawesome.ssr-loader.js"></script>
<link rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/default.css" />
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/utilities.css" />
<link rel="stylesheet" href="/dist/styles/forms.css" />
<link rel="stylesheet" id="theme-stylesheet" href="/dist/themes/default.css" />
<link rel="stylesheet" href="/dist/themes/applied.css" />
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/layout.css" />
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/utilities.css" />
<link rel="stylesheet" href="/dist/themes/forms.css" />
{# Docs styles #}
<link rel="stylesheet" href="/assets/styles/docs.css" />
@@ -62,7 +63,7 @@
const newStylesheet = document.createElement("link")
let preset = getPresetTheme()
newStylesheet.href = `/dist/styles/themes/${preset}.css`
newStylesheet.href = `/dist/themes/${preset}.css`
newStylesheet.rel = "preload"
newStylesheet.as = "style"
@@ -89,16 +90,16 @@
{# Logo #}
<div id="docs-branding">
{# Nav toggle #}
<wa-button appearance="plain" size="small" data-toggle-nav>
<wa-button appearance="text" size="small" data-toggle-nav>
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
</wa-button>
<a href="/" aria-label="Web Awesome">
<span class="wa-desktop-only">{% include "logo.njk" %}</span>
<span class="wa-mobile-only">{% include "logo-simple.njk" %}</span>
<span class="only-desktop">{% include "logo.njk" %}</span>
<span class="only-mobile">{% include "logo-simple.njk" %}</span>
</a>
<small id="version-number" class="only-desktop">{{ package.version }}</small>
<wa-badge variant="warning" appearance="filled" class="only-desktop">Alpha</wa-badge>
<wa-badge variant="warning" class="only-desktop">Alpha</wa-badge>
</div>
<div id="docs-toolbar">
@@ -120,7 +121,7 @@
{# Sidebar #}
{% if hasSidebar %}
{# Mobile selectors #}
<div class="wa-mobile-only" slot="navigation-header">
<div class="only-mobile" slot="navigation-header">
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));">
{% include "preset-theme-selector.njk" %}
{% include "color-scheme-selector.njk" %}
@@ -149,17 +150,6 @@
</details>
</nav>
{% set breadcrumbs = page.url | breadcrumbs %}
{% if breadcrumbs.length > 0 %}
<wa-breadcrumb id="docs-breadcrumbs">
{% for crumb in breadcrumbs %}
<wa-breadcrumb-item href="{{ crumb.url }}">{{ crumb.title }}</wa-breadcrumb-item>
{% endfor %}
<wa-breadcrumb-item>{# Current page #}</wa-breadcrumb-item>
</wa-breadcrumb>
{% else %}
{% endif %}
{% block beforeContent %}{% endblock %}
{% block content %}

View File

@@ -1,6 +1,6 @@
{# Color scheme selector #}
<wa-dropdown id="color-scheme-selector">
<wa-button slot="trigger" appearance="filled" size="small" pill caret title="Press \ to toggle">
<wa-button slot="trigger" appearance="tinted" size="small" pill caret 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>
<span class="only-light">Light</span>

View File

@@ -1,13 +0,0 @@
{# Cards for pages listed by category #}
<section id="grid" class="index-grid">
{% for category, pages in allPages | groupByTags(categories) -%}
<h2 class="index-category">{{ category | getCategoryTitle(categories) }}</h2>
{%- for page in pages -%}
{%- if not page.data.unlisted and not page.data.parent -%}
{% include "page-card.njk" %}
{%- endif -%}
{%- endfor -%}
{%- endfor -%}
</section>

View File

@@ -1,8 +0,0 @@
<a href="{{ page.url }}" data-keywords="{{ page.data.keywords }}">
<wa-card with-header>
<div slot="header">
{% include "svgs/" + (page.data.icon or "thumbnail-placeholder") + ".njk" %}
</div>
<span class="page-name">{{ page.data.title }}</span>
</wa-card>
</a>

View File

@@ -16,11 +16,7 @@
</div>
</fieldset>
<wa-viewport-demo viewport="1000">
<iframe srcdoc="" id="page_slots_iframe"></iframe>
<iframe srcdoc="" id="page_slots_iframe" data-turbo="false" data-turbo-temporary></iframe>
</wa-viewport-demo>
</div>
<script type="module">
const cacheBust = new Date().toString()
import(`/assets/examples/page-demo/demo.js?${cacheBust}`)
</script>
<script type=module src="/assets/examples/page-demo/demo.js"></script>

View File

@@ -1,6 +1,6 @@
{# Preset theme selector #}
<wa-dropdown id="preset-theme-selector">
<wa-button slot="trigger" appearance="filled" size="small" pill caret>
<wa-button slot="trigger" appearance="tinted" size="small" pill caret>
<wa-icon slot="prefix" name="paintbrush" variant="regular"></wa-icon>
<span id="preset-theme-selector__text">Default</span>
</wa-button>

View File

@@ -6,7 +6,7 @@
<wa-input
id="site-search-input"
type="search"
appearance="filled"
filled
size="large"
clearable
placeholder="Search"

View File

@@ -20,85 +20,234 @@
</ul>
{# Components #}
<wa-details {{ 'open' if '/components/' in page.url }}>
<h2 slot=summary>
<a href="/docs/components/" title="Overview">Components
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
{% for component in collections.components | sort %}
{% if not component.data.parent and not (isAlpha and component.data.noAlpha) and not component.data.unlisted %}
<li>
<a href="/docs/components/{{ component.fileSlug }}">{{ component.data.title }}</a>
{% if components[component.fileSlug].status == 'experimental' %}<wa-icon name="flask"></wa-icon>{% endif %}
{% if component.data.isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
<ul>
{% for child in collections.components | sort %}
{% if child.data.parent == component.fileSlug and not (isAlpha and child.data.noAlpha) %}
<li>
<a href="/docs/components/{{ child.fileSlug }}">{{ child.data.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
</wa-details>
<wa-details {{ 'open' if '/native/' in page.url }}>
<h2 slot=summary>
<a href="/docs/native/" title="Overview">Native Styles
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
{% for page in collections.native | sort %}
{% if page.fileSlug != 'native' and not page.unlisted %}
<li>
<a href="/docs/native/{{ page.fileSlug }}">{{ page.data.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</wa-details>
<wa-details {{ 'open' if '/utilities/' in page.url }}>
<h2 slot=summary>
<a href="/docs/utilities/" title="Overview">Style Utilities
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
{% for page in collections.utilities | sort %}
{% if page.fileSlug != 'utilities' and not page.unlisted %}
<li>
<a href="/docs/utilities/{{ page.fileSlug }}">{{ page.data.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</wa-details>
<h2>
<a href="/docs/components/" title="Overview">Components
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
<li>
<a href="/docs/components/animated-image">Animated Image</a>
</li>
<li>
<a href="/docs/components/animation">Animation</a>
</li>
<li>
<a href="/docs/components/avatar">Avatar</a>
</li>
<li>
<a href="/docs/components/badge">Badge</a>
</li>
<li>
<a href="/docs/components/breadcrumb">Breadcrumb</a>
<ul>
<li>
<a href="/docs/components/breadcrumb-item">Breadcrumb Item</a>
</li>
</ul>
</li>
<li>
<a href="/docs/components/button">Button</a>
</li>
<li>
<a href="/docs/components/button-group">Button Group</a>
</li>
<li>
<a href="/docs/components/callout">Callout</a>
</li>
<li>
<a href="/docs/components/card">Card</a>
</li>
<li>
<a href="/docs/components/carousel">Carousel</a>
<ul>
<li>
<a href="/docs/components/carousel-item">Carousel Item</a>
</li>
</ul>
</li>
<li>
<a href="/docs/components/checkbox">Checkbox</a>
</li>
{% if not isAlpha %}
<li>
<a href="/docs/components/code-demo">Code Demo</a>
</li>
{% endif %}
<li>
<a href="/docs/components/color-picker">Color Picker</a>
</li>
<li>
<a href="/docs/components/copy-button">Copy Button</a>
</li>
<li>
<a href="/docs/components/details">Details</a>
</li>
<li>
<a href="/docs/components/dialog">Dialog</a>
</li>
<li>
<a href="/docs/components/divider">Divider</a>
</li>
<li>
<a href="/docs/components/drawer">Drawer</a>
</li>
<li>
<a href="/docs/components/dropdown">Dropdown</a>
</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/image-comparer">Image Comparer</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/page">Page</a>
<wa-icon name="flask"></wa-icon>
<wa-badge class="pro">PRO</wa-badge>
</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>
<li>
<a href="/docs/components/qr-code">QR Code</a>
</li>
<li>
<a href="/docs/components/radio-group">Radio Group</a>
<ul>
<li>
<a href="/docs/components/radio">Radio</a>
</li>
<li>
<a href="/docs/components/radio-button">Radio Button</a>
</li>
</ul>
</li>
<li>
<a href="/docs/components/range">Range</a>
</li>
<li>
<a href="/docs/components/rating">Rating</a>
</li>
<li>
<a href="/docs/components/relative-time">Relative Time</a>
</li>
<li>
<a href="/docs/components/resize-observer">Resize Observer</a>
</li>
<li>
<a href="/docs/components/select">Select</a>
<ul>
<li>
<a href="/docs/components/option">Option</a>
</li>
</ul>
</li>
<li>
<a href="/docs/components/skeleton">Skeleton</a>
</li>
<li>
<a href="/docs/components/spinner">Spinner</a>
</li>
<li>
<a href="/docs/components/split-panel">Split Panel</a>
</li>
<li>
<a href="/docs/components/switch">Switch</a>
</li>
<li>
<a href="/docs/components/tab-group">Tab Group</a>
<ul>
<li>
<a href="/docs/components/tab">Tab</a>
</li>
<li>
<a href="/docs/components/tab-panel">Tab Panel</a>
</li>
</ul>
</li>
<li>
<a href="/docs/components/tag">Tag</a>
</li>
<li>
<a href="/docs/components/textarea">Textarea</a>
</li>
<li>
<a href="/docs/components/tooltip">Tooltip</a>
</li>
<li>
<a href="/docs/components/tree">Tree</a>
<ul>
<li>
<a href="/docs/components/tree-item">Tree Item</a>
</li>
</ul>
</li>
{% if not isAlpha %}
<li>
<a href="/docs/components/viewport-demo">Viewport Demo</a>
</li>
{% endif %}
<li>
<a href="/docs/components/visually-hidden">Visually Hidden</a>
</li>
</ul>
{# Layout #}
{% if not isAlpha %}
<h2>
<a href="/docs/layout" title="Overview">Layout
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
{% for page in collections.layout | sort %}
{% if page.fileSlug != 'layout' and not page.unlisted %}
<li>
<a href="{{ page.url }}">{{ page.data.title }}</a>
</li>
{% endif %}
{% endfor %}
<li><a href="/docs/components/page">Page</a></li>
<li><a href="/docs/layout/cluster">Cluster</a></li>
<li><a href="/docs/layout/flank">Flank</a></li>
<li><a href="/docs/layout/frame">Frame</a></li>
<li><a href="/docs/layout/grid">Grid</a></li>
<li><a href="/docs/layout/split">Split</a></li>
<li><a href="/docs/layout/stack">Stack</a></li>
</ul>
{% endif %}
{# Patterns #}
{% if not isAlpha %}
@@ -129,11 +278,39 @@
</a>
</h2>
<ul>
{% for page in collections.theming | sort %}
{% if page.fileSlug != 'theming' and not page.unlisted %}
<li>
<a href="/docs/theming/{{ page.fileSlug }}">{{ page.data.title }}</a>
</li>
{% endif %}
{% endfor %}
<li>
<a href="/docs/theming/color">Color</a>
</li>
<li>
<a href="/docs/theming/typography">Typography</a>
</li>
<li>
<a href="/docs/theming/space">Space</a>
</li>
<li>
<a href="/docs/theming/borders">Borders</a>
</li>
<li>
<a href="/docs/theming/focus">Focus</a>
</li>
<li>
<a href="/docs/theming/shadows">Shadows</a>
</li>
<li>
<a href="/docs/theming/transitions">Transitions</a>
</li>
<li>
<a href="/docs/theming/component-groups">Component Groups</a>
</li>
</ul>
{# Style Utilities #}
{% if not isAlpha %}
<h2>Style Utilities</h2>
<ul>
<li><a href="/docs/style-utilities/align-items">Align Items</a></li>
<li><a href="/docs/style-utilities/border-radius">Border Radius</a></li>
<li><a href="/docs/style-utilities/gap">Gap</a></li>
<li><a href="/docs/style-utilities/text">Text</a></li>
</ul>
{% endif %}

View File

@@ -1,25 +0,0 @@
{% if since -%}
<wa-badge variant="neutral">Since {{ since }}</wa-badge>
{%- endif %}
{% if status -%}
{%- if status == "wip" %}
<wa-badge variant="danger">
<wa-icon name="pickaxe"></wa-icon>
Work In Progress
</wa-badge>
{%- elif status == "experimental" -%}
<wa-badge variant="warning">
<wa-icon name="flask"></wa-icon>
Experimental
</wa-badge>
{%- elif status == "stable" -%}
<wa-badge variant="brand">Stable</wa-badge>
{%- else %}
<wa-badge>{{ status}}</wa-badge>
{%- endif %}
{%- endif %}
{% if isPro -%}
<wa-badge class="pro">PRO</wa-badge>
{%- endif %}

View File

@@ -21,9 +21,10 @@
{# Web Awesome #}
<script type="module" src="/dist/webawesome.ssr-loader.js"></script>
<link rel="stylesheet" id="theme-stylesheet" />
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/utilities.css" />
<link rel="stylesheet" href="/dist/styles/forms.css" />
<link rel="stylesheet" href="/dist/themes/applied.css" />
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/layout.css" />
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/utilities.css" />
<link rel="stylesheet" href="/dist/themes/forms.css" />
{# Set the theme to prevent flashing #}
<script>
@@ -46,7 +47,7 @@
const stylesheet = document.getElementById("theme-stylesheet")
let preset = getPresetTheme()
stylesheet.href = `/dist/styles/themes/${preset}.css`
stylesheet.href = `/dist/themes/${preset}.css`
document.documentElement.classList.toggle(
`wa-theme-${preset}-dark`,

View File

@@ -2,8 +2,6 @@
{% set hasOutline = true %}
{% set component = components[page.fileSlug] %}
{% set description = component.summary %}
{% set status = component.status %}
{% set since = component.since %}
{% extends '../_includes/base.njk' %}
@@ -11,20 +9,22 @@
{% block beforeContent %}
<h1 class="title">{{ title }}</h1>
<div class="component-info">
<code class="tag">&lt;{{ component.tagName }}&gt;</code>
{% include '../_includes/status.njk' %}
<code class="component-tag">&lt;{{ component.tagName }}&gt;</code>
<wa-badge variant="neutral">Since {{ component.since }}</wa-badge>
<wa-badge
{% if component.status == 'stable' %}variant="brand"{% endif %}
{% if component.status == 'experimental' %}variant="warning"{% endif %}
>
{{ component.status }}
</wa-badge>
{# TODO - add a pro flag for pro components #}
{% if component.tagName == 'wa-page' %}
<wa-badge class="pro">PRO</wa-badge>
{% endif %}
</div>
<p class="summary">
<p class="component-summary">
{{ component.summary | inlineMarkdown | safe }}
</p>
{% if native %}
<wa-callout variant="success">
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
Just want the styles?
Check out the <a href="/docs/native/{{ native }}/">{{ ('/docs/native/' + native + '/') | getTitleFromUrl }} native styles</a>!
</wa-callout>
{% endif %}
{% endblock %}
{# Content #}
@@ -37,7 +37,6 @@
{# Slots #}
{% if component.slots.length %}
<h2>Slots</h2>
<p>Learn more about <a href="/docs/usage/#slots">using slots</a>.</p>
<div class="table-scroll">
<table class="component-table">
@@ -68,7 +67,6 @@
{# Properties #}
{% if component.properties.length %}
<h2>Attributes & Properties</h2>
<p>Learn more about <a href="/docs/usage/#attributes-and-properties">attributes and properties</a>.</p>
<div class="table-scroll">
<table class="component-table">
@@ -115,8 +113,6 @@
{# Methods #}
{% if component.methods.length %}
<h2>Methods</h2>
<p>Learn more about <a href="/docs/usage/#methods">methods</a>.</p>
<div class="table-scroll">
<table class="component-table">
<thead>
@@ -147,10 +143,34 @@
</div>
{% endif %}
{# States #}
{% if component.states.length %}
<h2>States</h2>
<div class="table-scroll">
<table class="component-table">
<thead>
<tr>
<th class="table-name">Name</th>
<th class="table-description">Description</th>
<th class="table-selector">CSS selector</th>
</tr>
</thead>
<tbody>
{% for state in component.states %}
<tr>
<td class="table-name"><code>{{ state.name }}</code></td>
<td class="table-description">{{ state.description | inlineMarkdown | safe }}</td>
<td class="table-selector"><code>[data-state-{{ state.name }}]</code></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{# Events #}
{% if component.events.length %}
<h2>Events</h2>
<p>Learn more about <a href="/docs/usage/#events">events</a>.</p>
<div class="table-scroll">
<table class="component-table">
@@ -177,7 +197,6 @@
{# Custom Properties #}
{% if component.cssProperties.length %}
<h2>CSS custom properties</h2>
<p>Learn more about <a href="/docs/customizing/#custom-properties">CSS custom properties</a>.</p>
<div class="table-scroll">
<table class="component-table">
@@ -206,37 +225,9 @@
</div>
{% endif %}
{# Custom States #}
{% if component.cssStates.length %}
<h2>Custom States</h2>
<p>Learn more about <a href="/docs/customizing/#custom-states">custom states</a>.</p>
<div class="table-scroll">
<table class="component-table">
<thead>
<tr>
<th class="table-name">Name</th>
<th class="table-description">Description</th>
<th class="table-selector">CSS selector</th>
</tr>
</thead>
<tbody>
{% for state in component.cssStates %}
<tr>
<td class="table-name"><code>{{ state.name }}</code></td>
<td class="table-description">{{ state.description | inlineMarkdown | safe }}</td>
<td class="table-selector"><code>:state({{ state.name }})</code></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{# CSS Parts #}
{% if component.cssParts.length %}
<h2>CSS parts</h2>
<p>Learn more about <a href="/docs/customizing/#css-parts">CSS parts</a>.</p>
<div class="table-scroll">
<table class="component-table">
@@ -262,7 +253,7 @@
{% if component.dependencies.length %}
<h2>Dependencies</h2>
<p>
This component automatically imports the following elements. Sub-dependencies, if any exist, will also be included in this list.
This component automatically imports the following elements. Subdependencies, if any exist, will also be included in this list.
</p>
<ul class="dependency-list">

View File

@@ -1,43 +0,0 @@
{% set hasSidebar = true %}
{% set hasOutline = true %}
{% extends '../_includes/base.njk' %}
{# Component header #}
{% block beforeContent %}
<h1 class="title">{{ title }}</h1>
<div class="component-info">
{% for tag, url in elements %}
<code class="tag"><a href="{{ url }}">{{ tag }}</a></code>
{% endfor %}
{% include '../_includes/status.njk' %}
</div>
{% if description -%}
<p class="summary">{{ description | inlineMarkdown | safe }}</p>
{%- endif %}
{% if component %}
<wa-callout variant="success">
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
Want to do more?
Check out the {% for name in (component | toArray) -%}
{{ ' and ' if loop.last and not loop.first }}<a href="/docs/components/{{ name }}"><code>&lt;wa-{{ name }}&gt;</code></a>{{ ', ' if not loop.last }}
{%- endfor %} component{{ 's' if (component | isArray) }}</a>!
</wa-callout>
{% endif %}
{% endblock %}
{# Content #}
{% block content %}
{{ content | safe }}
{% endblock %}
{# Component API #}
{% block afterContent %}
{# Slots #}
{% if css_file %}
<h2>Using these styles</h2>
<p>If you want to use these styles without using the entirety of Web Awesome Native Styles, you can include the following CSS files:</p>
{% endif %}
{% endblock %}

View File

@@ -1,25 +0,0 @@
{% set hasSidebar = true %}
{% set hasOutline = true %}
{% extends '../_includes/base.njk' %}
{# Component header #}
{% block beforeContent %}
<h1 class="title">{{ title }}</h1>
<div class="component-info">
{% for className in classes %}
<code class="class">.{{ className }}</code>
{% endfor %}
{% include '../_includes/status.njk' %}
</div>
{% if description -%}
<p class="summary">{{ description | inlineMarkdown | safe }}</p>
{%- endif %}
{% endblock %}
{# Content #}
{% block content %}
{{ content | safe }}
{% endblock %}

View File

@@ -1,11 +1,11 @@
import { parse } from 'node-html-parser';
import slugify from 'slugify';
import { v4 as uuid } from 'uuid';
import slugify from 'slugify';
function createId(text) {
let slug = slugify(String(text), {
remove: /[^\w|\s]/g,
lower: true,
lower: true
});
// ids must start with a letter
@@ -24,7 +24,7 @@ export function anchorHeadingsPlugin(options = {}) {
container: 'body',
headingSelector: 'h2, h3, h4, h5, h6',
anchorLabel: 'Jump to heading',
...options,
...options
};
return function (eleventyConfig) {

View File

@@ -53,7 +53,7 @@ const templates = {
attributes = {
open,
include: `link[rel=stylesheet][href^='/dist/']`,
...attributes,
...attributes
};
const attributesString = Object.entries(attributes)
@@ -93,7 +93,7 @@ const templates = {
${pre.outerHTML}
</wa-code-demo>
`;
},
}
};
/**
@@ -107,13 +107,13 @@ export function codeExamplesPlugin(eleventyConfig, options = {}) {
outputPathIndex === 1 && // is first
code.textContent.length < 500
); // is short
},
}
};
options = { ...defaultOptions, ...options };
const stats = {
inputPaths: {},
outputPaths: {},
outputPaths: {}
};
eleventyConfig.addTransform('code-examples', function (content) {
@@ -144,7 +144,7 @@ export function codeExamplesPlugin(eleventyConfig, options = {}) {
edit: true,
buttons: true,
new: true, // comment this line to default back to the old demos
attributes: {},
attributes: {}
};
for (const prop of ['new', 'open', 'buttons', 'edit']) {
@@ -174,7 +174,7 @@ export function codeExamplesPlugin(eleventyConfig, options = {}) {
localOptions.open = localOptions.defaultOpen(code, {
pre,
inputPathIndex: stats.inputPaths[inputPath],
outputPathIndex: stats.outputPaths[outputPath],
outputPathIndex: stats.outputPaths[outputPath]
});
}
}

View File

@@ -6,7 +6,7 @@ import { parse } from 'node-html-parser';
export function copyCodePlugin(options = {}) {
options = {
container: 'body',
...options,
...options
};
return function (eleventyConfig) {

View File

@@ -28,7 +28,7 @@ export function currentLink(options = {}) {
options = {
container: 'body',
className: 'current',
...options,
...options
};
return function (eleventyConfig) {

View File

@@ -1,200 +0,0 @@
import { parse } from 'path';
export function stripExtension(string) {
return parse(string).name;
}
export function stripPrefix(content) {
return content.replace(/^wa-/, '');
}
// Trims whitespace and pipes from the start and end of a string. Useful for CEM types, which can be pipe-delimited.
// With Prettier 3, this means a leading pipe will exist be present when the line wraps.
export function trimPipes(content) {
return typeof content === 'string' ? content.replace(/^(\s|\|)/g, '').replace(/(\s|\|)$/g, '') : content;
}
export function keys(obj) {
return Object.keys(obj);
}
export function log(firstArg, ...rest) {
console.log(firstArg, ...rest);
return firstArg;
}
function getCollection(name) {
// From https://github.com/11ty/eleventy/blob/d3d24ccddb804e6e14773501d8c4e07e2c4b9c2b/src/Filters/GetLocaleCollectionItem.js#L39-L43
return this.collections?.[name] || this.ctx?.collections?.[name] || this.context?.environments?.collections?.[name];
}
export function getCollectionItemFromUrl(url, collection) {
collection ??= getCollection.call(this, 'all') || [];
return collection.find(item => item.url === url);
}
export function getTitleFromUrl(url, collection) {
const item = getCollectionItemFromUrl.call(this, url, collection);
return item?.data.title || '';
}
export function breadcrumbs(url, { withCurrent = false } = {}) {
const parts = url.split('/').filter(Boolean);
const ret = [];
while (parts.length) {
let partialUrl = '/' + parts.join('/') + '/';
let item = getCollectionItemFromUrl.call(this, partialUrl);
if (item && (partialUrl !== url || withCurrent)) {
let title = item.data.title;
if (title) {
ret.unshift({ url: partialUrl, title });
}
}
parts.pop();
if (item?.data.parent) {
let parentURL = item.data.parent;
if (!item.data.parent.startsWith('/')) {
// Parent is in the same directory
parts.push(item.data.parent);
parentURL = '/' + parts.join('/') + '/';
}
let parentBreadcrumbs = breadcrumbs.call(this, parentURL, { withCurrent: true });
return [...parentBreadcrumbs, ...ret];
}
}
return ret;
}
export function isArray(value) {
return Array.isArray(value);
}
export function toArray(value) {
return isArray(value) ? value : [value];
}
export function deepValue(obj, key) {
key = Array.isArray(key) ? key : key.split('.');
return key.reduce((subObj, property) => subObj?.[property], obj);
}
function isNumeric(value) {
return typeof value === 'number' || (typeof value === 'string' && !isNaN(value));
}
function isEmpty(value) {
return value === null || value === undefined || value === '';
}
function compare(a, b) {
let isEmptyA = isEmpty(a);
let isEmptyB = isEmpty(b);
if (isEmptyA) {
if (isEmptyB) {
return 0;
} else {
return 1;
}
} else if (isEmptyB) {
return -1;
}
// Both strings, and at least one non-numeric
if (isNumeric(a) || isNumeric(b)) {
return a - b;
}
return (a + '').localeCompare(b);
}
/** Sort an array of objects */
export function sort(arr, keys = ['data.order', 'data.title']) {
keys = toArray(keys);
return arr.sort((a, b) => {
let aValues = keys.map(key => deepValue(a, key));
let bValues = keys.map(key => deepValue(b, key));
for (let i = 0; i < aValues.length; i++) {
let aVal = aValues[i];
let bVal = bValues[i];
let result = compare(aVal, bVal);
// They are not equal in terms of comparison OR we're at the last key
if (result !== 0 || i === aValues.length - 1) {
return result;
}
}
});
}
/**
* Group an 11ty collection (or any array of objects with a `data.tags` property) by certain tags.
* @param {object[]} collection
* @param { Object<string, string> | (string | Object<string, string>)[]} [tags] The tags to group by. If not provided/empty, defaults to grouping by all tags.
* @returns { Object.<string, object[]> } An object with keys for each tag, and an array of items for each tag.
*/
export function groupByTags(collection, tags) {
if (!tags) {
// Default to grouping by union of all tags
tags = Array.from(new Set(collection.flatMap(item => item.data.tags)));
} else if (Array.isArray(tags)) {
// May contain objects of one-off tag -> label mappings
tags = tags.map(tag => (typeof tag === 'object' ? Object.keys(tag)[0] : tag));
} else if (typeof tags === 'object') {
// tags is an object of tags to labels, so we just want the keys
tags = Object.keys(tags);
}
let ret = Object.fromEntries(tags.map(tag => [tag, []]));
ret.other = [];
for (let item of collection) {
let categorized = false;
for (let tag of tags) {
if (item.data.tags.includes(tag)) {
ret[tag].push(item);
categorized = true;
}
}
if (!categorized) {
ret.other.push(item);
}
}
// Remove empty categories
for (let category in ret) {
if (ret[category].length === 0) {
delete ret[category];
}
}
return ret;
}
export function getCategoryTitle(category, categories) {
let title;
if (Array.isArray(categories)) {
// Find relevant entry
// [{id: "Title"}, id2, ...]
title = categories.find(entry => typeof entry === 'object' && entry?.[category])?.[category];
} else if (typeof categories === 'object') {
// {id: "Title", id2: "Title 2", ...}
title = categories[category];
}
if (title) {
return title;
}
// Capitalized
return category.charAt(0).toUpperCase() + category.slice(1);
}

View File

@@ -11,7 +11,7 @@ import defaultOptions from '../../prettier.config.js';
export async function formatCode(string, options) {
return await format(string, {
...defaultOptions,
...options,
...options
});
}
@@ -21,7 +21,7 @@ export async function formatCode(string, options) {
export function formatCodePlugin(options = {}) {
options = {
parser: 'html',
...options,
...options
};
return function (eleventyConfig) {

View File

@@ -1,8 +1,8 @@
/* eslint sort-imports-es6-autofix/sort-imports-es6: 0 */
import { parse } from 'node-html-parser';
import Prism from 'prismjs';
import PrismLoader from 'prismjs/components/index.js';
import 'prismjs/plugins/custom-class/prism-custom-class.js';
import PrismLoader from 'prismjs/components/index.js';
PrismLoader('diff');
PrismLoader.silent = true;
@@ -40,7 +40,7 @@ export function highlightCode(code, language = 'plain') {
export function highlightCodePlugin(options = {}) {
options = {
container: 'body',
...options,
...options
};
return function (eleventyConfig) {

View File

@@ -14,7 +14,7 @@ export const markdown = MarkdownIt({
breaks: false,
langPrefix: 'language-',
linkify: false,
typographer: false,
typographer: false
});
markdown.use(markdownItIns);
@@ -34,7 +34,7 @@ markdown.use(markdownItMark);
`;
}
return '</div></div>\n';
},
}
});
});
@@ -44,7 +44,7 @@ markdown.use(markdownItContainer, 'aside', {
return `<aside>`;
}
return '</aside>\n';
},
}
});
markdown.use(markdownItContainer, 'details', {
@@ -55,9 +55,9 @@ markdown.use(markdownItContainer, 'details', {
return `<details>\n<summary><span>${markdown.utils.escapeHtml(m[1])}</span></summary>\n`;
}
return '</details>\n';
},
}
});
markdown.use(markdownItAttrs, {
allowedAttributes: [],
allowedAttributes: []
});

View File

@@ -15,7 +15,7 @@ export function outlinePlugin(options = {}) {
target: '.outline',
selector: 'h2,h3',
ifEmpty: () => null,
...options,
...options
};
return function (eleventyConfig) {

View File

@@ -6,7 +6,7 @@ import { parse } from 'node-html-parser';
export function removeDataAlphaElements(options = {}) {
options = {
isAlpha: false,
...options,
...options
};
return function (eleventyConfig) {

View File

@@ -1,8 +1,8 @@
/* eslint-disable no-invalid-this */
import { mkdir, writeFile } from 'fs/promises';
import lunr from 'lunr';
import { parse } from 'node-html-parser';
import { dirname, join } from 'path';
import { mkdir, writeFile } from 'fs/promises';
import { parse } from 'node-html-parser';
import lunr from 'lunr';
function collapseWhitespace(string) {
return string.replace(/\s+/g, ' ');
@@ -19,7 +19,7 @@ export function searchPlugin(options = {}) {
getDescription: doc => doc.querySelector('meta[name="description"]')?.getAttribute('content') ?? '',
getHeadings: doc => [...doc.querySelectorAll('h1, h2, h3, h4, h5, h6')].map(heading => heading.textContent ?? ''),
getContent: doc => doc.querySelector('body')?.textContent ?? '',
...options,
...options
};
return function (eleventyConfig) {
@@ -32,8 +32,8 @@ export function searchPlugin(options = {}) {
noscript: false,
style: false,
pre: false,
code: false,
},
code: false
}
});
// Remove content that shouldn't be searchable to reduce the index size
@@ -46,7 +46,7 @@ export function searchPlugin(options = {}) {
description: collapseWhitespace(options.getDescription(doc)),
headings: options.getHeadings(doc).map(collapseWhitespace),
content: collapseWhitespace(options.getContent(doc)),
url: this.page.url === '/' ? '/' : this.page.url.replace(/\/$/, ''),
url: this.page.url === '/' ? '/' : this.page.url.replace(/\/$/, '')
});
return content;

View File

@@ -1,5 +1,5 @@
await customElements.whenDefined('wa-checkbox');
let container = document.getElementById('page_slots_demo');
let fieldset = container.querySelector('fieldset');
let iframe = container.querySelector('iframe');
let stylesheets = Array.from(document.querySelectorAll("link[rel=stylesheet][href^='/dist/']"))
@@ -9,17 +9,8 @@ let includes = `${stylesheets}
<script src="/dist/webawesome.loader.js" type="module"></script>
<link rel="stylesheet" href="/assets/examples/page-demo/page.css">`;
async function render() {
await customElements.whenDefined('wa-checkbox');
// Let checkboxes update their "state"
await Promise.allSettled(
Array.from(fieldset.querySelectorAll('wa-checkbox[name=slot]')).map(checkbox => {
return checkbox.updateComplete;
}),
);
let slots = Array.from(fieldset.querySelectorAll('wa-checkbox[name=slot]:state(checked)'));
function render() {
let slots = Array.from(fieldset.querySelectorAll('wa-checkbox[name=slot]:is([data-wa-checked])'));
let slotsHTML = slots
.map(slot => {
let name = slot.getAttribute('value');
@@ -47,5 +38,13 @@ async function render() {
iframe.srcdoc = `${includes}<wa-page>${slotsHTML}</wa-page>`;
}
}
await render();
fieldset?.addEventListener('input', render);
render();
//
// TODO - fix Turbo caching. When this is removed, visiting the <wa-page> docs via Turbo will cause the <iframe srcdoc>
// to not render. Even with this, there are console errors when leaving the page.
//
// NOTE - the iframe already has `data-turbo="false"` and `data-turbo-temporary` on it.
//
document.body.setAttribute('data-turbo', 'false');

View File

@@ -26,7 +26,7 @@ wa-page {
.slot-content {
padding: var(--wa-space-m);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
align-content: center;
justify-content: center;
text-align: center;

View File

@@ -13,7 +13,7 @@ const matchers = {
regexp(textContent, query) {
query.lastIndex = 0;
return query.test(textContent);
},
}
};
matchers.iregexp = matchers.regexp; // i is baked into the query

View File

@@ -18,11 +18,12 @@ document.addEventListener('click', event => {
const cdnUrl = document.documentElement.dataset.cdnUrl;
const html =
`<script type="module" src="${cdnUrl}webawesome.loader.js"></script>\n` +
`<link rel="stylesheet" href="${cdnUrl}styles/themes/default.css">\n` +
`<link rel="stylesheet" href="${cdnUrl}styles/webawesome.css">\n` +
`<link rel="stylesheet" href="${cdnUrl}styles/utilities.css">\n\n` +
`<link rel="stylesheet" href="${cdnUrl}themes/default.css">\n` +
`<link rel="stylesheet" href="${cdnUrl}themes/applied.css">\n` +
`<link rel="stylesheet" href="${cdnUrl}themes/layout.css">\n` +
`<link rel="stylesheet" href="${cdnUrl}themes/utilities.css">\n\n` +
`${code.textContent}`;
const css = 'html > body {\n padding: 2rem !important;\n}';
const css = 'html > body {\n font: 16px sans-serif;\n padding: 2rem;\n}';
const js = '';
const form = document.createElement('form');
@@ -43,7 +44,7 @@ document.addEventListener('click', event => {
js_pre_processor: 'none',
html,
css,
js,
js
};
const input = document.createElement('input');

View File

@@ -79,8 +79,8 @@
diffViewer.appendChild(
createDiff({
serverHTML,
clientHTML,
}),
clientHTML
})
);
});
}
@@ -88,7 +88,7 @@
function createDiff({ serverHTML, clientHTML }) {
const diff = diffLines(serverHTML, clientHTML, {
ignoreWhitespace: false,
newLineIsToken: true,
newLineIsToken: true
});
const fragment = document.createDocumentFragment();
for (var i = 0; i < diff.length; i++) {

View File

@@ -9,9 +9,9 @@
const stylesheet = document.getElementById('theme-stylesheet');
const newStylesheet = Object.assign(document.createElement('link'), {
href: `/dist/styles/themes/${presetTheme}.css`,
href: `/dist/themes/${presetTheme}.css`,
rel: 'preload',
as: 'style',
as: 'style'
});
newStylesheet.addEventListener(
@@ -23,7 +23,7 @@
stylesheet.remove();
});
},
{ once: true },
{ once: true }
);
document.head.append(newStylesheet);

View File

@@ -1,14 +1,13 @@
// Smooth links
document.addEventListener('click', event => {
const link = event.target.closest('a');
const id = (link?.hash ?? '').substr(1);
if (!link || link.getAttribute('data-smooth-link') === 'off') {
return;
}
const id = (link.hash ?? '').substr(1);
// Only handle smooth scroll if there's a hash and the link points to the current page
if (id && link.pathname === window.location.pathname) {
if (id) {
const target = document.getElementById(id);
const headerHeight = document.querySelector('wa-page > header').clientHeight;
@@ -16,7 +15,7 @@ document.addEventListener('click', event => {
event.preventDefault();
window.scroll({
top: target.offsetTop - headerHeight,
behavior: 'smooth',
behavior: 'smooth'
});
history.pushState(undefined, undefined, `#${id}`);
}

View File

@@ -9,7 +9,7 @@ const icons = {
component: 'puzzle-piece',
document: 'file',
home: 'house',
theme: 'palette',
theme: 'palette'
};
let searchTimeout;
@@ -18,7 +18,7 @@ function getElements() {
return {
dialog: document.getElementById('site-search'),
input: document.getElementById('site-search-input'),
results: document.getElementById('site-search-listbox'),
results: document.getElementById('site-search-listbox')
};
}

View File

@@ -9,7 +9,7 @@ function saveScrollPosition() {
if (element.id) {
positions[element.id] = {
top: element.scrollTop,
left: element.scrollLeft,
left: element.scrollLeft
};
} else {
console.warn(`Can't save scroll position for elements without an id.`, el);

View File

@@ -1,6 +1,6 @@
.code-example {
border: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
border-radius: var(--wa-border-radius-l);
border-radius: var(--wa-border-radius-m);
color: var(--wa-color-text-normal);
margin-block-end: var(--wa-flow-spacing);
}
@@ -41,8 +41,8 @@
border-bottom: none;
pre {
border-bottom-right-radius: var(--wa-border-radius-l);
border-bottom-left-radius: var(--wa-border-radius-l);
border-bottom-right-radius: var(--wa-border-radius-m);
border-bottom-left-radius: var(--wa-border-radius-m);
}
}
@@ -62,11 +62,11 @@
&:first-of-type {
border-left: none;
border-bottom-left-radius: var(--wa-border-radius-l);
border-bottom-left-radius: var(--wa-border-radius-m);
}
&:last-of-type {
border-bottom-right-radius: var(--wa-border-radius-l);
border-bottom-right-radius: var(--wa-border-radius-m);
}
&:focus-visible {

View File

@@ -6,7 +6,7 @@ wa-copy-button.copy-button {
right: 0.25rem;
font-family: var(--wa-font-family-body);
color: var(--wa-color-gray-80);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
padding: 0.25rem;
&:hover {

View File

@@ -25,11 +25,11 @@ wa-page::part(header) {
border-bottom: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
}
wa-page::part(body) {
wa-page::part(drawer__body) {
padding-top: 0px;
}
wa-page::part(header-actions) {
wa-page::part(drawer__header-actions) {
align-self: center;
}
@@ -46,7 +46,7 @@ wa-page > header {
}
wa-button[data-toggle-nav] {
--text-color: currentColor;
--label-color: currentColor;
font-size: 1rem;
margin-inline-start: -0.875rem;
margin-inline-end: 0;
@@ -76,6 +76,8 @@ wa-page > header {
margin-block-start: var(--wa-space-2xs);
}
#version-number + wa-badge {
--background-color: var(--wa-color-warning-fill-quiet);
--content-color: var(--wa-color-warning-on-quiet);
font-size: var(--wa-font-size-2xs);
text-transform: uppercase;
}
@@ -95,18 +97,9 @@ wa-page > header {
font-size: var(--wa-font-size-m);
margin: 0;
}
h2:not(:first-child),
wa-details:not(:first-child) {
h2:not(:first-child) {
margin-block-start: var(--wa-space-xs);
}
wa-details {
border: none;
background: none;
padding: 0;
}
ul {
border-inline-start: var(--wa-border-width-s) solid var(--wa-color-surface-border);
font-size: var(--wa-font-size-s);
@@ -114,30 +107,21 @@ wa-page > header {
margin: 0;
padding-inline-start: var(--wa-space-m);
}
ul ul {
margin-block-start: var(--wa-space-m);
}
ul:empty {
display: none;
}
li {
list-style: none;
+ li {
margin-block-start: var(--wa-space-m);
}
}
li + li {
margin-block-start: var(--wa-space-m);
}
li a {
color: var(--wa-color-text-normal);
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
li a:hover {
text-decoration: underline;
}
li wa-badge::part(base) {
@@ -261,7 +245,7 @@ h1.title wa-badge {
display: flex;
gap: 1rem;
border: var(--wa-border-style) var(--wa-border-width-s);
border-radius: var(--wa-border-radius-l);
border-radius: var(--wa-border-radius-m);
padding: 1rem;
margin-block-end: var(--wa-flow-spacing);
@@ -321,45 +305,8 @@ wa-page > main:has(> .index-grid) {
.index-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(22ch, 100%), 1fr));
grid-template-columns: repeat(auto-fit, minmax(min(20ch, 100%), 1fr));
gap: var(--wa-space-2xl);
a {
border-radius: var(--wa-border-radius-l);
}
wa-card {
--box-shadow: none;
--spacing: var(--wa-space-m);
inline-size: 100%;
&:hover {
--border-color: var(--wa-color-brand-border-loud);
--box-shadow: 0 0 0 var(--wa-border-width-s) var(--border-color);
.page-name {
color: var(--wa-color-brand-on-quiet);
}
}
[slot='header'] {
display: flex;
}
&::part(header) {
background-color: var(--wa-color-neutral-fill-quiet);
border-bottom: none;
display: flex;
align-items: center;
justify-content: center;
min-block-size: calc(6rem + var(--spacing));
}
}
.page-name {
font-size: var(--wa-font-size-s);
font-weight: var(--wa-font-weight-action);
}
}
.index-category {
@@ -368,13 +315,107 @@ wa-page > main:has(> .index-grid) {
margin-block-start: var(--wa-space-2xl);
}
.index-grid a {
border-radius: var(--wa-border-radius-m);
}
.index-grid wa-card {
--box-shadow: none;
--spacing: var(--wa-space-m);
inline-size: 100%;
}
.index-grid wa-card:hover {
--border-color: var(--wa-color-brand-border-loud);
--box-shadow: 0 0 0 var(--wa-border-width-s) var(--border-color);
& .page-name {
color: var(--wa-color-brand-on-quiet);
}
}
.index-grid wa-card [slot='header'] {
display: flex;
}
.index-grid wa-card::part(header) {
background-color: var(--wa-color-neutral-fill-quiet);
border-bottom: none;
display: flex;
align-items: center;
justify-content: center;
min-block-size: calc(6rem + var(--spacing));
}
.index-grid .page-name {
font-size: var(--wa-font-size-s);
font-weight: var(--wa-font-weight-action);
}
/* Index Pages */
wa-page > main:has(> .index-grid) {
max-width: 120ch;
margin-inline: auto;
}
.index-summary {
max-inline-size: 80ch;
}
.index-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(20ch, 100%), 1fr));
gap: var(--wa-space-2xl);
}
.index-category {
grid-column: 1 / -1;
margin-block-end: 0;
margin-block-start: var(--wa-space-2xl);
}
.index-grid a {
border-radius: var(--wa-border-radius-m);
}
.index-grid wa-card {
--box-shadow: none;
--spacing: var(--wa-space-m);
inline-size: 100%;
}
.index-grid wa-card:hover {
--border-color: var(--wa-color-brand-border-loud);
--box-shadow: 0 0 0 var(--wa-border-width-s) var(--border-color);
& .page-name {
color: var(--wa-color-brand-on-quiet);
}
}
.index-grid wa-card [slot='header'] {
display: flex;
}
.index-grid wa-card::part(header) {
background-color: var(--wa-color-neutral-fill-quiet);
border-bottom: none;
display: flex;
align-items: center;
justify-content: center;
min-block-size: calc(6rem + var(--spacing));
}
.index-grid .page-name {
font-size: var(--wa-font-size-s);
font-weight: var(--wa-font-weight-action);
}
/* Swatches */
.swatch {
background-color: transparent;
border-color: var(--wa-color-neutral-border-normal);
border-style: var(--wa-border-style);
border-width: var(--wa-border-width-s);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
box-sizing: border-box;
line-height: 2.5;
height: 2.5em;
@@ -384,13 +425,13 @@ wa-page > main:has(> .index-grid) {
/* Layout Examples */
.layout-example-boundary {
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
border-radius: var(--wa-border-radius-l);
border-radius: var(--wa-border-radius-m);
padding: var(--wa-space-s);
}
.layout-example-block {
background-color: var(--wa-color-indigo-60);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
min-block-size: 4rem;
min-inline-size: 4rem;
}
@@ -414,7 +455,6 @@ wa-page > main:has(> .index-grid) {
.table-scroll {
overflow-x: auto;
margin-block-end: var(--wa-flow-spacing);
}
/** mobile */
@@ -426,6 +466,11 @@ wa-page > main:has(> .index-grid) {
/** desktop */
@media screen and not (max-width: 768px) {
wa-page [data-toggle-nav],
wa-page .only-mobile {
display: none;
}
/* Navigation sidebar */
wa-page::part(navigation) {
border-right: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);

View File

@@ -18,7 +18,7 @@
.diff-grid > * {
height: 100%;
}
.diff-dialog {
.diff-dialog::part(dialog) {
max-width: 90vw;
width: 90vw;
}

View File

@@ -42,6 +42,5 @@
#outline-expandable {
display: block;
margin-block-end: var(--wa-space-xl);
}
}

View File

@@ -1,14 +1,13 @@
#site-search {
width: 38rem;
position: absolute;
top: 0;
border-radius: var(--wa-border-radius-l);
padding: 0;
margin: 0 auto;
overflow: hidden;
--width: 38rem;
&::part(base) {
margin-block: 10rem;
&::part(dialog) {
position: absolute;
top: 0;
border-radius: var(--wa-border-radius-m);
padding: 0;
margin: 10rem auto;
overflow: hidden;
}
&::part(body) {
@@ -19,22 +18,21 @@
justify-content: center;
gap: 0.5rem;
}
@media screen and (max-width: 900px) {
max-width: calc(100% - 2rem);
&::part(base) {
margin-block: 1rem;
}
}
}
#site-search-container {
display: flex;
flex-direction: column;
max-height: calc(100vh - 20rem);
}
@media screen and (max-width: 900px) {
@media screen and (max-width: 900px) {
#site-search::part(dialog) {
max-width: calc(100% - 2rem);
margin-block: 1rem;
}
#site-search-container {
max-height: calc(100dvh - 2rem);
}
}
@@ -231,8 +229,8 @@ header {
gap: 2rem;
color: var(--wa-color-text-quiet);
border-top: var(--wa-panel-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
border-bottom-left-radius: var(--wa-border-radius-l);
border-bottom-right-radius: var(--wa-border-radius-l);
border-bottom-left-radius: var(--wa-border-radius-m);
border-bottom-right-radius: var(--wa-border-radius-m);
padding: 1rem;
kbd {

View File

@@ -23,7 +23,7 @@
.hero wa-button[variant='brand'] {
--background: var(--wa-color-neutral-fill-quiet);
--text-color: var(--wa-color-neutral-on-normal);
--label-color: var(--wa-color-neutral-on-normal);
}
.project-header {

View File

@@ -1,8 +1,7 @@
---
title: Animated Image
description: A component for displaying animated GIFs and WEBPs that play and pause on interaction.
tags: [imagery, niche]
icon: animated-image
layout: component
---
```html {.example}

View File

@@ -1,8 +1,7 @@
---
title: Animation
description: Animate elements declaratively with nearly 100 baked-in presets, or roll your own with custom keyframes.
tags: [helpers, primitives]
icon: animation
layout: component
---
To animate an element, wrap it in `<wa-animation>` and set an animation `name`. The animation will not start until you add the `play` attribute. Refer to the [properties table](#properties) for a list of all animation options.
@@ -197,3 +196,4 @@ Animations won't play until you apply the `play` attribute. You can omit it init
animation.play = true;
});
</script>
```

View File

@@ -1,8 +1,7 @@
---
title: Avatar
description: Avatars are used to represent a person or object.
tags: [imagery, apps, content]
icon: avatar
layout: component
---
By default, a generic icon will be shown. You can personalize avatars by adding custom icons, initials, and images. You should always provide a `label` for assistive devices.
@@ -98,7 +97,7 @@ You can group avatars with a few lines of CSS.
margin-left: calc(-1 * var(--wa-space-m));
}
.avatar-group wa-avatar {
.avatar-group wa-avatar::part(base) {
border: solid 2px var(--wa-color-surface-default);
}
</style>

View File

@@ -1,8 +1,7 @@
---
title: Badge
description: Badges are used to draw attention and display statuses or counts.
tags: [feedback, content]
icon: badge
layout: component
---
```html {.example}
@@ -23,48 +22,6 @@ Set the `variant` attribute to change the badge's variant.
<wa-badge variant="danger">Danger</wa-badge>
```
### Appearance
Use the `appearance` attribute to change the badge's visual appearance.
```html {.example}
<div style="margin-block-end: 1rem;">
<wa-badge appearance="accent outlined" variant="neutral">A+O</wa-badge>
<wa-badge appearance="accent" variant="neutral">Accent</wa-badge>
<wa-badge appearance="filled outlined" variant="neutral">F+O</wa-badge>
<wa-badge appearance="filled" variant="neutral">Filled</wa-badge>
<wa-badge appearance="outlined" variant="neutral">Outlined</wa-badge>
</div>
<div style="margin-block-end: 1rem;">
<wa-badge appearance="accent outlined" variant="brand">A+O</wa-badge>
<wa-badge appearance="accent" variant="brand">Accent</wa-badge>
<wa-badge appearance="filled outlined" variant="brand">F+O</wa-badge>
<wa-badge appearance="filled" variant="brand">Filled</wa-badge>
<wa-badge appearance="outlined" variant="brand">Outlined</wa-badge>
</div>
<div style="margin-block-end: 1rem;">
<wa-badge appearance="accent outlined" variant="success">A+O</wa-badge>
<wa-badge appearance="accent" variant="success">Accent</wa-badge>
<wa-badge appearance="filled outlined" variant="success">F+O</wa-badge>
<wa-badge appearance="filled" variant="success">Filled</wa-badge>
<wa-badge appearance="outlined" variant="success">Outlined</wa-badge>
</div>
<div style="margin-block-end: 1rem;">
<wa-badge appearance="accent outlined" variant="warning">A+O</wa-badge>
<wa-badge appearance="accent" variant="warning">Accent</wa-badge>
<wa-badge appearance="filled outlined" variant="warning">F+O</wa-badge>
<wa-badge appearance="filled" variant="warning">Filled</wa-badge>
<wa-badge appearance="outlined" variant="warning">Outlined</wa-badge>
</div>
<div>
<wa-badge appearance="accent outlined" variant="danger">A+O</wa-badge>
<wa-badge appearance="accent" variant="danger">Accent</wa-badge>
<wa-badge appearance="filled outlined" variant="danger">F+O</wa-badge>
<wa-badge appearance="filled" variant="danger">Filled</wa-badge>
<wa-badge appearance="outlined" variant="danger">Outlined</wa-badge>
</div>
```
### Pill Badges
Use the `pill` attribute to give badges rounded edges.
@@ -128,3 +85,4 @@ When including badges in menu items, use the `suffix` slot to make sure they're
<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

@@ -1,8 +1,7 @@
---
title: Breadcrumb Item
description: Breadcrumb Items are used inside breadcrumbs to represent different links.
tags: component
parent: breadcrumb
layout: component
---
```html {.example}

View File

@@ -1,8 +1,7 @@
---
title: Breadcrumb
description: Breadcrumbs provide a group of links so users can easily navigate a website's hierarchy.
tags: [navigation]
icon: breadcrumb
layout: component
---
Breadcrumbs are usually placed before a page's main content with the current page shown last to indicate the user's position in the navigation.
@@ -136,7 +135,7 @@ Dropdown menus can be placed in the default slot to provide additional options.
<wa-breadcrumb-item>Homepage</wa-breadcrumb-item>
<wa-breadcrumb-item>
<wa-dropdown>
<wa-button slot="trigger" size="small" appearance="filled" pill>
<wa-button slot="trigger" size="small" appearance="tinted" pill>
<wa-icon label="More options" name="ellipsis" variant="solid"></wa-icon>
</wa-button>
<wa-menu>
@@ -161,7 +160,7 @@ Alternatively, you can place dropdown menus in a prefix or suffix slot.
<wa-breadcrumb-item>
Web Design
<wa-dropdown slot="suffix">
<wa-button slot="trigger" size="small" appearance="filled" pill>
<wa-button slot="trigger" size="small" appearance="tinted" pill>
<wa-icon label="More options" name="ellipsis" variant="solid"></wa-icon>
</wa-button>
<wa-menu>
@@ -172,3 +171,4 @@ Alternatively, you can place dropdown menus in a prefix or suffix slot.
</wa-dropdown>
</wa-breadcrumb-item>
</wa-breadcrumb>
```

View File

@@ -1,8 +1,7 @@
---
title: Button Group
description: Button groups can be used to group related buttons into sections.
tags: [actions, forms, apps]
icon: button-group
layout: component
---
```html {.example}
@@ -140,17 +139,15 @@ Pill buttons are supported through the button's `pill` attribute.
</wa-button-group>
```
### Dropdowns and Native Buttons in Button Groups
### Dropdowns in Button Groups
Other elements can also be placed inside button groups:
- Native buttons as long as their [native styles](/docs/native/button) are included
- Dropdowns as long as the trigger is either a `<wa-button>`, or a `<button>` with [native styles](/docs/native/button) included.
Dropdowns can be placed inside button groups as long as the trigger is an `<wa-button>` element.
```html {.example}
<wa-button-group label="Example Button Group">
<wa-button>Button</wa-button>
<button>Native Button</button>
<wa-dropdown hoist>
<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>
@@ -168,9 +165,9 @@ Create a split button using a button and a dropdown. Use a [visually hidden](/do
```html {.example}
<wa-button-group label="Example Button Group">
<wa-button variant="brand">Save</wa-button>
<wa-dropdown placement="bottom-end" hoist>
<wa-dropdown placement="bottom-end">
<wa-button slot="trigger" variant="brand" caret>
<span class="wa-visually-hidden">More options</span>
<wa-visually-hidden>More options</wa-visually-hidden>
</wa-button>
<wa-menu>
<wa-menu-item>Save</wa-menu-item>

View File

@@ -1,9 +1,7 @@
---
title: Button
description: Buttons represent actions that are available to the user.
tags: [actions, forms]
native: button
icon: button
layout: component
---
```html {.example}
@@ -29,37 +27,35 @@ Use the `variant` attribute to set the button's semantic variant.
Use the `appearance` attribute to change the button's visual appearance.
```html {.example}
<div class="wa-stack">
<div class="wa-gap-m">
<wa-button appearance="accent" variant="neutral">Accent</wa-button>
<wa-button appearance="outlined" variant="neutral">Outlined</wa-button>
<wa-button appearance="filled" variant="neutral">Filled</wa-button>
<wa-button appearance="plain" variant="neutral">Plain</wa-button>
</div>
<div class="wa-gap-m">
<wa-button appearance="accent" variant="brand">Accent</wa-button>
<wa-button appearance="outlined" variant="brand">Outlined</wa-button>
<wa-button appearance="filled" variant="brand">Filled</wa-button>
<wa-button appearance="plain" variant="brand">Plain</wa-button>
</div>
<div class="wa-gap-m">
<wa-button appearance="accent" variant="success">Accent</wa-button>
<wa-button appearance="outlined" variant="success">Outlined</wa-button>
<wa-button appearance="filled" variant="success">Filled</wa-button>
<wa-button appearance="plain" variant="success">Plain</wa-button>
</div>
<div class="wa-gap-m">
<wa-button appearance="accent" variant="warning">Accent</wa-button>
<wa-button appearance="outlined" variant="warning">Outlined</wa-button>
<wa-button appearance="filled" variant="warning">Filled</wa-button>
<wa-button appearance="plain" variant="warning">Plain</wa-button>
</div>
<div class="wa-gap-m">
<wa-button appearance="accent" variant="danger">Accent</wa-button>
<wa-button appearance="outlined" variant="danger">Outlined</wa-button>
<wa-button appearance="filled" variant="danger">Filled</wa-button>
<wa-button appearance="plain" variant="danger">Plain</wa-button>
</div>
<div style="margin-block-end: 1rem;">
<wa-button appearance="filled" variant="neutral">Filled</wa-button>
<wa-button appearance="tinted" variant="neutral">Tinted</wa-button>
<wa-button appearance="outlined" variant="neutral">Outlined</wa-button>
<wa-button appearance="text" variant="neutral">Text</wa-button>
</div>
<div style="margin-block-end: 1rem;">
<wa-button appearance="filled" variant="brand">Filled</wa-button>
<wa-button appearance="tinted" variant="brand">Tinted</wa-button>
<wa-button appearance="outlined" variant="brand">Outlined</wa-button>
<wa-button appearance="text" variant="brand">Text</wa-button>
</div>
<div style="margin-block-end: 1rem;">
<wa-button appearance="filled" variant="success">Filled</wa-button>
<wa-button appearance="tinted" variant="success">Tinted</wa-button>
<wa-button appearance="outlined" variant="success">Outlined</wa-button>
<wa-button appearance="text" variant="success">Text</wa-button>
</div>
<div style="margin-block-end: 1rem;">
<wa-button appearance="filled" variant="warning">Filled</wa-button>
<wa-button appearance="tinted" variant="warning">Tinted</wa-button>
<wa-button appearance="outlined" variant="warning">Outlined</wa-button>
<wa-button appearance="text" variant="warning">Text</wa-button>
</div>
<div>
<wa-button appearance="filled" variant="danger">Filled</wa-button>
<wa-button appearance="tinted" variant="danger">Tinted</wa-button>
<wa-button appearance="outlined" variant="danger">Outlined</wa-button>
<wa-button appearance="text" variant="danger">Text</wa-button>
</div>
```
@@ -95,7 +91,7 @@ It's often helpful to have a button that works like a link. This is possible by
### 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.
As expected, buttons can be given a custom width by setting the `width` attribute. This is useful for making buttons span the full width of their container on smaller screens.
```html {.example}
<wa-button size="small" style="width: 100%; margin-bottom: 1rem;">Small</wa-button>

View File

@@ -1,8 +1,7 @@
---
title: Callout
description: Callouts are used to display important messages inline.
tags: [feedback, content]
icon: callout
layout: component
---
```html {.example}

View File

@@ -1,8 +1,7 @@
---
title: Card
description: Cards can be used to group related subjects in a container.
tags: [organization, layout]
icon: card
layout: component
---
```html {.example}

View File

@@ -1,9 +1,7 @@
---
title: Carousel Item
description: A carousel item represent a slide within a carousel.
tags: component
parent: carousel
icon: carousel-item
layout: component
---
```html {.example}

View File

@@ -1,8 +1,7 @@
---
title: Carousel
description: Carousels display an arbitrary number of content slides along a horizontal or vertical axis.
tags: [imagery, disclosure]
icon: carousel
layout: component
---
```html {.example}
@@ -535,12 +534,12 @@ The carousel has a robust API that makes it possible to extend and customize. Th
</wa-carousel>
<div class="thumbnails">
<div class="scroller">
<img alt="Thumbnail by 1" class="image active" src="https://images.unsplash.com/photo-1426604966848-d7adac402bff?q=10" />
<img alt="Thumbnail by 2" class="image" src="https://images.unsplash.com/photo-1473448912268-2022ce9509d8?q=10" />
<img alt="Thumbnail by 3" class="image" src="https://images.unsplash.com/photo-1499002238440-d264edd596ec?q=10" />
<img alt="Thumbnail by 4" class="image" src="https://images.unsplash.com/photo-1475113548554-5a36f1f523d6?q=10" />
<img alt="Thumbnail by 5" class="image" src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?q=10" />
<div class="thumbnails__scroller">
<img alt="Thumbnail by 1" class="thumbnails__image active" src="https://images.unsplash.com/photo-1426604966848-d7adac402bff?q=10" />
<img alt="Thumbnail by 2" class="thumbnails__image" src="https://images.unsplash.com/photo-1473448912268-2022ce9509d8?q=10" />
<img alt="Thumbnail by 3" class="thumbnails__image" src="https://images.unsplash.com/photo-1499002238440-d264edd596ec?q=10" />
<img alt="Thumbnail by 4" class="thumbnails__image" src="https://images.unsplash.com/photo-1475113548554-5a36f1f523d6?q=10" />
<img alt="Thumbnail by 5" class="thumbnails__image" src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?q=10" />
</div>
</div>
@@ -554,7 +553,7 @@ The carousel has a robust API that makes it possible to extend and customize. Th
justify-content: center;
}
.scroller {
.thumbnails__scroller {
display: flex;
gap: var(--wa-space-s);
overflow-x: auto;
@@ -563,11 +562,11 @@ The carousel has a robust API that makes it possible to extend and customize. Th
scroll-padding: var(--wa-space-s);
}
.scroller::-webkit-scrollbar {
.thumbnails__scroller::-webkit-scrollbar {
display: none;
}
.image {
.thumbnails__image {
width: 64px;
height: 64px;
object-fit: cover;
@@ -579,7 +578,7 @@ The carousel has a robust API that makes it possible to extend and customize. Th
cursor: pointer;
}
.image.active {
.thumbnails__image.active {
opacity: 1;
}
</style>
@@ -587,13 +586,13 @@ The carousel has a robust API that makes it possible to extend and customize. Th
<script>
{
const carousel = document.querySelector('.carousel-thumbnails');
const scroller = document.querySelector('.scroller');
const thumbnails = document.querySelectorAll('.image');
const scroller = document.querySelector('.thumbnails__scroller');
const thumbnails = document.querySelectorAll('.thumbnails__image');
scroller.addEventListener('click', e => {
const target = e.target;
if (target.matches('.image')) {
if (target.matches('.thumbnails__image')) {
const index = [...thumbnails].indexOf(target);
carousel.goToSlide(index);
}

View File

@@ -1,7 +1,6 @@
---
title: Component Cheatsheet
layout: docs
unlisted: true
---
<style>
@@ -65,21 +64,15 @@ table code {
<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 }}
{% endif %}
{% for component in thingComponents %}
<a href="../{{ component.slug }}"><code>&lt;{{ component.tagName }}&gt;</code></a>
{%- endfor -%}
{% if thingComponents.length > 1 %}
</details>
{% else %}
{{ componentLinks | safe }}
{% endif %}
</td>
</tr>

View File

@@ -1,9 +1,7 @@
---
title: Checkbox
description: Checkboxes allow the user to toggle an option on or off.
tags: [inputs, forms]
native: checkbox
icon: checkbox
layout: component
---
```html {.example}
@@ -52,12 +50,12 @@ Use the `size` attribute to change a checkbox's size.
<wa-checkbox size="large">Large</wa-checkbox>
```
### Hint
### Help Text
Add descriptive hint to a switch with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
Add descriptive help text to a switch with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
```html {.example}
<wa-checkbox hint="What should the user know about the checkbox?">Label</wa-checkbox>
<wa-checkbox help-text="What should the user know about the checkbox?">Label</wa-checkbox>
```
### Custom Validity
@@ -94,4 +92,4 @@ Use the `setCustomValidity()` method to set a custom validation message. This wi
});
});
</script>
```
```

View File

@@ -1,8 +1,7 @@
---
title: Code Demo
description: Code demos can be used to render code examples as inline live demos.
tags: component
noAlpha: true
layout: component
---
```html {.example}
@@ -82,7 +81,7 @@ There are certain types of elements that are handled specially:
This is useful for including resources in your demo that you don't want rendered outside the demo.
The following example shows both methods.
It includes all stylesheets on this page whose URLs start with `/dist/styles/themes/`,
It includes all stylesheets on this page whose URLs start with `/dist/themes/`,
plus any other elements with the class `.demo-import`, plus a CSS file with the class `wa-code-demo-include`:
```html {.example}
@@ -174,7 +173,7 @@ i.e. the previews of demos using the `viewport` attribute, but also opening demo
Just setting `border-radius` or `border` should work as expected:
```html{.example}
<wa-code-demo style="border: 2px dotted var(--wa-color-blue-50); border-radius: var(--wa-border-radius-m)">
<wa-code-demo style="border: 2px dotted var(--wa-color-blue-50); border-radius: var(--wa-border-radius-s)">
<pre><code class="language-html">
&lt;button&gt;Click me!&lt;/button&gt;
&lt;wa-button&gt;Click me!&lt;/wa-button&gt;

View File

@@ -1,9 +1,7 @@
---
title: Color Picker
description: Color pickers allow the user to select a color.
tags: [inputs, forms]
native: input
icon: color-picker
layout: component
---
```html {.example}
@@ -39,12 +37,10 @@ Set the color picker's format with the `format` attribute. Valid options include
To prevent users from toggling the format themselves, add the `no-format-toggle` attribute.
```html {.example}
<div class="wa-grid" style="--min-column-size: 12ch;">
<wa-color-picker format="hex" value="#4a90e2" label="Pick a hex color"></wa-color-picker>
<wa-color-picker format="rgb" value="rgb(80, 227, 194)" label="Pick an RGB color"></wa-color-picker>
<wa-color-picker format="hsl" value="hsl(290, 87%, 47%)" label="Pick an HSL color"></wa-color-picker>
<wa-color-picker format="hsv" value="hsv(55, 89%, 97%)" label="Pick an HSV color"></wa-color-picker>
</div>
<wa-color-picker format="hex" value="#4a90e2" label="Select a color"></wa-color-picker>
<wa-color-picker format="rgb" value="rgb(80, 227, 194)" label="Select a color"></wa-color-picker>
<wa-color-picker format="hsl" value="hsl(290, 87%, 47%)" label="Select a color"></wa-color-picker>
<wa-color-picker format="hsv" value="hsv(55, 89%, 97%)" label="Select a color"></wa-color-picker>
```
### Swatches
@@ -79,10 +75,10 @@ The color picker can be rendered as disabled.
<wa-color-picker disabled label="Select a color"></wa-color-picker>
```
### Hint
### Help Text
Add descriptive hint to a color picker with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
Add descriptive help text to a color picker with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
```html {.example}
<wa-color-picker label="Select a color" hint="Choose a color with appropate contrast!"></wa-color-picker>
```
<wa-color-picker label="Select a color" help-text="Choose a color with appropate contrast!"></wa-color-picker>
```

View File

@@ -1,4 +0,0 @@
{
"layout": "component.njk",
"tags": ["components"]
}

View File

@@ -1,8 +1,7 @@
---
title: Copy Button
description: Copies data to the clipboard when the user clicks the button.
tags: [actions, apps]
icon: copy-button
layout: component
---
```html {.example}

View File

@@ -1,9 +1,7 @@
---
title: Details
description: Details show a brief summary and expand to show additional content.
tags: [organization, apps, content, disclosure]
icon: details
native: details
layout: component
---
<!-- cspell:dictionaries lorem-ipsum -->
@@ -19,7 +17,7 @@ native: details
### Disabled
Use the `disabled` attribute to prevent the details from expanding.
Use the `disable` attribute to prevent the details from expanding.
```html {.example}
<wa-details summary="Disabled" disabled>
@@ -30,7 +28,7 @@ Use the `disabled` attribute to prevent the details from expanding.
### Customizing the Summary Icon
Use the `expand-icon` and `collapse-icon` slots to change the expand and collapse icons, respectively. To disable the animation, override the `rotate` property on the `icon` part as shown below.
Use the `expand-icon` and `collapse-icon` slots to change the expand and collapse icons, respectively. To disable the animation, override the `rotate` property on the `summary-icon` part as shown below.
```html {.example}
<wa-details summary="Toggle Me" class="custom-icons">
@@ -42,41 +40,13 @@ Use the `expand-icon` and `collapse-icon` slots to change the expand and collaps
</wa-details>
<style>
/* Disable the expand/collapse animation */
wa-details.custom-icons::part(icon) {
wa-details.custom-icons::part(summary-icon) {
/* Disable the expand/collapse animation */
rotate: none;
}
</style>
```
### HTML in summary
To use HTML in the summary, use the `summary` slot.
Links and other interactive elements will still retain their behavior:
```html {.example}
<wa-details>
<span slot="summary">
Some text
<a href="https://webawesome.com" target="_blank">a link</a>
more text
</span>
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>
```
### Right-to-Left languages
The details component automatically adapts to right-to-left languages:
```html {.example}
<wa-details summary="تبديلني" lang="ar" dir="rtl">
استخدام طريقة لوريم إيبسوم لأنها تعطي توزيعاَ طبيعياَ -إلى حد ما- للأحرف عوضاً عن
</wa-details>
```
### 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.

View File

@@ -1,16 +1,13 @@
---
title: Dialog
description: 'Dialogs, sometimes called "modals", appear above the page and require the user''s immediate attention.'
tags: [organization, apps, disclosure]
icon: dialog
native: dialog
keywords: modal
layout: component
---
<!-- cspell:dictionaries lorem-ipsum -->
```html {.example}
<wa-dialog label="Dialog" with-header with-footer id="dialog-overview">
<wa-dialog label="Dialog" with-header with-footer class="dialog-overview">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
</wa-dialog>
@@ -18,7 +15,7 @@ keywords: modal
<wa-button>Open Dialog</wa-button>
<script>
const dialog = document.querySelector('#dialog-overview');
const dialog = document.querySelector('.dialog-overview');
const openButton = dialog.nextElementSibling;
openButton.addEventListener('click', () => dialog.open = true);
@@ -88,10 +85,10 @@ You can add the special `data-dialog="close"` attribute to a button inside the d
### Custom Width
Just use the CSS `width` property to set the dialog's width.
Use the `--width` custom property to set the dialog's width.
```html {.example}
<wa-dialog label="Dialog" with-header with-footer class="dialog-width" style="width: 50vw;">
<wa-dialog label="Dialog" with-header with-footer class="dialog-width" style="--width: 50vw;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
</wa-dialog>
@@ -222,4 +219,4 @@ To give focus to a specific element when the dialog opens, use the `autofocus` a
openButton.addEventListener('click', () => dialog.open = true);
</script>
```
```

View File

@@ -1,8 +1,7 @@
---
title: Divider
description: Dividers are used to visually separate or group elements.
tags: [organization, content, forms]
icon: divider
layout: component
---
```html {.example}

View File

@@ -1,8 +1,7 @@
---
title: Drawer
description: Drawers slide in from a container to expose additional options and information.
tags: [organization, disclosure]
icon: drawer
layout: component
---
<!-- cspell:dictionaries lorem-ipsum -->

View File

@@ -1,8 +1,7 @@
---
title: Dropdown
description: 'Dropdowns expose additional content that "drops down" in a panel.'
tags: [actions, apps]
icon: dropdown
layout: component
---
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.

View File

@@ -1,8 +1,7 @@
---
title: Format Bytes
description: Formats a number as a human readable bytes value.
tags: [helpers, content, inline]
icon: format-bytes
layout: component
---
```html {.example}

View File

@@ -1,8 +1,7 @@
---
title: Format Date
description: Formats a date/time using the specified locale and options.
tags: [helpers, content, inline]
icon: format-date
layout: component
---
Localization is handled by the browser's [`Intl.DateTimeFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat). No language packs are required.

View File

@@ -1,8 +1,7 @@
---
title: Format Number
description: Formats a number using the specified locale and options.
tags: [helpers, content, inline]
icon: format-number
layout: component
---
Localization is handled by the browser's [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat). No language packs are required.

View File

@@ -1,8 +1,7 @@
---
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
layout: component
---
For a full list of icons that come bundled with Web Awesome, refer to the [icon component](/docs/components/icon).

View File

@@ -1,8 +1,7 @@
---
title: Icon
description: Icons are symbols that can be used to represent various options within an application.
tags: [imagery, apps, popular]
icon: icon
layout: component
---
Web Awesome comes bundled with over 2,000 free icons courtesy of [Font Awesome](https://fontawesome.com/). These icons are part of the `default` icon library. Font Awesome Pro users can unlock additional icon families. Or, if you prefer, you can register your own [custom icon library](#icon-library).
@@ -147,7 +146,7 @@ Icons in this library are licensed under the [MIT License](https://github.com/tw
resolver: (name, family) => {
const suffix = family === 'filled' ? '-fill' : '';
return `https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/icons/${name}${suffix}.svg`
}
}
});
</script>
```
@@ -518,7 +517,7 @@ For example, this will change the default icon library to use [Bootstrap Icons](
resolver: (name, family) => {
const suffix = family === 'filled' ? '-fill' : '';
return `https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/icons/${name}${suffix}.svg`
}
}
});
</script>
```

View File

@@ -1,8 +1,7 @@
---
title: Image Comparer
description: Compare visual differences between similar photos with a sliding panel.
tags: [imagery, niche]
icon: image-comparer
layout: component
---
For best results, use images that share the same dimensions. The slider can be controlled by dragging or pressing the left and right arrow keys. (Tip: press shift + arrows to move the slider in larger intervals, or home + end to jump to the beginning or end.)

View File

@@ -1,8 +1,7 @@
---
title: Include
description: Includes give you the power to embed external HTML files into the page.
tags: [helpers, primitives]
icon: include
layout: component
---
Included files are asynchronously requested using `window.fetch()`. Requests are cached, so the same file can be included multiple times, but only one request will be made.

View File

@@ -1,81 +1,423 @@
---
title: Components
description: Components are the essential building blocks to create intuitive, cohesive experiences. Browse the library of customizable, framework-friendly web components included in Web Awesome.
description: Browse the library of customizable, framework-friendly web components included in Web Awesome.
layout: page-outline
categories:
- actions
- feedback: 'Feedback & Status'
- imagery
- inputs
- navigation
- organization
- helpers: 'Utilities'
override:tags: []
---
<div id="component-filter">
<wa-input type="search" placeholder="Search components" clearable autofocus></wa-input>
</div>
{% set allPages = collections.components %}
{% include "grouped-pages.njk" %}
<div id="component-filter-empty" hidden>
No results
</div>
<script type="module">
const container = document.getElementById('component-filter');
const empty = document.getElementById('component-filter-empty');
const grid = document.getElementById('content');
const input = container.querySelector('wa-input');
function updateResults() {
const filter = input.value.toLowerCase().trim();
// Hide headings while filtering
grid.querySelectorAll('h2').forEach(heading => {
heading.hidden = filter === '' ? false : true;
});
// Show matching components
grid.querySelectorAll('a:has(> wa-card)').forEach(link => {
console.log(link);
const content = link.textContent.toLowerCase();
const keywords = link.getAttribute('data-keywords') || '';
const isMatch = filter === '' || (content + keywords).includes(filter);
link.hidden = !isMatch;
});
// Show empty state when there's a search filter and no results
if (filter !== '' && grid.querySelector('a:not([hidden])') === null) {
empty.hidden = false;
} else {
empty.hidden = true;
}
}
input.addEventListener('wa-input', updateResults);
</script>
<style>
wa-card#drawer-card::part(header) {
--spacing: 0;
justify-content: flex-end;
overflow: hidden;
}
#component-filter {
margin-block-end: var(--wa-space-xl);
}
#component-filter-empty {
border: dashed var(--wa-border-width-m) var(--wa-color-neutral-border-quiet);
border-radius: var(--wa-border-radius-l);
font-size: var(--wa-font-size-l);
color: var(--wa-color-text-quiet);
text-align: center;
padding-block: var(--wa-space-2xl);
margin-block-start: 0
}
</style>
<p class="index-summary">Components are the essential building blocks to create intuitive, cohesive experiences. Browse the library of customizable, framework-friendly web components included in Web Awesome.</p>
<div class="index-grid">
<h2 class="index-category">Actions</h2>
<a href="/docs/components/button">
<wa-card with-header>
<div slot="header">
{% include "svgs/button.njk" %}
</div>
<span class="page-name">Button</span>
</wa-card>
</a>
<a href="/docs/components/button-group">
<wa-card with-header>
<div slot="header">
{% include "svgs/button-group.njk" %}
</div>
<span class="page-name">Button Group</span>
</wa-card>
</a>
<a href="/docs/components/copy-button">
<wa-card with-header>
<div slot="header">
{% include "svgs/copy-button.njk" %}
</div>
<span class="page-name">Copy Button</span>
</wa-card>
</a>
<a href="/docs/components/dropdown">
<wa-card with-header>
<div slot="header">
{% include "svgs/dropdown.njk" %}
</div>
<span class="page-name">Dropdown</span>
</wa-card>
</a>
<a href="/docs/components/icon-button">
<wa-card with-header>
<div slot="header">
{% include "svgs/icon-button.njk" %}
</div>
<span class="page-name">Icon Button</span>
</wa-card>
</a>
<a href="/docs/components/menu">
<wa-card with-header>
<div slot="header">
{% include "svgs/menu.njk" %}
</div>
<span class="page-name">Menu</span>
</wa-card>
</a>
<a href="/docs/components/qr-code">
<wa-card with-header>
<div slot="header">
{% include "svgs/qr-code.njk" %}
</div>
<span class="page-name">QR Code</span>
</wa-card>
</a>
<h2 class="index-category" style="grid-column: 1 / -1">Feedback and Status</h2>
<a href="/docs/components/badge">
<wa-card with-header>
<div slot="header">
{% include "svgs/badge.njk" %}
</div>
<span class="page-name">Badge</span>
</wa-card>
</a>
<a href="/docs/components/callout">
<wa-card with-header>
<div slot="header">
{% include "svgs/callout.njk" %}
</div>
<span class="page-name">Callout</span>
</wa-card>
</a>
<a href="/docs/components/progress-bar">
<wa-card with-header>
<div slot="header">
{% include "svgs/progress-bar.njk" %}
</div>
<span class="page-name">Progress Bar</span>
</wa-card>
</a>
<a href="/docs/components/progress-ring">
<wa-card with-header>
<div slot="header">
{% include "svgs/progress-ring.njk" %}
</div>
<span class="page-name">Progress Ring</span>
</wa-card>
</a>
<a href="/docs/components/skeleton">
<wa-card with-header>
<div slot="header">
{% include "svgs/skeleton.njk" %}
</div>
<span class="page-name">Skeleton</span>
</wa-card>
</a>
<a href="/docs/components/spinner">
<wa-card with-header>
<div slot="header">
{% include "svgs/spinner.njk" %}
</div>
<span class="page-name">Spinner</span>
</wa-card>
</a>
<a href="/docs/components/tag">
<wa-card with-header>
<div slot="header">
{% include "svgs/tag.njk" %}
</div>
<span class="page-name">Tag</span>
</wa-card>
</a>
<a href="/docs/components/tooltip">
<wa-card with-header>
<div slot="header">
{% include "svgs/tooltip.njk" %}
</div>
<span class="page-name">Tooltip</span>
</wa-card>
</a>
<h2 class="index-category">Imagery</h2>
<a href="/docs/components/animated-image">
<wa-card with-header>
<div slot="header">
{% include "svgs/animated-image.njk" %}
</div>
<span class="page-name">Animated Image</span>
</wa-card>
</a>
<a href="/docs/components/avatar">
<wa-card with-header>
<div slot="header">
{% include "svgs/avatar.njk" %}
</div>
<span class="page-name">Avatar</span>
</wa-card>
</a>
<a href="/docs/components/carousel">
<wa-card with-header>
<div slot="header">
{% include "svgs/carousel.njk" %}
</div>
<span class="page-name">Carousel</span>
</wa-card>
</a>
<a href="/docs/components/icon">
<wa-card with-header>
<div slot="header">
{% include "svgs/icon.njk" %}
</div>
<span class="page-name">Icon</span>
</wa-card>
</a>
<a href="/docs/components/image-comparer">
<wa-card with-header>
<div slot="header">
{% include "svgs/image-comparer.njk" %}
</div>
<span class="page-name">Image Comparer</span>
</wa-card>
</a>
<h2 class="index-category">Inputs</h2>
<a href="/docs/components/checkbox">
<wa-card with-header>
<div slot="header">
{% include "svgs/checkbox.njk" %}
</div>
<span class="page-name">Checkbox</span>
</wa-card>
</a>
<a href="/docs/components/color-picker">
<wa-card with-header>
<div slot="header">
{% include "svgs/color-picker.njk" %}
</div>
<span class="page-name">Color Picker</span>
</wa-card>
</a>
<a href="/docs/components/input">
<wa-card with-header>
<div slot="header">
{% include "svgs/input.njk" %}
</div>
<span class="page-name">Input</span>
</wa-card>
</a>
<a href="/docs/components/radio-group">
<wa-card with-header>
<div slot="header">
{% include "svgs/radio-group.njk" %}
</div>
<span class="page-name">Radio Group</span>
</wa-card>
</a>
<a href="/docs/components/range">
<wa-card with-header>
<div slot="header">
{% include "svgs/range.njk" %}
</div>
<span class="page-name">Range</span>
</wa-card>
</a>
<a href="/docs/components/rating">
<wa-card with-header>
<div slot="header">
{% include "svgs/rating.njk" %}
</div>
<span class="page-name">Rating</span>
</wa-card>
</a>
<a href="/docs/components/select">
<wa-card with-header>
<div slot="header">
{% include "svgs/select.njk" %}
</div>
<span class="page-name">Select</span>
</wa-card>
</a>
<a href="/docs/components/switch">
<wa-card with-header>
<div slot="header">
{% include "svgs/switch.njk" %}
</div>
<span class="page-name">Switch</span>
</wa-card>
</a>
<a href="/docs/components/textarea">
<wa-card with-header>
<div slot="header">
{% include "svgs/textarea.njk" %}
</div>
<span class="page-name">Textarea</span>
</wa-card>
</a>
<h2 class="index-category">Navigation</h2>
<a href="/docs/components/breadcrumb">
<wa-card with-header>
<div slot="header">
{% include "svgs/breadcrumb.njk" %}
</div>
<span class="page-name">Breadcrumb</span>
</wa-card>
</a>
<a href="/docs/components/tab-group">
<wa-card with-header>
<div slot="header">
{% include "svgs/tab-group.njk" %}
</div>
<span class="page-name">Tab Group</span>
</wa-card>
</a>
<a href="/docs/components/tree">
<wa-card with-header>
<div slot="header">
{% include "svgs/tree.njk" %}
</div>
<span class="page-name">Tree</span>
</wa-card>
</a>
<h2 class="index-category">Organization</h2>
<a href="/docs/components/card">
<wa-card with-header>
<div slot="header">
{% include "svgs/card.njk" %}
</div>
<span class="page-name">Card</span>
</wa-card>
</a>
<a href="/docs/components/details">
<wa-card with-header>
<div slot="header">
{% include "svgs/details.njk" %}
</div>
<span class="page-name">Details</span>
</wa-card>
</a>
<a href="/docs/components/dialog">
<wa-card with-header>
<div slot="header">
{% include "svgs/dialog.njk" %}
</div>
<span class="page-name">Dialog</span>
</wa-card>
</a>
<a href="/docs/components/divider">
<wa-card with-header>
<div slot="header">
{% include "svgs/divider.njk" %}
</div>
<span class="page-name">Divider</span>
</wa-card>
</a>
<a href="/docs/components/drawer">
<wa-card with-header id="drawer-card">
<div slot="header">
{% include "svgs/drawer.njk" %}
</div>
<span class="page-name">Drawer</span>
</wa-card>
</a>
<a href="/docs/components/page">
<wa-card with-header>
<div slot="header">
{% include "svgs/page.njk" %}
</div>
<span class="page-name">Page</span>
</wa-card>
</a>
<a href="/docs/components/split-panel">
<wa-card with-header>
<div slot="header">
{% include "svgs/split-panel.njk" %}
</div>
<span class="page-name">Split Panel</span>
</wa-card>
</a>
<h2 class="index-category">Utilities</h2>
<a href="/docs/components/animation">
<wa-card with-header>
<div slot="header">
{% include "svgs/animation.njk" %}
</div>
<span class="page-name">Animation</span>
</wa-card>
</a>
<a href="/docs/components/format-bytes">
<wa-card with-header>
<div slot="header">
{% include "svgs/format-bytes.njk" %}
</div>
<span class="page-name">Format Bytes</span>
</wa-card>
</a>
<a href="/docs/components/format-date">
<wa-card with-header>
<div slot="header">
{% include "svgs/format-date.njk" %}
</div>
<span class="page-name">Format Date</span>
</wa-card>
</a>
<a href="/docs/components/format-number">
<wa-card with-header>
<div slot="header">
{% include "svgs/format-number.njk" %}
</div>
<span class="page-name">Format Number</span>
</wa-card>
</a>
<a href="/docs/components/include">
<wa-card with-header>
<div slot="header">
{% include "svgs/include.njk" %}
</div>
<span class="page-name">Include</span>
</wa-card>
</a>
<a href="/docs/components/mutation-observer">
<wa-card with-header>
<div slot="header">
{% include "svgs/mutation-observer.njk" %}
</div>
<span class="page-name">Mutation Observer</span>
</wa-card>
</a>
<a href="/docs/components/popup">
<wa-card with-header>
<div slot="header">
{% include "svgs/popup.njk" %}
</div>
<span class="page-name">Popup</span>
</wa-card>
</a>
<a href="/docs/components/relative-time">
<wa-card with-header>
<div slot="header">
{% include "svgs/relative-time.njk" %}
</div>
<span class="page-name">Relative Time</span>
</wa-card>
</a>
<a href="/docs/components/resize-observer">
<wa-card with-header>
<div slot="header">
{% include "svgs/resize-observer.njk" %}
</div>
<span class="page-name">Resize Observer</span>
</wa-card>
</a>
<a href="/docs/components/visually-hidden">
<wa-card with-header>
<div slot="header">
{% include "svgs/visually-hidden.njk" %}
</div>
<span class="page-name">Visually Hidden</span>
</wa-card>
</a>
</div>

View File

@@ -1,10 +1,7 @@
---
title: Input
description: Inputs collect data from the user.
tags: [inputs, forms]
icon: input
native: input
keywords: textfield text field
layout: component
---
```html {.example}
@@ -25,12 +22,12 @@ Use the `label` attribute to give the input an accessible label. For labels that
<wa-input label="What is your name?"></wa-input>
```
### Hint
### Help Text
Add descriptive hint to an input with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
Add descriptive help text to an input with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
```html {.example}
<wa-input label="Nickname" hint="What would you like people to call you?"></wa-input>
<wa-input label="Nickname" help-text="What would you like people to call you?"></wa-input>
```
### Placeholders
@@ -57,12 +54,12 @@ Add the `password-toggle` attribute to add a toggle button that will show the pa
<wa-input type="password" placeholder="Password Toggle" password-toggle></wa-input>
```
### Appearance
### Filled Inputs
Use the `appearance` attribute to change the input's visual appearance.
Add the `filled` attribute to draw a filled input.
```html {.example}
<wa-input placeholder="Type something" appearance="filled"></wa-input>
<wa-input placeholder="Type something" filled></wa-input>
```
### Disabled
@@ -135,35 +132,33 @@ Use the `prefix` and `suffix` slots to add icons.
Use [CSS parts](#css-parts) to customize the way form controls are drawn. This example uses CSS grid to position the label to the left of the control, but the possible orientations are nearly endless. The same technique works for inputs, textareas, radio groups, and similar form controls.
```html {.example}
<div class="label-on-left">
<wa-input label="Name" hint="Enter your name"></wa-input>
<wa-input label="Email" type="email" hint="Enter your email"></wa-input>
<wa-textarea label="Bio" hint="Tell us something about yourself"></wa-textarea>
</div>
<wa-input class="label-on-left" label="Name" help-text="Enter your name"></wa-input>
<wa-input class="label-on-left" label="Email" type="email" help-text="Enter your email"></wa-input>
<wa-textarea class="label-on-left" label="Bio" help-text="Tell us something about yourself"></wa-textarea>
<style>
.label-on-left {
--label-width: 3.75rem;
--gap-width: 1rem;
}
.label-on-left + .label-on-left {
margin-top: var(--wa-space-m);
}
.label-on-left::part(form-control) {
display: grid;
grid-template-columns: auto 1fr;
gap: var(--wa-space-l);
grid: auto / var(--label-width) 1fr;
gap: var(--wa-space-3xs) var(--gap-width);
align-items: center;
}
wa-input, wa-textarea {
grid-column: 1 / -1;
grid-row-end: span 2;
display: grid;
grid-template-columns: subgrid;
gap: 0 var(--wa-space-l);
align-items: center;
}
.label-on-left::part(form-control-label) {
text-align: right;
}
::part(label) {
text-align: right;
}
::part(hint) {
grid-column: 2;
}
.label-on-left::part(form-control-help-text) {
grid-column-start: 2;
}
</style>
```
```

View File

@@ -1,9 +1,7 @@
---
title: Menu Item
description: Menu items provide options for the user to pick from in a menu.
tags: component
parent: menu
icon: menu
layout: component
---
```html {.example}

View File

@@ -1,9 +1,7 @@
---
title: Menu Label
description: Menu labels are used to describe a group of menu items.
tags: component
parent: menu
icon: menu
layout: component
---
```html {.example}

View File

@@ -1,8 +1,7 @@
---
title: Menu
description: Menus provide a list of options for the user to choose from.
tags: [actions, apps]
icon: menu
layout: component
---
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.

View File

@@ -1,8 +1,7 @@
---
title: Mutation Observer
description: The Mutation Observer component offers a thin, declarative interface to the MutationObserver API.
tags: [helpers, primitives]
icon: mutation-observer
layout: component
---
The mutation observer will report changes to the content it wraps through the `wa-mutation` event. When emitted, a collection of [MutationRecord](https://developer.mozilla.org/en-US/docs/Web/API/MutationRecord) objects will be attached to `event.detail` that contains information about how it changed.

View File

@@ -1,9 +1,7 @@
---
title: Option
description: Options define the selectable items within various form controls such as select.
tags: component
parent: select
icon: option
layout: component
---
```html {.example}

View File

@@ -2,7 +2,6 @@
title: Sample Documentation Page
description: A sample page for a documentation website using Web Awesome's page component.
layout: blank
eleventyExcludeFromCollections: true
---
<style>
@@ -10,7 +9,9 @@ eleventyExcludeFromCollections: true
--menu-width: 15rem;
--aside-width: 15rem;
}
wa-page[view='desktop'] [data-toggle-nav] {
display: none;
}
wa-page[view='mobile'] {
--menu-width: auto;
--aside-width: auto;
@@ -127,7 +128,7 @@ eleventyExcludeFromCollections: true
</a>
</nav>
<header slot="main-header">
<div class="wa-flank:end wa-border-radius-l wa-theme-default-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
<div class="wa-flank:end wa-border-radius-m wa-theme-default-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
<div class="wa-stack" style="margin: var(--wa-space-2xl);">
<h1>Great Horned Owl</h1>
<wa-divider></wa-divider>
@@ -149,7 +150,7 @@ eleventyExcludeFromCollections: true
<span class="wa-caption-m">Least Concern</span>
</div>
</div>
<div class="wa-frame" style="wa-border-radius-l max-inline-size: 40ch;">
<div class="wa-frame" style="border-radius: var(--wa-border-radius-m); max-inline-size: 40ch;">
<img src="https://images.unsplash.com/photo-1544648720-132573cb590d?q=20" />
</div>
</div>
@@ -234,4 +235,4 @@ eleventyExcludeFromCollections: true
<a href="#">Youth Audubon Camps</a>
</div>
</footer>
</wa-page>
</wa-page>

View File

@@ -2,7 +2,6 @@
title: Sample Media App Page
description: A sample page for a media app using Web Awesome's page component.
layout: blank
eleventyExcludeFromCollections: true
---
<wa-page class="wa-theme-default-dark">
@@ -277,21 +276,21 @@ eleventyExcludeFromCollections: true
<div slot="main-footer" class="wa-grid wa-gap-xl">
<h2 class="wa-heading-2xl">More You Might Like</h2>
<div class="wa-stack wa-gap-xs">
<div class="wa-frame wa-border-radius-l">
<div class="wa-frame wa-border-radius-m">
<img src="https://images.unsplash.com/photo-1675219119611-40323b738563?q=20" alt="" />
</div>
<span class="wa-heading-s">Festival of Lights</span>
<span class="wa-caption-s">Station</span>
</div>
<div class="wa-stack wa-gap-xs">
<div class="wa-frame wa-border-radius-l">
<div class="wa-frame wa-border-radius-m">
<img src="https://images.unsplash.com/photo-1481930916222-5ec4696fc0f2?q=20" alt="" />
</div>
<span class="wa-heading-s">Holiday Cheer</span>
<span class="wa-caption-s">Essential Playlist</span>
</div>
<div class="wa-stack wa-gap-xs">
<div class="wa-frame wa-border-radius-l">
<div class="wa-frame wa-border-radius-m">
<img src="https://images.unsplash.com/photo-1667514627762-521b1c815a89?q=20" alt="" />
</div>
<span class="wa-heading-s">Nursery Rhymes from the Shire</span>
@@ -306,7 +305,9 @@ eleventyExcludeFromCollections: true
--wa-tooltip-arrow-size: 0;
background-color: var(--wa-color-surface-lowered);
}
wa-page[view='desktop'] [data-toggle-nav] {
display: none;
}
wa-page[view='mobile'] {
--menu-width: auto;
}
@@ -341,7 +342,7 @@ eleventyExcludeFromCollections: true
margin: 0;
}
[slot='navigation'] ul a {
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
padding: var(--wa-space-xs);
}
[slot='navigation'] ul a:hover,
@@ -357,7 +358,7 @@ eleventyExcludeFromCollections: true
justify-content: center;
}
[slot='navigation'] #recent wa-icon {
border-radius: var(--wa-border-radius-s);
border-radius: var(--wa-border-radius-xs);
}
[slot='main-header'] {
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
@@ -397,4 +398,4 @@ eleventyExcludeFromCollections: true
font-size: 3rem;
padding: 1.5rem;
}
</style>
</style>

View File

@@ -1,10 +1,8 @@
---
title: Page
description: Pages offer an easy way to scaffold entire page layouts using minimal markup.
tags: [organization, layout]
layout: component
isPro: true
order: 1
# icon: page
---
The page component is designed to power full webpages. It is flexible enough to handle most modern designs and includes a simple mechanism for handling desktop and mobile navigation.
@@ -41,10 +39,6 @@ body {
}
```
::info
If you use [native styles](/docs/native/), this is already taken care of.
:::
## Examples
:::warning
@@ -69,7 +63,7 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
<header slot="header" class="wa-split">
<div class="wa-cluster">
<wa-icon name="feather-pointed" style="color: var(--wa-color-brand-fill-loud); font-size: 1.5em;"></wa-icon>
<span id="brand-name" class="wa-heading-s wa-desktop-only">Audubon Worldwide</span>
<span id="brand-name" class="wa-heading-s">Audubon Worldwide</span>
<a href="#">Our Work</a>
<a href="#">About Us</a>
<a href="#">Discover</a>
@@ -89,7 +83,7 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
<wa-breadcrumb-item>Great Horned Owl</wa-breadcrumb-item>
</wa-breadcrumb>
</div>
<wa-input id="search" class="wa-desktop-only" placeholder="Search" size="small" style="max-inline-size: 12rem;">
<wa-input id="search" placeholder="Search" size="small" style="max-inline-size: 12rem;">
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
</wa-input>
</nav>
@@ -109,17 +103,17 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
<a href="#conservation">Conservation</a>
</nav>
<nav slot="navigation-footer">
<a href="#" class="wa-flank">
<a href="#" class="wa-flank" style="--flank-size: 1.25em;">
<wa-icon name="camera"></wa-icon>
<span>Photo Gallery</span>
</a>
<a href="#" class="wa-flank">
<a href="#" class="wa-flank" style="--flank-size: 1.25em;">
<wa-icon name="map-location-dot"></wa-icon>
<span>Interactive Range Map</span>
</a>
</nav>
<header slot="main-header">
<div class="wa-flank:end wa-border-radius-l wa-theme-default-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
<div class="wa-flank:end wa-border-radius-m wa-theme-default-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
<div class="wa-stack" style="margin: var(--wa-space-2xl);">
<h1>Great Horned Owl</h1>
<wa-divider></wa-divider>
@@ -141,7 +135,7 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
<span class="wa-caption-m">Least Concern</span>
</div>
</div>
<div class="wa-frame" style="border-radius: var(--wa-border-radius-l); max-inline-size: 40ch;">
<div class="wa-frame" style="border-radius: var(--wa-border-radius-m); max-inline-size: 40ch;">
<img src="https://images.unsplash.com/photo-1544648720-132573cb590d?q=20" />
</div>
</div>
@@ -166,7 +160,7 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
</ul>
</section>
</footer>
<aside slot="aside" class="wa-desktop-only">
<aside slot="aside">
<h2 class="wa-heading-m">Discover More Birds</h2>
<wa-card with-image>
<div slot="image" class="wa-frame">
@@ -233,16 +227,18 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
--menu-width: 15rem;
--aside-width: 15rem;
}
wa-page[view='desktop'] {
[slot*='navigation'] {
border-inline-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
}
wa-page[view='desktop'] [data-toggle-nav] {
display: none;
}
wa-page[view='mobile'] {
--menu-width: auto;
--aside-width: auto;
}
wa-page[view='mobile'] [slot='aside'],
wa-page[view='mobile'] #brand-name,
wa-page[view='mobile'] #search {
display: none;
}
[slot='banner'] {
--wa-color-text-link: var(--wa-color-neutral-on-loud);
background-color: var(--wa-color-neutral-fill-loud);
@@ -261,16 +257,14 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
[slot='navigation-header'] {
border-block-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
}
wa-page[view='desktop'] [slot*='navigation'] {
border-inline-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
}
[slot*='navigation'] a {
--wa-color-text-link: var(--wa-color-text-normal);
}
[slot='navigation-footer'] {
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
.wa-flank {
--flank-size: 1.25em;
}
}
[slot='main-header'],
main,
@@ -287,11 +281,6 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
font-size: var(--wa-font-size-s);
}
</style>
<script>
const sectionAnchors = document.querySelectorAll("[slot*='navigation'] a[href*='#']");
sectionAnchors.forEach((sectionAnchor) => sectionAnchor.setAttribute("data-drawer", "close"));
</script>
```
### Media
@@ -306,7 +295,7 @@ A sample media app page using `header`, `navigation-header`, `main-header`, and
<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-input id="search-header" placeholder="Search" style="max-inline-size: 100%;">
<wa-icon slot="prefix" name="magnifying-glass" ></wa-icon>
</wa-input>
<div class="wa-cluster">
@@ -315,7 +304,7 @@ A sample media app page using `header`, `navigation-header`, `main-header`, and
</div>
</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-input id="search-nav-drawer" placeholder="Search" style="max-inline-size: 100%;">
<wa-icon slot="prefix" name="magnifying-glass" ></wa-icon>
</wa-input>
<div class="wa-split">
@@ -576,21 +565,21 @@ A sample media app page using `header`, `navigation-header`, `main-header`, and
<div slot="main-footer" class="wa-grid wa-gap-xl wa-align-items-center">
<h2 class="wa-heading-2xl">More You Might Like</h2>
<div class="wa-stack wa-gap-xs">
<div class="wa-frame wa-border-radius-l">
<div class="wa-frame wa-border-radius-m">
<img src="https://images.unsplash.com/photo-1675219119611-40323b738563?q=20" alt="" />
</div>
<span class="wa-heading-s">Festival of Lights</span>
<span class="wa-caption-s">Station</span>
</div>
<div class="wa-stack wa-gap-xs">
<div class="wa-frame wa-border-radius-l">
<div class="wa-frame wa-border-radius-m">
<img src="https://images.unsplash.com/photo-1481930916222-5ec4696fc0f2?q=20" alt="" />
</div>
<span class="wa-heading-s">Holiday Cheer</span>
<span class="wa-caption-s">Essential Playlist</span>
</div>
<div class="wa-stack wa-gap-xs">
<div class="wa-frame wa-border-radius-l">
<div class="wa-frame wa-border-radius-m">
<img src="https://images.unsplash.com/photo-1667514627762-521b1c815a89?q=20" alt="" />
</div>
<span class="wa-heading-s">Nursery Rhymes from the Shire</span>
@@ -605,15 +594,18 @@ A sample media app page using `header`, `navigation-header`, `main-header`, and
--wa-tooltip-arrow-size: 0;
background-color: var(--wa-color-surface-lowered);
}
wa-page[view='desktop'] :is([data-toggle-nav], #search-nav-drawer) {
display: none;
}
wa-page[view='mobile'] {
--menu-width: auto;
[slot*='main'], main {
padding: var(--wa-space-xl);
}
}
wa-page[view='mobile'] #search-header {
display: none;
}
wa-page[view='mobile'] :is([slot*='main'], main) {
padding: var(--wa-space-xl);
}
wa-page,
[slot='header'],
wa-page[view='desktop'] [slot*='navigation'] {
@@ -633,41 +625,37 @@ A sample media app page using `header`, `navigation-header`, `main-header`, and
padding-block-end: 0 !important;
padding-block-start: var(--wa-space-3xl);
}
[slot='navigation'] {
a {
--wa-color-text-link: var(--wa-color-text-normal);
--wa-link-decoration-default: none;
--wa-link-decoration-hover: none;
--flank-size: 2rem;
font-weight: var(--wa-font-weight-action);
gap: 0.5rem;
}
ul {
list-style: none;
margin: 0;
a {
border-radius: var(--wa-border-radius-m);
padding: var(--wa-space-xs);
&:hover {
background-color: color-mix(in oklab, var(--wa-color-surface-default), var(--wa-color-brand-fill-quiet));
}
}
}
wa-icon {
align-items: center;
aspect-ratio: 1;
color: var(--wa-color-brand-fill-loud);
display: flex;
height: var(--flank-size);
justify-content: center;
}
#recent wa-icon {
border-radius: var(--wa-border-radius-s);
}
[slot='navigation'] a {
--wa-color-text-link: var(--wa-color-text-normal);
--wa-link-decoration-default: none;
--wa-link-decoration-hover: none;
--flank-size: 2rem;
font-weight: var(--wa-font-weight-action);
gap: 0.5rem;
}
[slot='navigation'] ul {
list-style: none;
margin: 0;
}
[slot='navigation'] ul a {
border-radius: var(--wa-border-radius-s);
padding: var(--wa-space-xs);
}
[slot='navigation'] ul a:hover,
main ol li:hover {
background-color: color-mix(in oklab, var(--wa-color-surface-default), var(--wa-color-brand-fill-quiet));
}
[slot='navigation'] wa-icon {
align-items: center;
aspect-ratio: 1;
color: var(--wa-color-brand-fill-loud);
display: flex;
height: var(--flank-size);
justify-content: center;
}
[slot='navigation'] #recent wa-icon {
border-radius: var(--wa-border-radius-xs);
}
[slot='main-header'] {
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
border-inline: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
@@ -679,18 +667,12 @@ A sample media app page using `header`, `navigation-header`, `main-header`, and
}
main ol li {
padding: var(--wa-space-m);
&:hover {
background-color: color-mix(in oklab, var(--wa-color-surface-default), var(--wa-color-brand-fill-quiet));
}
&:not(:first-child) {
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
}
.wa-flank {
--flank-size: 2rem;
}
}
main ol li .wa-flank {
--flank-size: 2rem;
}
main ol li:not(:first-child) {
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
}
main,
[slot='main-footer'] {
@@ -716,11 +698,6 @@ A sample media app page using `header`, `navigation-header`, `main-header`, and
max-inline-size: 30ch;
}
</style>
<script>
const sectionAnchors = document.querySelectorAll("[slot*='navigation'] a[href*='#']");
sectionAnchors.forEach((sectionAnchor) => sectionAnchor.setAttribute("data-drawer", "close"));
</script>
```
@@ -784,29 +761,11 @@ You can override the default display and flex properties for each slot with your
#### Responsive Navigation
When you use the `navigation` slot, your slotted content automatically collapses into a drawer on smaller screens.
The breakpoint at which this occurs is `768px` by default, but you can change it using the `mobile-breakpoint` attribute,
which takes either a number or a [CSS length](https://developer.mozilla.org/en-US/docs/Web/CSS/length).
The breakpoint at which this occurs is `768px` by default, but you can change it using the `mobile-breakpoint` attribute.
```html
<wa-page mobile-breakpoint="600"> ... </wa-page>
```
```html {.example viewport}
<wa-page mobile-breakpoint="50ch">
<div slot=navigation>Nav</div>
<header slot=header>
<div style="width: 50ch; background: gold">Im 50ch wide</div>
</header>
</wa-page>
<style>
html,
body {
min-height: 100%;
height: 100%;
padding: 0;
margin: 0;
}
</style>
```
By default, a "hamburger" button appears in the `header` slot to toggle the navigation menu on smaller screens.
You can customize what this looks like by slotting your own button in the `toggle-navigation` slot,
@@ -835,10 +794,6 @@ wa-page[view='desktop'] [data-toggle-nav] {
}
```
::info
If you use [native styles](/docs/native/), this is already taken care for you, and the `data-toggle-nav` button is already hidden on wider screens.
:::
#### Custom Widths
You specify widths for some slots on your page with [CSS custom properties](#css-custom-properties) for `--menu-width`, `--main-width`, and `--aside-width`.
@@ -854,10 +809,9 @@ You can use a similar approach for `--aside-width` to hide the `aside` slot on s
```css
wa-page[view='mobile'] {
--aside-width: auto;
[slot='aside'] {
display: none;
}
}
wa-page[view='mobile'] [slot='aside'] {
display: none;
}
```
@@ -873,16 +827,3 @@ You can override the default spacing for each slot with your own CSS. In this ex
}
```
## Utility classes
[Native styles](/docs/native/) define a few useful defaults for `<wa-page>`, as well as
two utility classes you can use for common responsive design tasks:
- `.wa-mobile-only` hides an element on the desktop view
- `.wa-desktop-only` hides an element on the mobile view
If you dont want to use [native styles](/docs/native/), you can include this stylesheet in your project to use these:
```html
<link rel="stylesheet" href="{% cdnUrl 'styles/components/page.css' %}" />
```

View File

@@ -1,8 +1,7 @@
---
title: Popup
description: 'Popup is a utility that lets you declaratively anchor "popup" containers to another element.'
tags: [helpers, primitives]
icon: popup
layout: component
---
This component's name is inspired by [`<popup>`](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md). It uses [Floating UI](https://floating-ui.com/) under the hood to provide a well-tested, lightweight, and fully declarative positioning utility for tooltips, dropdowns, and more.
@@ -78,7 +77,7 @@ Popup is a low-level utility built specifically for positioning elements. Do not
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
.popup-overview-options {
@@ -136,7 +135,7 @@ Popups are inactive and hidden until the `active` attribute is applied. Removing
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
</style>
@@ -173,7 +172,7 @@ By default, anchors are slotted into the popup using the `anchor` slot. If your
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
</style>
```
@@ -220,7 +219,7 @@ Since placement is preferred when using `flip`, you can observe the popup's curr
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
.popup-placement wa-select {
@@ -264,7 +263,7 @@ Use the `distance` attribute to change the distance between the popup and its an
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
.popup-distance wa-range {
@@ -308,7 +307,7 @@ The `skidding` attribute is similar to `distance`, but instead allows you to off
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
.popup-skidding wa-range {
@@ -383,7 +382,7 @@ By default, the arrow will be aligned as close to the center of the _anchor_ as
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
.popup-arrow-options {
@@ -450,7 +449,7 @@ Use the `sync` attribute to make the popup the same width or height as the ancho
min-width: 50px;
min-height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
.popup-sync wa-select {
@@ -510,7 +509,7 @@ Toggle the switch and scroll the container to see the difference.
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
.popup-strategy wa-switch {
@@ -566,7 +565,7 @@ Scroll the container to see how the popup flips to prevent clipping.
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
</style>
@@ -619,7 +618,7 @@ Scroll the container to see how the popup changes it's fallback placement to pre
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
</style>
```
@@ -661,7 +660,7 @@ Toggle the switch to see the difference.
width: 300px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
</style>
@@ -713,7 +712,7 @@ Scroll the container to see the popup resize as its available space changes.
.popup-auto-size .box {
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
/* This sets the preferred size of the popup's content */
width: 100px;
@@ -763,7 +762,7 @@ When a gap exists between the anchor and the popup element, this option will add
width: 100px;
height: 50px;
background: var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
}
.popup-hover-bridge wa-range {

View File

@@ -1,15 +1,11 @@
---
title: Progress Bar
description: Progress bars are used to show the status of an ongoing operation.
tags: [feedback, apps]
native: progress
icon: progress-bar
layout: component
---
```html {.example}
<wa-progress-bar value="40">
<wa-icon slot="prefix" name="tasks"></wa-icon>
</wa-progress-bar>
<wa-progress-bar value="50"></wa-progress-bar>
```
## Examples
@@ -17,16 +13,17 @@ icon: progress-bar
### Labels
Use the `label` attribute to label the progress bar and tell assistive devices how to announce it.
```html {.example}
<wa-progress-bar value="50" label="Upload progress"></wa-progress-bar>
```
### Custom Height
Use the `height` CSS property to set the progress bar's height.
Use the `--height` custom property to set the progress bar's height.
```html {.example}
<wa-progress-bar value="50" style="height: 6px;"></wa-progress-bar>
<wa-progress-bar value="50" style="--height: 6px;"></wa-progress-bar>
```
### Showing Values
@@ -34,19 +31,17 @@ Use the `height` CSS property to set the progress bar's height.
Use the default slot to show a value.
```html {.example}
<div class="wa-stack">
<wa-progress-bar value="50" id="progress-bar-demo">50%</wa-progress-bar>
<wa-progress-bar value="50" class="progress-bar-values">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>
</div>
</div>
<br />
<wa-button circle><wa-icon name="minus" variant="solid" label="Decrease"></wa-icon></wa-button>
<wa-button circle><wa-icon name="plus" variant="solid" label="Increase"></wa-icon></wa-button>
<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 progressBar = document.querySelector('.progress-bar-values');
const subtractButton = progressBar.nextElementSibling.nextElementSibling;
const addButton = subtractButton.nextElementSibling;
addButton.addEventListener('click', () => {
const value = Math.min(100, progressBar.value + 10);

View File

@@ -1,14 +1,11 @@
---
title: Progress Ring
description: Progress rings are used to show the progress of a determinate operation in a circular fashion.
tags: [feedback, apps]
icon: progress-ring
layout: component
---
```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 +15,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 +23,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
@@ -44,13 +37,19 @@ To change the color, use the `--track-color` and `--indicator-color` custom prop
--track-color: pink;
--indicator-color: deeppink;
"
>
<wa-icon slot="prefix" name="palette"></wa-icon>
</wa-progress-ring>
></wa-progress-ring>
```
### Labels
Use the `label` attribute to label the progress ring and tell assistive devices how to announce it.
```html {.example}
<wa-progress-ring value="50" label="Upload progress"></wa-progress-ring>
```
### Showing Values
Use the default slot to show a label inside the progress ring.
```html {.example}

View File

@@ -1,8 +1,7 @@
---
title: QR Code
description: Generates a QR code and renders it using the Canvas API.
tags: [actions, apps, niche]
icon: qr-code
layout: component
---
QR codes are useful for providing small pieces of information to users who can quickly scan them with a smartphone. Most smartphones have built-in QR code scanners, so simply pointing the camera at a QR code will decode it and allow the user to visit a website, dial a phone number, read a message, etc.
@@ -12,9 +11,7 @@ QR codes are useful for providing small pieces of information to users who can q
<wa-qr-code value="https://shoelace.style/" label="Scan this code to visit Web Awesome on the web!"></wa-qr-code>
<br />
<wa-input maxlength="255" clearable label="Value">
<wa-icon slot="prefix" name="link"></wa-icon>
</wa-input>
<wa-input maxlength="255" clearable label="Value"></wa-input>
</div>
<script>
@@ -46,9 +43,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 +51,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 +59,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 +68,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

@@ -1,9 +1,7 @@
---
title: Radio Button
description: Radios buttons allow the user to select a single option from a group using a button-like control.
tags: forms
parent: radio-group
icon: radio-group
layout: component
---
Radio buttons are designed to be used with [radio groups](/docs/components/radio-group). When a radio button has focus, the arrow keys can be used to change the selected option just like standard radio controls.

View File

@@ -1,8 +1,7 @@
---
title: Radio Group
description: Radio groups are used to group multiple radios or radio buttons so they function as a single form control.
tags: [inputs, forms]
icon: radio-group
layout: component
---
```html {.example}
@@ -15,12 +14,12 @@ icon: radio-group
## Examples
### Hint
### Help Text
Add descriptive hint to a radio group with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
Add descriptive help text to a radio group with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
```html {.example}
<wa-radio-group label="Select an option" hint="Choose the most appropriate option." name="a" value="1">
<wa-radio-group label="Select an option" help-text="Choose the most appropriate 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>
@@ -32,7 +31,7 @@ Add descriptive hint to a radio group with the `hint` attribute. For hints that
[Radio buttons](/docs/components/radio-button) offer an alternate way to display radio controls. In this case, an internal [button group](/docs/components/button-group) is used to group the buttons into a single, cohesive control.
```html {.example}
<wa-radio-group label="Select an option" hint="Select an option that makes you proud." name="a" value="1">
<wa-radio-group label="Select an option" help-text="Select an option that makes you proud." name="a" value="1">
<wa-radio-button value="1">Option 1</wa-radio-button>
<wa-radio-button value="2">Option 2</wa-radio-button>
<wa-radio-button value="3">Option 3</wa-radio-button>
@@ -138,4 +137,4 @@ Use the `setCustomValidity()` method to set a custom validation message. This wi
alert('All fields are valid!');
});
</script>
```
```

View File

@@ -1,10 +1,7 @@
---
title: Radio
description: Radios allow the user to select a single option from a group.
tags: component
parent: radio-group
native: radio
icon: radio-group
layout: component
---
Radios are designed to be used with [radio groups](/docs/components/radio-group).
@@ -47,7 +44,7 @@ Use the `disabled` attribute to disable a radio.
</wa-radio-group>
```
### Sizes
## Sizes
Add the `size` attribute to the [Radio Group](/docs/components/radio-group) to change the radios' size.

View File

@@ -1,9 +1,7 @@
---
title: Range
description: Ranges allow the user to select a single value within a given range using a slider.
tags: [inputs, forms]
native: slider
icon: range
layout: component
---
```html {.example}
@@ -24,12 +22,12 @@ Use the `label` attribute to give the range an accessible label. For labels that
<wa-range label="Volume" min="0" max="100"></wa-range>
```
### Hint
### Help Text
Add descriptive hint to a range with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
Add descriptive help text to a range with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
```html {.example}
<wa-range label="Volume" hint="Controls the volume of the current song." min="0" max="100"></wa-range>
<wa-range label="Volume" help-text="Controls the volume of the current song." min="0" max="100"></wa-range>
```
### Min, Max, and Step
@@ -105,14 +103,3 @@ You can change the tooltip's content by setting the `tooltipFormatter` property
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-range dir="rtl"
label="مقدار"
hint="التحكم في مستوى صوت الأغنية الحالية."
style="--track-color-active: var(--wa-color-brand-fill-loud)" value="10"></wa-range>
```

View File

@@ -1,8 +1,7 @@
---
title: Rating
description: Ratings give users a way to quickly view and provide feedback.
tags: [inputs, interactive]
icon: rating
layout: component
---
```html {.example}
@@ -91,7 +90,7 @@ The event has a payload with `phase` and `value` properties. The `phase` propert
position: relative;
top: -4px;
left: 8px;
border-radius: var(--wa-border-radius-m);
border-radius: var(--wa-border-radius-s);
background: var(--wa-color-neutral-fill-loud);
color: var(--wa-color-neutral-on-loud);
text-align: center;
@@ -139,4 +138,4 @@ You can also use the `getSymbol` property to render different icons based on val
return `<wa-icon name="${icons[value - 1]}"></wa-icon>`;
};
</script>
```
```

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