mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 20:19:13 +00:00
fixed conflicts
This commit is contained in:
9
.github/workflows/ssr_tests.js.yml
vendored
9
.github/workflows/ssr_tests.js.yml
vendored
@@ -1,11 +1,12 @@
|
||||
# # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: SSR Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [next]
|
||||
# push:
|
||||
# branches: [next]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
ssr_test:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as path from 'node:path';
|
||||
import { anchorHeadingsPlugin } from './_utils/anchor-headings.js';
|
||||
import { codeExamplesPlugin } from './_utils/code-examples.js';
|
||||
import { copyCodePlugin } from './_utils/copy-code.js';
|
||||
@@ -6,9 +7,10 @@ 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 litPlugin from '@lit-labs/eleventy-plugin-lit';
|
||||
import { readFile } from 'fs/promises';
|
||||
import componentList from './_data/componentList.js';
|
||||
import nunjucks from 'nunjucks';
|
||||
// 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';
|
||||
@@ -16,7 +18,10 @@ import { searchPlugin } from './_utils/search.js';
|
||||
|
||||
import process from 'process';
|
||||
|
||||
const packageData = JSON.parse(await readFile('./package.json', 'utf-8'));
|
||||
import * as url from 'url';
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
||||
|
||||
const packageData = JSON.parse(await readFile(path.join(__dirname, '..', 'package.json'), 'utf-8'));
|
||||
const isAlpha = process.argv.includes('--alpha');
|
||||
const isDev = process.argv.includes('--develop');
|
||||
|
||||
@@ -24,12 +29,22 @@ const globalData = {
|
||||
package: packageData,
|
||||
isAlpha,
|
||||
layout: 'page.njk',
|
||||
server: {
|
||||
head: '',
|
||||
loginOrAvatar: '',
|
||||
flashes: '',
|
||||
},
|
||||
};
|
||||
|
||||
const passThroughExtensions = ['js', 'css', 'png', 'svg', 'jpg', 'mp4'];
|
||||
const passThrough = [...passThroughExtensions.map(ext => 'docs/**/*.' + ext)];
|
||||
|
||||
export default function (eleventyConfig) {
|
||||
/**
|
||||
* This is the guard we use for now to make sure our final built files dont need a 2nd pass by the server. This keeps us able to still deploy the bare HTML files on Vercel until the app is ready.
|
||||
*/
|
||||
const serverBuild = process.env.WEBAWESOME_SERVER === 'true';
|
||||
|
||||
// NOTE - alpha setting removes certain pages
|
||||
if (isAlpha) {
|
||||
eleventyConfig.ignores.add('**/experimental/**');
|
||||
@@ -55,7 +70,38 @@ export default function (eleventyConfig) {
|
||||
|
||||
// Shortcodes - {% shortCode arg1, arg2 %}
|
||||
eleventyConfig.addShortcode('cdnUrl', location => {
|
||||
return `https://early.webawesome.com/webawesome@${packageData.version}/dist/` + location.replace(/^\//, '');
|
||||
return `https://early.webawesome.com/webawesome@${packageData.version}/dist/` + (location || '').replace(/^\//, '');
|
||||
});
|
||||
|
||||
// Turns `{% server "foo" %} into `{{ server.foo | safe }}` when the WEBAWESOME_SERVER variable is set to "true"
|
||||
eleventyConfig.addShortcode('server', function (property) {
|
||||
if (serverBuild) {
|
||||
return `{{ server.${property} | safe }}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
|
||||
eleventyConfig.addTransform('second-nunjucks-transform', function NunjucksTransform(content) {
|
||||
// For a server build, we expect a server to run the second transform.
|
||||
if (serverBuild) {
|
||||
return content;
|
||||
}
|
||||
|
||||
// Only run the transform on files nunjucks would transform.
|
||||
if (!this.page.inputPath.match(/.(md|html|njk)$/)) {
|
||||
return content;
|
||||
}
|
||||
|
||||
/** This largely mimics what an app would do and just stubs out what we don't care about. */
|
||||
return nunjucks.renderString(content, {
|
||||
// Stub the server EJS shortcodes.
|
||||
server: {
|
||||
head: '',
|
||||
loginOrAvatar: '',
|
||||
flashes: '',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// Paired shortcodes - {% shortCode %}content{% endShortCode %}
|
||||
@@ -117,29 +163,6 @@ export default function (eleventyConfig) {
|
||||
]),
|
||||
);
|
||||
|
||||
// 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`;
|
||||
});
|
||||
|
||||
eleventyConfig.addPlugin(litPlugin, {
|
||||
mode: 'worker',
|
||||
componentModules,
|
||||
});
|
||||
}
|
||||
|
||||
// Build the search index
|
||||
eleventyConfig.addPlugin(
|
||||
searchPlugin({
|
||||
@@ -166,6 +189,31 @@ export default function (eleventyConfig) {
|
||||
eleventyConfig.addPassthroughCopy(glob);
|
||||
}
|
||||
|
||||
// // SSR plugin
|
||||
// // Make sure this is the last thing, we don't want to run the risk of accidentally transforming shadow roots with the nunjucks 2nd transform.
|
||||
// if (!isDev) {
|
||||
// //
|
||||
// // Problematic components in SSR land:
|
||||
// // - 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];
|
||||
// const componentDirectory = process.env.UNBUNDLED_DIST_DIRECTORY || path.join('.', 'dist');
|
||||
// return path.join(componentDirectory, 'components', name, `${name}.js`);
|
||||
// });
|
||||
//
|
||||
// eleventyConfig.addPlugin(litPlugin, {
|
||||
// mode: 'worker',
|
||||
// componentModules,
|
||||
// });
|
||||
// }
|
||||
|
||||
return {
|
||||
markdownTemplateEngine: 'njk',
|
||||
dir: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-fa-kit-code="b10bfbde90" data-cdn-url="{% cdnUrl %}">
|
||||
<html lang="en" data-fa-kit-code="b10bfbde90" data-cdn-url="{% cdnUrl %}" class="wa-cloak">
|
||||
<head>
|
||||
{% include 'head.njk' %}
|
||||
<meta name="theme-color" content="#f36944">
|
||||
@@ -50,6 +50,9 @@
|
||||
Search
|
||||
<kbd slot="suffix" class="only-desktop">/</kbd>
|
||||
</wa-button>
|
||||
|
||||
{# Login #}
|
||||
{% server "loginOrAvatar" %}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -76,14 +79,19 @@
|
||||
</aside>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{# Main #}
|
||||
<main id="content">
|
||||
{# Expandable outline #}
|
||||
{% if hasOutline %}
|
||||
<nav id="outline-expandable">
|
||||
<details class="outline-links">
|
||||
<summary>On this page</summary>
|
||||
</details>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
<div id="flashes">{% server "flashes" %}</div>
|
||||
|
||||
{% block header %}
|
||||
{% include 'breadcrumbs.njk' %}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
{% set breadcrumbs = page.url | breadcrumbs %}
|
||||
{% if breadcrumbs.length > 0 %}
|
||||
{% set ancestors = page.url | ancestors %}
|
||||
|
||||
{% if ancestors.length > 0 %}
|
||||
<wa-breadcrumb id="docs-breadcrumbs">
|
||||
{% for crumb in breadcrumbs %}
|
||||
<wa-breadcrumb-item href="{{ crumb.url }}">{{ crumb.title }}</wa-breadcrumb-item>
|
||||
{% for ancestor in ancestors %}
|
||||
{% if ancestor.page.url != "/" %}
|
||||
<wa-breadcrumb-item href="{{ ancestor.page.url }}">{{ ancestor.data.title }}</wa-breadcrumb-item>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<wa-breadcrumb-item>{# Current page #}</wa-breadcrumb-item>
|
||||
</wa-breadcrumb>
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
{# 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.parent or listChildren -%}
|
||||
{% include "page-card.njk" %}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{% set groupedPages = allPages | groupPages(categories, page) %}
|
||||
{% for category, pages in groupedPages -%}
|
||||
{% if groupedPages.meta.groupCount > 1 and pages.length > 0 %}
|
||||
<h2 class="index-category" id="{{ category | slugify }}">
|
||||
{% if pages.meta.url %}<a href="{{ pages.meta.url }}">{{ pages.meta.title }}</a>
|
||||
{% else %}
|
||||
{{ pages.meta.title }}
|
||||
{% endif %}
|
||||
</h2>
|
||||
{% endif %}
|
||||
{%- for page in pages -%}
|
||||
{% include "page-card.njk" %}
|
||||
{%- endfor -%}
|
||||
{%- endfor -%}
|
||||
</section>
|
||||
|
||||
@@ -23,10 +23,9 @@
|
||||
<script src="/assets/scripts/hydration-errors.js"></script>
|
||||
<link rel="stylesheet" href="/assets/styles/hydration-errors.css">
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.10/+esm"></script>
|
||||
|
||||
{# Web Awesome #}
|
||||
<script type="module" src="/dist/webawesome.ssr-loader.js"></script>
|
||||
<script type="module" src="/dist/webawesome.loader.js"></script>
|
||||
|
||||
<script type="module" src="/assets/scripts/theme-picker.js"></script>
|
||||
{# Preset Theme #}
|
||||
@@ -47,3 +46,7 @@
|
||||
<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" />
|
||||
|
||||
|
||||
{# Used by Web Awesome App to inject other assets into the head. #}
|
||||
{% server "head" %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<a href="{{ page.url }}"{{ page.data.keywords | attr('data-keywords') }}>
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/" + (page.data.icon or "thumbnail-placeholder") + ".njk" %}
|
||||
{% include "svgs/" + (page.data.icon or "thumbnail-placeholder") + ".njk" ignore missing %}
|
||||
</div>
|
||||
<span class="page-name">{{ page.data.title }}</span>
|
||||
{% if pageSubtitle -%}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
{# Some collections (like "patterns") will not have any items in the alpha build for example. So this checks to make sure the collection exists. #}
|
||||
{% if collections[tag] -%}
|
||||
{% set groupUrl %}/docs/{{ tag }}/{% endset %}
|
||||
{% set groupItem = groupUrl | getCollectionItemFromUrl %}
|
||||
{% set children = groupItem.data.children if groupItem.data.children.length > 0 else (collections[tag] | sort) %}
|
||||
|
||||
<wa-details {{ ((tag in (tags or [])) or (groupUrl in page.url)) | attr('open') }}>
|
||||
<h2 slot="summary">
|
||||
{% if groupUrl | getCollectionItemFromUrl %}
|
||||
{% if groupItem %}
|
||||
<a href="{{ groupUrl }}" title="Overview">{{ title or (tag | capitalize) }}
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
@@ -12,10 +15,8 @@
|
||||
{% endif %}
|
||||
</h2>
|
||||
<ul>
|
||||
{% for page in collections[tag] | sort %}
|
||||
{% if not page.data.parent -%}
|
||||
{% for page in children %}
|
||||
{% include 'sidebar-link.njk' %}
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</wa-details>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% if not (isAlpha and page.data.noAlpha) and page.fileSlug != tag and not page.data.unlisted -%}
|
||||
{% if page | show -%}
|
||||
<li>
|
||||
<a href="{{ page.url }}">{{ page.data.title }}</a>
|
||||
{% if page.data.status == 'experimental' %}<wa-icon name="flask"></wa-icon>{% endif %}
|
||||
|
||||
8
docs/_includes/svgs/action-panel.njk
Normal file
8
docs/_includes/svgs/action-panel.njk
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg width="96" height="57" viewBox="0 0 96 57" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 1H84C90.0751 1 95 5.92487 95 12V45C95 51.0751 90.0751 56 84 56H12C5.92487 56 1 51.0751 1 45V12C1 5.92487 5.92487 1 12 1Z" fill="white" stroke="#E4E5E9" stroke-width="2"/>
|
||||
<rect x="7" y="39" width="50" height="11" rx="4" fill="#4895FD"/>
|
||||
<rect x="7" y="8" width="41" height="5" fill="#616D8A"/>
|
||||
<rect x="7" y="19.75" width="76" height="3" fill="#D9D9D9"/>
|
||||
<rect x="7" y="25" width="76" height="3" fill="#D9D9D9"/>
|
||||
<rect x="7" y="32" width="76" height="3" fill="#D9D9D9"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 587 B |
@@ -1,6 +1,5 @@
|
||||
---
|
||||
layout: page-outline
|
||||
tags: ["overview"]
|
||||
---
|
||||
{% set forTag = forTag or (page.url | split('/') | last) %}
|
||||
{% if description %}
|
||||
@@ -13,8 +12,10 @@ tags: ["overview"]
|
||||
</wa-input>
|
||||
</div>
|
||||
|
||||
{% set allPages = collections[forTag] %}
|
||||
{% set allPages = allPages or collections[forTag] %}
|
||||
{% if allPages and allPages.length > 0 %}
|
||||
{% include "grouped-pages.njk" %}
|
||||
{% endif %}
|
||||
|
||||
<link href="/assets/styles/filter.css" rel="stylesheet">
|
||||
<script type="module" src="/assets/scripts/filter.js"></script>
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = false %}
|
||||
{% if hasSidebar == undefined %}
|
||||
{% set hasSidebar = true %}
|
||||
{% endif %}
|
||||
|
||||
{% if hasOutline == undefined %}
|
||||
{% set hasOutline = false %}
|
||||
{% endif %}
|
||||
|
||||
{% extends "../_includes/base.njk" %}
|
||||
|
||||
@@ -68,7 +68,7 @@ wa_data.palettes = {
|
||||
<wa-option label="{{ palette.data.title }}" value="{{ palette.fileSlug if not currentPalette }}" {{ (palette.fileSlug if currentPalette) | attr('data-id') }}>
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/" + (palette.data.icon or "thumbnail-placeholder") + ".njk" %}
|
||||
{% include "svgs/" + (palette.data.icon or "thumbnail-placeholder") + ".njk" ignore missing %}
|
||||
</div>
|
||||
<span class="page-name">
|
||||
{{ palette.data.title }}
|
||||
|
||||
@@ -29,6 +29,9 @@ function getCollection(name) {
|
||||
}
|
||||
|
||||
export function getCollectionItemFromUrl(url, collection) {
|
||||
if (!url) {
|
||||
return null;
|
||||
}
|
||||
collection ??= getCollection.call(this, 'all') || [];
|
||||
return collection.find(item => item.url === url);
|
||||
}
|
||||
@@ -42,35 +45,33 @@ export function split(text, separator) {
|
||||
return (text + '').split(separator).filter(Boolean);
|
||||
}
|
||||
|
||||
export function breadcrumbs(url, { withCurrent = false } = {}) {
|
||||
const parts = split(url, '/');
|
||||
const ret = [];
|
||||
export function ancestors(url, { withCurrent = false, withRoot = false } = {}) {
|
||||
let ret = [];
|
||||
let currentUrl = url;
|
||||
let currentItem = getCollectionItemFromUrl.call(this, url);
|
||||
|
||||
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];
|
||||
if (!currentItem) {
|
||||
// Might have eleventyExcludeFromCollections, jump to parent
|
||||
let parentUrl = this.ctx.parentUrl;
|
||||
if (parentUrl) {
|
||||
url = parentUrl;
|
||||
}
|
||||
}
|
||||
|
||||
for (let item; (item = getCollectionItemFromUrl.call(this, url)); url = item.data.parentUrl) {
|
||||
ret.unshift(item);
|
||||
}
|
||||
|
||||
if (!withRoot && ret[0]?.page.url === '/') {
|
||||
// Remove root
|
||||
ret.shift();
|
||||
}
|
||||
|
||||
if (!withCurrent && ret.at(-1)?.page.url === currentUrl) {
|
||||
// Remove current page
|
||||
ret.pop();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -177,72 +178,196 @@ export function sort(arr, by = { 'data.order': 1, 'data.title': '' }) {
|
||||
});
|
||||
}
|
||||
|
||||
export function show(page) {
|
||||
return !(page.data.noAlpha && page.data.isAlpha) && !page.data.unlisted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param { Object<string, string> | string[]} [options] Options object or array of tags to group by.
|
||||
* @param {string[] | true} [options.tags] Tags to group by. If true, groups by all tags.
|
||||
* If not provided/empty, defaults to grouping by page hierarchy, with any pages with more than 1 children becoming groups.
|
||||
* @param {string[]} [options.groups] The groups to use if only a subset or a specific order is desired. Defaults to `options.tags`.
|
||||
* @param {string[]} [options.titles] Any title overrides for groups.
|
||||
* @param {string | false} [options.other="Other"] The title to use for the "Other" group. If `false`, the "Other" group is removed..
|
||||
* @returns { Object.<string, object[]> } An object of group ids to arrays of page objects.
|
||||
*/
|
||||
export function groupByTags(collection, tags) {
|
||||
export function groupPages(collection, options = {}, page) {
|
||||
if (!collection) {
|
||||
console.error(`Empty collection passed to groupByTags() to group by ${JSON.stringify(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);
|
||||
console.error(`Empty collection passed to groupPages() to group by ${JSON.stringify(options)}`);
|
||||
}
|
||||
|
||||
let ret = Object.fromEntries(tags.map(tag => [tag, []]));
|
||||
ret.other = [];
|
||||
if (Array.isArray(options)) {
|
||||
options = { tags: options };
|
||||
}
|
||||
|
||||
let { tags, groups, titles = {}, other = 'Other', filter = show } = options;
|
||||
|
||||
if (groups === undefined && Array.isArray(tags)) {
|
||||
groups = tags;
|
||||
}
|
||||
|
||||
let grouping;
|
||||
|
||||
if (tags) {
|
||||
grouping = {
|
||||
isGroup: item => undefined,
|
||||
getCandidateGroups: item => item.data.tags,
|
||||
getGroupMeta: group => ({}),
|
||||
};
|
||||
} else {
|
||||
grouping = {
|
||||
isGroup: item => (item.data.children.length >= 2 ? item.page.url : undefined),
|
||||
getCandidateGroups: item => {
|
||||
let parentUrl = item.data.parentUrl;
|
||||
if (page?.url === parentUrl) {
|
||||
return [];
|
||||
}
|
||||
return [parentUrl];
|
||||
},
|
||||
getGroupMeta: group => {
|
||||
let item = byUrl[group] || getCollectionItemFromUrl.call(this, group);
|
||||
return {
|
||||
title: item?.data.title,
|
||||
url: group,
|
||||
item,
|
||||
};
|
||||
},
|
||||
sortGroups: groups => sort(groups.map(url => byUrl[url]).filter(Boolean)).map(item => item.page.url),
|
||||
};
|
||||
}
|
||||
|
||||
let byUrl = {};
|
||||
let byParentUrl = {};
|
||||
|
||||
if (filter) {
|
||||
collection = collection.filter(filter);
|
||||
}
|
||||
|
||||
for (let item of collection) {
|
||||
let categorized = false;
|
||||
let url = item.page.url;
|
||||
let parentUrl = item.data.parentUrl;
|
||||
|
||||
for (let tag of tags) {
|
||||
if (item.data.tags.includes(tag)) {
|
||||
ret[tag].push(item);
|
||||
categorized = true;
|
||||
}
|
||||
}
|
||||
byUrl[url] = item;
|
||||
|
||||
if (!categorized) {
|
||||
ret.other.push(item);
|
||||
if (parentUrl) {
|
||||
byParentUrl[parentUrl] ??= [];
|
||||
byParentUrl[parentUrl].push(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove empty categories
|
||||
for (let category in ret) {
|
||||
if (ret[category].length === 0) {
|
||||
delete ret[category];
|
||||
let urlToGroups = {};
|
||||
|
||||
for (let item of collection) {
|
||||
let url = item.page.url;
|
||||
let parentUrl = item.data.parentUrl;
|
||||
|
||||
if (grouping.isGroup(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let parentItem = byUrl[parentUrl];
|
||||
if (parentItem && !grouping.isGroup(parentItem)) {
|
||||
// Their parent is also here and is not a group
|
||||
continue;
|
||||
}
|
||||
|
||||
let candidateGroups = grouping.getCandidateGroups(item);
|
||||
|
||||
if (groups) {
|
||||
candidateGroups = candidateGroups.filter(group => groups.includes(group));
|
||||
}
|
||||
|
||||
urlToGroups[url] ??= [];
|
||||
|
||||
for (let group of candidateGroups) {
|
||||
urlToGroups[url].push(group);
|
||||
}
|
||||
}
|
||||
|
||||
let ret = {};
|
||||
|
||||
for (let url in urlToGroups) {
|
||||
let groups = urlToGroups[url];
|
||||
let item = byUrl[url];
|
||||
|
||||
if (groups.length === 0) {
|
||||
// Not filtered out but also not categorized
|
||||
groups = ['other'];
|
||||
}
|
||||
|
||||
for (let group of groups) {
|
||||
ret[group] ??= [];
|
||||
ret[group].push(item);
|
||||
|
||||
if (!ret[group].meta) {
|
||||
if (group === 'other') {
|
||||
ret[group].meta = { title: other };
|
||||
} else {
|
||||
ret[group].meta = grouping.getGroupMeta(group);
|
||||
ret[group].meta.title = titles[group] ?? ret[group].meta.title ?? capitalize(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (other === false) {
|
||||
delete ret.other;
|
||||
}
|
||||
|
||||
// Sort
|
||||
let sortedGroups = groups ?? grouping.sortGroups?.(Object.keys(ret));
|
||||
|
||||
if (sortedGroups) {
|
||||
ret = sortObject(ret, sortedGroups);
|
||||
} else {
|
||||
// At least make sure other is last
|
||||
if (ret.other) {
|
||||
let otherGroup = ret.other;
|
||||
delete ret.other;
|
||||
ret.other = otherGroup;
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(ret, 'meta', {
|
||||
value: {
|
||||
groupCount: Object.keys(ret).length,
|
||||
},
|
||||
enumerable: false,
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort an object by its keys
|
||||
* @param {*} obj
|
||||
* @param {function | string[]} order
|
||||
*/
|
||||
function sortObject(obj, order) {
|
||||
let ret = {};
|
||||
let sortedKeys = Array.isArray(order) ? order : Object.keys(obj).sort(order);
|
||||
|
||||
for (let key of sortedKeys) {
|
||||
if (key in obj) {
|
||||
ret[key] = obj[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Add any keys that weren't in the order
|
||||
for (let key in obj) {
|
||||
if (!(key in ret)) {
|
||||
ret[key] = obj[key];
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
function capitalize(str) {
|
||||
str += '';
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
const IDENTITY = x => x;
|
||||
|
||||
@@ -39,7 +39,7 @@ export function outlinePlugin(options = {}) {
|
||||
}
|
||||
|
||||
// Create a clone of the heading so we can remove links and [data-no-outline] elements from the text content
|
||||
clone.querySelectorAll('a').forEach(a => a.remove());
|
||||
clone.querySelectorAll('.wa-visually-hidden, [hidden], [aria-hidden="true"]').forEach(el => el.remove());
|
||||
clone.querySelectorAll('[data-no-outline]').forEach(el => el.remove());
|
||||
|
||||
// Generate the link
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
function debounce(func, wait) {
|
||||
let timeout;
|
||||
return function (...args) {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => func.apply(this, args), wait);
|
||||
};
|
||||
}
|
||||
|
||||
function updateResults(input) {
|
||||
const filter = input.value.toLowerCase().trim();
|
||||
let filtered = Boolean(filter);
|
||||
@@ -18,8 +26,10 @@ function updateResults(input) {
|
||||
}
|
||||
}
|
||||
|
||||
const debouncedUpdateResults = debounce(updateResults, 300);
|
||||
|
||||
document.documentElement.addEventListener('input', e => {
|
||||
if (e.target?.matches('#block-filter wa-input')) {
|
||||
updateResults(e.target);
|
||||
debouncedUpdateResults(e.target);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
let initialPageLoadComplete = false;
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
initialPageLoadComplete = true;
|
||||
});
|
||||
|
||||
// Helper for view transitions
|
||||
export function domChange(fn, { behavior = 'smooth' } = {}) {
|
||||
export function domChange(fn, { behavior = 'smooth', ignoreInitialLoad = true } = {}) {
|
||||
const canUseViewTransitions =
|
||||
document.startViewTransition && !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
|
||||
// Skip transitions on initial page load
|
||||
if (!initialPageLoadComplete && ignoreInitialLoad) {
|
||||
fn(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (canUseViewTransitions && behavior === 'smooth') {
|
||||
document.startViewTransition(fn);
|
||||
const transition = document.startViewTransition(() => {
|
||||
fn(true);
|
||||
// Wait a brief delay before finishing the transition to prevent jumpiness
|
||||
return new Promise(resolve => setTimeout(resolve, 200));
|
||||
});
|
||||
return transition;
|
||||
} else {
|
||||
fn(true);
|
||||
fn(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import 'https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.10/+esm';
|
||||
import { preventTurboFouce } from '/dist/webawesome.js';
|
||||
|
||||
if (!window.___turboScrollPositions___) {
|
||||
window.___turboScrollPositions___ = {};
|
||||
}
|
||||
@@ -70,3 +73,4 @@ function fixDSD(e) {
|
||||
window.addEventListener('turbo:before-cache', saveScrollPosition);
|
||||
window.addEventListener('turbo:before-render', restoreScrollPosition);
|
||||
window.addEventListener('turbo:render', restoreScrollPosition);
|
||||
preventTurboFouce();
|
||||
|
||||
@@ -370,10 +370,22 @@ 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(4, 1fr);
|
||||
gap: var(--wa-space-2xl);
|
||||
margin-block-end: var(--wa-space-3xl);
|
||||
|
||||
@media screen and (max-width: 1470px) {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 960px) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
}
|
||||
|
||||
a {
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
text-decoration: none;
|
||||
|
||||
@@ -15,9 +15,9 @@ icon: card
|
||||
|
||||
<strong>Mittens</strong><br />
|
||||
This kitten is as cute as he is playful. Bring him home today!<br />
|
||||
<small>6 weeks old</small>
|
||||
<small class="wa-caption-m">6 weeks old</small>
|
||||
|
||||
<div slot="footer">
|
||||
<div slot="footer" class="wa-split">
|
||||
<wa-button variant="brand" pill>More Info</wa-button>
|
||||
<wa-rating label="Rating"></wa-rating>
|
||||
</div>
|
||||
@@ -27,16 +27,6 @@ icon: card
|
||||
.card-overview {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.card-overview small {
|
||||
color: var(--wa-color-text-quiet);
|
||||
}
|
||||
|
||||
.card-overview [slot='footer'] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@@ -65,9 +55,9 @@ If using SSR, you need to also use the `with-header` attribute to add a header t
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-header class="card-header">
|
||||
<div slot="header">
|
||||
<div slot="header" class="wa-split">
|
||||
Header Title
|
||||
<wa-icon-button name="gear" variant="solid" label="Settings"></wa-icon-button>
|
||||
<wa-icon-button name="gear" variant="solid" label="Settings" class="wa-size-m"></wa-icon-button>
|
||||
</div>
|
||||
|
||||
This card has a header. You can put all sorts of things in it!
|
||||
@@ -78,19 +68,9 @@ If using SSR, you need to also use the `with-header` attribute to add a header t
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.card-header [slot='header'] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-header h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.card-header wa-icon-button {
|
||||
font-size: var(--wa-font-size-m);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@@ -103,7 +83,7 @@ If using SSR, you need to also use the `with-footer` attribute to add a footer t
|
||||
<wa-card with-footer class="card-footer">
|
||||
This card has a footer. You can put all sorts of things in it!
|
||||
|
||||
<div slot="footer">
|
||||
<div slot="footer" class="wa-split">
|
||||
<wa-rating></wa-rating>
|
||||
<wa-button variant="brand">Preview</wa-button>
|
||||
</div>
|
||||
@@ -113,12 +93,6 @@ If using SSR, you need to also use the `with-footer` attribute to add a footer t
|
||||
.card-footer {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.card-footer [slot='footer'] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@@ -153,7 +127,7 @@ Use the `size` attribute to change a card's size.
|
||||
<wa-card with-footer size="small">
|
||||
This is a small card.
|
||||
|
||||
<footer slot="footer" class="wa-flank">
|
||||
<footer slot="footer" class="wa-split">
|
||||
<wa-button variant="brand" pill>More Info</wa-button>
|
||||
<wa-rating></wa-rating>
|
||||
</footer>
|
||||
@@ -162,7 +136,7 @@ Use the `size` attribute to change a card's size.
|
||||
<wa-card with-footer size="medium">
|
||||
This is a medium card (default).
|
||||
|
||||
<footer slot="footer" class="wa-flank">
|
||||
<footer slot="footer" class="wa-split">
|
||||
<wa-button variant="brand" pill>More Info</wa-button>
|
||||
<wa-rating></wa-rating>
|
||||
</footer>
|
||||
@@ -171,14 +145,39 @@ Use the `size` attribute to change a card's size.
|
||||
<wa-card with-footer size="large">
|
||||
This is a large card.
|
||||
|
||||
<footer slot="footer" class="wa-flank">
|
||||
<footer slot="footer" class="wa-split">
|
||||
<wa-button variant="brand" pill>More Info</wa-button>
|
||||
<wa-rating></wa-rating>
|
||||
</footer>
|
||||
</wa-card>
|
||||
</div>
|
||||
|
||||
```
|
||||
|
||||
<style>
|
||||
</style>
|
||||
### Appearance
|
||||
|
||||
Use the `appearance` attribute to change the card's visual appearance.
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-grid">
|
||||
<wa-card>
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
alt="A kitten sits patiently between a terracotta pot and decorative grasses."
|
||||
/>
|
||||
<div slot="header">Outlined (default)</div>
|
||||
Card content.
|
||||
</wa-card>
|
||||
{% for appearance in ['outlined filled', 'outlined accent', 'plain', 'filled', 'accent'] -%}
|
||||
<wa-card appearance="{{ appearance }}">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
alt="A kitten sits patiently between a terracotta pot and decorative grasses."
|
||||
/>
|
||||
<div slot="header">{{ appearance | capitalize }}</div>
|
||||
Card content.
|
||||
</wa-card>
|
||||
{%- endfor %}
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -77,6 +77,31 @@ The details component automatically adapts to right-to-left languages:
|
||||
</wa-details>
|
||||
```
|
||||
|
||||
### Appearance
|
||||
|
||||
Use the `appearance` attribute to change the element’s visual appearance.
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack">
|
||||
<wa-details summary="Outlined (default)">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
||||
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</wa-details>
|
||||
<wa-details summary="Filled" appearance="filled">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
||||
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</wa-details>
|
||||
<wa-details summary="Filled + Outlined" appearance="filled outlined">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
||||
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</wa-details>
|
||||
<wa-details summary="Plain" appearance="plain">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
||||
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</wa-details>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
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.
|
||||
layout: overview
|
||||
categories:
|
||||
- actions
|
||||
- feedback: 'Feedback & Status'
|
||||
- imagery
|
||||
- inputs
|
||||
- navigation
|
||||
- organization
|
||||
- helpers: 'Utilities'
|
||||
override:tags: []
|
||||
categories:
|
||||
tags: [actions, feedback, imagery, inputs, navigation, organization, helpers]
|
||||
titles:
|
||||
feedback: 'Feedback & Status'
|
||||
helpers: 'Utilities'
|
||||
---
|
||||
|
||||
@@ -1,10 +1,80 @@
|
||||
/**
|
||||
* Global data for all pages
|
||||
*/
|
||||
import { sort } from '../_utils/filters.js';
|
||||
|
||||
export default {
|
||||
eleventyComputed: {
|
||||
children(data) {
|
||||
let mainTag = data.tags?.[0];
|
||||
let collection = data.collections[mainTag] ?? [];
|
||||
// Default parent. Can be overridden by explicitly setting parent in the data.
|
||||
// parent can refer to either an ancestor page in the URL or another page in the same directory
|
||||
parent(data) {
|
||||
let { parent, page } = data;
|
||||
|
||||
return collection.filter(item => item.data.parent === data.page.fileSlug);
|
||||
if (parent) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
return page.url.split('/').filter(Boolean).at(-2);
|
||||
},
|
||||
|
||||
parentUrl(data) {
|
||||
let { parent, page } = data;
|
||||
return getParentUrl(page.url, parent);
|
||||
},
|
||||
|
||||
parentItem(data) {
|
||||
let { parentUrl } = data;
|
||||
return data.collections.all.find(item => item.url === parentUrl);
|
||||
},
|
||||
|
||||
children(data) {
|
||||
let { collections, page, parentOf } = data;
|
||||
|
||||
if (parentOf) {
|
||||
return collections[parentOf];
|
||||
}
|
||||
|
||||
let collection = collections.all ?? [];
|
||||
let url = page.url;
|
||||
|
||||
let ret = collection.filter(item => {
|
||||
return item.data.parentUrl === url;
|
||||
});
|
||||
|
||||
sort(ret);
|
||||
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function getParentUrl(url, parent) {
|
||||
let parts = url.split('/').filter(Boolean);
|
||||
let ancestorIndex = parts.findLastIndex(part => part === parent);
|
||||
let retParts = parts.slice();
|
||||
|
||||
if (ancestorIndex > -1) {
|
||||
// parent is an ancestor
|
||||
retParts.splice(ancestorIndex + 1);
|
||||
} else {
|
||||
// parent is a sibling in the same directory
|
||||
retParts.splice(-1, 1, parent);
|
||||
}
|
||||
|
||||
let ret = retParts.join('/');
|
||||
|
||||
if (url.startsWith('/')) {
|
||||
ret = '/' + ret;
|
||||
}
|
||||
|
||||
if (!retParts.at(-1).includes('.') && !ret.endsWith('/')) {
|
||||
// If no extension, make sure to end with a slash
|
||||
ret += '/';
|
||||
}
|
||||
|
||||
if (ret === '/docs/') {
|
||||
ret = '/';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -37,10 +37,6 @@ This snippet includes three parts:
|
||||
|
||||
Now you can [start using Web Awesome!](/docs/usage)
|
||||
|
||||
:::info
|
||||
While convenient, autoloading may lead to a [Flash of Undefined Custom Elements](https://www.abeautifulsite.net/posts/flash-of-undefined-custom-elements/). The linked article describes some ways to alleviate it.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Using Font Awesome Kit Codes
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Layout
|
||||
description: Layout components and utility classes help you organize content that can adapt to any device or screen size. See the [installation instructions](#installation) to use Web Awesome's layout tools in your project.
|
||||
layout: overview
|
||||
parentOf: layout
|
||||
categories: ["components", "utilities"]
|
||||
override:tags: []
|
||||
---
|
||||
@@ -22,4 +23,4 @@ Or, you can choose to import _only_ the utilities:
|
||||
```html
|
||||
<link rel="stylesheet" href="{% cdnUrl 'styles/utilities.css' %}" />
|
||||
```
|
||||
{% endmarkdown %}
|
||||
{% endmarkdown %}
|
||||
|
||||
@@ -33,7 +33,7 @@ Use the [variant utility classes](../utilities/color.md) to set the button's sem
|
||||
|
||||
### Appearance
|
||||
|
||||
Use the [appearance utility classes](../utilities/appearance.md) to change the button's visual appearance:
|
||||
Use the [appearance utility classes](/docs/utilities/appearance) to change the button's visual appearance:
|
||||
|
||||
```html {.example}
|
||||
<div style="margin-block-end: 1rem;">
|
||||
|
||||
@@ -57,7 +57,7 @@ Use the [variant utility classes](../utilities/color.md) to set the callout's co
|
||||
|
||||
### Appearance
|
||||
|
||||
Use the [appearance utility classes](../utilities/appearance.md) to change the callout's visual appearance (the default is `outlined filled`).
|
||||
Use the [appearance utility classes](/docs/utilities/appearance) to change the callout's visual appearance (the default is `outlined filled`).
|
||||
|
||||
```html {.example}
|
||||
<article class="wa-callout wa-brand wa-outlined wa-accent">
|
||||
|
||||
@@ -19,6 +19,35 @@ file: styles/native/details.css
|
||||
|
||||
## Examples
|
||||
|
||||
### Appearance
|
||||
|
||||
Use the [appearance utility classes](/docs/utilities/appearance) to change the element's visual appearance:
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack">
|
||||
<details>
|
||||
<summary>Outlined (default)</summary>
|
||||
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.
|
||||
</details>
|
||||
<details class="wa-filled">
|
||||
<summary>Filled</summary>
|
||||
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.
|
||||
</details>
|
||||
<details class="wa-filled wa-outlined">
|
||||
<summary>Filled + Outlined</summary>
|
||||
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.
|
||||
</details>
|
||||
<details class="wa-plain">
|
||||
<summary>Plain</summary>
|
||||
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.
|
||||
</details>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Right-to-Left Languages
|
||||
|
||||
The details styling automatically adapts to right-to-left languages:
|
||||
|
||||
@@ -5,6 +5,6 @@ layout: overview
|
||||
override:tags: []
|
||||
forTag: palette
|
||||
categories:
|
||||
tags: [other, pro]
|
||||
other: Free
|
||||
pro: Pro
|
||||
---
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Action Panel
|
||||
description: 'These patterns help add user actions to dashboards'
|
||||
parent: app
|
||||
tags: app
|
||||
icon: action-panel
|
||||
---
|
||||
## Examples
|
||||
|
||||
@@ -40,4 +39,4 @@ tags: app
|
||||
<wa-switch size="large"></wa-switch>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
3
docs/docs/patterns/app/app.json
Normal file
3
docs/docs/patterns/app/app.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"tags": ["app"]
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Comments
|
||||
description: 'For feedback forms and message boxes'
|
||||
parent: app
|
||||
tags: app
|
||||
---
|
||||
## Examples
|
||||
|
||||
@@ -34,7 +32,7 @@ tags: app
|
||||
<wa-icon-button name="link" variant="solid" label="Bold"></wa-icon-button>
|
||||
<wa-icon-button name="face-smile" variant="solid" label="Italic"></wa-icon-button>
|
||||
</div>
|
||||
</wa-button><wa-button>Comment</wa-button>
|
||||
</wa-button><wa-button>Comment</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,4 +70,4 @@ tags: app
|
||||
<wa-button variant="brand">Save</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Data Display
|
||||
description: TODO
|
||||
parent: app
|
||||
tags: app
|
||||
---
|
||||
## Examples
|
||||
|
||||
@@ -27,13 +25,13 @@ tags: app
|
||||
<wa-card>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar shape="square" label="Square avatar" class="wa-callout wa-neutral">
|
||||
<wa-icon slot="icon" name="user-plus" variant="solid"></wa-icon>
|
||||
<wa-icon slot="icon" name="envelope" variant="solid"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-heading-xs">Total Subscribers</span>
|
||||
<span class="wa-heading-xs">Avg. Open Rate</span>
|
||||
<div class="wa-cluster">
|
||||
<span class="wa-heading-l">71,897</span>
|
||||
<wa-tag size="small" variant="success" appearance="filled outlined" pill><wa-icon fixed-width name="arrow-up"></wa-icon> 122</wa-tag>
|
||||
<span class="wa-heading-l">58.16%</span>
|
||||
<wa-tag size="small" variant="success" appearance="filled outlined" pill><wa-icon fixed-width name="arrow-up"></wa-icon> 5.4%</wa-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -41,13 +39,13 @@ tags: app
|
||||
<wa-card>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar shape="square" label="Square avatar" class="wa-callout wa-neutral">
|
||||
<wa-icon slot="icon" name="user-plus" variant="solid"></wa-icon>
|
||||
<wa-icon slot="icon" name="arrow-pointer" variant="solid"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-heading-xs">Total Subscribers</span>
|
||||
<span class="wa-heading-xs">Avg. Click Rate</span>
|
||||
<div class="wa-cluster">
|
||||
<span class="wa-heading-l">71,897</span>
|
||||
<wa-tag size="small" variant="success" appearance="filled outlined" pill><wa-icon fixed-width name="arrow-up"></wa-icon> 122</wa-tag>
|
||||
<span class="wa-heading-l">24.57%</span>
|
||||
<wa-tag size="small" variant="danger" appearance="filled outlined" pill><wa-icon fixed-width name="arrow-down"></wa-icon> 3.2%</wa-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -71,11 +69,11 @@ tags: app
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-flank">
|
||||
<wa-icon family="brands" name="youtube"></wa-icon>
|
||||
<wa-icon family="brands" name="amazon"></wa-icon>
|
||||
<div class="wa-align-items-center wa-cluster" style="justify-content: space-between;">
|
||||
<span>YouTube Premium</span>
|
||||
<span>Amazon</span>
|
||||
<span>5 minutes ago</span>
|
||||
<wa-tag variant="danger" appearance="outlined filled" pill>-$5.00</wa-tag>
|
||||
<wa-tag variant="success" appearance="outlined filled" pill>+$79.79</wa-tag>
|
||||
</div>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
@@ -105,7 +103,6 @@ tags: app
|
||||
<wa-tag variant="danger" appearance="outlined filled" pill>-$5.00</wa-tag>
|
||||
</div>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
</div>
|
||||
</wa-card>
|
||||
</div>
|
||||
@@ -158,4 +155,4 @@ tags: app
|
||||
</section>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Description List
|
||||
description: 'Shows the user information with labels and values in an easy to read format.'
|
||||
parent: app
|
||||
tags: app
|
||||
---
|
||||
## Examples
|
||||
|
||||
@@ -241,4 +239,4 @@ tags: app
|
||||
</a>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Empty State
|
||||
description: TODO
|
||||
parent: app
|
||||
tags: app
|
||||
---
|
||||
## Examples
|
||||
|
||||
@@ -110,4 +108,4 @@ tags: app
|
||||
<a href="#">Or start from an empty project →</a>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
title: FAQ
|
||||
description: TODO
|
||||
parent: app
|
||||
tags: app
|
||||
description: 'The user has questions concerning a site and its related services'
|
||||
---
|
||||
## Examples
|
||||
|
||||
### Offset
|
||||
```html{.example}
|
||||
<div class="wa-grid">
|
||||
<div>
|
||||
@@ -13,49 +13,73 @@ tags: app
|
||||
</div>
|
||||
<dl class="wa-stack wa-gap-m">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">How often do you update your courses?</dt>
|
||||
<dd>A course is updated once there is a fundamental shift in the language or library’s underlying API. You can check our <a href="#">workshop</a> list to see if a new version of a given course is on the schedule. You may also write to us as <a href="#">support@frontendmasters.com</a> with suggestions for updates.</dd>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">Do you offer certificates of completion?</dt>
|
||||
<dd>You can download certificates of completion from the <a href="#">Completed Courses</a> list in your Learning Library. Click the diploma icon next to the course to download the certificate in light or dark mode. A link to your Public Profile is included on each certificate if you’ve created one. Public Profiles showcase your learning journey and are a fantastic way to share progress with friends, co-workers, or employers. Public Profiles are available to members with an active Frontend Masters subscription who have watched ten or more hours of content. Visit the <a href="#">Public Profile</a> section in My Account to get started.</dd>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">Do you offer a free trial?</dt>
|
||||
<dd>
|
||||
<p>We offer a free trial to first-time subscribers. You can find more about the trial here.</p>
|
||||
<p>We also have the following opportunities to learn for free:</p>
|
||||
<ul>
|
||||
<li>The online bootcamp is a free, two-week curriculum to get you started with web development.</li>
|
||||
<li>You can create a free account to gain access to five full courses for free.</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">Do you have discounts for students?</dt>
|
||||
<dd>We are part of the <a href="#">GitHub Student Developer Pack</a>, allowing students six months of free access to the entire platform.</dd>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">How do I cancel my plan?</dt>
|
||||
<dd>You can cancel your Frontend Masters subscription by visiting the <a href="#">Subscription tab</a> in your My Account area.</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
```
|
||||
|
||||
### With detail component
|
||||
```html{.example}
|
||||
<div style="max-width: 960px; margin: 0 auto;">
|
||||
<h2>Frequently Asked Questions</h2>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<wa-details summary="How do you make holy water?">
|
||||
<wa-details>
|
||||
<span slot="summary" class="wa-heading-m">
|
||||
How often do you update your courses?
|
||||
</span>
|
||||
A course is updated once there is a fundamental shift in the language or library’s underlying API. You can check our <a href="#">workshop</a> list to see if a new version of a given course is on the schedule. You may also write to us as <a href="#">support@frontendmasters.com</a> with suggestions for updates.
|
||||
</wa-details>
|
||||
<wa-details>
|
||||
<span slot="summary" class="wa-heading-m">
|
||||
Do you offer certificates of completion?
|
||||
</span>
|
||||
You boil the hell out of it.
|
||||
</wa-details>
|
||||
<wa-details summary="How do you make holy water?">
|
||||
You boil the hell out of it.
|
||||
<wa-details>
|
||||
<span slot="summary" class="wa-heading-m">
|
||||
Do you offer a free trial?
|
||||
</span>
|
||||
You can download certificates of completion from the <a href="#">Completed Courses</a> list in your Learning Library. Click the diploma icon next to the course to download the certificate in light or dark mode. A link to your Public Profile is included on each certificate if you’ve created one. Public Profiles showcase your learning journey and are a fantastic way to share progress with friends, co-workers, or employers. Public Profiles are available to members with an active Frontend Masters subscription who have watched ten or more hours of content. Visit the <a href="#">Public Profile</a> section in My Account to get started.
|
||||
</wa-details>
|
||||
<wa-details summary="How do you make holy water?">
|
||||
You boil the hell out of it.
|
||||
</wa-details>
|
||||
<wa-details summary="How do you make holy water?">
|
||||
You boil the hell out of it.
|
||||
<wa-details>
|
||||
<span slot="summary" class="wa-heading-m">
|
||||
Do you have discounts for students?
|
||||
</span>
|
||||
<p>We offer a free trial to first-time subscribers. You can find more about the trial here.</p>
|
||||
<p>We also have the following opportunities to learn for free:</p>
|
||||
<ul>
|
||||
<li>The online bootcamp is a free, two-week curriculum to get you started with web development.</li>
|
||||
<li>You can create a free account to gain access to five full courses for free.</li>
|
||||
</ul>
|
||||
</wa-details>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 2 Column
|
||||
```html{.example}
|
||||
<div>
|
||||
|
||||
@@ -64,29 +88,36 @@ tags: app
|
||||
|
||||
<dl class="wa-stack wa-gap-m">
|
||||
<div class="wa-grid wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">How often do you update your courses?</dt>
|
||||
<dd>A course is updated once there is a fundamental shift in the language or library’s underlying API. You can check our <a href="#">workshop</a> list to see if a new version of a given course is on the schedule. You may also write to us as <a href="#">support@frontendmasters.com</a> with suggestions for updates.</dd>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-grid wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">Do you offer certificates of completion?</dt>
|
||||
<dd>You can download certificates of completion from the <a href="#">Completed Courses</a> list in your Learning Library. Click the diploma icon next to the course to download the certificate in light or dark mode. A link to your Public Profile is included on each certificate if you’ve created one. Public Profiles showcase your learning journey and are a fantastic way to share progress with friends, co-workers, or employers. Public Profiles are available to members with an active Frontend Masters subscription who have watched ten or more hours of content. Visit the <a href="#">Public Profile</a> section in My Account to get started.</dd>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-grid wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">Do you offer a free trial?</dt>
|
||||
<dd>
|
||||
<p>We offer a free trial to first-time subscribers. You can find more about the trial here.</p>
|
||||
<p>We also have the following opportunities to learn for free:</p>
|
||||
<ul>
|
||||
<li>The online bootcamp is a free, two-week curriculum to get you started with web development.</li>
|
||||
<li>You can create a free account to gain access to five full courses for free.</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-grid wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">Do you have discounts for students?</dt>
|
||||
<dd>We are part of the <a href="#">GitHub Student Developer Pack</a>, allowing students six months of free access to the entire platform.</dd>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-grid wa-gap-xs">
|
||||
<dt class="wa-heading-m">How do you make holy water?</dt>
|
||||
<dd class="wa-caption-l">You boil the hell out of it. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas cupiditate laboriosam fugiat.</dd>
|
||||
<dt class="wa-heading-m">How do I cancel my plan?</dt>
|
||||
<dd>You can cancel your Frontend Masters subscription by visiting the <a href="#">Subscription tab</a> in your My Account area.</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,86 +1,157 @@
|
||||
---
|
||||
title: Feed
|
||||
description: TODO
|
||||
parent: app
|
||||
tags: app
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
<div class="activity-feed">
|
||||
<div class="activity-group">
|
||||
<span class="connector"></span>
|
||||
<div class="activity">
|
||||
<wa-icon name="user-circle" class="fa-fw"></wa-icon>
|
||||
<p>Kicked ass and <strong>chewed bubblegum</strong></p>
|
||||
<span style="margin-left: auto"><em>Oct. 31st</em></span>
|
||||
## Comment Section
|
||||
```html{.example}
|
||||
<wa-card style="max-width: 60ch; margin: 0 auto;">
|
||||
<div class="wa-stack">
|
||||
<h1 class="wa-heading-m">Activity</h1>
|
||||
<wa-textarea></wa-textarea>
|
||||
<wa-divider></wa-divider>
|
||||
<section class="wa-stack">
|
||||
<div class="wa-flank">
|
||||
<wa-avatar label="User avatar"></wa-avatar>
|
||||
<div>
|
||||
<span class="wa-heading-s">Robert Fox</span>
|
||||
<span class="wa-caption-m">commented 32 min ago</span>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="wa-stack wa-gap-xl" style="list-style-type: none; margin-inline-start: 1em;">
|
||||
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras convallis mollis nunc, vel tempor sem faucibus nec. Suspendisse potenti. Pellentesque lobortis pulvinar nulla non tempor. Interdum et malesuada fames ac ante ipsum primis in faucibus.</li>
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-flank">
|
||||
<wa-avatar label="User avatar"></wa-avatar>
|
||||
<div>
|
||||
<span>Robert Fox</span>
|
||||
<span class="wa-caption-m">commented 32 min ago</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras convallis mollis nunc, vel tempor sem faucibus nec.</p>
|
||||
</li>
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-flank">
|
||||
<wa-avatar label="User avatar"></wa-avatar>
|
||||
<div>
|
||||
<span>Robert Fox</span>
|
||||
<span class="wa-caption-m">commented 32 min ago</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras convallis mollis nunc, vel tempor sem faucibus nec.</p>
|
||||
</li>
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="reply"></wa-icon>
|
||||
<a href="#">Leave Comment</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<div class="activity-group">
|
||||
<span class="connector"></span>
|
||||
<div class="activity">
|
||||
<wa-icon name="thumbs-up" style="color: blue" class="fa-fw"></wa-icon>
|
||||
<p>Kicked ass and <strong>chewed bubblegum</strong></p>
|
||||
<span style="margin-left: auto"><em>Oct. 31st</em></span>
|
||||
</wa-card>
|
||||
```
|
||||
## With Summary Components
|
||||
```html{.example}
|
||||
<wa-card style="max-width: 68ch; margin: 0 auto;">
|
||||
<h1 class="wa-heading-l">Monthly Activity</h1>
|
||||
<div class="wa-stack">
|
||||
<wa-details>
|
||||
<span class="wa-heading-m" slot="summary">
|
||||
February
|
||||
</span>
|
||||
<div class="wa-stack">
|
||||
<section class="wa-flank wa-gap-xs">
|
||||
<wa-icon style="font-size: var(--wa-font-size-xl)" name="envelope"></wa-icon>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Email blasts</span>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<a href="#">Nick Burkhart</a><span>sent to</span><a href="#">likely customers</a>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-caption-m">Feb 28th</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="activity-group">
|
||||
<span class="connector"></span>
|
||||
<div class="activity">
|
||||
<wa-icon name="crown" class="fa-fw"></wa-icon>
|
||||
<p>Kicked ass and <strong>chewed bubblegum</strong></p>
|
||||
<span style="margin-left: auto"><em>Oct. 31st</em></span>
|
||||
</section>
|
||||
<wa-divider></wa-divider>
|
||||
<section class="wa-flank wa-gap-xs">
|
||||
<wa-icon style="font-size: var(--wa-font-size-xl)" name="phone"></wa-icon>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Spoke with the Pope</span>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<a href="#">Artur Fleck</a><span>for 1 hour</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-caption-m">Feb 23rd</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="activity-group">
|
||||
<span class="connector"></span>
|
||||
<div class="activity">
|
||||
<wa-icon name="turtle" style="color: green" class="fa-fw"></wa-icon>
|
||||
<p>Kicked ass and <strong>chewed bubblegum</strong></p>
|
||||
<span style="margin-left: auto"><em>Oct. 31st</em></span>
|
||||
</wa-details>
|
||||
<wa-details>
|
||||
<span class="wa-heading-m" slot="summary">
|
||||
March
|
||||
</span>
|
||||
<div class="wa-stack">
|
||||
<section class="wa-flank wa-gap-xs">
|
||||
<wa-icon style="font-size: var(--wa-font-size-xl)" name="video"></wa-icon>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Zoom Call with Northeast office</span>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<a href="#">Axel Foley</a><span>for 47 minutes</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-caption-m">Mar 15th</span>
|
||||
</div>
|
||||
</section>
|
||||
<wa-divider></wa-divider>
|
||||
<section class="wa-flank wa-gap-s">
|
||||
<wa-icon style="font-size: var(--wa-font-size-xl)" name="calendar"></wa-icon>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Scheduled birthday party</span>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<a href="#">John Blaze</a><span>in</span><a href="#">Social Events</a>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-caption-m">Mar 3rd</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</wa-details>
|
||||
<wa-details>
|
||||
<span class="wa-heading-m" slot="summary">
|
||||
April
|
||||
</span>
|
||||
<div class="wa-stack">
|
||||
<section class="wa-flank wa-gap-s">
|
||||
<wa-icon style="font-size: var(--wa-font-size-xl)" family="brands" name="intercom"></wa-icon>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Got new lead</span>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<a href="#">Jack Carter</a><span>on Intercom switchboard</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-caption-m">Apr 18th</span>
|
||||
</div>
|
||||
</section>
|
||||
<wa-divider></wa-divider>
|
||||
<section class="wa-flank wa-gap-s">
|
||||
<wa-icon style="font-size: var(--wa-font-size-xl)" name="list-check"></wa-icon>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Completed Todo</span>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<a href="#">Huey Freeman</a><span>marked complete on</span><a href="#">Daily Tasks</a>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-caption-m">Apr 2nd</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</wa-details>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--border-color: var(--wa-color-surface-border);
|
||||
}
|
||||
.activity-feed {
|
||||
wa-icon {
|
||||
margin-right: 1rem;
|
||||
font-size: 32px;
|
||||
}
|
||||
.fa-fw {
|
||||
text-align: center;
|
||||
width: 1.25em;
|
||||
}
|
||||
.activity {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.activity-group:not(:first-child) {
|
||||
margin-top: .5rem;
|
||||
}
|
||||
.activity-group {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.connector {
|
||||
position: absolute;
|
||||
background-color: var(--border-color);
|
||||
height: 25%;
|
||||
width: 0.125rem;
|
||||
margin-left: -1px;
|
||||
top: 2.5rem;
|
||||
left: 1rem;
|
||||
}
|
||||
|
||||
.activity-group:last-of-type .connector {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</wa-card>
|
||||
```
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Grid
|
||||
description: TODO
|
||||
parent: app
|
||||
tags: app
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -163,4 +161,4 @@ tags: app
|
||||
</div>
|
||||
</wa-card>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,28 +1,8 @@
|
||||
---
|
||||
title: App
|
||||
description: TODO
|
||||
layout: page
|
||||
categories: ["app"]
|
||||
parent: patterns
|
||||
layout: overview
|
||||
override:tags: []
|
||||
listChildren: true
|
||||
---
|
||||
|
||||
{% set appPages = collections.app %}
|
||||
|
||||
<section class="index-grid">
|
||||
{%- for page in appPages -%}
|
||||
|
||||
<a href="{{ page.url }}"{{ page.data.keywords | attr('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>
|
||||
{% if pageSubtitle -%}
|
||||
<div class="wa-caption-s">{{ pageSubtitle }}</div>
|
||||
{%- endif %}
|
||||
</wa-card>
|
||||
</a>
|
||||
|
||||
{%- endfor -%}
|
||||
|
||||
</section>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Leaderboard
|
||||
description: TODO
|
||||
parent: app
|
||||
tags: app
|
||||
---
|
||||
|
||||
```html{.example}
|
||||
@@ -366,4 +364,4 @@ tags: app
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Pagination
|
||||
description: TODO
|
||||
parent: app
|
||||
tags: app
|
||||
---
|
||||
|
||||
## Simple Pagination
|
||||
@@ -41,4 +39,4 @@ tags: app
|
||||
<wa-button><wa-icon slot="suffix" name="gear" variant="solid"></wa-icon>Next </wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Pricing
|
||||
description: TODO
|
||||
parent: app
|
||||
tags: app
|
||||
---
|
||||
|
||||
```html{.example}
|
||||
@@ -29,23 +27,23 @@ tags: app
|
||||
<div class="wa-stack">
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="check"></wa-icon>
|
||||
<span class="wa-caption-m">Access to basic features</span>
|
||||
<span class="wa-caption-m">Access to basic features</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="check"></wa-icon>
|
||||
<span class="wa-caption-m">Basic Reporting and Analytics</span>
|
||||
<span class="wa-caption-m">Basic Reporting and Analytics</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="check"></wa-icon>
|
||||
<span class="wa-caption-m">10 Individual users</span>
|
||||
<span class="wa-caption-m">10 Individual users</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="check"></wa-icon>
|
||||
<span class="wa-caption-m">20GB of data for user</span>
|
||||
<span class="wa-caption-m">20GB of data for user</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="check"></wa-icon>
|
||||
<span class="wa-caption-m">Basic Chat and email</span>
|
||||
<span class="wa-caption-m">Basic Chat and email</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,7 +70,7 @@ tags: app
|
||||
<div class="wa-stack">
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="check"></wa-icon>
|
||||
<span class="wa-caption-m">Access to basic features</span>
|
||||
<span class="wa-caption-m">Access to basic features</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -99,7 +97,7 @@ tags: app
|
||||
<div class="wa-stack">
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="check"></wa-icon>
|
||||
<span class="wa-caption-m">Access to basic features</span>
|
||||
<span class="wa-caption-m">Access to basic features</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -134,4 +132,4 @@ tags: app
|
||||
|
||||
### With templates
|
||||
|
||||
### With recommendations grid
|
||||
### With recommendations grid
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Category Filter
|
||||
description: 'Helps the user find the right products with filters to refine search results by specific attributes.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
icon: checkbox
|
||||
---
|
||||
|
||||
@@ -42,7 +40,7 @@ icon: checkbox
|
||||
<wa-checkbox>XXL</wa-checkbox>
|
||||
</div>
|
||||
</wa-details>
|
||||
</form>
|
||||
</form>
|
||||
<div class="wa-placeholder"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -82,4 +80,4 @@ icon: checkbox
|
||||
</div>
|
||||
<div class="wa-placeholder"></div>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Category Preview
|
||||
description: 'Help shoppers discover your product offerings with showcases of product categories.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
icon: preview
|
||||
---
|
||||
|
||||
@@ -17,20 +15,20 @@ icon: preview
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<div class="wa-frame:landscape wa-border-radius-s">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1544441893-675973e31985?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="An analog watch, cotton pants, crew neck tee, and pair of tennis shoes (Photograph by Mnz)"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-grid">
|
||||
<div class="wa-frame:landscape wa-border-radius-s">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1548768041-2fceab4c0b85?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Stack of three folded solid color tees (Photograph by Mnz)"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-frame:landscape wa-border-radius-s">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1544441892-794166f1e3be?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Pair of bright white tennis shoes(Photograph by Mnz)"
|
||||
/>
|
||||
@@ -48,7 +46,7 @@ icon: preview
|
||||
<div class="wa-grid">
|
||||
<a href="" class="wa-stack wa-link-plain">
|
||||
<div class="wa-frame:portrait wa-border-radius-s">
|
||||
<img
|
||||
<img
|
||||
src="https://uploads.webawesome.com/organization.jpg"
|
||||
alt="Inside of a closet filled with clothes on wooden hangers and integrated shelving with shoes"
|
||||
/>
|
||||
@@ -57,7 +55,7 @@ icon: preview
|
||||
</a>
|
||||
<a href="" class="wa-stack wa-link-plain">
|
||||
<div class="wa-frame:portrait wa-border-radius-s">
|
||||
<img
|
||||
<img
|
||||
src="https://uploads.webawesome.com/bags.jpg"
|
||||
alt="Young person hugging a small floral patterned book bag between their arms"
|
||||
/>
|
||||
@@ -66,7 +64,7 @@ icon: preview
|
||||
</a>
|
||||
<a href="" class="wa-stack wa-link-plain">
|
||||
<div class="wa-frame:portrait wa-border-radius-s">
|
||||
<img
|
||||
<img
|
||||
src="https://uploads.webawesome.com/outdoor-2.jpg"
|
||||
alt="Person in a mountain clearing wearing a waterproof hooded windbreaker in black and orange"
|
||||
/>
|
||||
@@ -161,4 +159,4 @@ icon: preview
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Checkout Form
|
||||
description: 'Let shoppers checkout with ease with streamlined forms to capture shipping and payment info.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
---
|
||||
|
||||
|
||||
@@ -243,4 +241,4 @@ tags: e-commerce
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
3
docs/docs/patterns/ecommerce/ecommerce.json
Normal file
3
docs/docs/patterns/ecommerce/ecommerce.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"tags": ["ecommerce"]
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Incentives
|
||||
description: 'Encourage shoppers to buy your products with value propositions, discounts, and promotions.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
---
|
||||
|
||||
## 3 Column
|
||||
@@ -17,7 +15,7 @@ tags: e-commerce
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img src="https://uploads.webawesome.com/online-learning.jpg" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="wa-grid">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
@@ -122,4 +120,4 @@ tags: e-commerce
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,26 +1,6 @@
|
||||
---
|
||||
title: E-commerce
|
||||
description: ''
|
||||
layout: page
|
||||
title: Ecommerce
|
||||
parent: patterns
|
||||
layout: overview
|
||||
override:tags: []
|
||||
---
|
||||
|
||||
{% set ecommercePages = collections['e-commerce'] %}
|
||||
|
||||
<section class="index-grid">
|
||||
{%- for page in ecommercePages -%}
|
||||
|
||||
<a href="{{ page.url }}"{{ page.data.keywords | attr('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>
|
||||
{% if pageSubtitle -%}
|
||||
<div class="wa-caption-s">{{ pageSubtitle }}</div>
|
||||
{%- endif %}
|
||||
</wa-card>
|
||||
</a>
|
||||
|
||||
{%- endfor -%}
|
||||
|
||||
</section>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Order History
|
||||
description: 'Empower your customers to view past purchases and track upcoming orders with comprehensive order histories.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
---
|
||||
|
||||
## List
|
||||
@@ -32,7 +30,7 @@ tags: e-commerce
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-flank" style="--flank-size: 12rem">
|
||||
<div class="wa-frame wa-border-radius-s" style="aspect-ratio: 3 / 2">
|
||||
<img
|
||||
<img
|
||||
src="https://img.fortawesome.com/cfa83f3c/light-fixtures.jpg"
|
||||
alt=""
|
||||
/>
|
||||
@@ -49,7 +47,7 @@ tags: e-commerce
|
||||
<wa-button size="small" appearance="plain" variant="neutral">View Product</wa-button>
|
||||
<wa-button size="small" appearance="accent" variant="brand">Buy Again</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Order Summary
|
||||
description: 'Give shoppers confidence in their purchases with summaries of everything included in their order.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
---
|
||||
|
||||
## Simple
|
||||
@@ -26,7 +24,7 @@ tags: e-commerce
|
||||
<ul class="wa-stack wa-gap-xl">
|
||||
<li class="wa-flank wa-align-items-start">
|
||||
<div class="wa-frame wa-border-radius-s">
|
||||
<img
|
||||
<img
|
||||
src="https://uploads.webawesome.com/vase-1.jpg"
|
||||
alt=""
|
||||
/>
|
||||
@@ -39,7 +37,7 @@ tags: e-commerce
|
||||
<wa-divider></wa-divider>
|
||||
<li class="wa-flank wa-align-items-start">
|
||||
<div class="wa-frame wa-border-radius-s">
|
||||
<img
|
||||
<img
|
||||
src="https://uploads.webawesome.com/decorative-vase.jpg"
|
||||
alt=""
|
||||
/>
|
||||
@@ -219,7 +217,7 @@ tags: e-commerce
|
||||
<p class="wa-caption-m">Wood fired, salt glaze</p>
|
||||
<wa-tag variant="success" appearance="filled" size="small">Delivered</wa-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
@@ -237,7 +235,7 @@ tags: e-commerce
|
||||
<p class="wa-caption-m">High quality Japanese Kutani-yaki ceramic-ware</p>
|
||||
<wa-tag variant="neutral" appearance="filled" size="small">Shipping Soon</wa-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
@@ -255,7 +253,7 @@ tags: e-commerce
|
||||
<p class="wa-caption-m">Koishiwara-yaki style with crystalline glaze</p>
|
||||
<wa-tag variant="brand" appearance="filled" size="small">Out for Delivery</wa-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-divider></wa-divider>
|
||||
<wa-callout variant="neutral" appearance="filled">
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Product Lists
|
||||
description: 'Let shoppers browse and compare products with detailed lists of the products in your store.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
---
|
||||
|
||||
## Simple Grid with Ratings
|
||||
@@ -11,7 +9,7 @@ tags: e-commerce
|
||||
<div class="wa-grid wa-gap-2xl">
|
||||
<a class="wa-stack wa-align-items-center wa-gap-xs wa-link-plain" href="">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1633933329864-5d4c4423ad54?q=80&w=3387&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Bunch of fresh basil leaves with purple veins (Photograph by Svitlana)"
|
||||
/>
|
||||
@@ -23,7 +21,7 @@ tags: e-commerce
|
||||
</a>
|
||||
<a class="wa-stack wa-align-items-center wa-gap-xs wa-link-plain" href="">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1662892194342-f95c33cc16e3?q=80&w=3000&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Bunch of cut chamomile blooms (Photograph by Rootnot Creations)"
|
||||
/>
|
||||
@@ -35,7 +33,7 @@ tags: e-commerce
|
||||
</a>
|
||||
<a class="wa-stack wa-align-items-center wa-gap-xs wa-link-plain" href="">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1636396279461-f875646332d9?q=80&w=3360&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Canvas bundle of cut lavender blooms (Photograph by volant)"
|
||||
/>
|
||||
@@ -47,7 +45,7 @@ tags: e-commerce
|
||||
</a>
|
||||
<a class="wa-stack wa-align-items-center wa-gap-xs wa-link-plain" href="">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1501085934018-450c8e615dbc?q=80&w=3387&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Blooming marjoram plant (Photograph by Monika Grabkowska)"
|
||||
/>
|
||||
@@ -59,7 +57,7 @@ tags: e-commerce
|
||||
</a>
|
||||
<a class="wa-stack wa-align-items-center wa-gap-xs wa-link-plain" href="">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1688633767797-455f59c98272?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Group of mature oregano plants (Photograph Nikolett Emmert)"
|
||||
/>
|
||||
@@ -71,7 +69,7 @@ tags: e-commerce
|
||||
</a>
|
||||
<a class="wa-stack wa-align-items-center wa-gap-xs wa-link-plain" href="">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1603109731710-dba41b1096a7?q=80&w=2259&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Cluster of peppermint plants (Photograph by Josefin)"
|
||||
/>
|
||||
@@ -83,7 +81,7 @@ tags: e-commerce
|
||||
</a>
|
||||
<a class="wa-stack wa-align-items-center wa-gap-xs wa-link-plain" href="">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1726994803809-0e065bd4b25b?q=80&w=3387&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Mature rosemary stems (Photograph by 360floralflaves)"
|
||||
/>
|
||||
@@ -95,7 +93,7 @@ tags: e-commerce
|
||||
</a>
|
||||
<a class="wa-stack wa-align-items-center wa-gap-xs wa-link-plain" href="">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1659834742696-44573974981b?q=80&w=3542&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Group of sage plants (Photograph by Susie Burleson)"
|
||||
/>
|
||||
@@ -115,7 +113,7 @@ tags: e-commerce
|
||||
<div class="wa-grid">
|
||||
<a href="" class="wa-link-plain">
|
||||
<wa-card>
|
||||
<img slot="image"
|
||||
<img slot="image"
|
||||
src="https://images.unsplash.com/photo-1622445272461-c6580cab8755?q=80&w=3387&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Man in a relaxed fit, white, crew neck t-shirt (Photography by Mediamodifier)"
|
||||
/>
|
||||
@@ -131,7 +129,7 @@ tags: e-commerce
|
||||
</a>
|
||||
<a href="" class="wa-link-plain">
|
||||
<wa-card>
|
||||
<img slot="image"
|
||||
<img slot="image"
|
||||
src="https://images.unsplash.com/photo-1554568218-0f1715e72254?q=80&w=3387&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Woman in a light heather t-shirt printed with sharp black ink (Photograph by Christian Bolt)"
|
||||
/>
|
||||
@@ -181,4 +179,4 @@ tags: e-commerce
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Product Overview
|
||||
description: 'Showcase your products with overviews including images, ratings, features, options, and more.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
---
|
||||
|
||||
## Split with Image
|
||||
@@ -77,7 +75,7 @@ tags: e-commerce
|
||||
</dl>
|
||||
</div>
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1600396538702-d234dbb79139?q=80&w=3833&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Whole roasted coffee beans (Photograph by Jocelyn Morales)"
|
||||
/>
|
||||
@@ -362,7 +360,7 @@ tags: e-commerce
|
||||
<div class="wa-stack">
|
||||
<img class="wa-border-radius-l"
|
||||
src="https://img.fortawesome.com/cfa83f3c/icon-grid-wallpaper.png"
|
||||
alt="Sample of 48 line-style icons"
|
||||
alt="Sample of 48 line-style icons"
|
||||
/>
|
||||
<wa-tab-group>
|
||||
<wa-tab panel="license">License</wa-tab>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
---
|
||||
title: Product Preview
|
||||
description: 'Give shoppers a quick look at your products as they browse with modal previews.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
icon: preview
|
||||
---
|
||||
|
||||
|
||||
## With Product Options
|
||||
|
||||
```html {.example}
|
||||
@@ -16,7 +14,7 @@ icon: preview
|
||||
</div>
|
||||
<div class="wa-grid wa-gap-xl">
|
||||
<div class="wa-frame wa-border-radius-l" style="aspect-ratio: auto">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1660997351262-6c31d8a35b6c?q=80&w=2000&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Stan Smith graphic crew-neck tee in honeydew color"
|
||||
/>
|
||||
@@ -128,7 +126,7 @@ icon: preview
|
||||
<div class="wa-gap-xs wa-stack">
|
||||
<h4 class="wa-heading-m">About</h4>
|
||||
<p class="wa-body-s">The Champion® Crossbody Bag is crafted for the trendsetter. Its sleek silhouette, paired with a tonal branded adjustable sling strap, ensures you look effortlessly cool no matter where you go.</p>
|
||||
</div>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-gap-xs wa-stack">
|
||||
<h4 class="wa-heading-m">Details</h4>
|
||||
@@ -150,7 +148,7 @@ icon: preview
|
||||
</div>
|
||||
<div class="wa-flank:end wa-align-items-end">
|
||||
<wa-button variant="brand" size="medium">
|
||||
<wa-icon slot="suffix" name="cart-shopping" variant="solid"></wa-icon>Add to Cart
|
||||
<wa-icon slot="suffix" name="cart-shopping" variant="solid"></wa-icon>Add to Cart
|
||||
</wa-button>
|
||||
<wa-button appearance="outlined" size="medium">
|
||||
<wa-icon slot="suffix" name="arrow-right" variant="solid"></wa-icon>View Full Details
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Product Reviews
|
||||
description: 'Help shoppers make informed decisions with ratings, reviews, and testimonials from your customers.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
---
|
||||
## Multi column
|
||||
|
||||
@@ -174,7 +172,7 @@ tags: e-commerce
|
||||
<wa-rating label="Rating" precision="0.5" value="5" readonly></wa-rating>
|
||||
<p>I recently purchased the Modern Sofa Couch, and I couldn't be happier with my decision! The process from ordering to delivery was smooth and hassle-free</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-flank wa-align-items-center">
|
||||
@@ -190,7 +188,7 @@ tags: e-commerce
|
||||
<wa-rating label="Rating" precision="0.5" value="3.4" readonly></wa-rating>
|
||||
<p>The cushions are soft yet supportive, and the sectional layout gives plenty of space to stretch out. It’s perfect for movie nights or just lounging with a good book.</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-flank wa-align-items-center">
|
||||
@@ -206,8 +204,8 @@ tags: e-commerce
|
||||
<wa-rating label="Rating" precision="0.5" value="3.8" readonly></wa-rating>
|
||||
<p>The leather is high quality, but it’s a little firmer than I thought. That said, after sitting on it for a while, it does soften up and feels more comfortable. It’s perfect if you’re looking for a more structured seating experience.</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Shopping Cart
|
||||
description: 'Give shoppers an overview of selected items with shopping carts that let them edit items and proceed to checkout.'
|
||||
parent: ecommerce
|
||||
tags: e-commerce
|
||||
---
|
||||
|
||||
## Two Columns with Summary Card
|
||||
@@ -14,7 +12,7 @@ tags: e-commerce
|
||||
<div class="wa-stack wa-gap-xl">
|
||||
<article class="wa-flank wa-gap-xl" style="--flank-size: 8rem">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1523381294911-8d3cead13475?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w1OTAyOTl8MHwxfGFsbHx8fHx8fHx8fDE3MTg2NDIzNDd8&ixlib=rb-4.0.3&q=80&w=1080"
|
||||
alt=""
|
||||
/>
|
||||
@@ -32,7 +30,7 @@ tags: e-commerce
|
||||
</article>
|
||||
<article class="wa-flank wa-gap-xl" style="--flank-size: 8rem">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1564859227552-81fde4a1df0b?q=80&w=2671&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt=""
|
||||
/>
|
||||
@@ -50,7 +48,7 @@ tags: e-commerce
|
||||
</article>
|
||||
<article class="wa-flank wa-gap-xl" style="--flank-size: 8rem">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1503341733017-1901578f9f1e?q=80&w=2670&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt=""
|
||||
/>
|
||||
@@ -205,12 +203,12 @@ tags: e-commerce
|
||||
<div class="wa-stack">
|
||||
<article class="wa-flank" style="--flank-size: 6rem">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1704677982224-89cd6d039fa6?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w1OTAyOTl8MHwxfGFsbHx8fHx8fHx8fDE3MTg2NDEwOTJ8&ixlib=rb-4.0.3&q=80&w=1080"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-split wa-gap-2xs">
|
||||
<strong>AJ1 Low</strong>
|
||||
<strong>$170.00</strong>
|
||||
@@ -230,7 +228,7 @@ tags: e-commerce
|
||||
alt="(Photograph by Hamed darzi)"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-split wa-gap-2xs">
|
||||
<strong>The Trails</strong>
|
||||
<strong>$35.00</strong>
|
||||
@@ -245,12 +243,12 @@ tags: e-commerce
|
||||
<wa-divider></wa-divider>
|
||||
<article class="wa-flank" style="--flank-size: 6rem">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1693443687750-611ad77f3aba?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="(Photograph by tian dayong)"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-split wa-gap-2xs">
|
||||
<strong>Outcast 2-pack</strong>
|
||||
<strong>$27.00</strong>
|
||||
@@ -276,4 +274,4 @@ tags: e-commerce
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-drawer>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Store Navigation
|
||||
description: 'Help shoppers explore categories and find products with all of the links they need to navigate your store.'
|
||||
parent: ecommerce
|
||||
unlisted: true
|
||||
---
|
||||
|
||||
@@ -82,4 +81,4 @@ unlisted: true
|
||||
|
||||
|
||||
</style>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
title: Patterns
|
||||
description: Patterns are reusable UI solutions to common design problems, ready to copy and paste into any project.
|
||||
layout: overview
|
||||
categories: ["app", "e-commerce", "information"]
|
||||
listChildren: true
|
||||
override:tags: []
|
||||
---
|
||||
|
||||
@@ -12,7 +10,7 @@ override:tags: []
|
||||
|
||||
## What's a Pattern?
|
||||
|
||||
A pattern is a code snippet composed of components, style utilities, and native HTML that you can copy and paste into any project that uses Web Awesome.
|
||||
A pattern is a code snippet composed of components, style utilities, and native HTML that you can copy and paste into any project that uses Web Awesome.
|
||||
It's a chunk of a user interface, rather than a single component, that allows you to implement UI solutions without designing something from scratch.
|
||||
|
||||
Patterns are designed according to proven usability practices so they're responsive, accessible, and cohesive out-of-the-box. Importantly, patterns don't handle business logic or functionality like form submissions, data processing, encryption, etc. It's up to you to implement the logic you need for your project.
|
||||
@@ -26,4 +24,4 @@ To use a pattern in your project, refer to each pattern's docs for a copyable co
|
||||
Because patterns use a combination of Web Awesome features, they work best when you have [native styles](/docs/native), [style utilities](/docs/utilities), and a [theme](/docs/themes) installed in addition to Web Awesome [components](/docs/components). Refer to the [Installation page](/docs/installation) to set up all of these features in your project.
|
||||
|
||||
{% endmarkdown %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,26 +1,8 @@
|
||||
---
|
||||
title: Information
|
||||
description: ''
|
||||
layout: page
|
||||
parent: patterns
|
||||
layout: overview
|
||||
override:tags: []
|
||||
listChildren: true
|
||||
---
|
||||
|
||||
{% set infoPages = collections.information %}
|
||||
|
||||
<section class="index-grid">
|
||||
{%- for page in infoPages -%}
|
||||
|
||||
<a href="{{ page.url }}"{{ page.data.keywords | attr('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>
|
||||
{% if pageSubtitle -%}
|
||||
<div class="wa-caption-s">{{ pageSubtitle }}</div>
|
||||
{%- endif %}
|
||||
</wa-card>
|
||||
</a>
|
||||
|
||||
{%- endfor -%}
|
||||
|
||||
</section>
|
||||
|
||||
3
docs/docs/patterns/information/information.json
Normal file
3
docs/docs/patterns/information/information.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"tags": ["information"]
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
title: Newsletter
|
||||
description: 'Empower your customers to view past purchases and track upcoming orders with comprehensive order histories.'
|
||||
parent: information
|
||||
tags: information
|
||||
---
|
||||
|
||||
## Newsletter signup
|
||||
@@ -62,4 +60,4 @@ For questions, Please <a href="#">contact us</a>. <a href="#">Terms</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -105,4 +105,4 @@ tags: information
|
||||
</script>
|
||||
|
||||
</div>
|
||||
``` -->
|
||||
``` -->
|
||||
|
||||
@@ -14,9 +14,21 @@ During the alpha period, things might break! We take breaking changes very serio
|
||||
|
||||
## Next
|
||||
|
||||
- Fixed `wa-pill` class for text fields
|
||||
### Enhancements
|
||||
|
||||
- Added `appearance` to [`<wa-details>`](/docs/components/details) and [`<wa-card>`](/docs/components/card) and support for the [appearance utilities](/docs/utilities/appearance/) in the [`<details>` native styles](/docs/native/details).
|
||||
- Added an `orange` scale to all color palettes
|
||||
- Added the `.wa-cloak` utility to prevent FOUCE
|
||||
- Added the `allDefined()` utility for awaiting component registration
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Specifying inherited CSS properties on `<wa-tooltip>` now works as expected ([thanks Dennis!](https://github.com/shoelace-style/webawesome-alpha/discussions/203))
|
||||
- Fixed a bug in `<wa-select>` that made it hard to use with VueJS, Svelte, and many other frameworks
|
||||
- Fixed the `wa-pill` class for text fields
|
||||
- Fixed `pill` style for `<wa-input>` elements
|
||||
- Fixed a bug in `<wa-color-picker>` that prevented light dismiss from working when clicking immediately above the color picker dropdown
|
||||
- Fixed a bug in `<wa-select multiple>` that sometimes resulted in empty `<div>` elements being output
|
||||
|
||||
## 3.0.0-alpha.11
|
||||
|
||||
|
||||
3
docs/docs/themes/creating.md
vendored
3
docs/docs/themes/creating.md
vendored
@@ -31,8 +31,7 @@ If you're customizing the default dark styles, scope your styles to the followin
|
||||
|
||||
```css
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
/* your custom styles here */
|
||||
}
|
||||
```
|
||||
|
||||
9
docs/docs/themes/index.njk
vendored
9
docs/docs/themes/index.njk
vendored
@@ -1,13 +1,13 @@
|
||||
---
|
||||
title: Themes
|
||||
description: Themes are collections of design tokens that thread through every Web Awesome component and pattern.
|
||||
description: Themes are collections of design tokens that thread through every Web Awesome component and pattern.
|
||||
Themes play a crucial role in [customizing Web Awesome](/docs/customizing).
|
||||
layout: overview
|
||||
override:tags: []
|
||||
forTag: theme
|
||||
categories:
|
||||
tags: [other, pro]
|
||||
other: Free
|
||||
pro: Pro
|
||||
---
|
||||
|
||||
<div class="max-line-length">
|
||||
@@ -30,7 +30,7 @@ In pre-made themes, we use a light color scheme by default.
|
||||
Additionally, styles may be scoped to the `:root` selector to be activated automatically.
|
||||
For pre-made themes, *all* custom properties are scoped to `:root`, the theme class, and `wa-light`.
|
||||
|
||||
Finally, we scope themes to `:host` and `:host-context()` to ensure the styles are applied to the shadow roots of custom elements.
|
||||
Finally, we scope themes to `:host` to ensure the styles are applied to the shadow roots of custom elements.
|
||||
|
||||
For example, the default theme is set up like this:
|
||||
|
||||
@@ -44,8 +44,7 @@ For example, the default theme is set up like this:
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:host-context(.wa-dark) {
|
||||
.wa-invert {
|
||||
/* subset of CSS custom properties for a dark color scheme */
|
||||
}
|
||||
```
|
||||
|
||||
@@ -3,4 +3,5 @@ title: Design Tokens
|
||||
description: A theme is a collection of predefined CSS custom properties that control global styles from color to shadows. These custom properties thread through all Web Awesome components for a consistent look and feel.
|
||||
layout: overview
|
||||
override:tags: []
|
||||
categories: {tags: true}
|
||||
---
|
||||
|
||||
@@ -8,6 +8,30 @@ Web Awesome components are just regular HTML elements, or [custom elements](http
|
||||
|
||||
If you're new to custom elements, often referred to as "web components," this section will familiarize you with how to use them.
|
||||
|
||||
## Awaiting Registration
|
||||
|
||||
Unlike traditional frameworks, custom elements don't have a centralized initialization phase. This means you need to verify that a custom element has been properly registered before attempting to interact with its properties or methods.
|
||||
|
||||
You can use the [`customElements.whenDefined()`](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/whenDefined) method to ensure a specific component is ready:
|
||||
|
||||
```ts
|
||||
await customElements.whenDefined('wa-button');
|
||||
|
||||
// <wa-button> is ready to use!
|
||||
const button = document.querySelector('wa-button');
|
||||
```
|
||||
|
||||
When working with multiple components, checking each one individually can become tedious. For convenience, Web Awesome provides the `allDefined()` function which automatically detects and waits for all Web Awesome components in the DOM to be initialized before resolving.
|
||||
|
||||
```ts
|
||||
import { allDefined } from '/dist/webawesome.js';
|
||||
|
||||
// Waits for all Web Awesome components in the DOM to be registered
|
||||
await allDefined();
|
||||
|
||||
// All Web Awesome components on the page are ready!
|
||||
```
|
||||
|
||||
## Attributes & Properties
|
||||
|
||||
Many components have properties that can be set using attributes. For example, buttons accept a `size` attribute that maps to the `size` property which dictates the button's size.
|
||||
|
||||
32
docs/docs/utilities/fouce.md
Normal file
32
docs/docs/utilities/fouce.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Reduce FOUCE
|
||||
description: Utility to improve the loading experience by hiding non-prerendered custom elements until they are registered.
|
||||
file: styles/utilities/fouce.css
|
||||
icon: spinner
|
||||
---
|
||||
|
||||
While convenient, autoloading can lead to a [Flash of Undefined Custom Elements](https://www.abeautifulsite.net/posts/flash-of-undefined-custom-elements/).
|
||||
The [FOUCE style utility](/docs/utilities/fouce/#opting-in) (which is automatically applied if you use the [Web Awesome utilities](/docs/utilities/)) takes care of hiding custom elements until they and their contents have been registered, up to a maximum of two seconds.
|
||||
|
||||
In many cases, this is not enough, and you may wish to hide a broader wrapper element or even the entire page until all WA elements within it have loaded. To do that, you can add the `wa-reduce-fouce` class to any element on the page or even apply it to the whole page by placing the class on the `<html>` element.
|
||||
|
||||
```html
|
||||
<html class="wa-cloak">
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
As soon as all elements are registered _or_ after two seconds have elapsed, the autoloader will show the page. The two-second timeout prevents blank screens from persisting on slow networks and pages that have errors.
|
||||
|
||||
:::details Are you using Turbo in your app?
|
||||
|
||||
If you're using [Turbo](https://turbo.hotwired.dev/) to serve a multi-page application (MPA) as a single page application (SPA), you might notice FOUCE when navigating from page to page. This is because Turbo renders the new page's content before the autoloader has a change to register new components.
|
||||
|
||||
The following function acts as a middleware to ensure components are registered _before_ the page shows, eliminating FOUCE for page-to-page navigation with Turbo.
|
||||
|
||||
```js
|
||||
import { preventTurboFouce } from '/dist/webawesome.js';
|
||||
|
||||
preventTurboFouce();
|
||||
```
|
||||
:::
|
||||
@@ -1,131 +0,0 @@
|
||||
---
|
||||
title: Reduce FOUCE
|
||||
description: Utility to improve the loading experience by hiding non-prerendered custom elements until they are registered.
|
||||
file: styles/utilities/fouce.css
|
||||
icon: spinner
|
||||
---
|
||||
{% markdown %}
|
||||
No class is needed to use this utility, it will be applied automatically as long as it its CSS is included.
|
||||
|
||||
Here is a comparison of the loading experience with and without this utility,
|
||||
with a simulated slow loading time:
|
||||
|
||||
{% endmarkdown %}
|
||||
|
||||
|
||||
<div class="wa-split wa-align-items-end">
|
||||
<strong>Normal loading</strong>
|
||||
<wa-button onclick="document.querySelectorAll('iframe').forEach(iframe => iframe.srcdoc = iframe.srcdoc)">
|
||||
<wa-icon name="refresh"></wa-icon>
|
||||
Refresh
|
||||
</wa-button>
|
||||
<strong>With FOUCE reduction</strong>
|
||||
</div>
|
||||
|
||||
|
||||
{% set sample_card %}
|
||||
<link id="theme-stylesheet" rel="stylesheet" href="/dist/styles/themes/default.css" render="blocking" fetchpriority="high">
|
||||
<link rel="stylesheet" href="/dist/styles/webawesome.css">
|
||||
<link rel="stylesheet" href="/dist/styles/forms.css">
|
||||
<script type=module>
|
||||
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||
const loadScript = src => new Promise((resolve, reject) => {
|
||||
const script = document.createElement("script");
|
||||
script.src = src;
|
||||
script.type = "module";
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
|
||||
await delay(500);
|
||||
await loadScript("/dist/components/button/button.js");
|
||||
await delay(500);
|
||||
await loadScript("/dist/components/card/card.js");
|
||||
await delay(500);
|
||||
await loadScript("/dist/components/rating/rating.js");
|
||||
</script>
|
||||
|
||||
<wa-card with-footer with-image class="card-overview">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
alt="A kitten sits patiently between a terracotta pot and decorative grasses."
|
||||
/>
|
||||
|
||||
<strong>Mittens</strong><br />
|
||||
This kitten is as cute as he is playful. Bring him home today!<br />
|
||||
<small>6 weeks old</small>
|
||||
|
||||
<div slot="footer">
|
||||
<wa-button variant="brand" pill>More Info</wa-button>
|
||||
<wa-rating></wa-rating>
|
||||
</div>
|
||||
</wa-card>
|
||||
|
||||
<style>
|
||||
.card-overview small {
|
||||
color: var(--wa-color-text-quiet);
|
||||
}
|
||||
|
||||
.card-overview [slot=footer] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
{% endset %}
|
||||
|
||||
|
||||
<div class="iframes">
|
||||
<iframe srcdoc='<body class="wa-fouce-off">{{ sample_card }}</body>'></iframe>
|
||||
<iframe srcdoc='{{ sample_card }}'></iframe>
|
||||
</div>
|
||||
<style>
|
||||
.iframes {
|
||||
display: flex;
|
||||
gap: var(--wa-space-m);
|
||||
margin-top: var(--wa-space-l);
|
||||
|
||||
iframe {
|
||||
flex: 1;
|
||||
height: 60ch;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
{% markdown %}
|
||||
## How does it work?
|
||||
|
||||
The utility consists of a timeout (`2s` by default) and a fade duration (`200ms` by default).
|
||||
- If the element is _ready_ before the timeout, it will appear immediately.
|
||||
- If it takes longer than _timeout_ + _fade_, it will fade in over the fade duration.
|
||||
- If it takes somewhere between _timeout_ and _timeout_ + _fade_, you will get an interrupted fade.
|
||||
|
||||
An element is considered ready when both of these are true:
|
||||
1. Either It has been registered or has a `did-ssr` attribute (indicating it was pre-rendered)
|
||||
2. If it’s a Web Awesome component, its contents are also ready
|
||||
|
||||
## Customization
|
||||
|
||||
You can use the following CSS variables to customize the behavior:
|
||||
|
||||
| Variable | Description | Default |
|
||||
| --- | --- | --- |
|
||||
| `--wa-fouce-fade` | The transition duration for the fade effect. | `200ms` |
|
||||
| `--wa-fouce-timeout` | The timeout after which elements will appear even if not registered | `2s` |
|
||||
|
||||
The fade duration cannot be longer than the timeout.
|
||||
This means that you can disable FOUCE reduction on an element by setting `--wa-fouce-timeout: 0s`.
|
||||
|
||||
For example, if instead of `did-ssr` you used an `ssr` attribute to mark elements that were pre-rendered, you can do this to get them to appear immediately:
|
||||
|
||||
```css
|
||||
[ssr] {
|
||||
--wa-fouce-timeout: 0s;
|
||||
}
|
||||
```
|
||||
|
||||
You can also opt-out from FOUCE reduction for an element and its contents by adding the `.wa-fouce-off` class to it.
|
||||
Applying this class to the root element will disable the utility for the entire page.
|
||||
{% endmarkdown %}
|
||||
@@ -4,8 +4,6 @@ description: Build better with Web Awesome, the open source library of web compo
|
||||
layout: page
|
||||
---
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
.title,
|
||||
.anchor-heading a,
|
||||
@@ -387,4 +385,4 @@ layout: page
|
||||
© Fonticons, Inc.
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
@@ -4,6 +4,7 @@ import { execSync } from 'child_process';
|
||||
import { deleteAsync } from 'del';
|
||||
import esbuild from 'esbuild';
|
||||
import { replace } from 'esbuild-plugin-replace';
|
||||
|
||||
import { mkdir, readFile } from 'fs/promises';
|
||||
import getPort, { portNumbers } from 'get-port';
|
||||
import { globby } from 'globby';
|
||||
@@ -266,6 +267,13 @@ async function regenerateBundle() {
|
||||
* Generates the documentation site.
|
||||
*/
|
||||
async function generateDocs() {
|
||||
/**
|
||||
* Used by the webawesome-app to skip doc generation since it will do its own.
|
||||
*/
|
||||
if (process.env.SKIP_ELEVENTY === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
spinner.start('Writing the docs');
|
||||
|
||||
const args = [];
|
||||
|
||||
@@ -109,7 +109,7 @@ export default class WaButton extends WebAwesomeFormAssociatedElement {
|
||||
@property({ reflect: true }) value: string | null = null;
|
||||
|
||||
/** When set, the underlying button will be rendered as an `<a>` with this `href` instead of a `<button>`. */
|
||||
@property() href = '';
|
||||
@property({ reflect: true }) href = null;
|
||||
|
||||
/** Tells the browser where to open the link. Only used when `href` is present. */
|
||||
@property() target: '_blank' | '_parent' | '_self' | '_top';
|
||||
|
||||
@@ -5,15 +5,16 @@
|
||||
|
||||
--spacing: var(--wa-space);
|
||||
--border-width: var(--wa-panel-border-width);
|
||||
--border-color: var(--wa-color-surface-border);
|
||||
--outlined-background-color: var(--wa-color-surface-default);
|
||||
--outlined-border-color: var(--wa-color-surface-border);
|
||||
--border-radius: var(--wa-panel-border-radius);
|
||||
|
||||
--inner-border-radius: calc(var(--border-radius) - var(--border-width));
|
||||
--inner-border-color: var(--outlined-border-color);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--wa-color-surface-default);
|
||||
border-color: var(--border-color);
|
||||
background-color: var(--background-color, var(--wa-color-surface-default));
|
||||
border-color: var(--border-color, var(--wa-color-surface-border));
|
||||
border-radius: var(--border-radius);
|
||||
border-style: var(--wa-panel-border-style);
|
||||
box-shadow: var(--wa-shadow-s);
|
||||
@@ -21,6 +22,20 @@
|
||||
color: var(--wa-color-text-normal);
|
||||
}
|
||||
|
||||
:host(:is([appearance~='accent'], .wa-accent)) {
|
||||
color: var(--text-color, var(--wa-color-text-normal));
|
||||
}
|
||||
|
||||
:host([appearance~='filled']),
|
||||
:host(.wa-filled) {
|
||||
--inner-border-color: oklab(from var(--outlined-border-color) l a b / 65%);
|
||||
}
|
||||
|
||||
:host([appearance='plain']) {
|
||||
--inner-border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Take care of top and bottom radii */
|
||||
.image,
|
||||
:host(:not([with-image])) .header,
|
||||
@@ -46,10 +61,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Round all corners for plain appearance */
|
||||
:host([appearance='plain']) .image {
|
||||
border-radius: var(--inner-border-radius);
|
||||
|
||||
&::slotted(img) {
|
||||
border-radius: inherit !important;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
display: block;
|
||||
border-block-end-style: inherit;
|
||||
border-block-end-color: var(--border-color);
|
||||
border-block-end-color: var(--inner-border-color);
|
||||
border-block-end-width: var(--border-width);
|
||||
padding: calc(var(--spacing) / 2) var(--spacing);
|
||||
}
|
||||
@@ -62,7 +86,7 @@
|
||||
.footer {
|
||||
display: block;
|
||||
border-block-start-style: inherit;
|
||||
border-block-start-color: var(--border-color);
|
||||
border-block-start-color: var(--inner-border-color);
|
||||
border-block-start-width: var(--border-width);
|
||||
padding: var(--spacing);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { html } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { HasSlotController } from '../../internal/slot.js';
|
||||
import WebAwesomeElement from '../../internal/webawesome-element.js';
|
||||
import appearanceStyles from '../../styles/utilities/appearance.css';
|
||||
import sizeStyles from '../../styles/utilities/size.css';
|
||||
import styles from './card.css';
|
||||
|
||||
@@ -22,19 +23,24 @@ import styles from './card.css';
|
||||
* @csspart footer - The container that wraps the card's footer.
|
||||
*
|
||||
* @cssproperty [--border-radius=var(--wa-panel-border-radius)] - The radius for the card's corners. Expects a single value.
|
||||
* @cssproperty [--border-color=var(--wa-color-surface-border)] - The color of the card's borders, including inner borders. Expects a single value.
|
||||
* @cssproperty [--border-color=var(--wa-color-surface-border)] - The color of the card's borders. Expects a single value.
|
||||
* @cssproperty [--inner-border-color=var(--wa-color-surface-border)] - The color of the card's inner borders, e.g. those separating headers and footers from the main content. Expects a single value.
|
||||
* @cssproperty [--border-width=var(--wa-panel-border-width)] - The width of the card's borders. Expects a single value.
|
||||
* @cssproperty [--spacing=var(--wa-space)] - The amount of space around and between sections of the card. Expects a single value.
|
||||
*/
|
||||
@customElement('wa-card')
|
||||
export default class WaCard extends WebAwesomeElement {
|
||||
static shadowStyle = [sizeStyles, styles];
|
||||
static shadowStyle = [sizeStyles, appearanceStyles, styles];
|
||||
|
||||
private readonly hasSlotController = new HasSlotController(this, 'footer', 'header', 'image');
|
||||
|
||||
/** The component's size. Will be inherited by any descendants with a `size` attribute. */
|
||||
@property({ reflect: true, initial: 'medium' }) size: 'small' | 'medium' | 'large' | 'inherit' = 'inherit';
|
||||
|
||||
/** The card's visual appearance. */
|
||||
@property({ reflect: true })
|
||||
appearance: 'accent' | 'filled' | 'outlined' | 'plain' = 'outlined';
|
||||
|
||||
/** Renders the card with a header. Only needed for SSR, otherwise is automatically added. */
|
||||
@property({ attribute: 'with-header', type: Boolean, reflect: true }) withHeader = false;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { getTargetElement, waitForEvent } from '../../internal/event.js';
|
||||
import { watch } from '../../internal/watch.js';
|
||||
import WebAwesomeElement from '../../internal/webawesome-element.js';
|
||||
import nativeStyles from '../../styles/native/details.css';
|
||||
import appearanceStyles from '../../styles/utilities/appearance.css';
|
||||
import { LocalizeController } from '../../utilities/localize.js';
|
||||
import '../icon/icon.js';
|
||||
import styles from './details.css';
|
||||
@@ -45,7 +46,7 @@ import styles from './details.css';
|
||||
*/
|
||||
@customElement('wa-details')
|
||||
export default class WaDetails extends WebAwesomeElement {
|
||||
static shadowStyle = [nativeStyles, styles];
|
||||
static shadowStyle = [appearanceStyles, nativeStyles, styles];
|
||||
|
||||
private detailsObserver: MutationObserver;
|
||||
private readonly localize = new LocalizeController(this);
|
||||
@@ -67,6 +68,9 @@ export default class WaDetails extends WebAwesomeElement {
|
||||
/** Disables the details so it can't be toggled. */
|
||||
@property({ type: Boolean, reflect: true }) disabled = false;
|
||||
|
||||
/** The element's visual appearance. */
|
||||
@property({ reflect: true }) appearance: 'filled' | 'outlined' | 'plain' = 'outlined';
|
||||
|
||||
firstUpdated() {
|
||||
this.body.style.height = this.open ? 'auto' : '0';
|
||||
if (this.open) {
|
||||
|
||||
@@ -291,7 +291,6 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
|
||||
?pill=${this.pill}
|
||||
size=${this.size}
|
||||
removable
|
||||
@wa-remove=${(event: WaRemoveEvent) => this.handleTagRemove(event, option)}
|
||||
>
|
||||
${option.label}
|
||||
</wa-tag>
|
||||
@@ -587,10 +586,33 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
|
||||
this.setSelectedOptions(allOptions.filter(el => value.includes(el.value)));
|
||||
}
|
||||
|
||||
private handleTagRemove(event: WaRemoveEvent, option: WaOption) {
|
||||
private handleTagRemove(event: WaRemoveEvent, directOption?: WaOption) {
|
||||
event.stopPropagation();
|
||||
|
||||
if (!this.disabled) {
|
||||
if (this.disabled) return;
|
||||
|
||||
// Use the directly provided option if available (from getTag method)
|
||||
let option = directOption;
|
||||
|
||||
// If no direct option was provided, find the option from the event path
|
||||
if (!option) {
|
||||
const tagElement = (event.target as Element).closest('wa-tag[part~=tag]');
|
||||
|
||||
if (tagElement) {
|
||||
// Find the index of this tag among all tags
|
||||
const tagsContainer = this.shadowRoot?.querySelector('[part="tags"]');
|
||||
if (tagsContainer) {
|
||||
const allTags = Array.from(tagsContainer.children);
|
||||
const index = allTags.indexOf(tagElement as HTMLElement);
|
||||
|
||||
if (index >= 0 && index < this.selectedOptions.length) {
|
||||
option = this.selectedOptions[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (option) {
|
||||
this.toggleOptionSelection(option, false);
|
||||
|
||||
// Emit after updating
|
||||
@@ -707,10 +729,8 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
|
||||
return this.selectedOptions.map((option, index) => {
|
||||
if (index < this.maxOptionsVisible || this.maxOptionsVisible <= 0) {
|
||||
const tag = this.getTag(option, index);
|
||||
// Wrap so we can handle the remove
|
||||
return html`<div @wa-remove=${(e: WaRemoveEvent) => this.handleTagRemove(e, option)}>
|
||||
${typeof tag === 'string' ? unsafeHTML(tag) : tag}
|
||||
</div>`;
|
||||
if (!tag) return null;
|
||||
return typeof tag === 'string' ? unsafeHTML(tag) : tag;
|
||||
} else if (index === this.maxOptionsVisible) {
|
||||
// Hit tag limit
|
||||
return html`
|
||||
@@ -726,7 +746,7 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
|
||||
>
|
||||
`;
|
||||
}
|
||||
return html``;
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -926,7 +946,9 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
|
||||
/>
|
||||
|
||||
<!-- Tags need to wait for first hydration before populating otherwise it will create a hydration mismatch. -->
|
||||
${this.multiple && this.hasUpdated ? html`<div part="tags" class="tags">${this.tags}</div>` : ''}
|
||||
${this.multiple && this.hasUpdated
|
||||
? html`<div part="tags" class="tags" @wa-remove=${this.handleTagRemove}>${this.tags}</div>`
|
||||
: ''}
|
||||
|
||||
<input
|
||||
class="value-input"
|
||||
|
||||
@@ -18,17 +18,17 @@
|
||||
--wa-color-red: var(--wa-color-red-70);
|
||||
--wa-color-red-key: 70;
|
||||
|
||||
--wa-color-orange-95: oklch(96.462% 0.02077 52.138);
|
||||
--wa-color-orange-90: oklch(92.556% 0.04363 51.242);
|
||||
--wa-color-orange-80: #fdbb96 /* oklch(84.396% 0.09052 50.397) */;
|
||||
--wa-color-orange-70: #eb9c74 /* oklch(76.151% 0.10953 47.299) */;
|
||||
--wa-color-orange-60: #cf8162 /* oklch(67.86% 0.10698 42.148) */;
|
||||
--wa-color-orange-50: #aa6248 /* oklch(57.281% 0.1014 40.415) */;
|
||||
--wa-color-orange-40: #864834 /* oklch(47.233% 0.08958 39.166) */;
|
||||
--wa-color-orange-30: #6b3727 /* oklch(39.974% 0.07776 38.975) */;
|
||||
--wa-color-orange-20: #50271a /* oklch(32.519% 0.0649 38.022) */;
|
||||
--wa-color-orange-10: #32160e /* oklch(23.873% 0.04713 38.423) */;
|
||||
--wa-color-orange-05: #210c06 /* oklch(18.614% 0.03797 38.589) */;
|
||||
--wa-color-orange-95: #ffefe8 /* oklch(96.287% 0.01978 45.262) */;
|
||||
--wa-color-orange-90: #ffe0d2 /* oklch(92.854% 0.03927 45.816) */;
|
||||
--wa-color-orange-80: #fbbc9e /* oklch(84.557% 0.08373 46.569) */;
|
||||
--wa-color-orange-70: #f3976f /* oklch(76.236% 0.12363 43.995) */;
|
||||
--wa-color-orange-60: #d67e59 /* oklch(68.046% 0.12088 43.174) */;
|
||||
--wa-color-orange-50: #ae6140 /* oklch(57.433% 0.11041 43.333) */;
|
||||
--wa-color-orange-40: #89472c /* oklch(47.39% 0.09837 42.278) */;
|
||||
--wa-color-orange-30: #6f351e /* oklch(40.084% 0.08944 41.51) */;
|
||||
--wa-color-orange-20: #542513 /* oklch(32.696% 0.07578 40.822) */;
|
||||
--wa-color-orange-10: #341408 /* oklch(23.762% 0.05577 40.619) */;
|
||||
--wa-color-orange-05: #230b04 /* oklch(18.679% 0.04417 39.815) */;
|
||||
--wa-color-orange: var(--wa-color-orange-70);
|
||||
--wa-color-orange-key: 70;
|
||||
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
--wa-color-orange-90: oklch(92.395% 0.07984 53.06);
|
||||
--wa-color-orange-80: oklch(84.389% 0.12224 47.981);
|
||||
--wa-color-orange-70: oklch(76.55% 0.16521 42.512);
|
||||
--wa-color-orange-60: #ea7237 /* oklch(68.444% 0.16501 44.349) */;
|
||||
--wa-color-orange-50: #c0561a /* oklch(57.844% 0.15254 45.085) */;
|
||||
--wa-color-orange-40: #963e05 /* oklch(47.639% 0.13153 45.898) */;
|
||||
--wa-color-orange-30: oklch(40.376% 0.11554 45.517);
|
||||
--wa-color-orange-20: oklch(32.94% 0.09927 45.913);
|
||||
--wa-color-orange-10: oklch(24.083% 0.07743 46.027);
|
||||
--wa-color-orange-05: oklch(18.817% 0.06098 48.455);
|
||||
--wa-color-orange-60: #e97331 /* oklch(68.357% 0.16507 46.504) */;
|
||||
--wa-color-orange-50: #bf5712 /* oklch(57.834% 0.15197 47.326) */;
|
||||
--wa-color-orange-40: oklch(47.62% 0.132 48.51);
|
||||
--wa-color-orange-30: oklch(40.38% 0.11554 50);
|
||||
--wa-color-orange-20: oklch(32.94% 0.09927 52);
|
||||
--wa-color-orange-10: oklch(24.083% 0.07743 54);
|
||||
--wa-color-orange-05: oklch(18.817% 0.06098 55);
|
||||
--wa-color-orange: var(--wa-color-orange-70);
|
||||
--wa-color-orange-key: 70;
|
||||
|
||||
|
||||
@@ -6,45 +6,45 @@
|
||||
.wa-palette-classic {
|
||||
--wa-color-red-95: #fff0ef /* oklch(96.667% 0.01632 22.08) */;
|
||||
--wa-color-red-90: #ffdedc /* oklch(92.735% 0.03679 21.966) */;
|
||||
--wa-color-red-80: #ffb8b4 /* oklch(84.753% 0.08313 22.598) */;
|
||||
--wa-color-red-70: #fd908e /* oklch(76.913% 0.13219 21.705) */;
|
||||
--wa-color-red-60: #f46766 /* oklch(68.945% 0.17423 23.179) */;
|
||||
--wa-color-red-50: #df2f2e /* oklch(58.922% 0.21141 26.911) */;
|
||||
--wa-color-red-40: #b60000 /* oklch(48.747% 0.20003 29.234) */;
|
||||
--wa-color-red-30: #910000 /* oklch(41.235% 0.16921 29.234) */;
|
||||
--wa-color-red-20: #6d0000 /* oklch(33.581% 0.1378 29.234) */;
|
||||
--wa-color-red-10: #450000 /* oklch(24.517% 0.1006 29.234) */;
|
||||
--wa-color-red-05: #2f0000 /* oklch(19.165% 0.07864 29.234) */;
|
||||
--wa-color-red-80: #ffb8b5 /* oklch(84.778% 0.083 21.686) */;
|
||||
--wa-color-red-70: #fe8f8d /* oklch(76.859% 0.13466 21.762) */;
|
||||
--wa-color-red-60: #f56667 /* oklch(68.982% 0.17631 22.472) */;
|
||||
--wa-color-red-50: #e02c2b /* oklch(58.861% 0.21461 27.156) */;
|
||||
--wa-color-red-40: #b5051a /* oklch(48.833% 0.19611 25.68) */;
|
||||
--wa-color-red-30: #900015 /* oklch(41.172% 0.16676 24.609) */;
|
||||
--wa-color-red-20: #6c000d /* oklch(33.479% 0.1356 24.617) */;
|
||||
--wa-color-red-10: #450005 /* oklch(24.598% 0.09968 24.835) */;
|
||||
--wa-color-red-05: #2f0002 /* oklch(19.218% 0.07801 25.517) */;
|
||||
--wa-color-red: var(--wa-color-red-50);
|
||||
--wa-color-red-key: 50;
|
||||
|
||||
--wa-color-orange-95: oklch(96.245% 0.04153 59.224);
|
||||
--wa-color-orange-90: oklch(92.468% 0.07656 58.647);
|
||||
--wa-color-orange-80: oklch(84.375% 0.11283 54.179);
|
||||
--wa-color-orange-70: #fb945a /* oklch(76.369% 0.14454 48.621) */;
|
||||
--wa-color-orange-60: #f26b31 /* oklch(68.509% 0.18046 41.503) */;
|
||||
--wa-color-orange-50: #cf4812 /* oklch(58.288% 0.18026 38.576) */;
|
||||
--wa-color-orange-40: oklch(48.175% 0.16316 38.526);
|
||||
--wa-color-orange-30: oklch(40.779% 0.13925 37.899);
|
||||
--wa-color-orange-20: oklch(33.129% 0.11288 38.58);
|
||||
--wa-color-orange-10: oklch(24.259% 0.0831 38.502);
|
||||
--wa-color-orange-05: oklch(18.969% 0.06527 38.137);
|
||||
--wa-color-orange-95: #fff0e4 /* oklch(96.374% 0.0228 61.238) */;
|
||||
--wa-color-orange-90: #ffe0c8 /* oklch(92.611% 0.04689 59.917) */;
|
||||
--wa-color-orange-80: #ffbb89 /* oklch(84.386% 0.10217 57.161) */;
|
||||
--wa-color-orange-70: #ff9342 /* oklch(76.486% 0.15964 54.102) */;
|
||||
--wa-color-orange-60: #f36d00 /* oklch(68.715% 0.18774 47.79) */;
|
||||
--wa-color-orange-50: #c94e00 /* oklch(58.068% 0.17131 43.217) */;
|
||||
--wa-color-orange-40: #9d3800 /* oklch(47.924% 0.14534 41.739) */;
|
||||
--wa-color-orange-30: #7e2900 /* oklch(40.53% 0.1259 40.51) */;
|
||||
--wa-color-orange-20: #5e1c00 /* oklch(32.874% 0.1027 40.228) */;
|
||||
--wa-color-orange-10: #3b0f00 /* oklch(24.125% 0.07446 40.837) */;
|
||||
--wa-color-orange-05: #280700 /* oklch(18.837% 0.05933 39.827) */;
|
||||
--wa-color-orange: var(--wa-color-orange-60);
|
||||
--wa-color-orange-key: 60;
|
||||
|
||||
--wa-color-yellow-95: #fef2bf /* oklch(95.823% 0.06674 96.369) */;
|
||||
--wa-color-yellow-90: #fde588 /* oklch(92.2% 0.11633 95.327) */;
|
||||
--wa-color-yellow-80: #f4c34e /* oklch(83.998% 0.14252 85.76) */;
|
||||
--wa-color-yellow-80: #f5c24b /* oklch(83.879% 0.14445 85.083) */;
|
||||
--wa-color-yellow-70: #e9a010 /* oklch(75.825% 0.15689 75.537) */;
|
||||
--wa-color-yellow-60: #de7c00 /* oklch(68.073% 0.15991 59.827) */;
|
||||
--wa-color-yellow-50: #bc5908 /* oklch(57.654% 0.1491 50.241) */;
|
||||
--wa-color-yellow-40: #934107 /* oklch(47.603% 0.12628 47.819) */;
|
||||
--wa-color-yellow-30: #763104 /* oklch(40.324% 0.1093 46.564) */;
|
||||
--wa-color-yellow-20: #572301 /* oklch(32.677% 0.08796 47.926) */;
|
||||
--wa-color-yellow-10: #371300 /* oklch(24.001% 0.06559 47.77) */;
|
||||
--wa-color-yellow-05: #250a00 /* oklch(18.773% 0.0519 47.039) */;
|
||||
--wa-color-yellow: var(--wa-color-yellow-60);
|
||||
--wa-color-yellow-key: 60;
|
||||
--wa-color-yellow-60: #d78000 /* oklch(67.839% 0.15287 64.455) */;
|
||||
--wa-color-yellow-50: #b26000 /* oklch(57.324% 0.13672 58.338) */;
|
||||
--wa-color-yellow-40: #8a4700 /* oklch(47.183% 0.11461 56.655) */;
|
||||
--wa-color-yellow-30: #6e3700 /* oklch(40.03% 0.0976 56.323) */;
|
||||
--wa-color-yellow-20: #522700 /* oklch(32.54% 0.07981 55.802) */;
|
||||
--wa-color-yellow-10: #331600 /* oklch(23.846% 0.05834 56.02) */;
|
||||
--wa-color-yellow-05: #210d00 /* oklch(18.619% 0.04431 58.553) */;
|
||||
--wa-color-yellow: var(--wa-color-yellow-70);
|
||||
--wa-color-yellow-key: 70;
|
||||
|
||||
--wa-color-green-95: #d4fce1 /* oklch(95.554% 0.05477 155.71) */;
|
||||
--wa-color-green-90: #a4f8c2 /* oklch(91.11% 0.1107 155.35) */;
|
||||
|
||||
@@ -18,19 +18,19 @@
|
||||
--wa-color-red: var(--wa-color-red-50);
|
||||
--wa-color-red-key: 50;
|
||||
|
||||
--wa-color-orange-95: oklch(96.494% 0.0335 57.914);
|
||||
--wa-color-orange-90: oklch(92.556% 0.06963 56.631);
|
||||
--wa-color-orange-80: oklch(84.494% 0.12276 53.381);
|
||||
--wa-color-orange-70: oklch(76.375% 0.17194 46.091);
|
||||
--wa-color-orange-60: #eb713f /* oklch(68.398% 0.16422 41.446) */;
|
||||
--wa-color-orange-50: #cb4b1d /* oklch(58.153% 0.17174 38.404) */;
|
||||
--wa-color-orange-40: #a2310c /* oklch(48.028% 0.15488 36.538) */;
|
||||
--wa-color-orange-30: #7f2810 /* oklch(40.591% 0.12506 35.663) */;
|
||||
--wa-color-orange-20: #5d1d0e /* oklch(32.908% 0.09683 34.387) */;
|
||||
--wa-color-orange-10: #3a1005 /* oklch(24.088% 0.06954 35.613) */;
|
||||
--wa-color-orange-05: #270803 /* oklch(18.801% 0.05509 34.149) */;
|
||||
--wa-color-orange: var(--wa-color-orange-70);
|
||||
--wa-color-orange-key: 70;
|
||||
--wa-color-orange-95: #fff0e6 /* oklch(96.426% 0.02105 56.133) */;
|
||||
--wa-color-orange-90: #ffdfca /* oklch(92.468% 0.04529 55.325) */;
|
||||
--wa-color-orange-80: #ffbb94 /* oklch(84.588% 0.09454 50.876) */;
|
||||
--wa-color-orange-70: #ff9266 /* oklch(76.744% 0.14429 42.309) */;
|
||||
--wa-color-orange-60: #f46a45 /* oklch(68.848% 0.17805 35.951) */;
|
||||
--wa-color-orange-50: #cd491c /* oklch(58.195% 0.17597 37.577) */;
|
||||
--wa-color-orange-40: #9f3501 /* oklch(47.889% 0.14981 39.957) */;
|
||||
--wa-color-orange-30: #802700 /* oklch(40.637% 0.1298 39.149) */;
|
||||
--wa-color-orange-20: #601b00 /* oklch(33.123% 0.10587 39.117) */;
|
||||
--wa-color-orange-10: #3c0d00 /* oklch(24.043% 0.07768 38.607) */;
|
||||
--wa-color-orange-05: #280600 /* oklch(18.644% 0.0607 38.252) */;
|
||||
--wa-color-orange: var(--wa-color-orange-60);
|
||||
--wa-color-orange-key: 60;
|
||||
|
||||
--wa-color-yellow-95: #fef3cd /* oklch(96.322% 0.05069 93.748) */;
|
||||
--wa-color-yellow-90: #ffe495 /* oklch(92.377% 0.10246 91.296) */;
|
||||
|
||||
@@ -18,17 +18,17 @@
|
||||
--wa-color-red: var(--wa-color-red-40);
|
||||
--wa-color-red-key: 40;
|
||||
|
||||
--wa-color-orange-95: oklch(96.238% 0.02664 61.788);
|
||||
--wa-color-orange-90: #fbe1cc /* oklch(92.512% 0.04019 60.45) */;
|
||||
--wa-color-orange-80: #edc1a0 /* oklch(84.097% 0.06661 58.236) */;
|
||||
--wa-color-orange-70: #dda178 /* oklch(75.734% 0.09064 55.123) */;
|
||||
--wa-color-orange-60: #cd8351 /* oklch(67.646% 0.1134 53.172) */;
|
||||
--wa-color-orange-50: #b65d22 /* oklch(57.437% 0.13446 49.881) */;
|
||||
--wa-color-orange-40: oklch(47.576% 0.13426 46.452);
|
||||
--wa-color-orange-30: oklch(40.382% 0.12087 47.003);
|
||||
--wa-color-orange-20: oklch(32.846% 0.0965 46.227);
|
||||
--wa-color-orange-10: oklch(24.06% 0.06873 45.849);
|
||||
--wa-color-orange-05: #260900 /* oklch(18.727% 0.05359 44.791) */;
|
||||
--wa-color-orange-95: #ffefe1 /* oklch(96.105% 0.02545 63.746) */;
|
||||
--wa-color-orange-90: #fbe0cb /* oklch(92.334% 0.04096 60.142) */;
|
||||
--wa-color-orange-80: #efc19f /* oklch(84.313% 0.06973 58.09) */;
|
||||
--wa-color-orange-70: #e1a173 /* oklch(76.013% 0.09772 56.368) */;
|
||||
--wa-color-orange-60: #d1824d /* oklch(67.937% 0.11938 53.195) */;
|
||||
--wa-color-orange-50: #b65d22 /* oklch(57.543% 0.13444 49.914) */;
|
||||
--wa-color-orange-40: #934107 /* oklch(47.603% 0.12628 47.819) */;
|
||||
--wa-color-orange-30: #773001 /* oklch(40.317% 0.11198 46.326) */;
|
||||
--wa-color-orange-20: #592100 /* oklch(32.692% 0.09239 45.689) */;
|
||||
--wa-color-orange-10: #381200 /* oklch(24.015% 0.06777 45.771) */;
|
||||
--wa-color-orange-05: #260900 /* oklch(18.789% 0.05427 44.405) */;
|
||||
--wa-color-orange: var(--wa-color-orange-50);
|
||||
--wa-color-orange-key: 50;
|
||||
|
||||
|
||||
@@ -18,19 +18,19 @@
|
||||
--wa-color-red: var(--wa-color-red-40);
|
||||
--wa-color-red-key: 40;
|
||||
|
||||
--wa-color-orange-95: oklch(96.126% 0.05417 66.333);
|
||||
--wa-color-orange-90: oklch(92.413% 0.07898 62.545);
|
||||
--wa-color-orange-80: #f9bd86 /* oklch(84.088% 0.09891 63.847) */;
|
||||
--wa-color-orange-70: #e2a05f /* oklch(75.707% 0.11352 64.057) */;
|
||||
--wa-color-orange-60: #d18228 /* oklch(67.572% 0.13809 64.146) */;
|
||||
--wa-color-orange-50: oklch(57.202% 0.13583 64.309);
|
||||
--wa-color-orange-40: oklch(47.462% 0.13789 64.939);
|
||||
--wa-color-orange-30: oklch(40.049% 0.12025 65.207);
|
||||
--wa-color-orange-20: oklch(32.552% 0.09777 64.859);
|
||||
--wa-color-orange-10: oklch(23.884% 0.07141 64.246);
|
||||
--wa-color-orange-05: oklch(18.698% 0.05597 65.589);
|
||||
--wa-color-orange: var(--wa-color-orange-60);
|
||||
--wa-color-orange-key: 60;
|
||||
--wa-color-orange-95: #fff0e8 /* oklch(96.479% 0.01949 50.157) */;
|
||||
--wa-color-orange-90: #ffdfc8 /* oklch(92.42% 0.04692 57.822) */;
|
||||
--wa-color-orange-80: #ffbb84 /* oklch(84.3% 0.10585 59.641) */;
|
||||
--wa-color-orange-70: #e79f64 /* oklch(76.075% 0.1143 59.207) */;
|
||||
--wa-color-orange-60: #ca854c /* oklch(67.612% 0.11209 58.789) */;
|
||||
--wa-color-orange-50: #a56732 /* oklch(57.133% 0.10488 58.75) */;
|
||||
--wa-color-orange-40: #824c1a /* oklch(47.091% 0.09621 59.168) */;
|
||||
--wa-color-orange-30: #6a3907 /* oklch(39.832% 0.09012 58.688) */;
|
||||
--wa-color-orange-20: #512800 /* oklch(32.57% 0.07814 57.787) */;
|
||||
--wa-color-orange-10: #331600 /* oklch(23.846% 0.05834 56.02) */;
|
||||
--wa-color-orange-05: #220c00 /* oklch(18.585% 0.04625 54.588) */;
|
||||
--wa-color-orange: var(--wa-color-orange-70);
|
||||
--wa-color-orange-key: 70;
|
||||
|
||||
--wa-color-yellow-95: #fff4b3 /* oklch(96.064% 0.08319 99.657) */;
|
||||
--wa-color-yellow-90: #fee58c /* oklch(92.346% 0.11242 94.205) */;
|
||||
|
||||
@@ -18,17 +18,17 @@
|
||||
--wa-color-red: var(--wa-color-red-50);
|
||||
--wa-color-red-key: 50;
|
||||
|
||||
--wa-color-orange-95: #f8f0ec /* oklch(96.084% 0.01043 54.557) */;
|
||||
--wa-color-orange-90: #f2e3d8 /* oklch(92.485% 0.02211 56.694) */;
|
||||
--wa-color-orange-80: #e4c4ad /* oklch(84.166% 0.04799 57.553) */;
|
||||
--wa-color-orange-70: #d3a583 /* oklch(75.674% 0.07148 57.481) */;
|
||||
--wa-color-orange-60: #bc8a65 /* oklch(67.319% 0.08062 57.054) */;
|
||||
--wa-color-orange-50: #9e6940 /* oklch(56.757% 0.08845 56.746) */;
|
||||
--wa-color-orange-40: #7e4d27 /* oklch(46.949% 0.08447 57.382) */;
|
||||
--wa-color-orange-30: #673a17 /* oklch(39.774% 0.0793 55.768) */;
|
||||
--wa-color-orange-20: #4f2906 /* oklch(32.45% 0.0725 57.629) */;
|
||||
--wa-color-orange-10: #311702 /* oklch(23.759% 0.05361 57.126) */;
|
||||
--wa-color-orange-05: #200d01 /* oklch(18.517% 0.04211 57.178) */;
|
||||
--wa-color-orange-95: #f9f2ed /* oklch(96.52% 0.01008 58.217) */;
|
||||
--wa-color-orange-90: #f4e3d6 /* oklch(92.595% 0.02556 59.903) */;
|
||||
--wa-color-orange-80: #e6c3aa /* oklch(84.087% 0.05242 57.474) */;
|
||||
--wa-color-orange-70: #d3a685 /* oklch(75.824% 0.06976 57.703) */;
|
||||
--wa-color-orange-60: #bf8962 /* oklch(67.428% 0.08515 56.553) */;
|
||||
--wa-color-orange-50: #a26839 /* oklch(57.025% 0.09733 58.071) */;
|
||||
--wa-color-orange-40: #824b20 /* oklch(46.959% 0.09366 55.634) */;
|
||||
--wa-color-orange-30: #683a17 /* oklch(39.855% 0.08077 54.814) */;
|
||||
--wa-color-orange-20: #4d2a0e /* oklch(32.469% 0.06563 55.984) */;
|
||||
--wa-color-orange-10: #301705 /* oklch(23.621% 0.04968 54.306) */;
|
||||
--wa-color-orange-05: #1f0e03 /* oklch(18.572% 0.03671 56.067) */;
|
||||
--wa-color-orange: var(--wa-color-orange-50);
|
||||
--wa-color-orange-key: 50;
|
||||
|
||||
|
||||
@@ -18,19 +18,19 @@
|
||||
--wa-color-red: var(--wa-color-red-50);
|
||||
--wa-color-red-key: 50;
|
||||
|
||||
--wa-color-orange-95: oklch(96.488% 0.04965 58.92);
|
||||
--wa-color-orange-90: oklch(92.244% 0.08759 57.789);
|
||||
--wa-color-orange-80: oklch(84.32% 0.12702 56.232);
|
||||
--wa-color-orange-70: oklch(76.31% 0.17967 50.95);
|
||||
--wa-color-orange-60: #e87431 /* oklch(68.352% 0.16354 47.083) */;
|
||||
--wa-color-orange-50: oklch(58.23% 0.17947 43.3);
|
||||
--wa-color-orange-40: oklch(48.089% 0.16071 40.798);
|
||||
--wa-color-orange-30: oklch(40.708% 0.13699 39.616);
|
||||
--wa-color-orange-20: oklch(33.124% 0.1121 39.599);
|
||||
--wa-color-orange-10: oklch(24.257% 0.08204 39.602);
|
||||
--wa-color-orange-05: oklch(18.966% 0.06414 39.606);
|
||||
--wa-color-orange: var(--wa-color-orange-70);
|
||||
--wa-color-orange-key: 70;
|
||||
--wa-color-orange-95: #fff1e4 /* oklch(96.567% 0.02297 65.466) */;
|
||||
--wa-color-orange-90: #ffdfc4 /* oklch(92.327% 0.0504 62.301) */;
|
||||
--wa-color-orange-80: #ffbc80 /* oklch(84.418% 0.10871 62.363) */;
|
||||
--wa-color-orange-70: #ff9427 /* oklch(76.467% 0.1689 59.353) */;
|
||||
--wa-color-orange-60: #f16e00 /* oklch(68.563% 0.18516 48.551) */;
|
||||
--wa-color-orange-50: #c75003 /* oklch(58.025% 0.16741 44.08) */;
|
||||
--wa-color-orange-40: #9e3702 /* oklch(47.974% 0.14693 40.809) */;
|
||||
--wa-color-orange-30: #802700 /* oklch(40.637% 0.1298 39.149) */;
|
||||
--wa-color-orange-20: #601a00 /* oklch(32.994% 0.10679 38.524) */;
|
||||
--wa-color-orange-10: #3d0d00 /* oklch(24.253% 0.07888 38.298) */;
|
||||
--wa-color-orange-05: #290600 /* oklch(18.868% 0.06197 37.848) */;
|
||||
--wa-color-orange: var(--wa-color-orange-60);
|
||||
--wa-color-orange-key: 60;
|
||||
|
||||
--wa-color-yellow-95: #fff5b4 /* oklch(96.281% 0.08306 100.4) */;
|
||||
--wa-color-yellow-90: #fde572 /* oklch(91.915% 0.13738 97.724) */;
|
||||
|
||||
@@ -18,19 +18,19 @@
|
||||
--wa-color-red: var(--wa-color-red-50);
|
||||
--wa-color-red-key: 50;
|
||||
|
||||
--wa-color-orange-95: oklch(96.355% 0.05982 62.448);
|
||||
--wa-color-orange-90: oklch(92.371% 0.10134 60.314);
|
||||
--wa-color-orange-80: oklch(84.228% 0.13101 54.157);
|
||||
--wa-color-orange-70: oklch(76.275% 0.16839 51.143);
|
||||
--wa-color-orange-60: #e67530 /* oklch(68.22% 0.16179 47.997) */;
|
||||
--wa-color-orange-50: oklch(58.011% 0.16819 44.953);
|
||||
--wa-color-orange-40: #9b390d /* oklch(47.739% 0.14004 40.585) */;
|
||||
--wa-color-orange-30: #7a2b17 /* oklch(40.323% 0.11475 35.602) */;
|
||||
--wa-color-orange-20: #5c1e0f /* oklch(32.963% 0.09552 34.666) */;
|
||||
--wa-color-orange-10: #3a0f06 /* oklch(24.042% 0.07066 34.715) */;
|
||||
--wa-color-orange-05: #270803 /* oklch(18.867% 0.05444 34.696) */;
|
||||
--wa-color-orange: var(--wa-color-orange-70);
|
||||
--wa-color-orange-key: 70;
|
||||
--wa-color-orange-95: #fff1de /* oklch(96.415% 0.02927 75.692) */;
|
||||
--wa-color-orange-90: #fee0bc /* oklch(92.25% 0.05764 72.084) */;
|
||||
--wa-color-orange-80: #fdbe7a /* oklch(84.485% 0.11179 67.463) */;
|
||||
--wa-color-orange-70: #fb9641 /* oklch(76.472% 0.15504 57.097) */;
|
||||
--wa-color-orange-60: #f56b11 /* oklch(68.77% 0.18951 45.673) */;
|
||||
--wa-color-orange-50: #cf480e /* oklch(58.335% 0.18077 39.019) */;
|
||||
--wa-color-orange-40: #a13308 /* oklch(48.025% 0.15268 37.837) */;
|
||||
--wa-color-orange-30: #802604 /* oklch(40.538% 0.12998 37.701) */;
|
||||
--wa-color-orange-20: #601a02 /* oklch(33.012% 0.10627 37.613) */;
|
||||
--wa-color-orange-10: #3d0d01 /* oklch(24.269% 0.07841 37.157) */;
|
||||
--wa-color-orange-05: #290600 /* oklch(18.868% 0.06197 37.848) */;
|
||||
--wa-color-orange: var(--wa-color-orange-60);
|
||||
--wa-color-orange-key: 60;
|
||||
|
||||
--wa-color-yellow-95: #fef6ab /* oklch(96.234% 0.09455 102.83) */;
|
||||
--wa-color-yellow-90: #fde761 /* oklch(92.138% 0.15325 99.997) */;
|
||||
|
||||
@@ -2,10 +2,12 @@ details:where(:not(:host *)),
|
||||
:host {
|
||||
--icon-color: var(--wa-color-text-quiet);
|
||||
--spacing: var(--wa-space-m);
|
||||
--outlined-border-color: var(--wa-color-surface-border);
|
||||
|
||||
background-color: var(--wa-color-surface-default);
|
||||
border: var(--wa-panel-border-width) var(--wa-color-surface-border) var(--wa-panel-border-style);
|
||||
background-color: var(--background-color, var(--wa-color-surface-default));
|
||||
border: var(--wa-panel-border-width) var(--border-color, var(--wa-color-surface-border)) var(--wa-panel-border-style);
|
||||
border-radius: var(--wa-panel-border-radius);
|
||||
color: var(--text-color, inherit);
|
||||
padding: var(--spacing);
|
||||
|
||||
/* Print styles */
|
||||
@@ -19,6 +21,12 @@ details:where(:not(:host *)),
|
||||
}
|
||||
}
|
||||
|
||||
details.wa-plain,
|
||||
:host(wa-details[appearance='plain']),
|
||||
:host(wa-details.wa-plain) {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
details:where(:not(:host *)) summary,
|
||||
:host summary /* nesting these summary styles in the rule above breaks in Firefox and Safari */ {
|
||||
display: flex;
|
||||
|
||||
@@ -80,8 +80,7 @@
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
/**
|
||||
* Foundational Colors
|
||||
*/
|
||||
|
||||
@@ -71,8 +71,7 @@
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
color-scheme: dark;
|
||||
color: var(--wa-color-text-normal);
|
||||
|
||||
|
||||
@@ -78,8 +78,7 @@
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
color-scheme: dark;
|
||||
color: var(--wa-color-text-normal);
|
||||
|
||||
|
||||
@@ -68,8 +68,7 @@
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
/**
|
||||
* Foundational Colors
|
||||
*/
|
||||
|
||||
@@ -114,10 +114,8 @@
|
||||
--wa-color-neutral-on-loud: white;
|
||||
}
|
||||
|
||||
/** need to wrap :host-context() in an :is() selector for unsupported browsers */
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
color-scheme: dark;
|
||||
color: var(--wa-color-text-normal);
|
||||
|
||||
|
||||
@@ -85,8 +85,7 @@
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
/**
|
||||
* Foundational Colors
|
||||
*/
|
||||
|
||||
@@ -83,8 +83,7 @@
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
/**
|
||||
* Foundational Colors
|
||||
*/
|
||||
|
||||
@@ -75,8 +75,7 @@
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
/**
|
||||
* Foundational Colors
|
||||
*/
|
||||
|
||||
@@ -74,8 +74,7 @@
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
/**
|
||||
* Foundational Colors
|
||||
*/
|
||||
|
||||
@@ -84,8 +84,7 @@
|
||||
}
|
||||
|
||||
.wa-dark,
|
||||
.wa-invert,
|
||||
:is(:host-context(.wa-dark)) {
|
||||
.wa-invert {
|
||||
/**
|
||||
* Foundational Colors
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
:where(:root),
|
||||
:host,
|
||||
.wa-theme-tailspin,
|
||||
:is(:host-context(.wa-theme-tailspin)) {
|
||||
.wa-theme-tailspin {
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
/*
|
||||
* Utility to minimize FOUCE and show custom elements only after they're registered
|
||||
*/
|
||||
:not(:defined),
|
||||
:state(wa-defined):has(:not(:defined)),
|
||||
.wa-cloak:has(:not(:defined)) {
|
||||
animation: 2s step-end wa-fouce-cloak;
|
||||
}
|
||||
|
||||
@keyframes wa-fade-in {
|
||||
@keyframes wa-fouce-cloak {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
:not(:defined),
|
||||
:state(wa-defined):has(:not(:defined)) {
|
||||
/* The clamp() ensures that if --wa-fouce-timeout is set to 0s, the whole effect is disabled */
|
||||
--wa-fouce-animation: clamp(0s, var(--wa-fouce-fade, 200ms), var(--wa-fouce-timeout, 2s)) var(--wa-fouce-timeout, 2s)
|
||||
wa-fade-in both;
|
||||
|
||||
&:where(:not([did-ssr], .wa-fouce-off, .wa-fouce-off *)) {
|
||||
animation: var(--wa-fouce-animation);
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,12 @@ export async function discover(root: Element | ShadowRoot) {
|
||||
console.warn(imp.reason); // eslint-disable-line no-console
|
||||
}
|
||||
}
|
||||
|
||||
// Wait a cycle to allow the first Lit update to run
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
// Dispatch an event when discovery is complete.
|
||||
document.dispatchEvent(new CustomEvent('wa-discovery-complete'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,3 +75,22 @@ function register(tagName: string): Promise<void> {
|
||||
import(path).then(() => resolve()).catch(() => reject(new Error(`Unable to autoload <${tagName}> from ${path}`)));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Acts as a middleware for Turbo's `turbo:before-render` event to ensure components are auto-loaded before showing the
|
||||
* next page, eliminating page-to-page FOUCE in a Turbo environment.
|
||||
*/
|
||||
export function preventTurboFouce(timeout = 2000) {
|
||||
document.addEventListener('turbo:before-render', async (event: CustomEvent) => {
|
||||
const newBody = event.detail.newBody;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
try {
|
||||
// Wait until all elements are registered or two seconds, whichever comes first
|
||||
await Promise.race([discover(newBody), new Promise(resolve => setTimeout(resolve, timeout))]);
|
||||
} finally {
|
||||
event.detail.resume();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
64
src/utilities/defined.ts
Normal file
64
src/utilities/defined.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
interface AllDefinedOptions {
|
||||
/**
|
||||
* A callback that accepts a custom element tag name and returns `true` if the custom element should be defined before
|
||||
* resolving or `false` to skip it. The tag name is always in lowercase.
|
||||
*/
|
||||
match: (tagName: string) => boolean;
|
||||
|
||||
/**
|
||||
* To wait for additional custom elements that may not be on the page when the function is called, provide them here.
|
||||
*/
|
||||
additionalElements: string | string[];
|
||||
|
||||
/**
|
||||
* The root in which to look for custom elements. Defaults to `document`. By design, shadow roots are not traversed,
|
||||
* but you can call this function and set `root` to a custom element's shadow root if needed.
|
||||
*/
|
||||
root: Document | ShadowRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for custom elements that are currently on the page to be registered before resolving. This is sugar for
|
||||
* awaiting `customElements.whenDefined()` multiple times. By default, the function waits for all undefined Web Awesome
|
||||
* elements, but you can pass a custom match function to wait for other custom elements instead.
|
||||
*
|
||||
* The function returns with `Promise.all()`, so any loading errors will cause it to reject. Make sure you handle errors
|
||||
* accordingly using a try/catch block or a `.catch()`.
|
||||
*
|
||||
* @example
|
||||
* // Wait for Web Awesome elements
|
||||
* await allDefined();
|
||||
*
|
||||
* // Wait for all custom elements that start with `foo-` as well as the `<bar-button>` element
|
||||
* await allDefined({
|
||||
* match: tagName => tagName.startsWith('foo-'),
|
||||
* additionalElements: ['bar-button', 'baz-dialog']
|
||||
* });
|
||||
*/
|
||||
export async function allDefined(options?: Partial<AllDefinedOptions>) {
|
||||
const opts: AllDefinedOptions = {
|
||||
match: tagName => tagName.startsWith('wa-'),
|
||||
additionalElements: [],
|
||||
root: document,
|
||||
...options,
|
||||
};
|
||||
|
||||
// Ensure additional elements is an array
|
||||
const additionalElements = Array.isArray(opts.additionalElements)
|
||||
? opts.additionalElements
|
||||
: [opts.additionalElements];
|
||||
|
||||
// Discover undefined elements in the document
|
||||
const undefinedElements = [...opts.root.querySelectorAll(':not(:defined)')]
|
||||
.map(el => el.localName)
|
||||
.filter((tag, index, arr) => arr.indexOf(tag) === index) // make it unique
|
||||
.filter(tag => opts.match(tag)); // make sure it matches
|
||||
|
||||
const tagsToAwait = [...undefinedElements, ...additionalElements];
|
||||
|
||||
// Wait for all to be registered
|
||||
await Promise.all(tagsToAwait.map(tag => customElements.whenDefined(tag)));
|
||||
|
||||
// Wait a cycle for the first update
|
||||
await new Promise(requestAnimationFrame);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
export { registerIconLibrary, unregisterIconLibrary } from './components/icon/library.js';
|
||||
export { discover, startLoader, stopLoader } from './utilities/autoloader.js';
|
||||
export { discover, preventTurboFouce, startLoader, stopLoader } from './utilities/autoloader.js';
|
||||
export { getBasePath, getKitCode, setBasePath, setKitCode } from './utilities/base-path.js';
|
||||
export { allDefined } from './utilities/defined.js';
|
||||
export { registerTranslation } from './utilities/localize.js';
|
||||
|
||||
// Utilities
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user