mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-17 22:49:14 +00:00
Compare commits
39 Commits
base
...
support-fa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67d8962e32 | ||
|
|
8b17b3d3e0 | ||
|
|
f5d1b74e00 | ||
|
|
40ea444c48 | ||
|
|
403927687e | ||
|
|
6af4e849af | ||
|
|
2c839a4225 | ||
|
|
3703ef26da | ||
|
|
3640b4c6e1 | ||
|
|
27fc269a94 | ||
|
|
a5b2fffb7a | ||
|
|
7de6a676b8 | ||
|
|
3c77d400f8 | ||
|
|
6ee10f44f4 | ||
|
|
6afc6e928c | ||
|
|
f8fcbd60ec | ||
|
|
bdd25571a8 | ||
|
|
38c13640fc | ||
|
|
00a3b1aa8d | ||
|
|
22298781c5 | ||
|
|
fe27710f57 | ||
|
|
d94589d113 | ||
|
|
3508bf6339 | ||
|
|
61e65ffcb9 | ||
|
|
aed28adbe4 | ||
|
|
15b8bde81b | ||
|
|
9ee3fb5d28 | ||
|
|
47aa376c08 | ||
|
|
69ba974a50 | ||
|
|
8dfb411e5e | ||
|
|
a35a8fd2ad | ||
|
|
2503005bbd | ||
|
|
78027170ea | ||
|
|
a20aa48992 | ||
|
|
ac8accd664 | ||
|
|
c571573063 | ||
|
|
e813440315 | ||
|
|
714250cc96 | ||
|
|
ac366987f3 |
2
.github/workflows/client_tests.js.yml
vendored
2
.github/workflows/client_tests.js.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Lint
|
||||
run: npm run prettier
|
||||
- name: Build
|
||||
run: npm run build:alpha
|
||||
run: npm run build
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
- name: Run CSR tests
|
||||
|
||||
2
.github/workflows/ssr_tests.js.yml
vendored
2
.github/workflows/ssr_tests.js.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
run: npm run prettier
|
||||
|
||||
- name: Build
|
||||
run: npm run build:alpha
|
||||
run: npm run build
|
||||
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
*.hbs
|
||||
*.md
|
||||
!docs/docs/patterns/**/*.md
|
||||
docs/docs/patterns/blog-news/post-list.md
|
||||
.cache
|
||||
.github
|
||||
cspell.json
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
"scrollbars",
|
||||
"scrollend",
|
||||
"scroller",
|
||||
"Scrollers",
|
||||
"Segoe",
|
||||
"semibold",
|
||||
"shadowrootmode",
|
||||
|
||||
@@ -5,7 +5,6 @@ import { copyCodePlugin } from './_utils/copy-code.js';
|
||||
import { currentLink } from './_utils/current-link.js';
|
||||
import { highlightCodePlugin } from './_utils/highlight-code.js';
|
||||
import { markdown } from './_utils/markdown.js';
|
||||
import { removeDataAlphaElements } from './_utils/remove-data-alpha-elements.js';
|
||||
// import { formatCodePlugin } from './_utils/format-code.js';
|
||||
// import litPlugin from '@lit-labs/eleventy-plugin-lit';
|
||||
import { readFile } from 'fs/promises';
|
||||
@@ -22,12 +21,10 @@ 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');
|
||||
|
||||
const globalData = {
|
||||
package: packageData,
|
||||
isAlpha,
|
||||
layout: 'page.njk',
|
||||
server: {
|
||||
head: '',
|
||||
@@ -51,16 +48,6 @@ export default function (eleventyConfig) {
|
||||
*/
|
||||
const serverBuild = process.env.WEBAWESOME_SERVER === 'true';
|
||||
|
||||
// NOTE - alpha setting removes certain pages
|
||||
if (isAlpha) {
|
||||
eleventyConfig.ignores.add('**/experimental/**');
|
||||
eleventyConfig.ignores.add('**/layout/**');
|
||||
eleventyConfig.ignores.add('**/patterns/**');
|
||||
eleventyConfig.ignores.add('**/style-utilities/**');
|
||||
eleventyConfig.ignores.add('**/components/code-demo.md');
|
||||
eleventyConfig.ignores.add('**/components/viewport-demo.md');
|
||||
}
|
||||
|
||||
// Add template data
|
||||
for (let name in globalData) {
|
||||
eleventyConfig.addGlobalData(name, globalData[name]);
|
||||
@@ -115,9 +102,6 @@ export default function (eleventyConfig) {
|
||||
|
||||
// Helpers
|
||||
|
||||
// Remove elements that have [data-alpha="remove"]
|
||||
eleventyConfig.addPlugin(removeDataAlphaElements({ isAlpha }));
|
||||
|
||||
// Use our own markdown instance
|
||||
eleventyConfig.setLibrary('md', markdown);
|
||||
|
||||
@@ -169,6 +153,15 @@ export default function (eleventyConfig) {
|
||||
]),
|
||||
);
|
||||
|
||||
eleventyConfig.addPreprocessor('unpublished', '*', (data, content) => {
|
||||
if (data.unpublished && process.env.ELEVENTY_RUN_MODE === 'build') {
|
||||
// Exclude "unpublished" pages from final builds.
|
||||
return false;
|
||||
}
|
||||
|
||||
return content;
|
||||
});
|
||||
|
||||
// Build the search index
|
||||
eleventyConfig.addPlugin(
|
||||
searchPlugin({
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { hueRanges as default } from '../assets/scripts/tweak/data.js';
|
||||
export { hueRanges as default } from '../assets/data/index.js';
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
{% include 'head.njk' %}
|
||||
<meta name="theme-color" content="#f36944">
|
||||
|
||||
<script type="module" src="/assets/scripts/code-examples.js"></script>
|
||||
|
||||
<script type="module" src="/assets/scripts/scroll.js"></script>
|
||||
<script type="module" src="/assets/scripts/turbo.js"></script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="{{ description }}">
|
||||
{% if noindex %}<meta name="robots" content="noindex">{% endif %}
|
||||
{% if noindex or unlisted %}<meta name="robots" content="noindex">{% endif %}
|
||||
|
||||
<title>{{ title }}</title>
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
|
||||
<script type="module" src="/assets/scripts/theme-picker.js"></script>
|
||||
{# Preset Theme #}
|
||||
{% if forceTheme %}
|
||||
{% if noTheme %}
|
||||
{% elif forceTheme %}
|
||||
<link id="theme-stylesheet" rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/{{ forceTheme }}.css" render="blocking" fetchpriority="high" />
|
||||
{% else %}
|
||||
<noscript><link id="theme-stylesheet" rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/default.css" render="blocking" fetchpriority="high" /></noscript>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{%- if not page.data.unlisted -%}
|
||||
<a href="{{ page.url }}"{{ page.data.keywords | attr('data-keywords') }}>
|
||||
{% if page.url %}<a href="{{ page.url }}"{{ page.data.keywords | attr('data-keywords') }}>{% endif %}
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/" + (page.data.icon or "thumbnail-placeholder") + ".njk" ignore missing %}
|
||||
@@ -9,5 +9,5 @@
|
||||
<div class="wa-caption-s">{{ pageSubtitle }}</div>
|
||||
{%- endif %}
|
||||
</wa-card>
|
||||
</a>
|
||||
{% if page.url %}</a>{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<wa-select appearance="filled" size="small" value="default" pill class="preset-theme-selector">
|
||||
<wa-icon slot="prefix" name="paintbrush" variant="regular"></wa-icon>
|
||||
{% for theme in collections.theme | sort %}
|
||||
<wa-option value="{{ theme.page.fileSlug }}"{{ ' data-alpha="remove"' if theme.noAlpha }}>
|
||||
<wa-option value="{{ theme.page.fileSlug }}">
|
||||
{{ theme.data.title }}
|
||||
</wa-option>
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<wa-dialog id="site-search" no-header light-dismiss>
|
||||
<wa-dialog id="site-search" without-header light-dismiss>
|
||||
<div id="site-search-container">
|
||||
{# Header #}
|
||||
<header>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% if page | show -%}
|
||||
{% if page -%}
|
||||
<li>
|
||||
<a href="{{ page.url }}">{{ page.data.title }}</a>
|
||||
{% if page.data.status == 'experimental' %}<wa-icon name="flask"></wa-icon>{% endif %}
|
||||
|
||||
3
docs/_includes/svgs/call-to-action.njk
Normal file
3
docs/_includes/svgs/call-to-action.njk
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M63 6.32811V61.3125C63 66.375 56.6719 68.9062 53.2969 65.25L49.9219 61.7344C43.7344 55.2656 35.7188 51.1875 27 50.0625V64.125C27 68.4844 23.3438 72 19.125 72H16.875C12.5156 72 9 68.4844 9 64.125V49.5C3.9375 49.5 0 45.5625 0 40.5V27C0 22.0781 3.9375 18 9 18H20.1094L24.1875 17.8594C34.0312 17.2969 43.1719 13.0781 49.9219 5.90624L53.2969 2.39061C56.6719 -1.26564 63 1.12499 63 6.32811ZM22.5 49.6406L20.1094 49.5H13.5V64.125C13.5 66.0937 14.9062 67.5 16.875 67.5H19.125C20.9531 67.5 22.5 66.0937 22.5 64.125V49.6406ZM56.5312 5.48436L53.1562 8.99999C47.25 15.1875 39.6562 19.5469 31.5 21.375V46.2656C39.6562 48.0937 47.25 52.3125 53.1562 58.6406L56.5312 62.1562C57.2344 62.8594 58.5 62.2969 58.5 61.3125V6.32811C58.5 5.20311 57.2344 4.78124 56.5312 5.48436ZM27 22.0781C26.1562 22.2187 25.3125 22.3594 24.4688 22.3594L20.25 22.5H9C6.46875 22.5 4.5 24.6094 4.5 27V40.5C4.5 43.0312 6.46875 45 9 45H20.25L24.4688 45.2812C25.3125 45.4219 26.1562 45.4219 27 45.5625V22.0781ZM69.75 27C70.875 27 72 28.125 72 29.25V38.25C72 39.5156 70.875 40.5 69.75 40.5C68.4844 40.5 67.5 39.5156 67.5 38.25V29.25C67.5 28.125 68.4844 27 69.75 27Z" fill="var(--wa-color-neutral-on-quiet"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
10
docs/_includes/svgs/category-list.njk
Normal file
10
docs/_includes/svgs/category-list.njk
Normal file
@@ -0,0 +1,10 @@
|
||||
<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="var(--wa-color-surface-default)" stroke="var(--wa-color-surface-border)" stroke-width="2"/>
|
||||
<rect x="7" y="8" width="41" height="5" fill="var(--wa-color-neutral-on-quiet)"/>
|
||||
<rect x="7" y="19" width="23" height="14" rx="3" fill="var(--wa-color-neutral-fill-normal)"/>
|
||||
<rect x="35" y="19" width="23" height="14" rx="3" fill="var(--wa-color-neutral-fill-normal)"/>
|
||||
<rect x="63" y="19" width="23" height="14" rx="3" fill="var(--wa-color-neutral-fill-normal)"/>
|
||||
<rect x="7" y="36" width="23" height="14" rx="3" fill="var(--wa-color-neutral-fill-normal)"/>
|
||||
<rect x="35" y="36" width="23" height="14" rx="3" fill="var(--wa-color-neutral-fill-normal)"/>
|
||||
<rect x="63" y="36" width="23" height="14" rx="3" fill="var(--wa-color-neutral-fill-normal)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 986 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
31
docs/_includes/svgs/scroller.njk
Normal file
31
docs/_includes/svgs/scroller.njk
Normal file
@@ -0,0 +1,31 @@
|
||||
<svg width="96" height="64" viewBox="0 0 96 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 1H84C90.0751 1 95 5.92487 95 12V52C95 58.0751 90.0751 63 84 63H12C5.92487 63 1 58.0751 1 52V12C1 5.92487 5.92487 1 12 1Z" fill="var(--wa-color-surface-default)"/>
|
||||
<path d="M12 1H84C90.0751 1 95 5.92487 95 12V52C95 58.0751 90.0751 63 84 63H12C5.92487 63 1 58.0751 1 52V12C1 5.92487 5.92487 1 12 1Z" stroke="var(--wa-color-surface-border)" stroke-width="2"/>
|
||||
<rect x="12" y="12" width="24" height="4" rx="2" fill="var(--wa-color-neutral-fill-quiet)"/>
|
||||
<rect x="12" y="21" width="24" height="4" rx="2" fill="var(--wa-color-neutral-fill-quiet)"/>
|
||||
<rect x="12" y="30" width="24" height="4" rx="2" fill="var(--wa-color-neutral-fill-quiet)"/>
|
||||
<rect x="44" y="12" width="24" height="4" rx="2" fill="var(--wa-color-neutral-fill-quiet)"/>
|
||||
<rect x="44" y="21" width="24" height="4" rx="2" fill="var(--wa-color-neutral-fill-quiet)"/>
|
||||
<rect x="44" y="30" width="24" height="4" rx="2" fill="var(--wa-color-neutral-fill-quiet)"/>
|
||||
<rect x="76" y="12" width="20" height="4" rx="2" fill="url(#paint0_linear_302_2)"/>
|
||||
<rect x="76" y="21" width="20" height="4" rx="2" fill="url(#paint1_linear_302_2)"/>
|
||||
<rect x="76" y="30" width="20" height="4" rx="2" fill="url(#paint2_linear_302_2)"/>
|
||||
<rect x="4" y="44" width="88" height="16" rx="8" fill="var(--wa-color-neutral-fill-normal)"/>
|
||||
<path d="M85.8438 51.6562C86.0469 51.8438 86.0469 52.1719 85.8438 52.3594L82.8438 55.3594C82.6562 55.5625 82.3281 55.5625 82.1406 55.3594C81.9375 55.1719 81.9375 54.8438 82.1406 54.6562L84.7812 52L82.1406 49.3594C81.9375 49.1719 81.9375 48.8438 82.1406 48.6562C82.3281 48.4531 82.6562 48.4531 82.8438 48.6562L85.8438 51.6562Z" fill="var(--wa-color-neutral-border-loud)"/>
|
||||
<path d="M10.1406 51.6562L13.1406 48.6562C13.3281 48.4531 13.6562 48.4531 13.8438 48.6562C14.0469 48.8438 14.0469 49.1719 13.8438 49.3594L11.2031 52L13.8438 54.6562C14.0469 54.8438 14.0469 55.1719 13.8438 55.3594C13.6562 55.5625 13.3281 55.5625 13.1406 55.3594L10.1406 52.3594C9.9375 52.1719 9.9375 51.8438 10.1406 51.6562Z" fill="var(--wa-color-neutral-border-loud)"/>
|
||||
<path d="M20 52C20 49.7909 21.7909 48 24 48H48C50.2091 48 52 49.7909 52 52V52C52 54.2091 50.2091 56 48 56H24C21.7909 56 20 54.2091 20 52V52Z" fill="var(--wa-color-neutral-border-loud)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_302_2" x1="76" y1="14" x2="96" y2="14" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.533654" stop-color="var(--wa-color-neutral-fill-quiet)"/>
|
||||
<stop offset="1" stop-color="var(--wa-color-neutral-fill-quiet)" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_302_2" x1="76" y1="23" x2="96" y2="23" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.533654" stop-color="var(--wa-color-neutral-fill-quiet)"/>
|
||||
<stop offset="1" stop-color="var(--wa-color-neutral-fill-quiet)" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_302_2" x1="76" y1="32" x2="96" y2="32" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.533654" stop-color="var(--wa-color-neutral-fill-quiet)"/>
|
||||
<stop offset="1" stop-color="var(--wa-color-neutral-fill-quiet)" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -1,14 +1,14 @@
|
||||
<div class="showcase-examples-wrapper" aria-hidden="true" data-no-outline>
|
||||
<div class="showcase-examples">
|
||||
<wa-card with-header with-footer>
|
||||
<wa-card>
|
||||
<div slot="header" class="wa-split">
|
||||
<h3 class="wa-heading-m">Your Cart</h3>
|
||||
<wa-icon-button name="xmark" tabindex="-1"></wa-icon-button>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xl">
|
||||
<div class="wa-flank">
|
||||
<wa-avatar shape="rounded" style="--size: 3em; --background-color: var(--wa-color-green-60); --text-color: var(--wa-color-green-95);">
|
||||
<wa-icon slot="icon" name="sword-laser" family="duotone" style="font-size: 1.5em;"></wa-icon>
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-green-60); --text-color: var(--wa-color-green-95);">
|
||||
<wa-icon slot="icon" name="sword-laser"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-split wa-gap-2xs">
|
||||
@@ -23,8 +23,8 @@
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar shape="rounded" style="--size: 3em; --background-color: var(--wa-color-cyan-60); --text-color: var(--wa-color-cyan-95);">
|
||||
<wa-icon slot="icon" name="robot-astromech" family="duotone" style="font-size: 1.5em;"></wa-icon>
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-cyan-60); --text-color: var(--wa-color-cyan-95);">
|
||||
<wa-icon slot="icon" name="robot-astromech"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-split wa-gap-2xs">
|
||||
@@ -52,7 +52,7 @@
|
||||
</wa-card>
|
||||
<wa-card>
|
||||
<wa-avatar shape="rounded" style="--size: 1.9lh; float: left; margin-right: var(--wa-space-m);">
|
||||
<wa-icon slot="icon" name="hat-wizard" family="duotone" style="font-size: 1.75em;"></wa-icon>
|
||||
<wa-icon slot="icon" name="hat-wizard" style="font-size: 1.75em;"></wa-icon>
|
||||
</wa-avatar>
|
||||
<p class="wa-body-l" style="margin: 0;">“All we have to decide is what to do with the time that is given to us. There are other forces at work in this world, Frodo, besides the will of evil.”</p>
|
||||
</wa-card>
|
||||
@@ -69,7 +69,7 @@
|
||||
<a href="#" tabindex="-1" class="wa-body-s">I forgot my password</a>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-stack">
|
||||
<div class="wa-split">
|
||||
<h3 class="wa-heading-m">To-Do</h3>
|
||||
@@ -140,5 +140,196 @@
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card>
|
||||
<div class="wa-stack">
|
||||
<div class="wa-flank:end">
|
||||
<h3 id="odds-label" class="wa-heading-m">Tell Me the Odds</h3>
|
||||
<wa-switch size="large" aria-labelledby="odds-label"></wa-switch>
|
||||
</div>
|
||||
<p class="wa-body-s">Allow protocol droids to inform you of probabilities, such as the success rate of navigating an asteroid field. We recommend setting this to "Never."</p>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card>
|
||||
<div class="wa-stack">
|
||||
<div class="wa-split wa-align-items-start">
|
||||
<dl class="wa-stack wa-gap-2xs">
|
||||
<dt class="wa-heading-s">Amount</dt>
|
||||
<dd class="wa-heading-l">$5,610.00</dd>
|
||||
</dl>
|
||||
<wa-badge appearance="filled outlined" variant="success">Paid</wa-badge>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<dl class="wa-stack">
|
||||
<div class="wa-flank wa-align-items-center">
|
||||
<dt><wa-icon name="user" label="Name" fixed-width></wa-icon></dt>
|
||||
<dd>Tom Bombadil</dd>
|
||||
</div>
|
||||
<div class="wa-flank wa-align-items-center">
|
||||
<dt><wa-icon name="calendar-days" label="Date" fixed-width></wa-icon></dt>
|
||||
<dd><wa-format-date date="2025-03-15"></wa-format-date></dd>
|
||||
</div>
|
||||
<div class="wa-flank wa-align-items-center">
|
||||
<dt><wa-icon name="coin-vertical" fixed-width></wa-icon></dt>
|
||||
<dd>Paid with copper pennies</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<a href="" class="wa-cluster wa-gap-2xs">
|
||||
<span>Download Receipt</span>
|
||||
<wa-icon name="arrow-right"></wa-icon>
|
||||
</a>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card>
|
||||
<div class="wa-stack">
|
||||
<div class="wa-split">
|
||||
<div class="wa-cluster wa-heading-l">
|
||||
<wa-icon name="book-sparkles"></wa-icon>
|
||||
<h3>Fellowship</h3>
|
||||
</div>
|
||||
<wa-badge>Most Popular</wa-badge>
|
||||
</div>
|
||||
<span class="wa-flank wa-align-items-baseline wa-gap-2xs">
|
||||
<span class="wa-heading-2xl">$120</span>
|
||||
<span class="wa-caption-l">per year</span>
|
||||
</span>
|
||||
<p class="wa-caption-l">Carry great power (and great responsibility).</p>
|
||||
<wa-button variant="brand">Get this Plan</wa-button>
|
||||
</div>
|
||||
<div slot="footer" class="wa-stack wap-gap-s">
|
||||
<h4 class="wa-heading-s">What You Get</h4>
|
||||
<div class="wa-stack">
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="user" fixed-width></wa-icon>
|
||||
<span class="wa-caption-m">9 users</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="ring" fixed-width></wa-icon>
|
||||
<span class="wa-caption-m">1 ring</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="chess-rook" fixed-width></wa-icon>
|
||||
<span class="wa-caption-m">API access to Isengard</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="feather" fixed-width></wa-icon>
|
||||
<span class="wa-caption-m">Priority eagle support</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
<h3 class="wa-heading-s">Migs Mayfeld</h3 class="wa-heading-s">
|
||||
<wa-badge pill>Admin</wa-badge>
|
||||
</div>
|
||||
<span class="wa-caption-m">Bounty Hunter</span>
|
||||
</div>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1633268335280-a41fbde58707?q=80&w=3348&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="Avatar of a man wearing a sci-fi helmet (Photograph by Nandu Vasudevan)"></wa-avatar>
|
||||
</div>
|
||||
<div slot="footer" class="wa-grid wa-gap-xs" style="--min-column-size: 10ch;">
|
||||
<wa-button appearance="outlined">
|
||||
<wa-icon slot="prefix" name="at"></wa-icon>
|
||||
Email
|
||||
</wa-button>
|
||||
<wa-button appearance="outlined">
|
||||
<wa-icon slot="prefix" name="phone"></wa-icon>
|
||||
Phone
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<a href="" class="wa-flank wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-yellow-90); --text-color: var(--wa-color-yellow-50)">
|
||||
<wa-icon slot="icon" name="egg-fried"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-gap-2xs wa-stack">
|
||||
<span class="wa-heading-s">Second Breakfast</span>
|
||||
<span class="wa-caption-m">19 Items</span>
|
||||
</div>
|
||||
</a>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="more-actions-2" slot="trigger" name="ellipsis-vertical" label="View menu"></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
<wa-menu-item>Move to trash</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
<wa-tooltip for="more-actions-2">View menu</wa-tooltip>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-header with-footer>
|
||||
<div slot="header" class="wa-stack wa-gap-xs">
|
||||
<h2 class="wa-heading-m">Decks</h2>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xl">
|
||||
<p class="wa-caption-m">You haven’t created any decks yet. Get started by selecting an aspect that matches your play style.</p>
|
||||
<div class="wa-grid wa-gap-xl" style="--min-column-size: 30ch;">
|
||||
<a href="" class="wa-flank wa-align-items-start wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-blue-90);color: var(--wa-color-blue-50);">
|
||||
<wa-icon slot="icon" name="shield"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Vigilance <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
Protect, defend, and restore as you ready heavy-hitters.
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="" class="wa-flank wa-align-items-start wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-green-90);color: var(--wa-color-green-50);">
|
||||
<wa-icon slot="icon" name="chevrons-up"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Command <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
Build imposing armies and stockpile resources.
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href=""class="wa-flank wa-align-items-start wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-red-90);color: var(--wa-color-red-50);">
|
||||
<wa-icon slot="icon" name="explosion"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Aggression <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
Relentlessly deal damage and apply pressure to your opponent.
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="" class="wa-flank wa-align-items-start wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-yellow-90);color: var(--wa-color-yellow-50);">
|
||||
<wa-icon slot="icon" name="moon-stars"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Cunning <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
Disrupt and frustrate your opponent with dastardly tricks.
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<a href="" class="wa-cluster wa-gap-xs">
|
||||
<span>Or start a deck from scratch</span>
|
||||
<wa-icon name="arrow-right"></wa-icon>
|
||||
</a>
|
||||
</div>
|
||||
</wa-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<html lang="en" data-fa-kit-code="b10bfbde90" data-cdn-url="{% cdnUrl %}">
|
||||
<head>
|
||||
{% include 'head.njk' %}
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
<body class="layout-{{ layout | stripExtension }}">
|
||||
|
||||
|
||||
@@ -122,19 +122,8 @@
|
||||
</div>
|
||||
<div class="popup">
|
||||
{% if hue === 'gray' %}
|
||||
<wa-radio-group class="core-color" orientation="horizontal" v-model="grayColor">
|
||||
{% for h in hues -%}
|
||||
{%- if h !== 'gray' -%}
|
||||
<wa-radio-button id="gray-undertone-{{ h }}" value="{{ h }}" label="{{ h | capitalize }}" style="--color: var(--wa-color-{{ h }})"></wa-radio-button>
|
||||
<wa-tooltip for="gray-undertone-{{ h }}">
|
||||
{{ h | capitalize }}
|
||||
</wa-tooltip>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
<div slot="label">
|
||||
Gray undertone
|
||||
</div>
|
||||
</wa-radio-group>
|
||||
<swatch-select label="Gray undertone" shape="circle" :values="hues" v-model="grayColor"></swatch-select>
|
||||
|
||||
<div class="decorated-slider gray-chroma-slider" :style="{'--max': maxGrayChroma}">
|
||||
<wa-slider name="gray-chroma" v-model="grayChroma" ref="grayChromaSlider"
|
||||
value="0" min="0" :max="maxGrayChroma" step="0.01"
|
||||
|
||||
@@ -5,35 +5,22 @@
|
||||
{% extends '../_includes/base.njk' %}
|
||||
|
||||
{% block head %}
|
||||
<script>
|
||||
globalThis.wa_data ??= {};
|
||||
wa_data.baseTheme = "{{ page.fileSlug }}";
|
||||
wa_data.themes = {
|
||||
{% for theme in collections.theme -%}
|
||||
"{{ theme.fileSlug }}": {
|
||||
"title": "{{ theme.data.title }}",
|
||||
"palette": "{{ theme.data.palette }}",
|
||||
"brand": "{{ theme.data.brand }}"
|
||||
},
|
||||
{% endfor %}
|
||||
};
|
||||
wa_data.palettes = {
|
||||
{% for palette in collections.palette -%}
|
||||
"{{ palette.fileSlug }}": {
|
||||
"title": "{{ palette.data.title }}",
|
||||
},
|
||||
{% endfor %}
|
||||
};
|
||||
</script>
|
||||
<link href="/docs/themes/remix.css" rel="stylesheet">
|
||||
<script src="/docs/themes/remix.js" type="module"></script>
|
||||
<link href="{{ page.url }}../remix.css" rel="stylesheet">
|
||||
<script type="module" src="{{ page.url }}../edit/index.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
<script>
|
||||
if (location.pathname.endsWith('/custom/') && !location.search) {
|
||||
location.href = "../edit/";
|
||||
}
|
||||
</script>
|
||||
<div id="theme-app" data-theme-id="{{ page.fileSlug }}">
|
||||
|
||||
<iframe src='{{ page.url }}demo.html' id="demo"></iframe>
|
||||
<iframe ref="preview" :src="'{{ page.url }}demo.html' + urlParams" src='{{ page.url }}demo.html' id="demo"></iframe>
|
||||
|
||||
<wa-details id="mix_and_match" class="wa-gap-m" >
|
||||
{% if page.fileSlug !== 'custom' %}
|
||||
<wa-details id="mix_and_match" class="wa-gap-m" :open="saved || unsavedChanges">
|
||||
<h4 slot="summary" data-no-anchor data-no-outline id="remix">
|
||||
<wa-icon name="arrows-rotate"></wa-icon>
|
||||
Remix this theme
|
||||
@@ -41,92 +28,64 @@ wa_data.palettes = {
|
||||
<wa-tooltip for="what-is-remixing">Customize this theme by changing its colors and/or remixing it with design elements from other themes!</wa-tooltip>
|
||||
</h4>
|
||||
|
||||
<wa-select name="colors" label="Colors from…" value="" clearable>
|
||||
<wa-icon name="palette" slot="prefix" variant="regular"></wa-icon>
|
||||
{% for theme in collections.theme | sort %}
|
||||
{% set currentTheme = theme.fileSlug == page.fileSlug %}
|
||||
<wa-option label="{{ theme.data.title }}" value="{{ theme.fileSlug if not currentTheme }}" {{ (theme.fileSlug if currentTheme) | attr('data-id') }}>
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/theme-color.njk" %}
|
||||
</div>
|
||||
<span class="page-name">
|
||||
{{ theme.data.title }}
|
||||
{% if theme.data.isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
|
||||
{% if currentTheme %}<wa-badge variant="neutral" appearance="outlined">This theme</wa-badge>{% endif %}
|
||||
</span>
|
||||
</wa-card>
|
||||
</wa-option>
|
||||
{% endfor %}
|
||||
</wa-select>
|
||||
|
||||
<wa-select name="palette" label="Palette" clearable>
|
||||
<wa-select name="palette" label="Color palette" clearable v-model="theme.palette">
|
||||
<wa-icon name="swatchbook" slot="prefix" variant="regular"></wa-icon>
|
||||
{% set defaultPalette = palette %}
|
||||
{% for palette in collections.palette | sort %}
|
||||
{% set currentPalette = palette.fileSlug == defaultPalette %}
|
||||
<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" ignore missing %}
|
||||
</div>
|
||||
<span class="page-name">
|
||||
{{ palette.data.title }}
|
||||
{% if palette.data.isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
|
||||
{% if currentPalette %}<wa-badge variant="neutral" appearance="outlined">Theme default</wa-badge>{% endif %}
|
||||
</span>
|
||||
</wa-card>
|
||||
</wa-option>
|
||||
{% endfor %}
|
||||
{% set palette = defaultPalette %}
|
||||
<wa-option v-for="(palette, paletteId) in palettes" :label="palette.title" :value="paletteId === baseTheme.palette ? '' : paletteId">
|
||||
<palette-card :palette="paletteId" size="small">
|
||||
<template #extra>
|
||||
<wa-badge v-if="paletteId === baseTheme.palette" variant="neutral" appearance="outlined">Theme default</wa-badge>
|
||||
</template>
|
||||
</palette-card>
|
||||
</wa-option>
|
||||
</wa-select>
|
||||
|
||||
<wa-select name="brand" label="Brand color" value="" clearable>
|
||||
<div class="selected-swatch" slot="prefix"></div>
|
||||
{% for hue in hues %}
|
||||
{% set currentBrand = hue == brand %}
|
||||
<wa-option label="{{ hue | capitalize }}" value="{{ hue if not currentBrand }}" {{ (hue if currentBrand) | attr('data-id') }} style="--color: var(--wa-color-{{ hue }})">
|
||||
{{ hue | capitalize }}
|
||||
{% if currentBrand %}<wa-badge variant="neutral" appearance="outlined">Theme default</wa-badge>{% endif %}
|
||||
<color-select :model-value="computed.brand" @update:model-value="value => theme.brand = value" label="Brand color"
|
||||
:values="hues"></color-select>
|
||||
|
||||
<wa-select name="colors" class="theme-colors-select" label="Color contrast from…" value="" clearable v-model="theme.colors">
|
||||
<wa-icon name="palette" slot="prefix" variant="regular"></wa-icon>
|
||||
<template v-for="(themeMeta, themeId) in themes">
|
||||
<wa-option v-if="themeId !== 'custom'" :label="themeMeta.title" :value="themeId === computed.colors ? '' : themeId">
|
||||
<theme-card :theme="themeId" type="colors" :rest="{base: computed.base, palette: computed.palette, brand: computed.brand}" size="small">
|
||||
<template #extra>
|
||||
<wa-badge v-if="themeId === theme.base" variant="neutral" appearance="outlined">This theme</wa-badge>
|
||||
</template>
|
||||
</theme-card>
|
||||
</wa-option>
|
||||
{% endfor %}
|
||||
</template>
|
||||
</wa-select>
|
||||
|
||||
<wa-select name="typography" label="Typography from…" clearable>
|
||||
<wa-select name="typography" label="Typography from…" clearable v-model="theme.typography">
|
||||
<wa-icon name="font-case" slot="prefix"></wa-icon>
|
||||
{% for theme in collections.theme | sort %}
|
||||
{% set currentTheme = theme.fileSlug == page.fileSlug %}
|
||||
<wa-option label="{{ theme.data.title }}" value="{{ theme.fileSlug if not currentTheme }}" {{ (theme.fileSlug if currentTheme) | attr('data-id') }}>
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/theme-typography.njk" %}
|
||||
</div>
|
||||
<span class="page-name">
|
||||
{{ theme.data.title }}
|
||||
{% if theme.data.isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
|
||||
{% if currentTheme %}<wa-badge variant="neutral" appearance="outlined">This theme</wa-badge>{% endif %}
|
||||
</span>
|
||||
</wa-card>
|
||||
</wa-option>
|
||||
{% endfor %}
|
||||
|
||||
<wa-option v-for="(themeMeta, themeId) in themes" :label="themeMeta.title" :value="themeId === theme.base ? '' : themeId">
|
||||
<fonts-card :theme="themeId" size="small">
|
||||
<template #extra>
|
||||
<wa-badge v-if="themeId === theme.base" variant="neutral" appearance="outlined">This theme</wa-badge>
|
||||
</template>
|
||||
</fonts-card>
|
||||
</wa-option>
|
||||
</wa-select>
|
||||
</wa-details>
|
||||
|
||||
{% endif %}
|
||||
<h2>Color</h2>
|
||||
{% set paletteURL = '/docs/palettes/' + palette + '/' %}
|
||||
|
||||
|
||||
<div class="index-grid">
|
||||
{% set themePage = page %}
|
||||
{% set page = paletteURL | getCollectionItemFromUrl %}
|
||||
{% set pageSubtitle = "Default color palette" %}
|
||||
{% include 'page-card.njk' %}
|
||||
{% set page = themePage %}
|
||||
|
||||
<wa-card style="--header-background: var(--wa-color-{{ brand }})" class="wa-palette-{{ palette }}">
|
||||
{% if page.fileSlug === 'custom' %}
|
||||
<palette-card :palette="computed.palette" subtitle="Color palette"></palette-card>
|
||||
{% else %}
|
||||
{% set themePage = page %}
|
||||
{% set paletteURL = '/docs/palettes/' + palette + '/' %}
|
||||
{% set page = paletteURL | getCollectionItemFromUrl %}
|
||||
{% set pageSubtitle = "Default color palette" %}
|
||||
{% include 'page-card.njk' %}
|
||||
{% set page = themePage %}
|
||||
{% endif %}
|
||||
<wa-card class="wa-palette-{{ palette }}" style="--header-background: var(--wa-color-{{ brand }})"
|
||||
:class="`wa-palette-${computed.palette}`" :style="{'--header-background': palettes[computed.palette]?.colors[computed.brand]?.key}">
|
||||
<div slot="header"></div>
|
||||
<div class="page-name">{{ brand | capitalize }}</div>
|
||||
<div class="wa-caption-s">Default brand color</div>
|
||||
<div class="page-name" v-content="capitalize(computed.brand)">{{ brand | capitalize }}</div>
|
||||
<div class="wa-caption-s">{{ 'Brand color' if page.fileSlug === 'custom' else 'Default brand color' }}</div>
|
||||
</wa-card>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -139,7 +98,25 @@ wa_data.palettes = {
|
||||
You can import this theme from the Web Awesome CDN.
|
||||
|
||||
{% set stylesheet = 'styles/themes/' + page.fileSlug + '.css' %}
|
||||
{% include 'import-stylesheet-code.md.njk' %}
|
||||
|
||||
<wa-tab-group class="import-stylesheet-code">
|
||||
<wa-tab panel="html">In HTML</wa-tab>
|
||||
<wa-tab panel="css">In CSS</wa-tab>
|
||||
<wa-tab-panel name="html">
|
||||
|
||||
Add the following code to the `<head>` of your page:
|
||||
```html { v-content:html="code.html.highlighted" }
|
||||
<link rel="stylesheet" href="{% cdnUrl stylesheet %}" />
|
||||
```
|
||||
</wa-tab-panel>
|
||||
<wa-tab-panel name="css">
|
||||
|
||||
Add the following code at the top of your CSS file:
|
||||
```css { v-content:html="code.css.highlighted" }
|
||||
@import url('{% cdnUrl stylesheet %}');
|
||||
```
|
||||
</wa-tab-panel>
|
||||
</wa-tab-group>
|
||||
|
||||
## Dark mode
|
||||
|
||||
@@ -203,5 +180,6 @@ systemDark.addEventListener('change', applyDark);
|
||||
applyDark();
|
||||
```
|
||||
|
||||
</div> {# end theme app #}
|
||||
{% endmarkdown %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -102,12 +102,7 @@ const templates = {
|
||||
export function codeExamplesPlugin(eleventyConfig, options = {}) {
|
||||
const defaultOptions = {
|
||||
container: 'body',
|
||||
defaultOpen: (code, { outputPathIndex }) => {
|
||||
return (
|
||||
outputPathIndex === 1 && // is first
|
||||
code.textContent.length < 500
|
||||
); // is short
|
||||
},
|
||||
defaultOpen: () => false,
|
||||
};
|
||||
options = { ...defaultOptions, ...options };
|
||||
|
||||
|
||||
@@ -178,10 +178,6 @@ 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
|
||||
@@ -202,7 +198,7 @@ export function groupPages(collection, options = {}, page) {
|
||||
options = { tags: options };
|
||||
}
|
||||
|
||||
let { tags, groups, titles = {}, other = 'Other', filter = show } = options;
|
||||
let { tags, groups, titles = {}, other = 'Other' } = options;
|
||||
|
||||
if (groups === undefined && Array.isArray(tags)) {
|
||||
groups = tags;
|
||||
@@ -241,10 +237,6 @@ export function groupPages(collection, options = {}, page) {
|
||||
let byUrl = {};
|
||||
let byParentUrl = {};
|
||||
|
||||
if (filter) {
|
||||
collection = collection.filter(filter);
|
||||
}
|
||||
|
||||
for (let item of collection) {
|
||||
let url = item.page.url;
|
||||
let parentUrl = item.data.parentUrl;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { parse } from 'node-html-parser';
|
||||
|
||||
/**
|
||||
* Eleventy plugin to add remove elements with <div data-alpha="remove"> from the alpha build.
|
||||
*/
|
||||
export function removeDataAlphaElements(options = {}) {
|
||||
options = {
|
||||
isAlpha: false,
|
||||
...options,
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
eleventyConfig.addTransform('remove-data-alpha-elements', content => {
|
||||
const doc = parse(content, { blockTextElements: { code: true } });
|
||||
|
||||
if (options.isAlpha) {
|
||||
doc.querySelectorAll('[data-alpha="remove"]').forEach(el => el.remove());
|
||||
}
|
||||
|
||||
return doc.toString();
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -24,9 +24,23 @@ export function searchPlugin(options = {}) {
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
const pagesToIndex = [];
|
||||
const pagesToIndex = new Map();
|
||||
|
||||
eleventyConfig.addPreprocessor('exclude-unlisted-from-search', '*', function (data, content) {
|
||||
if (data.unlisted) {
|
||||
// no-op
|
||||
} else {
|
||||
pagesToIndex.set(data.page.inputPath, {});
|
||||
}
|
||||
|
||||
return content;
|
||||
});
|
||||
|
||||
eleventyConfig.addTransform('search', function (content) {
|
||||
if (!pagesToIndex.has(this.page.inputPath)) {
|
||||
return content;
|
||||
}
|
||||
|
||||
const doc = parse(content, {
|
||||
blockTextElements: {
|
||||
script: false,
|
||||
@@ -42,7 +56,7 @@ export function searchPlugin(options = {}) {
|
||||
doc.querySelectorAll(selector).forEach(el => el.remove());
|
||||
});
|
||||
|
||||
pagesToIndex.push({
|
||||
pagesToIndex.set(this.page.inputPath, {
|
||||
title: collapseWhitespace(options.getTitle(doc)),
|
||||
description: collapseWhitespace(options.getDescription(doc)),
|
||||
headings: options.getHeadings(doc).map(collapseWhitespace),
|
||||
@@ -65,7 +79,7 @@ export function searchPlugin(options = {}) {
|
||||
this.field('h', { boost: 10 });
|
||||
this.field('c');
|
||||
|
||||
for (const page of pagesToIndex) {
|
||||
for (const [_inputPath, page] of pagesToIndex) {
|
||||
this.add({ id: index, t: page.title, h: page.headings, c: page.content });
|
||||
map[index] = { title: page.title, description: page.description, url: page.url };
|
||||
index++;
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
/**
|
||||
* Data related to theme remixing and palette tweaking
|
||||
* Data related to palettes and colors.
|
||||
* Must work in both browser and Node.js
|
||||
*/
|
||||
export const cdnUrl = globalThis.document ? document.documentElement.dataset.cdnUrl : '/dist/';
|
||||
|
||||
export const urls = {
|
||||
theme: id => `styles/themes/${id}.css`,
|
||||
colors: id => `styles/themes/${id}/color.css`,
|
||||
palette: id => `styles/color/${id}.css`,
|
||||
brand: id => `styles/brand/${id}.css`,
|
||||
typography: id => `styles/themes/${id}/typography.css`,
|
||||
};
|
||||
|
||||
export const selectors = {
|
||||
palette: id =>
|
||||
[':where(:root)', ':host', ":where([class^='wa-theme-'], [class*=' wa-theme-'])", `.wa-palette-${id}`].join(',\n'),
|
||||
};
|
||||
export const tints = ['05', '10', '20', '30', '40', '50', '60', '70', '80', '90', '95'];
|
||||
|
||||
export const hueRanges = {
|
||||
red: { min: 5, max: 35 }, // 30
|
||||
@@ -29,6 +17,9 @@ export const hueRanges = {
|
||||
pink: { min: 320, max: 365 }, // 45
|
||||
};
|
||||
|
||||
export const hues = Object.keys(hueRanges);
|
||||
export const allHues = [...hues, 'gray'];
|
||||
|
||||
export const moreHue = {
|
||||
red: 'Redder',
|
||||
orange: 'More orange', // https://www.reddit.com/r/grammar/comments/u9n0uo/is_it_oranger_or_more_orange/
|
||||
@@ -54,20 +45,3 @@ export const maxGrayChroma = {
|
||||
purple: 0.3,
|
||||
pink: 0.25,
|
||||
};
|
||||
|
||||
export const docsURLs = {
|
||||
colors: '/docs/themes/',
|
||||
palette: '/docs/palettes/',
|
||||
typography: '/docs/themes/',
|
||||
};
|
||||
|
||||
export const icons = {
|
||||
colors: 'palette',
|
||||
palette: 'swatchbook',
|
||||
brand: 'droplet',
|
||||
typography: 'font-case',
|
||||
};
|
||||
|
||||
export const hues = Object.keys(hueRanges);
|
||||
|
||||
export const tints = ['05', '10', '20', '30', '40', '50', '60', '70', '80', '90', '95'];
|
||||
65
docs/assets/data/fonts.js
Normal file
65
docs/assets/data/fonts.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import { deepEntries } from '../scripts/util/deep.js';
|
||||
import { themeConfig } from './theming.js';
|
||||
import themes from '/assets/data/themes.js';
|
||||
|
||||
/**
|
||||
* Map of font pairings (body + heading) to the first theme that uses them.
|
||||
*/
|
||||
export const pairings = {};
|
||||
|
||||
// NOTE Do not use Symbols, we want these to be enumerable when used as keys
|
||||
export const sameAs = { body: '$body' };
|
||||
|
||||
export const fontNames = {
|
||||
'system-ui': 'OS Default',
|
||||
'ui-serif': 'OS Default Serif',
|
||||
'ui-sans-serif': 'OS Default Sans Serif',
|
||||
'ui-monospace': 'OS Default Code Font',
|
||||
'ui-monospace': 'OS Default Code Font',
|
||||
};
|
||||
|
||||
export function defaultTitle(fonts) {
|
||||
let { body, heading = sameAs.body } = fonts;
|
||||
let names = [body];
|
||||
|
||||
if (heading !== sameAs.body) {
|
||||
names.unshift(heading);
|
||||
}
|
||||
|
||||
return names.map(name => fontNames[name] ?? name).join(' • ');
|
||||
}
|
||||
|
||||
for (let id in themes) {
|
||||
let theme = themes[id];
|
||||
let { fonts } = theme;
|
||||
|
||||
if (fonts) {
|
||||
let { body, heading = sameAs.body } = fonts;
|
||||
|
||||
pairings[body] ??= {};
|
||||
pairings[body][heading] ??= {
|
||||
id, // First theme that uses this pairing
|
||||
ids: new Set([id]), // All themes that use this pairing
|
||||
url: themeConfig.typography.url(id), // Stylesheet URL
|
||||
fonts,
|
||||
get title() {
|
||||
return defaultTitle(this.fonts);
|
||||
},
|
||||
};
|
||||
pairings[body][heading].ids.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
export const pairingsEntries = deepEntries(pairings, {
|
||||
descend(value, key, parent, path) {
|
||||
if (value?.fonts) {
|
||||
return false; // Don't recurse into pairing objects
|
||||
}
|
||||
},
|
||||
filter(value, key, parent, path) {
|
||||
// Only keep 2 levels (body → heading → pairing)
|
||||
return path.length === 1;
|
||||
},
|
||||
});
|
||||
|
||||
export const pairingsList = pairingsEntries.map(arg => arg.at(-1));
|
||||
7
docs/assets/data/icons.js
Normal file
7
docs/assets/data/icons.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export const iconLibraries = {
|
||||
default: {
|
||||
title: 'Font Awesome',
|
||||
family: ['classic', 'sharp', 'duotone', 'sharp-duotone'],
|
||||
style: ['solid', 'regular', 'light', 'thin'],
|
||||
},
|
||||
};
|
||||
6
docs/assets/data/index.js
Normal file
6
docs/assets/data/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './colors.js';
|
||||
// export * from './fonts.js';
|
||||
export * from './icons.js';
|
||||
export * from './theming.js';
|
||||
|
||||
export const cdnUrl = globalThis.document ? document.documentElement.dataset.cdnUrl : '/dist/';
|
||||
32
docs/assets/data/palettes.js.njk
Normal file
32
docs/assets/data/palettes.js.njk
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
layout: null
|
||||
permalink: '/assets/data/palettes.js'
|
||||
eleventyExcludeFromCollections: true
|
||||
---
|
||||
export default {
|
||||
{%- for palette in collections.palette | sort %}
|
||||
{%- if not palette.data.unlisted %}
|
||||
{% set paletteId = palette.fileSlug -%}
|
||||
{%- set colors = palettes[paletteId] -%}
|
||||
'{{ paletteId }}': {
|
||||
id: '{{ paletteId }}',
|
||||
title: '{{ palette.data.title }}',
|
||||
colors: {
|
||||
{% for hue, tints in colors -%}
|
||||
'{{ hue }}': {
|
||||
{% for tint, value in tints -%}
|
||||
{%- if tint != '05' -%}
|
||||
'{{ '05' if tint == '5' else tint }}': '{{ value | safe }}',
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
|
||||
get key() {
|
||||
return this[this.maxChromaTint];
|
||||
}
|
||||
},
|
||||
{% endfor -%} // end colors
|
||||
}
|
||||
}, // end palette
|
||||
{%- endif -%}
|
||||
{% endfor %}
|
||||
};
|
||||
22
docs/assets/data/themes.js.njk
Normal file
22
docs/assets/data/themes.js.njk
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
layout: null
|
||||
permalink: '/assets/data/themes.js'
|
||||
eleventyExcludeFromCollections: true
|
||||
---
|
||||
export default {
|
||||
{%- for theme in collections.theme | sort %}
|
||||
{%- if not theme.data.unlisted %}
|
||||
{% set themeId = theme.fileSlug -%}
|
||||
{%- set colors = themes[themeId] -%}
|
||||
'{{ themeId }}': {
|
||||
id: '{{ themeId }}',
|
||||
title: '{{ theme.data.title }}',
|
||||
palette: '{{ theme.data.palette }}',
|
||||
brand: '{{ theme.data.brand }}',
|
||||
isPro: {{ theme.data.isPro or 'pro' in theme.data.tags }},
|
||||
fonts: {{ (theme.data.fonts | dump or 'null') | safe }},
|
||||
icons: {{ (theme.data.icons | dump or 'null') | safe }},
|
||||
},
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
};
|
||||
82
docs/assets/data/theming.js
Normal file
82
docs/assets/data/theming.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import { deepEach, isPlainObject } from '../scripts/util/deep.js';
|
||||
|
||||
/**
|
||||
* Data related to themes, theme remixing
|
||||
* Must work in both browser and Node.js
|
||||
*/
|
||||
export const cdnUrl = globalThis.document ? document.documentElement.dataset.cdnUrl : '/dist/';
|
||||
|
||||
// This should eventually replace all uses of `urls` and `themeParams`
|
||||
export const themeConfig = {
|
||||
base: { url: id => `styles/themes/${id}.css`, default: 'default' },
|
||||
colors: {
|
||||
url: id => `styles/themes/${id}/color.css`,
|
||||
docs: '/docs/themes/',
|
||||
icon: 'palette',
|
||||
default() {
|
||||
return this.base;
|
||||
},
|
||||
},
|
||||
palette: {
|
||||
url: id => `styles/color/${id}.css`,
|
||||
docs: '/docs/palette/',
|
||||
icon: 'swatchbook',
|
||||
default(baseTheme) {
|
||||
return baseTheme?.palette;
|
||||
},
|
||||
},
|
||||
brand: {
|
||||
url: id => `styles/brand/${id}.css`,
|
||||
icon: 'droplet',
|
||||
default(baseTheme) {
|
||||
return baseTheme?.brand;
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
url: id => `styles/themes/${id}/typography.css`,
|
||||
docs: '/docs/themes/',
|
||||
icon: 'font-case',
|
||||
default() {
|
||||
return this.base;
|
||||
},
|
||||
},
|
||||
icon: {
|
||||
library: { cssProperty: '--wa-icon-library', default: 'default' },
|
||||
family: {
|
||||
cssProperty: '--wa-icon-family',
|
||||
default(baseTheme) {
|
||||
return baseTheme?.icon?.family ?? 'classic';
|
||||
},
|
||||
},
|
||||
style: {
|
||||
cssProperty: '--wa-icon-variant',
|
||||
default(baseTheme) {
|
||||
return baseTheme?.icon?.style ?? 'solid';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Shallow remixing params in correct order
|
||||
// base must be first. brand needs to come after palette, which needs to come after colors.
|
||||
export const themeParams = Object.keys(themeConfig).filter(aspect => themeConfig[aspect].url);
|
||||
|
||||
export const urls = themeParams.reduce((acc, aspect) => {
|
||||
acc[aspect] = themeConfig[aspect].url;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
export const themeDefaults = { ...themeConfig };
|
||||
|
||||
deepEach(themeDefaults, (value, key, parent, path) => {
|
||||
if (isPlainObject(value)) {
|
||||
// Replace w/ default value or shallow clone
|
||||
return value.default ?? { ...value };
|
||||
}
|
||||
});
|
||||
|
||||
export const selectors = {
|
||||
palette: id =>
|
||||
[':where(:root)', ':host', ":where([class^='wa-theme-'], [class*=' wa-theme-'])", `.wa-palette-${id}`].join(',\n'),
|
||||
theme: id => [':where(:root)', ':host', `.wa-theme-${id}`].join(',\n'),
|
||||
};
|
||||
@@ -1,59 +0,0 @@
|
||||
document.addEventListener('click', event => {
|
||||
const toggle = event.target?.closest('.code-example-toggle');
|
||||
const pen = event.target?.closest('.code-example-pen');
|
||||
|
||||
// Toggle source
|
||||
if (toggle) {
|
||||
const codeExample = toggle.closest('.code-example');
|
||||
const isOpen = !codeExample.classList.contains('open');
|
||||
|
||||
toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
|
||||
codeExample.classList.toggle('open', isOpen);
|
||||
}
|
||||
|
||||
// Edit in CodePen
|
||||
if (pen) {
|
||||
const codeExample = pen.closest('.code-example');
|
||||
const code = codeExample.querySelector('code');
|
||||
const cdnUrl = document.documentElement.dataset.cdnUrl;
|
||||
const html =
|
||||
`<script data-fa-kit-code="b10bfbde90" type="module" src="${cdnUrl}webawesome.loader.js"></script>\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}styles/themes/default.css">\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}styles/webawesome.css">\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}styles/utilities.css">\n\n` +
|
||||
`${code.textContent}`;
|
||||
const css = 'html > body {\n padding: 2rem !important;\n}';
|
||||
const js = '';
|
||||
|
||||
const form = document.createElement('form');
|
||||
form.action = 'https://codepen.io/pen/define';
|
||||
form.method = 'POST';
|
||||
form.target = '_blank';
|
||||
|
||||
const data = {
|
||||
title: '',
|
||||
description: '',
|
||||
tags: ['webawesome'],
|
||||
editors: '1000',
|
||||
head: '<meta name="viewport" content="width=device-width">',
|
||||
html_classes: '',
|
||||
css_external: '',
|
||||
js_external: '',
|
||||
js_module: true,
|
||||
js_pre_processor: 'none',
|
||||
html,
|
||||
css,
|
||||
js,
|
||||
};
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'data';
|
||||
input.value = JSON.stringify(data);
|
||||
form.append(input);
|
||||
|
||||
document.documentElement.append(form);
|
||||
form.submit();
|
||||
form.remove();
|
||||
}
|
||||
});
|
||||
@@ -51,7 +51,7 @@
|
||||
<button class="diff-dialog-toggle">
|
||||
Show Hydration Mismatch
|
||||
</button>
|
||||
<wa-dialog class="diff-dialog" with-header light-dismiss>
|
||||
<wa-dialog class="diff-dialog" light-dismiss>
|
||||
<div class="diff-grid">
|
||||
<div>
|
||||
<div>Server</div>
|
||||
|
||||
@@ -165,3 +165,8 @@ my.palettes = new SavedEntities({
|
||||
key: 'savedPalettes',
|
||||
type: 'palette',
|
||||
});
|
||||
|
||||
my.themes = new SavedEntities({
|
||||
key: 'savedThemes',
|
||||
type: 'theme',
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const IDENTITY = x => x;
|
||||
import { deepEach, deepGet, deepSet } from './util/deep.js';
|
||||
|
||||
export default class Permalink extends URLSearchParams {
|
||||
/** Params changed since last URL I/O */
|
||||
@@ -13,6 +13,59 @@ export default class Permalink extends URLSearchParams {
|
||||
return Object.fromEntries(this.entries());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set multiple values from an object. Nested values will be joined with a hyphen.
|
||||
* @param {object} values - The object containing the values to set.
|
||||
* @param {object} defaults - The object containing the default values.
|
||||
*
|
||||
*/
|
||||
setAll(values, defaults) {
|
||||
deepEach(values, (value, key, parent, path) => {
|
||||
let fullPath = [...path, key];
|
||||
let param = fullPath.join('-');
|
||||
let defaultValue = deepGet(defaults, fullPath);
|
||||
|
||||
if (typeof value === 'object') {
|
||||
// We'll handle this when we descend into it
|
||||
return;
|
||||
}
|
||||
|
||||
if (!value || value === defaultValue) {
|
||||
// Remove the param from the URL
|
||||
this.delete(param);
|
||||
return;
|
||||
}
|
||||
|
||||
this.set(param, value);
|
||||
});
|
||||
}
|
||||
|
||||
getAll(...args) {
|
||||
if (args.length > 0) {
|
||||
return super.getAll(...args);
|
||||
}
|
||||
|
||||
// Get all values as a nested object
|
||||
// Assumes that hyphens always mean nesting
|
||||
let obj = {};
|
||||
|
||||
for (let [key, value] of this.entries()) {
|
||||
let path = key.split('-');
|
||||
deepSet(obj, path, value);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
delete(key, value) {
|
||||
let hadValue = this.has(key);
|
||||
super.delete(key, value);
|
||||
|
||||
if (hadValue) {
|
||||
this.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
set(key, value, defaultValue) {
|
||||
if (equals(value, defaultValue) || equals(value, '')) {
|
||||
value = null;
|
||||
@@ -74,7 +74,8 @@ const sidebar = {
|
||||
a = sidebar.addChild(a, parentA);
|
||||
|
||||
// This is mainly to port Pro badges
|
||||
let badges = Array.from(parentLi.querySelectorAll('wa-badge'), badge => badge.cloneNode(true));
|
||||
let badges = Array.from(parentLi.querySelectorAll(':scope > wa-badge'), badge => badge.cloneNode(true));
|
||||
|
||||
let append = [...badges];
|
||||
|
||||
if (entity.delete) {
|
||||
|
||||
@@ -106,6 +106,6 @@ document.addEventListener('keydown', event => {
|
||||
!event.composedPath().some(el => ['input', 'textarea'].includes(el?.tagName?.toLowerCase()))
|
||||
) {
|
||||
event.preventDefault();
|
||||
colorScheme.set(theming.colorScheme.resolvedValue === 'dark' ? 'light' : 'dark');
|
||||
colorScheme.set(colorScheme.get() === 'dark' ? 'light' : 'dark');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Get import code for remixed themes and tweaked palettes.
|
||||
*/
|
||||
export { cdnUrl, hueRanges, hues, selectors, tints, urls } from '../data/index.js';
|
||||
export { default as Permalink } from './permalink.js';
|
||||
export { getThemeCode } from './tweak/code.js';
|
||||
export { cdnUrl, hueRanges, hues, selectors, tints, urls } from './tweak/data.js';
|
||||
export { default as Permalink } from './tweak/permalink.js';
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Get import code for remixed themes and tweaked palettes.
|
||||
*/
|
||||
import { urls } from './data.js';
|
||||
import { selectors, themeConfig } from '../../data/theming.js';
|
||||
import { deepEach, deepGet } from '/assets/scripts/util/deep.js';
|
||||
|
||||
export function cssImport(url, options = {}) {
|
||||
let { language = 'html', cdnUrl = '/dist/', attributes } = options;
|
||||
@@ -21,29 +22,65 @@ export function cssLiteral(value, options = {}) {
|
||||
if (language === 'css') {
|
||||
return value;
|
||||
} else {
|
||||
return `<style>\n${value}\n</style>`;
|
||||
return `<style${options.attributes ?? ''}>\n${value}\n</style>`;
|
||||
}
|
||||
}
|
||||
|
||||
// Params in correct order
|
||||
export const themeParams = ['colors', 'palette', 'brand', 'typography'];
|
||||
/**
|
||||
* Get code for a theme, including tweaks
|
||||
* @param {*} theme
|
||||
* @param {*} options
|
||||
* @returns
|
||||
*/
|
||||
export function getThemeCode(theme, options = {}) {
|
||||
let urls = [];
|
||||
let declarations = [];
|
||||
let id = options.id ?? theme.base ?? 'default';
|
||||
|
||||
export function getThemeCode(base, params, options) {
|
||||
let ret = [];
|
||||
deepEach(themeConfig, (config, aspect, obj, path) => {
|
||||
if (!config?.default) {
|
||||
// We're not in a config object
|
||||
return;
|
||||
}
|
||||
|
||||
if (base) {
|
||||
ret.push(urls.theme(base));
|
||||
}
|
||||
let value = deepGet(theme, [...path, aspect]);
|
||||
|
||||
for (let aspect of themeParams) {
|
||||
let value = params[aspect];
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
ret.push(urls[aspect](value));
|
||||
if (config.url) {
|
||||
// This is implemented by pulling in different CSS files
|
||||
urls.push(config.url(value));
|
||||
} else {
|
||||
if (config.cssProperty) {
|
||||
declarations.push(`${config.cssProperty}: ${value};`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let ret = urls.map(url => cssImport(url, options)).join('\n');
|
||||
|
||||
if (declarations.length > 0) {
|
||||
let cssCode = cssRule(selectors.theme(id), declarations, options);
|
||||
|
||||
let faKitAttribute = ` data-fa-kit-code="${theme.icon.kit}"`;
|
||||
if (theme.icon.kit) {
|
||||
options.attributes ??= '';
|
||||
options.attributes += faKitAttribute;
|
||||
cssCode =
|
||||
`/* Note: To use Font Awesome Pro icons,\n set ${faKitAttribute} on the <link> (or any other) element */\n\n` +
|
||||
cssCode;
|
||||
}
|
||||
|
||||
cssCode = cssLiteral(cssCode, options);
|
||||
|
||||
if (ret) {
|
||||
ret += '\n\n' + cssCode;
|
||||
}
|
||||
}
|
||||
|
||||
return ret.map(url => cssImport(url, options)).join('\n');
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function cssRule(selector, declarations, { indent = ' ' } = {}) {
|
||||
|
||||
17
docs/assets/scripts/util/array.js
Normal file
17
docs/assets/scripts/util/array.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Picks a random element from an array.
|
||||
* @param {any[]} arr
|
||||
*/
|
||||
export function sample(arr) {
|
||||
if (!Array.isArray(arr)) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
if (arr.length < 2) {
|
||||
return arr[0];
|
||||
}
|
||||
|
||||
let index = Math.floor(Math.random() * arr.length);
|
||||
|
||||
return arr[index];
|
||||
}
|
||||
180
docs/assets/scripts/util/deep.js
Normal file
180
docs/assets/scripts/util/deep.js
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* @typedef { string | number | Symbol } Property
|
||||
* @typedef { (value: any, key: Property, parent: object, path: Property[]) => any } EachCallback
|
||||
*/
|
||||
|
||||
export function isPlainObject(obj) {
|
||||
return isObject(obj, 'Object');
|
||||
}
|
||||
|
||||
export function isObject(obj, type) {
|
||||
if (!obj || typeof obj !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
let proto = Object.getPrototypeOf(obj);
|
||||
return proto.constructor?.name === type;
|
||||
}
|
||||
|
||||
export function deepMerge(target, source, options = {}) {
|
||||
let {
|
||||
emptyValues = [undefined],
|
||||
containers = ['Object', 'EventTarget'],
|
||||
isContainer = value => containers.some(type => isObject(value, type)),
|
||||
} = options;
|
||||
|
||||
if (isContainer(target) && isContainer(source)) {
|
||||
for (let key in source) {
|
||||
if (key in target && isContainer(target[key]) && isContainer(source[key])) {
|
||||
target[key] = deepMerge(target[key], source[key], options);
|
||||
} else if (!emptyValues.includes(source[key])) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
return target ?? source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over a deep array, recursively for plain objects
|
||||
* @param { any } obj The object to iterate over. Can be an array or a plain object, or even a primitive value.
|
||||
* @param { EachCallback } callback. value is === parent[key]
|
||||
* @param { object } [parentObj] The parent object of the current value Mainly used internally to facilitate recursion.
|
||||
* @param { Property } [key] The key of the current value. Mainly used internally to facilitate recursion.
|
||||
* @param { Property[] } [path] Any existing path (not including the key). Mainly used internally to facilitate recursion.
|
||||
*/
|
||||
export function deepEach(obj, callback, parentObj, key, path = []) {
|
||||
if (key !== undefined) {
|
||||
let ret = callback(obj, key, parentObj, path);
|
||||
|
||||
if (ret !== undefined) {
|
||||
if (ret === false) {
|
||||
// Do not descend further
|
||||
return;
|
||||
}
|
||||
|
||||
// Overwrite value
|
||||
parentObj[key] = ret;
|
||||
obj = ret;
|
||||
}
|
||||
}
|
||||
|
||||
let newPath = key !== undefined ? [...path, key] : path;
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
deepEach(obj[i], callback, obj, i, newPath);
|
||||
}
|
||||
} else if (isPlainObject(obj)) {
|
||||
for (let key in obj) {
|
||||
deepEach(obj[key], callback, obj, key, newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from a deeply nested object
|
||||
* @param {*} obj
|
||||
* @param {PropertyPath} path
|
||||
* @returns
|
||||
*/
|
||||
export function deepGet(obj, path) {
|
||||
if (path.length === 0) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
let ret = obj;
|
||||
|
||||
for (let key of path) {
|
||||
if (ret === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
ret = ret[key];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in a deep object, creating object literals as needed
|
||||
* @param { * } obj
|
||||
* @param { Property[] } path
|
||||
* @param { any } value
|
||||
*/
|
||||
export function deepSet(obj, path, value) {
|
||||
if (path.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let key = path.pop();
|
||||
|
||||
let ret = path.reduce((acc, property) => {
|
||||
if (acc[property] === undefined) {
|
||||
acc[property] = {};
|
||||
}
|
||||
|
||||
return acc[property];
|
||||
}, obj);
|
||||
|
||||
ret[key] = value;
|
||||
}
|
||||
|
||||
export function deepClone(obj) {
|
||||
if (!obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
let ret = obj;
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
ret = obj.map(item => deepClone(item));
|
||||
} else if (isPlainObject(obj)) {
|
||||
ret = { ...obj };
|
||||
|
||||
for (let key in obj) {
|
||||
ret[key] = deepClone(obj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like Object.entries, but for deeply nested objects.
|
||||
* For shallow objects the output is the same as Object.entries.
|
||||
* @param {*} obj
|
||||
* @param { object } options
|
||||
* @param { EachCallback } each - If this returns false, the entry is not added to the result and the recursion is stopped.
|
||||
* @param { EachCallback } filter - If this returns false, the entry is not added to the result.
|
||||
* @param { EachCallback } descend - If this returns false, recursion is stopped.
|
||||
* @returns {any[][]}
|
||||
*/
|
||||
export function deepEntries(obj, options = {}) {
|
||||
let { each, filter, descend } = options;
|
||||
let entries = [];
|
||||
|
||||
deepEach(obj, (value, key, parent, path) => {
|
||||
let ret = each?.(value, key, parent, path);
|
||||
|
||||
if (ret !== false) {
|
||||
let included = filter?.(value, key, parent, path) ?? true;
|
||||
|
||||
if (included) {
|
||||
entries.push([...path, key, value]);
|
||||
}
|
||||
|
||||
let descendRet = descend?.(value, key, parent, path);
|
||||
if (descendRet === false) {
|
||||
return false; // Stop recursion
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
return entries;
|
||||
}
|
||||
@@ -35,3 +35,5 @@ export function domChange(fn, { behavior = 'smooth', ignoreInitialLoad = true }
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default domChange;
|
||||
|
||||
24
docs/assets/scripts/util/string.js
Normal file
24
docs/assets/scripts/util/string.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Make the first letter of a string uppercase
|
||||
* @param {*} str
|
||||
* @returns
|
||||
*/
|
||||
export function capitalize(str) {
|
||||
str += '';
|
||||
return str[0].toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a readable string to a slug.
|
||||
* @param {*} str - Input string. If argument is not a string, it will be stringified.
|
||||
* @returns {string} - The slugified string
|
||||
*/
|
||||
export function slugify(str) {
|
||||
return (str + '')
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '') // Convert accented letters to ASCII
|
||||
.replace(/[^\w\s-]/g, '') // Remove remaining non-ASCII characters
|
||||
.trim()
|
||||
.replace(/\s+/g, '-') // Convert whitespace to hyphens
|
||||
.toLowerCase();
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
.code-example {
|
||||
border: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
color: var(--wa-color-text-normal);
|
||||
margin-block-end: var(--wa-flow-spacing);
|
||||
}
|
||||
|
||||
.code-example-preview {
|
||||
padding: 2rem;
|
||||
border-bottom: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
|
||||
|
||||
> :first-child {
|
||||
margin-block-start: 0;
|
||||
}
|
||||
|
||||
> :last-child {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.code-example-source {
|
||||
border-bottom: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
|
||||
}
|
||||
|
||||
.code-example:not(.open) .code-example-source {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.code-example.open .code-example-toggle wa-icon {
|
||||
rotate: 180deg;
|
||||
}
|
||||
|
||||
.code-example-source pre {
|
||||
position: relative;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.code-example-source:not(:has(+ .code-example-buttons)) {
|
||||
border-bottom: none;
|
||||
|
||||
pre {
|
||||
border-bottom-right-radius: var(--wa-border-radius-l);
|
||||
border-bottom-left-radius: var(--wa-border-radius-l);
|
||||
}
|
||||
}
|
||||
|
||||
.code-example-buttons {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
|
||||
button {
|
||||
all: unset;
|
||||
flex: 1 0 auto;
|
||||
font-size: 0.875rem;
|
||||
color: var(--wa-color-text-quiet);
|
||||
border-left: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
|
||||
text-align: center;
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
|
||||
&:first-of-type {
|
||||
border-left: none;
|
||||
border-bottom-left-radius: var(--wa-border-radius-l);
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom-right-radius: var(--wa-border-radius-l);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: var(--wa-focus-ring);
|
||||
}
|
||||
}
|
||||
|
||||
.code-example-pen {
|
||||
flex: 0 0 100px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
wa-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -2px;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
@import 'code-examples.css';
|
||||
@import 'code-highlighter.css';
|
||||
@import 'copy-code.css';
|
||||
@import 'outline.css';
|
||||
@@ -257,15 +256,6 @@ wa-page > main {
|
||||
}
|
||||
|
||||
h1.title {
|
||||
wa-icon-button {
|
||||
font-size: var(--wa-font-size-l);
|
||||
color: var(--wa-color-text-quiet);
|
||||
|
||||
&:not(:hover, :focus) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
wa-badge {
|
||||
vertical-align: middle;
|
||||
font-size: 1.5rem;
|
||||
@@ -393,19 +383,7 @@ wa-page > main:has(> .index-grid) {
|
||||
}
|
||||
|
||||
wa-card {
|
||||
box-shadow: none;
|
||||
--spacing: var(--wa-space-m);
|
||||
inline-size: 100%;
|
||||
|
||||
&:hover {
|
||||
--border-color: var(--wa-color-brand-border-loud);
|
||||
border-color: var(--border-color);
|
||||
box-shadow: 0 0 0 var(--wa-border-width-s) var(--border-color);
|
||||
|
||||
.page-name {
|
||||
color: var(--wa-color-brand-on-quiet);
|
||||
}
|
||||
}
|
||||
|
||||
[slot='header'] {
|
||||
display: flex;
|
||||
@@ -419,11 +397,11 @@ wa-page > main:has(> .index-grid) {
|
||||
min-block-size: calc(6rem + var(--spacing));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-name {
|
||||
font-size: var(--wa-font-size-s);
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
}
|
||||
wa-card .page-name {
|
||||
font-size: var(--wa-font-size-s);
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
}
|
||||
|
||||
.index-category {
|
||||
@@ -432,6 +410,146 @@ wa-page > main:has(> .index-grid) {
|
||||
margin-block-start: var(--wa-space-2xl);
|
||||
}
|
||||
|
||||
/* Interactive cards */
|
||||
wa-card[role='button'][tabindex='0'],
|
||||
button,
|
||||
a[href],
|
||||
wa-option,
|
||||
wa-radio,
|
||||
wa-checkbox {
|
||||
/* Disabled state */
|
||||
&:is(:disabled, [disabled], [aria-disabled='true']) {
|
||||
&:is(wa-card, :has(> wa-card)) {
|
||||
opacity: 60%;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
&:where(:not(:disabled, [disabled], [aria-disabled='true'])) {
|
||||
&:has(> wa-card) {
|
||||
/* Parents only (not interactive <wa-card>) */
|
||||
margin: calc(var(--wa-border-width-m) + 1px);
|
||||
padding: 0;
|
||||
|
||||
/* Hover state */
|
||||
&:hover,
|
||||
&:state(hover),
|
||||
&:state(current) {
|
||||
/* Do not change the parent background as a hover effect (we style the card instead) */
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
&::part(control),
|
||||
&:is(wa-option)::part(checked-icon) {
|
||||
--background-color-checked: var(--wa-color-brand-fill-loud);
|
||||
--checked-icon-scale: 0.5;
|
||||
--offset: var(--wa-space-2xs);
|
||||
|
||||
position: absolute;
|
||||
inset: calc(var(--offset) + var(--wa-border-width-m));
|
||||
inset-block-end: auto;
|
||||
inset-inline-start: auto;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
background: var(--wa-color-brand-fill-loud);
|
||||
color: var(--wa-color-brand-on-loud);
|
||||
}
|
||||
|
||||
&::part(checked-icon) {
|
||||
color: var(--wa-color-brand-on-loud);
|
||||
}
|
||||
|
||||
&:is(wa-option)::part(checked-icon) {
|
||||
inset-block-start: calc(var(--wa-space-smaller) - 0.5em);
|
||||
inset-inline-end: calc(var(--wa-space-smaller) - 0.5em);
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
line-height: 1em;
|
||||
padding: 0.4em;
|
||||
border-radius: var(--wa-border-radius-circle);
|
||||
text-align: center;
|
||||
font-size: var(--wa-font-size-xs);
|
||||
}
|
||||
}
|
||||
|
||||
/* Hover state */
|
||||
&:hover,
|
||||
&:state(hover),
|
||||
&:state(current) {
|
||||
&:is(wa-card),
|
||||
> wa-card {
|
||||
--border-color: var(--wa-color-brand-border-loud);
|
||||
border-color: var(--border-color);
|
||||
box-shadow: 0 0 0 var(--wa-border-width-s) var(--border-color);
|
||||
}
|
||||
}
|
||||
|
||||
&:is(wa-card, :has(> wa-card)) {
|
||||
/* Interactive card parent */
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
/* Unselected state */
|
||||
&:where(:not(:state(checked), :state(selected), [aria-checked='true'], [aria-selected='true'])) {
|
||||
&::part(checked-icon),
|
||||
&::part(control) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:is(wa-card),
|
||||
> wa-card {
|
||||
/* The card itself */
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Selected cards */
|
||||
:state(selected),
|
||||
:state(checked),
|
||||
[aria-checked='true'],
|
||||
[aria-selected='true'] {
|
||||
&:is(wa-card, :has(> wa-card)) {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&:is(wa-card),
|
||||
> wa-card {
|
||||
--border-color: var(--wa-color-brand-border-loud);
|
||||
box-shadow: 0 0 0 var(--wa-border-width-m) var(--border-color);
|
||||
|
||||
&::part(body) {
|
||||
background: var(--wa-color-brand-fill-quiet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wa-select:has(> wa-option > wa-card) {
|
||||
&::part(listbox) {
|
||||
--column-width: 1fr;
|
||||
--columns: 1;
|
||||
--gap: var(--wa-space-smaller);
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(var(--column-width), 1fr));
|
||||
width: calc(var(--columns) * var(--column-width) + (var(--columns) - 1) * var(--gap) + 2 * var(--wa-space));
|
||||
max-width: var(--auto-size-available-width, 90vw);
|
||||
gap: var(--gap);
|
||||
padding: var(--wa-space-smaller) var(--wa-space);
|
||||
}
|
||||
|
||||
> wa-option > wa-card {
|
||||
--spacing: var(--wa-space-s);
|
||||
}
|
||||
}
|
||||
|
||||
wa-radio:has(> wa-card) {
|
||||
grid-template-columns: 1fr;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Swatches */
|
||||
.swatch {
|
||||
position: relative;
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
}
|
||||
|
||||
/* Header */
|
||||
header {
|
||||
#site-search-container header {
|
||||
flex: 0 0 auto;
|
||||
align-items: middle;
|
||||
align-items: center;
|
||||
/* Fixes an iOS Safari 16.4 bug that draws the parent element's border radius incorrectly when showing/hiding results */
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
wa-card:has(> .theme-icon-host, > [slot='header'] > .theme-icon-host) {
|
||||
wa-card:has(
|
||||
> .theme-icon-host,
|
||||
> [slot='header'] > .theme-icon-host,
|
||||
> .fonts-icon-host,
|
||||
> [slot='header'] > .fonts-icon-host
|
||||
) {
|
||||
&::part(header) {
|
||||
/* We want to add a background color, so any spacing needs to go on .theme-icon */
|
||||
flex: 1;
|
||||
@@ -12,6 +17,7 @@ wa-card:has(> .theme-icon-host, > [slot='header'] > .theme-icon-host) {
|
||||
}
|
||||
|
||||
.theme-icon-host,
|
||||
.fonts-icon-host,
|
||||
.palette-icon-host {
|
||||
flex: 1;
|
||||
border-radius: inherit;
|
||||
@@ -23,12 +29,17 @@ wa-card:has(> .theme-icon-host, > [slot='header'] > .theme-icon-host) {
|
||||
}
|
||||
}
|
||||
|
||||
.theme-icon:not(.theme-color-icon),
|
||||
.palette-icon,
|
||||
.icons-icon {
|
||||
min-height: 5.5rem;
|
||||
}
|
||||
|
||||
.palette-icon {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--hues, 9), 1fr);
|
||||
gap: var(--wa-space-3xs);
|
||||
min-width: 20ch;
|
||||
min-height: 9ch;
|
||||
align-content: center;
|
||||
|
||||
.swatch {
|
||||
@@ -42,7 +53,8 @@ wa-card:has(> .theme-icon-host, > [slot='header'] > .theme-icon-host) {
|
||||
}
|
||||
}
|
||||
|
||||
.theme-icon {
|
||||
.theme-icon,
|
||||
.fonts-icon {
|
||||
min-width: 18ch;
|
||||
padding: var(--wa-space-xs) var(--wa-space-m);
|
||||
border-radius: inherit;
|
||||
@@ -57,11 +69,18 @@ wa-card:has(> .theme-icon-host, > [slot='header'] > .theme-icon-host) {
|
||||
}
|
||||
|
||||
.theme-color-icon {
|
||||
display: grid;
|
||||
display: flex;
|
||||
gap: var(--wa-space-xs);
|
||||
grid-template-columns: repeat(4, auto);
|
||||
min-width: 15ch;
|
||||
background: var(--wa-color-surface-lowered);
|
||||
|
||||
& + & {
|
||||
border-start-start-radius: 0;
|
||||
border-start-end-radius: 0;
|
||||
}
|
||||
|
||||
div {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -72,26 +91,17 @@ wa-card:has(> .theme-icon-host, > [slot='header'] > .theme-icon-host) {
|
||||
padding: var(--wa-space-2xs) var(--wa-space-xs);
|
||||
color: var(--text-color);
|
||||
font-weight: var(--wa-font-weight-semibold);
|
||||
|
||||
&.plain {
|
||||
font-weight: var(--wa-font-weight-bold);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.theme-typography-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.theme-overall-icon {
|
||||
.theme-icon.theme-overall-icon,
|
||||
.fonts-icon {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: var(--wa-space-xs);
|
||||
gap: var(--wa-space-2xs);
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
min-height: 7.5rem;
|
||||
min-height: 6.75rem;
|
||||
box-sizing: border-box;
|
||||
background: var(--wa-color-surface-lowered);
|
||||
|
||||
@@ -130,3 +140,50 @@ wa-card:has(> .theme-icon-host, > [slot='header'] > .theme-icon-host) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fonts-icon {
|
||||
font-family: var(--wa-font-family-body);
|
||||
padding-block: var(--wa-space-s);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
& h2,
|
||||
& p {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background-image: linear-gradient(to left, var(--wa-color-surface-lowered), 20%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.icons-icon {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--columns, 5), auto);
|
||||
gap: var(--wa-space-xs);
|
||||
place-items: center;
|
||||
place-content: center;
|
||||
|
||||
& wa-icon {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
}
|
||||
|
||||
.page-card {
|
||||
wa-badge {
|
||||
margin-inline: var(--wa-space-3xs);
|
||||
}
|
||||
}
|
||||
|
||||
:is(.theme-card, .icons-card)::part(header) {
|
||||
background: var(--wa-color-surface-lowered);
|
||||
}
|
||||
|
||||
.icons-card::part(header) {
|
||||
color: var(--wa-color-neutral-on-quiet);
|
||||
}
|
||||
|
||||
145
docs/assets/styles/ui.css
Normal file
145
docs/assets/styles/ui.css
Normal file
@@ -0,0 +1,145 @@
|
||||
/* App UI, for themer, palette tweaking etc */
|
||||
|
||||
:root {
|
||||
--fa-sliders-simple: '\f1de';
|
||||
}
|
||||
|
||||
.title {
|
||||
wa-icon-button {
|
||||
font-size: var(--wa-font-size-l);
|
||||
color: var(--wa-color-text-quiet);
|
||||
|
||||
&:not(:hover, :focus) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup {
|
||||
background: var(--wa-color-surface-default);
|
||||
border: 1px solid var(--wa-color-surface-border);
|
||||
padding: var(--wa-space-xl);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
max-height: 90dvh;
|
||||
overflow: auto;
|
||||
|
||||
code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.color-select {
|
||||
&.default::part(display-input) {
|
||||
opacity: 0.6;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
> small {
|
||||
margin-inline-start: var(--wa-space-xs);
|
||||
padding-block: 0 var(--wa-space-xs);
|
||||
}
|
||||
|
||||
&::part(combobox)::before,
|
||||
wa-option::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 1.2em;
|
||||
aspect-ratio: 1;
|
||||
margin-inline-end: var(--wa-space-xs);
|
||||
flex: none;
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
background: var(--color);
|
||||
border: 1px solid var(--wa-color-surface-default);
|
||||
}
|
||||
|
||||
wa-option {
|
||||
white-space: nowrap;
|
||||
|
||||
&::before {
|
||||
width: 1em;
|
||||
margin-inline: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
&::part(checked-icon) {
|
||||
order: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.default-badge {
|
||||
opacity: 0.6;
|
||||
margin-inline-start: var(--wa-space-xs);
|
||||
}
|
||||
}
|
||||
|
||||
.swatch-select {
|
||||
padding: 2px;
|
||||
|
||||
wa-radio-button {
|
||||
--swatch-border-color: color-mix(in oklab, canvastext, transparent 80%);
|
||||
|
||||
&::part(base) {
|
||||
/* a <button> */
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
padding: 0;
|
||||
border-radius: var(--border-radius, var(--wa-border-radius-m));
|
||||
background: var(--color);
|
||||
background-clip: border-box;
|
||||
border-color: var(--swatch-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.swatch-shape-circle {
|
||||
--border-radius: var(--wa-border-radius-circle);
|
||||
}
|
||||
|
||||
wa-radio-button:is([checked], :state(checked)) {
|
||||
--swatch-border-color: var(--wa-color-surface-default);
|
||||
&::part(base) {
|
||||
box-shadow:
|
||||
inset 0 0 0 var(--indicator-width) var(--wa-color-surface-default),
|
||||
0 0 0 calc(var(--indicator-width) + 1px) var(--indicator-color);
|
||||
}
|
||||
}
|
||||
|
||||
&::part(form-control-input) {
|
||||
flex-wrap: wrap;
|
||||
gap: var(--wa-space-xs);
|
||||
}
|
||||
}
|
||||
|
||||
/* Repeated to increase specificity */
|
||||
.editable-text.editable-text {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--wa-space-xs);
|
||||
--edit-hint-color: oklab(from var(--wa-color-warning-fill-quiet) l a b / 50%);
|
||||
|
||||
> .text {
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: var(--edit-hint-color);
|
||||
box-shadow: 0 0 0 var(--wa-space-2xs) var(--edit-hint-color);
|
||||
color: inherit;
|
||||
border-radius: calc(var(--wa-border-radius-m) - var(--wa-space-2xs));
|
||||
}
|
||||
}
|
||||
|
||||
> input {
|
||||
font: inherit;
|
||||
margin-block: calc(-1 * var(--wa-space-smaller));
|
||||
field-sizing: content;
|
||||
}
|
||||
|
||||
wa-icon-button {
|
||||
font-size: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
.info-tip-default-trigger {
|
||||
color: var(--wa-color-text-quiet);
|
||||
|
||||
&:not(:hover, :focus) {
|
||||
opacity: 65%;
|
||||
}
|
||||
}
|
||||
78
docs/assets/vue/components/color-select.js
Normal file
78
docs/assets/vue/components/color-select.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { capitalize } from '../../scripts/util/string.js';
|
||||
|
||||
const template = `
|
||||
<wa-select class="color-select" name="brand" :label="label" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"
|
||||
:style="{'--color': getColor(modelValue)}">
|
||||
<template v-for="values, group in computedGroups">
|
||||
<template v-if="group">
|
||||
<wa-divider v-if="group !== firstGroup"></wa-divider>
|
||||
<small>{{ group }}</small>
|
||||
</template>
|
||||
<wa-option v-if="values?.length" v-for="value of values" :label="getLabel(value)" :value="value" :style="{'--color': getColor(value)}" v-html="getContent?.(value) ?? getLabel(value)"></wa-option>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</wa-select>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
modelValue: String,
|
||||
label: String,
|
||||
getLabel: {
|
||||
type: Function,
|
||||
default: capitalize,
|
||||
},
|
||||
getContent: {
|
||||
type: Function,
|
||||
},
|
||||
getColor: {
|
||||
type: Function,
|
||||
default: value => `var(--wa-color-${value})`,
|
||||
},
|
||||
values: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
groups: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue', 'input'],
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
computedGroups() {
|
||||
let ret = {};
|
||||
|
||||
if (this.values?.length) {
|
||||
ret[''] = this.values;
|
||||
}
|
||||
|
||||
if (this.groups) {
|
||||
for (let group in this.groups) {
|
||||
if (this.groups[group]?.length) {
|
||||
ret[group] = this.groups[group];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
firstGroup() {
|
||||
return Object.keys(this.computedGroups)[0];
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
capitalize,
|
||||
handleInput(e) {
|
||||
this.$emit('input', this.modelValue);
|
||||
},
|
||||
},
|
||||
template,
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
82
docs/assets/vue/components/editable-text.js
Normal file
82
docs/assets/vue/components/editable-text.js
Normal file
@@ -0,0 +1,82 @@
|
||||
const template = `
|
||||
<span class="editable-text">
|
||||
<template v-if="isEditing">
|
||||
<input ref="input" class="wa-size-s" :aria-label="label" :value="value" @input="handleInput" @keydown.enter="done" @keydown.esc="cancel" />
|
||||
<wa-icon-button name="check" label="Done editing" @click="done"></wa-icon-button>
|
||||
<wa-icon-button name="xmark" label="Cancel" @click="cancel"></wa-icon-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="text" ref="wrapper" @focus="edit" @click="edit" tabindex="0">{{ value }}</span>
|
||||
<wa-icon-button name="pencil" :label="'Edit ' + label" @click="edit"></wa-icon-button>
|
||||
</template>
|
||||
</span>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
modelValue: String,
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Rename',
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue', 'submit'],
|
||||
data() {
|
||||
return {
|
||||
value: this.modelValue,
|
||||
previousValue: undefined,
|
||||
isEditing: false,
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
|
||||
methods: {
|
||||
edit(event) {
|
||||
if (this.isEditing) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
this.isEditing = true;
|
||||
this.previousValue = this.value;
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.$refs.input.focus();
|
||||
this.$refs.input.select();
|
||||
});
|
||||
},
|
||||
done(event) {
|
||||
if (!this.isEditing) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
this.isEditing = false;
|
||||
|
||||
if (!this.previousValue || this.previousValue !== this.value) {
|
||||
this.$emit('submit', this.value);
|
||||
}
|
||||
},
|
||||
cancel(event) {
|
||||
if (!this.isEditing) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
this.isEditing = false;
|
||||
this.value = this.previousValue;
|
||||
},
|
||||
handleInput(event) {
|
||||
this.value = event.target.value;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
},
|
||||
},
|
||||
template,
|
||||
};
|
||||
132
docs/assets/vue/components/fonts-card.js
Normal file
132
docs/assets/vue/components/fonts-card.js
Normal file
@@ -0,0 +1,132 @@
|
||||
import PageCard from './page-card.js';
|
||||
import { defaultTitle, pairings, sameAs } from '/assets/data/fonts.js';
|
||||
import { themeConfig } from '/assets/data/theming.js';
|
||||
import { cssImport, getThemeCode } from '/assets/scripts/tweak/code.js';
|
||||
import themes from '/docs/themes/data.js';
|
||||
|
||||
const template = `
|
||||
<page-card class="fonts-card" :info="computedPairing">
|
||||
<template #icon>
|
||||
<wa-scoped slot="header" class="fonts-icon-host" inert>
|
||||
<template v-html="html"></template>
|
||||
<template>
|
||||
<link rel="stylesheet" href="/dist/styles/native/content.css">
|
||||
<link rel="stylesheet" href="/assets/styles/theme-icons.css">
|
||||
|
||||
<div class="fonts-icon" role="presentation">
|
||||
<h2>When my six o'clock alarm buzzes, I require a pot of good java.</h2>
|
||||
<p>By quarter past seven, I've jotted hazy musings in a flax-bound notebook, sipping lukewarm espresso.</p>
|
||||
</div>
|
||||
</template>
|
||||
</wa-scoped>
|
||||
</template>
|
||||
<slot></slot>
|
||||
<template #extra>
|
||||
<slot name="extra" />
|
||||
</template>
|
||||
</page-card>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
theme: String,
|
||||
src: String,
|
||||
fonts: Object,
|
||||
pairing: Object,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
|
||||
computed: {
|
||||
content() {
|
||||
let pairingTitle = this.computedPairing.title;
|
||||
// let themeTitle = this.themeId ? `As seen in ${this.themeMeta.title}` : '';
|
||||
|
||||
if (this.title) {
|
||||
return { title: this.title, subtitle: this.subtitle ?? pairingTitle };
|
||||
} else {
|
||||
return { title: pairingTitle, subtitle: this.subtitle };
|
||||
}
|
||||
},
|
||||
|
||||
url() {
|
||||
let ret = this.src ?? this.pairing?.url;
|
||||
|
||||
if (!ret && this.theme) {
|
||||
return themeConfig.typography.url(this.theme);
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
themeId() {
|
||||
return this.theme ?? this.pairing?.id;
|
||||
},
|
||||
|
||||
themeMeta() {
|
||||
return themes[this.themeId] ?? {};
|
||||
},
|
||||
|
||||
computedFonts() {
|
||||
let ret = this.fonts ?? this.pairing?.fonts ?? this.themeMeta?.fonts;
|
||||
let defaults = themes.default.fonts;
|
||||
return Object.assign({}, defaults, { ...ret });
|
||||
},
|
||||
|
||||
computedPairing() {
|
||||
let ret;
|
||||
|
||||
if (this.pairing) {
|
||||
ret = { ...this.pairing };
|
||||
} else {
|
||||
// Get from theme
|
||||
let fonts = this.computedFonts;
|
||||
let { body, heading = sameAs.body } = fonts;
|
||||
let pairing = pairings[body]?.[heading];
|
||||
ret = Object.assign({ fonts }, pairing);
|
||||
}
|
||||
|
||||
ret.url = this.url;
|
||||
ret.title ??= defaultTitle(fonts);
|
||||
return ret;
|
||||
},
|
||||
|
||||
computed() {
|
||||
let ret = { fonts: this.computedFonts };
|
||||
|
||||
for (let key in ret.fonts) {
|
||||
if (ret.fonts[key] === sameAs.body) {
|
||||
ret.fonts[key] = ret.fonts.body;
|
||||
}
|
||||
}
|
||||
|
||||
ret.pairing = this.computedPairing;
|
||||
ret.theme = this.themeId;
|
||||
ret.url = this.url;
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
html() {
|
||||
let { id, url } = this.computedPairing;
|
||||
|
||||
if (id) {
|
||||
let theme = { typography: id };
|
||||
|
||||
return getThemeCode(theme, { id, language: 'html' });
|
||||
} else {
|
||||
return cssImport(url, { language: 'html' });
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
template,
|
||||
components: {
|
||||
PageCard,
|
||||
},
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
175
docs/assets/vue/components/icons-card.js
Normal file
175
docs/assets/vue/components/icons-card.js
Normal file
@@ -0,0 +1,175 @@
|
||||
import { sample } from '../../scripts/util/array.js';
|
||||
import { capitalize } from '../../scripts/util/string.js';
|
||||
import PageCard from './page-card.js';
|
||||
import { iconLibraries } from '/assets/data/icons.js';
|
||||
|
||||
const iconNames = [
|
||||
'user',
|
||||
'paper-plane',
|
||||
'face-laugh',
|
||||
'pen-to-square',
|
||||
'trash',
|
||||
'cart-shopping',
|
||||
'link',
|
||||
'sun',
|
||||
'bookmark',
|
||||
'sparkles',
|
||||
'thumbs-up',
|
||||
'gear',
|
||||
];
|
||||
const brands = new Set(['web-awesome', 'font-awesome']);
|
||||
const ICON_GRID = { columns: 6, rows: 2 };
|
||||
const TOTAL_ICONS = ICON_GRID.columns * ICON_GRID.rows;
|
||||
|
||||
const template = `
|
||||
<page-card class="icons-card" :class="'icons-' + type + '-card'" :pro="$slots.default ? false : iconsMeta.isPro" :info="iconsMeta">
|
||||
<template #icon>
|
||||
<div slot="header" class="icons-icon" :class="'icons-' + type + '-icon'" :style="{ '--columns': ICON_GRID.columns }">
|
||||
<template v-for="icon of icons">
|
||||
<wa-icon v-bind="icon"></wa-icon>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</page-card>
|
||||
`;
|
||||
|
||||
const defaultDefaults = {
|
||||
library: 'default',
|
||||
family: 'classic',
|
||||
style: 'solid',
|
||||
};
|
||||
|
||||
export default {
|
||||
props: {
|
||||
library: String,
|
||||
family: String,
|
||||
style: String,
|
||||
defaults: Object,
|
||||
type: {
|
||||
type: String,
|
||||
validate(value) {
|
||||
return ['library', 'family', 'style'].includes(value);
|
||||
},
|
||||
},
|
||||
vary: {
|
||||
type: [Array, String],
|
||||
validate(value) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.every(v => ['family', 'style'].includes(v));
|
||||
}
|
||||
|
||||
return ['family', 'style'].includes(value);
|
||||
},
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
|
||||
created() {
|
||||
Object.assign(this, { iconNames, brands, ICON_GRID });
|
||||
},
|
||||
|
||||
computed: {
|
||||
computedLibrary() {
|
||||
return this.library ?? 'default';
|
||||
},
|
||||
|
||||
libraryMeta() {
|
||||
return iconLibraries[this.computedLibrary] ?? {};
|
||||
},
|
||||
|
||||
defaultTitle() {
|
||||
let titles = {};
|
||||
for (let key in this.computed) {
|
||||
let value = this.computed[key];
|
||||
|
||||
if (key === 'library') {
|
||||
titles[key] = iconLibraries[value].title;
|
||||
}
|
||||
|
||||
titles[key] ??= capitalize(value);
|
||||
}
|
||||
|
||||
if (this.type) {
|
||||
return titles[this.type];
|
||||
} else {
|
||||
return titles.library + ' ' + titles.family + ' • ' + titles.style;
|
||||
}
|
||||
},
|
||||
|
||||
icons() {
|
||||
let { family, style } = this.computed;
|
||||
let library = this.libraryMeta;
|
||||
let vary = Array.isArray(this.vary) ? this.vary : [this.vary];
|
||||
|
||||
let ret = [];
|
||||
|
||||
if (vary.length > 0) {
|
||||
for (let param of vary) {
|
||||
let allValues = library[param];
|
||||
let random = (allValues.random ??= []);
|
||||
|
||||
while (random.length < TOTAL_ICONS) {
|
||||
random.push(sample(allValues));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (ret.length < TOTAL_ICONS) {
|
||||
ret.push(
|
||||
...iconNames.map((name, i) => {
|
||||
let index = ret.length + i;
|
||||
|
||||
return {
|
||||
library: this.computedLibrary,
|
||||
name,
|
||||
family: !this.family && vary.includes('family') ? library.family.random[index] : family,
|
||||
variant: !this.style && vary.includes('style') ? library.style.random[index] : style,
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return ret.slice(0, TOTAL_ICONS);
|
||||
},
|
||||
|
||||
computedDefaults() {
|
||||
return Object.assign({}, defaultDefaults, this.defaults);
|
||||
},
|
||||
|
||||
computed() {
|
||||
let { library, family, style } = this;
|
||||
let ret = { library, family, style };
|
||||
|
||||
for (let key in this.computedDefaults) {
|
||||
if (!ret[key]) {
|
||||
ret[key] = this.computedDefaults[key];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
iconsMeta() {
|
||||
return { title: this.defaultTitle };
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
capitalize,
|
||||
},
|
||||
|
||||
template,
|
||||
components: {
|
||||
PageCard,
|
||||
},
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
12
docs/assets/vue/components/index.js
Normal file
12
docs/assets/vue/components/index.js
Normal file
@@ -0,0 +1,12 @@
|
||||
export { default as ColorSelect } from './color-select.js';
|
||||
export { default as EditableText } from './editable-text.js';
|
||||
export { default as FontsCard } from './fonts-card.js';
|
||||
export { default as IconsCard } from './icons-card.js';
|
||||
export { default as InfoTip } from './info-tip.js';
|
||||
export { default as PageCard } from './page-card.js';
|
||||
export { default as PaletteCard } from './palette-card.js';
|
||||
export { default as SwatchSelect } from './swatch-select.js';
|
||||
export { default as ThemeCard } from './theme-card.js';
|
||||
export { default as UiPanelContainer } from './ui-panel-container.js';
|
||||
export { default as UiPanel } from './ui-panel.js';
|
||||
export { default as UiScrollable } from './ui-scrollable.js';
|
||||
38
docs/assets/vue/components/info-tip.js
Normal file
38
docs/assets/vue/components/info-tip.js
Normal file
@@ -0,0 +1,38 @@
|
||||
const template = `
|
||||
<slot>
|
||||
<wa-icon :slot class="info-tip-default-trigger" :id="id" name="circle-question" variant="regular" tabindex="0"></wa-icon>
|
||||
</slot>
|
||||
<wa-tooltip :slot :for="id" ref="tooltip"><slot name="content"></slot></wa-tooltip>
|
||||
`;
|
||||
|
||||
let maxUid = 0;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
slot: String,
|
||||
},
|
||||
data() {
|
||||
let uid = ++maxUid;
|
||||
return { uid, id: 'info-tip-' + uid };
|
||||
},
|
||||
mounted() {
|
||||
let tooltip = this.$refs.tooltip;
|
||||
if (tooltip) {
|
||||
// Find trigger
|
||||
let trigger = tooltip.previousElementSibling;
|
||||
if (trigger) {
|
||||
if (trigger.id) {
|
||||
// Already has id
|
||||
this.id = trigger.id;
|
||||
} else {
|
||||
trigger.id = this.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
template,
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
83
docs/assets/vue/components/page-card.js
Normal file
83
docs/assets/vue/components/page-card.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Generic component for displaying a (possibly interactive) card that represents a page
|
||||
* For more specific use cases check out theme-card, icons-card, etc.
|
||||
*/
|
||||
export const ICON_PLACEHOLDER = `
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7C1 3.68629 3.68629 1 7 1H43C46.3137 1 49 3.68629 49 7V43C49 46.3137 46.3137 49 43 49H7C3.68629 49 1 46.3137 1 43V7Z" stroke="var(--wa-color-surface-border)" stroke-width="2" stroke-linecap="round" stroke-dasharray="6 6"/>
|
||||
<path d="M14.1566 18.7199L21.5367 16.7424C22.6036 16.4565 23.7003 17.0896 23.9862 18.1566L26.8463 28.8306C27.1322 29.8975 26.499 30.9942 25.4321 31.2801L18.052 33.2576C16.985 33.5435 15.8884 32.9103 15.6025 31.8434L12.7424 21.1694C12.4565 20.1024 13.0897 19.0057 14.1566 18.7199Z" stroke="var(--wa-color-neutral-border-normal)" stroke-width="2"/>
|
||||
<path d="M33.8449 16.3273H26.2045C23.9953 16.3273 22.2045 18.1181 22.2045 20.3273V31.3778C22.2045 33.587 23.9953 35.3778 26.2045 35.3778H33.8449C36.0541 35.3778 37.8449 33.587 37.8449 31.3778V20.3273C37.8449 18.1181 36.0541 16.3273 33.8449 16.3273Z" fill="var(--wa-color-neutral-border-normal)" stroke="var(--wa-color-neutral-fill-quiet)" stroke-width="2"/>
|
||||
</svg>`;
|
||||
|
||||
const template = `
|
||||
<wa-card with-header class="page-card" :aria-disabled="disabled ? 'true' : null" :inert="disabled"
|
||||
@click="handleClick" @keyup.enter="handleClick" @keyup.space="handleClick"
|
||||
:role="action ? 'button' : null" :tabindex="action? 0 : null">
|
||||
<slot name="icon" slot="header">
|
||||
<div slot="header" v-html="icon || ICON_PLACEHOLDER"></div>
|
||||
</slot>
|
||||
|
||||
<div class="page-name">
|
||||
<div>
|
||||
<slot>
|
||||
{{ content.title }}
|
||||
<wa-badge class="pro" v-if="pro">PRO</wa-badge>
|
||||
<div v-if="content.subtitle" class="wa-caption-m">{{ content.subtitle }}</div>
|
||||
</slot>
|
||||
</div>
|
||||
<slot name="extra"></slot>
|
||||
<wa-icon v-if="action" name="angle-right" class="angle-right" variant="regular"></wa-icon>
|
||||
</div>
|
||||
</wa-card>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
title: String,
|
||||
subtitle: String,
|
||||
info: Object,
|
||||
icon: String,
|
||||
pro: Boolean,
|
||||
disabled: Boolean,
|
||||
action: Function,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
|
||||
created() {
|
||||
Object.assign(this, { ICON_PLACEHOLDER });
|
||||
},
|
||||
|
||||
computed: {
|
||||
content() {
|
||||
let defaultTitle = this.info?.title ?? {};
|
||||
|
||||
if (this.title) {
|
||||
return { title: this.title, subtitle: this.subtitle ?? defaultTitle };
|
||||
} else {
|
||||
return { title: defaultTitle, subtitle: this.subtitle };
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClick(event) {
|
||||
if (this.disabled) {
|
||||
event.stopImmediatePropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.action) {
|
||||
this.action(event);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
template,
|
||||
components: {},
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
63
docs/assets/vue/components/palette-card.js
Normal file
63
docs/assets/vue/components/palette-card.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import PageCard from './page-card.js';
|
||||
import { hues } from '/assets/data/index.js';
|
||||
import palettes from '/docs/palettes/data.js';
|
||||
|
||||
// TODO import from data.js once available
|
||||
const allHues = [...hues, 'gray'];
|
||||
|
||||
const template = `
|
||||
<page-card class="palette-card" :pro="$slots.default ? false : paletteMeta.isPro" :info="paletteMeta">
|
||||
<template #icon>
|
||||
<wa-scoped slot="header" class="palette-icon-host">
|
||||
<template>
|
||||
<link rel="stylesheet" :href="'/dist/styles/color/' + palette + '.css'">
|
||||
<link rel="stylesheet" href="/assets/styles/theme-icons.css">
|
||||
|
||||
<div class="palette-icon" style="--hues: {{ hues|length }}; --suffixes: {{ suffixes|length }}">
|
||||
<template v-for="(hue, hueIndex) of hues">
|
||||
<div class="swatch" v-for="(suffix, suffixIndex) of suffixes"
|
||||
:data-hue="hue" :data-suffix="suffix"
|
||||
:style="{
|
||||
'--color': 'var(--wa-color-' + hue + suffix + ')',
|
||||
gridColumn: hueIndex + 1,
|
||||
gridRow: suffixIndex + 1
|
||||
}"> </div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</wa-scoped>
|
||||
</template>
|
||||
<slot></slot>
|
||||
<template #extra>
|
||||
<slot name="extra" />
|
||||
</template>
|
||||
</page-card>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
palette: String,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
|
||||
created() {
|
||||
Object.assign(this, { hues: allHues, suffixes: ['-80', '', '-20'] });
|
||||
},
|
||||
|
||||
computed: {
|
||||
paletteMeta() {
|
||||
return palettes[this.palette] ?? {};
|
||||
},
|
||||
},
|
||||
|
||||
template,
|
||||
components: {
|
||||
PageCard,
|
||||
},
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
173
docs/assets/vue/components/panel.css
Normal file
173
docs/assets/vue/components/panel.css
Normal file
@@ -0,0 +1,173 @@
|
||||
.sidebar.panel-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: 0;
|
||||
padding: 0;
|
||||
width: 32ch;
|
||||
overflow: hidden;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
@keyframes back-icon-hover {
|
||||
to {
|
||||
transform: translateX(-0.2em);
|
||||
}
|
||||
}
|
||||
|
||||
.panel {
|
||||
/* Remove the uniform spacing used in wa-details */
|
||||
--spacing: 0;
|
||||
/* Specify value to manually set spacing where needed */
|
||||
--panel-spacing: var(--wa-space-2xl);
|
||||
--panel-background: var(--wa-color-surface-default);
|
||||
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
max-height: 100%;
|
||||
margin-bottom: 0;
|
||||
position: relative;
|
||||
background: var(--panel-background);
|
||||
border: none;
|
||||
transition:
|
||||
translate var(--wa-transition-slow) allow-discrete,
|
||||
opacity var(--wa-transition-slow) 25ms allow-discrete;
|
||||
/* Ensure horizontal scrollbar isn't visible when translate takes effect */
|
||||
overflow-x: hidden !important;
|
||||
|
||||
@starting-style {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
flex-direction: row-reverse;
|
||||
justify-content: start;
|
||||
gap: var(--wa-space-xs);
|
||||
cursor: pointer;
|
||||
background: var(--panel-background);
|
||||
color: var(--wa-color-text-normal);
|
||||
padding-block-end: var(--panel-spacing);
|
||||
padding-inline: var(--panel-spacing);
|
||||
transition: inherit;
|
||||
transition-property: all;
|
||||
margin-block: 0;
|
||||
font-size: inherit;
|
||||
|
||||
[data-step='0'] &,
|
||||
.previous & {
|
||||
padding-block-start: var(--panel-spacing);
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
vertical-align: -0.15em;
|
||||
margin-inline-end: var(--wa-space-xs);
|
||||
font-size: var(--wa-font-size-m);
|
||||
transition: transform var(--wa-transition-normal);
|
||||
}
|
||||
|
||||
&:hover .back-icon {
|
||||
animation: back-icon-hover var(--wa-transition-slow) alternate infinite;
|
||||
}
|
||||
|
||||
label {
|
||||
pointer-events: none;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: var(--panel-spacing);
|
||||
padding-block-end: var(--panel-spacing);
|
||||
padding-inline: var(--panel-spacing);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
|
||||
&:not(.open) {
|
||||
padding: 0;
|
||||
|
||||
&:not(.previous, .next) {
|
||||
/* Hide all but the immediately preceding or following steps */
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.next {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&.next {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.next {
|
||||
translate: 100% 0%;
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
font-size: var(--wa-font-size-s);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
content-visibility: hidden;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.open {
|
||||
flex: 1;
|
||||
opacity: 1;
|
||||
|
||||
.panel-header {
|
||||
font-size: var(--wa-font-size-l);
|
||||
|
||||
.back-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
transition: inherit;
|
||||
|
||||
@starting-style {
|
||||
display: flex;
|
||||
content-visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.open) {
|
||||
&.previous {
|
||||
.panel-content {
|
||||
opacity: 0;
|
||||
translate: -100% 0%;
|
||||
}
|
||||
}
|
||||
|
||||
&.next {
|
||||
.panel-content {
|
||||
opacity: 0;
|
||||
translate: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
docs/assets/vue/components/scrollable.css
Normal file
89
docs/assets/vue/components/scrollable.css
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Scrollable element in a vertical flex container
|
||||
* Showing shadows as an indicator of scrollability (PE wherever scroll-timeline is supported for now, can be polyfilled with JS later)
|
||||
*/
|
||||
|
||||
.scrollable {
|
||||
--scroll-shadow-height: 0.5em;
|
||||
|
||||
flex-shrink: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
scrollbar-width: inherit;
|
||||
|
||||
&:is(.panel-content > div) {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: inherit;
|
||||
}
|
||||
|
||||
.scroll-shadow {
|
||||
position: sticky;
|
||||
z-index: 1;
|
||||
inset-inline: 0;
|
||||
display: block;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset-inline: 0;
|
||||
height: var(--scroll-shadow-height);
|
||||
pointer-events: none;
|
||||
mix-blend-mode: multiply;
|
||||
background: radial-gradient(farthest-side, var(--wa-color-shadow) 10%, transparent) center / 120% 200%;
|
||||
transition: var(--wa-transition-slow);
|
||||
/* transition-property: opacity, transform, display, height, min-height; */
|
||||
transition-behavior: allow-discrete;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.can-scroll-top) .scroll-shadow-top,
|
||||
&:not(.can-scroll-bottom) .scroll-shadow-bottom {
|
||||
opacity: 0;
|
||||
|
||||
&::before {
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.can-scroll-top) .scroll-shadow-top {
|
||||
&::before {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-shadow-top {
|
||||
top: 0;
|
||||
|
||||
&::before {
|
||||
background-position: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.can-scroll-bottom) .scroll-shadow-bottom {
|
||||
&::before {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-shadow-bottom {
|
||||
top: 100%;
|
||||
|
||||
&::before {
|
||||
bottom: 0;
|
||||
background-position: top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scrollable:where(.panel-content) {
|
||||
.scroll-shadow-top {
|
||||
/* TODO convert this magic number to a token that explains what it is */
|
||||
margin-bottom: -18px;
|
||||
}
|
||||
|
||||
.scroll-shadow-bottom {
|
||||
transform: translateY(var(--padding-bottom, var(--panel-spacing)));
|
||||
}
|
||||
}
|
||||
67
docs/assets/vue/components/swatch-select.js
Normal file
67
docs/assets/vue/components/swatch-select.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import { capitalize } from '../../scripts/util/string.js';
|
||||
import InfoTip from './info-tip.js';
|
||||
|
||||
const template = `
|
||||
<wa-radio-group :label class="swatch-select" :class="'swatch-shape-' + shape" orientation="horizontal" :value="modelValue" @input="handleInput">
|
||||
<info-tip v-for="value in values">
|
||||
<wa-radio-button :value :label="getLabel(value)" :style="{'--color': getColor(value)}"></wa-radio-button>
|
||||
<template #content>
|
||||
{{ getLabel(value) }}
|
||||
</template>
|
||||
</info-tip>
|
||||
</wa-radio-group>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
modelValue: String,
|
||||
name: String,
|
||||
label: String,
|
||||
shape: {
|
||||
type: String,
|
||||
default: 'rounded',
|
||||
validator: value => ['circle', 'rounded'].includes(value),
|
||||
},
|
||||
getLabel: {
|
||||
type: Function,
|
||||
default: capitalize,
|
||||
},
|
||||
getColor: {
|
||||
type: Function,
|
||||
default: value => `var(--wa-color-${value})`,
|
||||
},
|
||||
values: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue', 'input'],
|
||||
data() {
|
||||
return {
|
||||
value: this.modelValue,
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
|
||||
methods: {
|
||||
capitalize,
|
||||
handleInput(e) {
|
||||
this.value = e.target.value;
|
||||
this.$emit('input', this.value);
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
value() {
|
||||
this.$emit('update:modelValue', this.value);
|
||||
},
|
||||
},
|
||||
|
||||
template,
|
||||
components: {
|
||||
InfoTip,
|
||||
},
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
97
docs/assets/vue/components/theme-card.js
Normal file
97
docs/assets/vue/components/theme-card.js
Normal file
@@ -0,0 +1,97 @@
|
||||
import PageCard from './page-card.js';
|
||||
import { getThemeCode } from '/assets/scripts/tweak/code.js';
|
||||
import themes from '/docs/themes/data.js';
|
||||
|
||||
const iconTemplates = {
|
||||
colors: `
|
||||
<div class="theme-icon theme-color-icon" role="presentation">
|
||||
<div style="background: var(--wa-color-brand-fill-loud); border-color: var(--wa-color-brand-border-loud); color: var(--wa-color-brand-on-loud);">A</div>
|
||||
<div style="background: var(--wa-color-brand-fill-normal); border-color: var(--wa-color-brand-border-normal); color: var(--wa-color-brand-on-normal);">A</div>
|
||||
<div style="background: var(--wa-color-brand-fill-quiet); border-color: var(--wa-color-brand-border-quiet); color: var(--wa-color-brand-on-quiet);">A</div>
|
||||
</div>
|
||||
|
||||
<div class="wa-invert theme-icon theme-color-icon" role="presentation">
|
||||
<div style="background: var(--wa-color-brand-fill-loud); border-color: var(--wa-color-brand-border-loud); color: var(--wa-color-brand-on-loud);">A</div>
|
||||
<div style="background: var(--wa-color-brand-fill-normal); border-color: var(--wa-color-brand-border-normal); color: var(--wa-color-brand-on-normal);">A</div>
|
||||
<div style="background: var(--wa-color-brand-fill-quiet); border-color: var(--wa-color-brand-border-quiet); color: var(--wa-color-brand-on-quiet);">A</div>
|
||||
</div>`,
|
||||
theme: `
|
||||
<div class="row row-1">
|
||||
<h2>Aa</h2>
|
||||
<div class="swatches">
|
||||
<div class="wa-brand"></div>
|
||||
<div class="wa-success"></div>
|
||||
<div class="wa-warning"></div>
|
||||
<div class="wa-danger"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row row-2">
|
||||
<wa-input value="Input" size="small"></wa-input>
|
||||
<wa-button size="small" variant="brand">Go</wa-button>
|
||||
</div>`,
|
||||
};
|
||||
|
||||
const template = `
|
||||
<page-card class="theme-card" :class="type + '-card'" :info="themeMeta">
|
||||
<template #icon>
|
||||
<wa-scoped slot="header" class="theme-icon-host" inert>
|
||||
<template v-html="themeCode"></template>
|
||||
<template>
|
||||
<link rel="stylesheet" href="/dist/styles/utilities.css">
|
||||
<link rel="stylesheet" href="/dist/styles/native/content.css">
|
||||
<link rel="stylesheet" href="/assets/styles/theme-icons.css">
|
||||
|
||||
<template v-if="type == 'colors'" >
|
||||
${iconTemplates.colors}
|
||||
</template>
|
||||
|
||||
<div v-else class="theme-icon theme-overall-icon" :class="'wa-theme-' + theme" role="presentation">
|
||||
${iconTemplates.theme}
|
||||
</div>
|
||||
</template>
|
||||
</wa-scoped>
|
||||
</template>
|
||||
<slot></slot>
|
||||
<template #extra>
|
||||
<slot name="extra" />
|
||||
</template>
|
||||
</page-card>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
theme: String,
|
||||
type: {
|
||||
type: String,
|
||||
validator(value) {
|
||||
return !value || ['colors'].includes(value);
|
||||
},
|
||||
},
|
||||
rest: Object,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
|
||||
computed: {
|
||||
themeMeta() {
|
||||
return themes[this.theme] ?? {};
|
||||
},
|
||||
|
||||
themeCode() {
|
||||
let theme = { ...(this.rest || {}), [this.type || 'base']: this.theme };
|
||||
theme.base ||= 'default';
|
||||
|
||||
return getThemeCode(theme, { id: this.theme, language: 'html', cdnUrl: '/dist/' });
|
||||
},
|
||||
},
|
||||
|
||||
template,
|
||||
components: {
|
||||
PageCard,
|
||||
},
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
120
docs/assets/vue/components/ui-panel-container.js
Normal file
120
docs/assets/vue/components/ui-panel-container.js
Normal file
@@ -0,0 +1,120 @@
|
||||
const template = `
|
||||
<section class="panel-container" ref="container" :style="{'--panel-step': step}" @open="handleOpen">
|
||||
<slot ref="panels"></slot>
|
||||
</section>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
/** Currently selected id */
|
||||
modelValue: String,
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
previousValue: '',
|
||||
step: 0,
|
||||
trail: [],
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
let { container } = this.$refs;
|
||||
let activePanel = container.querySelector(':scope > .open');
|
||||
|
||||
if (activePanel) {
|
||||
let { step, value } = activePanel.dataset;
|
||||
this.step = Number(step);
|
||||
this.value = value;
|
||||
this.$emit('update:modelValue', this.value);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
panels() {
|
||||
if (!this.$refs.container) {
|
||||
return new Map();
|
||||
}
|
||||
|
||||
let { container } = this.$refs;
|
||||
|
||||
return new Map(
|
||||
[...container.querySelectorAll(':scope > .panel')].map(panel => [
|
||||
panel.dataset.value,
|
||||
Number(panel.dataset.step),
|
||||
]),
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleOpen(e) {
|
||||
let { value, step } = e.detail;
|
||||
this.value = value;
|
||||
this.step = step;
|
||||
},
|
||||
|
||||
updatePanels() {
|
||||
let { container } = this.$refs;
|
||||
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { step, value } = this;
|
||||
|
||||
if (this.panels.get(value) !== step) {
|
||||
// Hasn't stabilized yet
|
||||
return;
|
||||
}
|
||||
|
||||
let previousValue = this.trail.findLast(panel => this.panels.get(panel) === step - 1);
|
||||
|
||||
for (let panel of container.querySelectorAll(':scope > .panel')) {
|
||||
let panelStep = Number(panel.dataset.step);
|
||||
let panelValue = panel.dataset.value;
|
||||
let isPrevious = previousValue ? panelValue === previousValue : panelStep === step - 1;
|
||||
let isOpen = panelValue === value;
|
||||
let isNext = panelStep === step + 1;
|
||||
|
||||
panel.classList.toggle('previous', isPrevious);
|
||||
panel.classList.toggle('open', isOpen);
|
||||
panel.classList.toggle('next', isNext);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
value() {
|
||||
if (this.value !== this.modelValue) {
|
||||
this.$emit('update:modelValue', this.value);
|
||||
}
|
||||
},
|
||||
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
async handler(value, previousValue) {
|
||||
if (this.value !== this.modelValue) {
|
||||
this.value = this.modelValue;
|
||||
}
|
||||
|
||||
if (previousValue) {
|
||||
this.trail.push(previousValue);
|
||||
}
|
||||
|
||||
this.updatePanels();
|
||||
},
|
||||
},
|
||||
|
||||
step() {
|
||||
this.updatePanels();
|
||||
},
|
||||
},
|
||||
|
||||
template,
|
||||
components: {},
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
73
docs/assets/vue/components/ui-panel.js
Normal file
73
docs/assets/vue/components/ui-panel.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import UiScrollable from './ui-scrollable.js';
|
||||
|
||||
const template = `
|
||||
<ui-scrollable :disabled="!open" role="group" :name="name || 'panel'" :data-value="value" :data-step="step" class="panel" :class="{open}">
|
||||
<h2 :inert="open" class="panel-header" @click="openPanel" ref="panelHeader">
|
||||
<wa-icon name="chevron-left" class="back-icon" />
|
||||
<slot name="title">{{ title }}</slot>
|
||||
</h2>
|
||||
<div class="panel-content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</ui-scrollable>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
title: String,
|
||||
name: String,
|
||||
step: Number,
|
||||
|
||||
/** Id of this panel */
|
||||
value: String,
|
||||
|
||||
/** Currently selected id */
|
||||
modelValue: String,
|
||||
},
|
||||
emits: ['update:modelValue', 'open'],
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.open) {
|
||||
this.$refs.panelHeader.dispatchEvent(
|
||||
new CustomEvent('open', { detail: { value: this.value, step: this.step }, bubbles: true }),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
open() {
|
||||
return this.value === this.modelValue;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
openPanel() {
|
||||
let wasOpen = this.open;
|
||||
this.$emit('update:modelValue', wasOpen ? '' : this.value);
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
open: {
|
||||
immediate: true,
|
||||
handler(open) {
|
||||
if (open && this.$refs.panelHeader) {
|
||||
this.$refs.panelHeader.dispatchEvent(
|
||||
new CustomEvent('open', { detail: { value: this.value, step: this.step }, bubbles: true }),
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
template,
|
||||
components: {
|
||||
UiScrollable,
|
||||
},
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
77
docs/assets/vue/components/ui-scrollable.js
Normal file
77
docs/assets/vue/components/ui-scrollable.js
Normal file
@@ -0,0 +1,77 @@
|
||||
const template = `
|
||||
<div class="scrollable" :class="{'can-scroll-top': canScrollTop, 'can-scroll-bottom': canScrollBottom}" ref="container">
|
||||
<div v-if="!disabled" class="scroll-shadow scroll-shadow-top"></div>
|
||||
<slot></slot>
|
||||
<div v-if="!disabled" class="scroll-shadow scroll-shadow-bottom"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
disabled: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scrollTop: 0,
|
||||
scrollHeight: 0,
|
||||
height: 0,
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
let { container, content } = this.$refs;
|
||||
container.addEventListener('scroll', this.handleScroll, { passive: true });
|
||||
|
||||
this.scrollHeight = container.scrollHeight;
|
||||
this.height = container.clientHeight;
|
||||
},
|
||||
|
||||
computed: {
|
||||
canScrollTop() {
|
||||
return !this.disabled && this.scrollTop > 1;
|
||||
},
|
||||
|
||||
maxScrollTop() {
|
||||
return this.scrollHeight - this.height;
|
||||
},
|
||||
|
||||
canScrollBottom() {
|
||||
return !this.disabled && this.scrollTop < this.maxScrollTop - 1;
|
||||
},
|
||||
|
||||
scrollProgress() {
|
||||
return this.scrollTop / this.maxScrollTop;
|
||||
},
|
||||
|
||||
scrollProgressEnd() {
|
||||
return this.scrollProgress + this.maxScrollTop / this.scrollHeight;
|
||||
},
|
||||
|
||||
scrollBottom() {
|
||||
return this.scrollHeight * this.scrollProgressEnd;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleScroll(event) {
|
||||
let { container } = this.$refs;
|
||||
this.scrollTop = container.scrollTop;
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
scrollTop(value, oldValue) {
|
||||
let { container } = this.$refs;
|
||||
if (container && oldValue === 0) {
|
||||
this.scrollHeight = container.scrollHeight;
|
||||
this.height = container.clientHeight;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
template,
|
||||
components: {},
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import my from '/assets/scripts/my.js';
|
||||
import Permalink from '/assets/scripts/tweak/permalink.js';
|
||||
import Permalink from '/assets/scripts/permalink.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -65,6 +65,18 @@ Use the `appearance` attribute to change the badge's visual appearance.
|
||||
</div>
|
||||
```
|
||||
|
||||
### Size
|
||||
|
||||
Badges are sized relative to the current font size. You can set `font-size` on any badge (or an ancestor element) to change it.
|
||||
|
||||
```html {.example}
|
||||
<wa-badge variant="brand" style="font-size: var(--wa-font-size-xs);">Brand</wa-badge>
|
||||
<wa-badge variant="brand" style="font-size: var(--wa-font-size-s);">Brand</wa-badge>
|
||||
<wa-badge variant="brand" style="font-size: var(--wa-font-size-m);">Brand</wa-badge>
|
||||
<wa-badge variant="brand" style="font-size: var(--wa-font-size-l);">Brand</wa-badge>
|
||||
<wa-badge variant="brand" style="font-size: var(--wa-font-size-xl);">Brand</wa-badge>
|
||||
```
|
||||
|
||||
### Pill Badges
|
||||
|
||||
Use the `pill` attribute to give badges rounded edges.
|
||||
|
||||
@@ -6,7 +6,7 @@ icon: card
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-image with-footer class="card-overview">
|
||||
<wa-card 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"
|
||||
@@ -54,7 +54,7 @@ Headers can be used to display titles and more.
|
||||
If using SSR, you need to also use the `with-header` attribute to add a header to the card (if not, it is added automatically).
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-header class="card-header">
|
||||
<wa-card class="card-header">
|
||||
<div slot="header" class="wa-split">
|
||||
Header Title
|
||||
<wa-icon-button name="gear" variant="solid" label="Settings" class="wa-size-m"></wa-icon-button>
|
||||
@@ -80,7 +80,7 @@ Footers can be used to display actions, summaries, or other relevant content.
|
||||
If using SSR, you need to also use the `with-footer` attribute to add a footer to the card (if not, it is added automatically).
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-footer class="card-footer">
|
||||
<wa-card class="card-footer">
|
||||
This card has a footer. You can put all sorts of things in it!
|
||||
|
||||
<div slot="footer" class="wa-split">
|
||||
@@ -102,7 +102,7 @@ Card images are displayed atop the card and will stretch to fit.
|
||||
If using SSR, you need to also use the `with-image` attribute to add an image to the card (if not, it is added automatically).
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-image class="card-image">
|
||||
<wa-card class="card-image">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1547191783-94d5f8f6d8b1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=80"
|
||||
@@ -124,7 +124,7 @@ Use the `size` attribute to change a card's size.
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack">
|
||||
<wa-card with-footer size="small">
|
||||
<wa-card size="small">
|
||||
This is a small card.
|
||||
|
||||
<footer slot="footer" class="wa-split">
|
||||
@@ -133,7 +133,7 @@ Use the `size` attribute to change a card's size.
|
||||
</footer>
|
||||
</wa-card>
|
||||
|
||||
<wa-card with-footer size="medium">
|
||||
<wa-card size="medium">
|
||||
This is a medium card (default).
|
||||
|
||||
<footer slot="footer" class="wa-split">
|
||||
@@ -142,7 +142,7 @@ Use the `size` attribute to change a card's size.
|
||||
</footer>
|
||||
</wa-card>
|
||||
|
||||
<wa-card with-footer size="large">
|
||||
<wa-card size="large">
|
||||
This is a large card.
|
||||
|
||||
<footer slot="footer" class="wa-split">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Component Cheatsheet
|
||||
layout: docs
|
||||
unlisted: true
|
||||
unpublished: true
|
||||
---
|
||||
|
||||
<style>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
title: Code Demo
|
||||
description: Code demos can be used to render code examples as inline live demos.
|
||||
tags: component
|
||||
noAlpha: true
|
||||
isPro: true
|
||||
unpublished: true
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -210,4 +210,4 @@ It goes without saying that this list is a rough plan and subject to change.
|
||||
- Tabbed layout
|
||||
- Provide a way to display CSS and JS separately
|
||||
- Provide a way to customize the playground used (currently it is hardcoded to CodePen)
|
||||
- Provide a way to customize the buttons shown
|
||||
- Provide a way to customize the buttons shown
|
||||
@@ -1,14 +1,16 @@
|
||||
---
|
||||
title: Image Comparer
|
||||
description: Compare visual differences between similar photos with a sliding panel.
|
||||
title: Comparer
|
||||
description: Compare visual differences between similar content with a sliding panel.
|
||||
tags: [imagery, niche]
|
||||
icon: image-comparer
|
||||
icon: comparer
|
||||
---
|
||||
|
||||
For best results, use images that share the same dimensions. The slider can be controlled by dragging or pressing the left and right arrow keys. (Tip: press shift + arrows to move the slider in larger intervals, or home + end to jump to the beginning or end.)
|
||||
This is especially useful for comparing images, but can be used for comparing any type of content (for an example of using it to compare entire UIs, check out our [theme pages](/docs/themes/default/)).
|
||||
For best results, use content that shares the same dimensions.
|
||||
The slider can be controlled by dragging or pressing the left and right arrow keys. (Tip: press shift + arrows to move the slider in larger intervals, or home + end to jump to the beginning or end.)
|
||||
|
||||
```html {.example}
|
||||
<wa-image-comparer>
|
||||
<wa-comparer>
|
||||
<img
|
||||
slot="before"
|
||||
src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&sat=-100&bri=-5"
|
||||
@@ -19,7 +21,7 @@ For best results, use images that share the same dimensions. The slider can be c
|
||||
src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80"
|
||||
alt="Color version of kittens in a basket looking around."
|
||||
/>
|
||||
</wa-image-comparer>
|
||||
</wa-comparer>
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -29,7 +31,7 @@ For best results, use images that share the same dimensions. The slider can be c
|
||||
Use the `position` attribute to set the initial position of the slider. This is a percentage from `0` to `100`.
|
||||
|
||||
```html {.example}
|
||||
<wa-image-comparer position="25">
|
||||
<wa-comparer position="25">
|
||||
<img
|
||||
slot="before"
|
||||
src="https://images.unsplash.com/photo-1520903074185-8eca362b3dce?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1200&q=80"
|
||||
@@ -40,5 +42,5 @@ Use the `position` attribute to set the initial position of the slider. This is
|
||||
src="https://images.unsplash.com/photo-1520640023173-50a135e35804?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2250&q=80"
|
||||
alt="A person sitting on a yellow curb tying shoelaces on a boot."
|
||||
/>
|
||||
</wa-image-comparer>
|
||||
</wa-comparer>
|
||||
```
|
||||
@@ -10,7 +10,7 @@ keywords: modal
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer id="dialog-overview">
|
||||
<wa-dialog label="Dialog" id="dialog-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -27,19 +27,20 @@ keywords: modal
|
||||
|
||||
## Examples
|
||||
|
||||
### Dialog with Header
|
||||
### Dialog without Header
|
||||
|
||||
Headers can be used to display titles and more. Use the `with-header` attribute to add a header to the dialog.
|
||||
Headers are enabled by default. To render a dialog without a header, add the `without-header` attribute.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header class="dialog-header">
|
||||
<wa-dialog label="Dialog" without-header class="dialog-without-header">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
|
||||
<wa-button>Open Dialog</wa-button>
|
||||
|
||||
<script>
|
||||
const dialog = document.querySelector('.dialog-header');
|
||||
const dialog = document.querySelector('.dialog-without-header');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
|
||||
openButton.addEventListener('click', () => dialog.open = true);
|
||||
@@ -48,10 +49,10 @@ Headers can be used to display titles and more. Use the `with-header` attribute
|
||||
|
||||
### Dialog with Footer
|
||||
|
||||
Footers can be used to display titles and more. Use the `with-footer` attribute to add a footer to the dialog.
|
||||
Footers can be used to display titles and more. Use the `footer` slot to add a footer to the dialog.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-footer class="dialog-footer">
|
||||
<wa-dialog label="Dialog" class="dialog-footer">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -71,7 +72,7 @@ Footers can be used to display titles and more. Use the `with-footer` attribute
|
||||
You can add the special `data-dialog="close"` attribute to a button inside the dialog to tell it to close without additional JavaScript. Alternatively, you can set the `open` property to `false` to close the dialog programmatically.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-dismiss">
|
||||
<wa-dialog label="Dialog" class="dialog-dismiss">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -88,10 +89,10 @@ You can add the special `data-dialog="close"` attribute to a button inside the d
|
||||
|
||||
### Custom Width
|
||||
|
||||
Just use the CSS `width` property to set the dialog's width.
|
||||
Just use the `--width` custom property to set the dialog's width.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-width" style="width: 50vw;">
|
||||
<wa-dialog label="Dialog" class="dialog-width" style="--width: 50vw;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -111,7 +112,7 @@ Just use the CSS `width` property to set the dialog's width.
|
||||
By design, a dialog's height will never exceed that of the viewport. As such, dialogs will not scroll with the page ensuring the header and footer are always accessible to the user.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-scrolling">
|
||||
<wa-dialog label="Dialog" class="dialog-scrolling">
|
||||
<div style="height: 150vh; border: dashed 2px var(--wa-color-surface-border); padding: 0 1rem;">
|
||||
<p>Scroll down and give it a try! 👇</p>
|
||||
</div>
|
||||
@@ -133,7 +134,7 @@ By design, a dialog's height will never exceed that of the viewport. As such, di
|
||||
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/docs/components/icon-button) if needed.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-header-actions">
|
||||
<wa-dialog label="Dialog" class="dialog-header-actions">
|
||||
<wa-icon-button class="new-window" slot="header-actions" name="arrow-up-right-from-square" variant="solid"></wa-icon-button>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
@@ -156,7 +157,7 @@ The header shows a functional close button by default. You can use the `header-a
|
||||
If you want the dialog to close when the user clicks on the overlay, add the `light-dismiss` attribute.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" light-dismiss with-header with-footer class="dialog-light-dismiss">
|
||||
<wa-dialog label="Dialog" light-dismiss class="dialog-light-dismiss">
|
||||
This dialog will close when you click on the overlay.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -180,7 +181,7 @@ To keep the dialog open in such cases, you can cancel the `wa-hide` event. When
|
||||
You can use `event.detail.source` to determine which element triggered the request to close. This example prevents the dialog from closing when the overlay is clicked, but allows the close button or [[Escape]] to dismiss it.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-deny-close">
|
||||
<wa-dialog label="Dialog" class="dialog-deny-close">
|
||||
This dialog will only close when you click the button below.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Only this button will close it</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -208,7 +209,7 @@ You can use `event.detail.source` to determine which element triggered the reque
|
||||
To give focus to a specific element when the dialog opens, use the `autofocus` attribute.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-focus">
|
||||
<wa-dialog label="Dialog" class="dialog-focus">
|
||||
<wa-input autofocus placeholder="I will have focus when the dialog is opened"></wa-input>
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
|
||||
@@ -8,7 +8,7 @@ icon: drawer
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-overview">
|
||||
<wa-drawer label="Drawer" id="drawer-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -16,7 +16,7 @@ icon: drawer
|
||||
<wa-button>Open Drawer</wa-button>
|
||||
|
||||
<script>
|
||||
const drawer = document.querySelector('.drawer-overview');
|
||||
const drawer = document.querySelector('#drawer-overview');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
|
||||
openButton.addEventListener('click', () => drawer.open = true);
|
||||
@@ -25,19 +25,20 @@ icon: drawer
|
||||
|
||||
## Examples
|
||||
|
||||
### Drawer with Header
|
||||
### Drawer without Header
|
||||
|
||||
Headers can be used to display titles and more. Use the `with-header` attribute to add a header to the drawer.
|
||||
Headers are enabled by default. To render a drawer without a header, add the `without-header` attribute.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header class="drawer-header">
|
||||
<wa-drawer label="Drawer" without-header class="drawer-without-header">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
|
||||
<wa-button>Open Drawer</wa-button>
|
||||
|
||||
<script>
|
||||
const drawer = document.querySelector('.drawer-header');
|
||||
const drawer = document.querySelector('.drawer-without-header');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
|
||||
openButton.addEventListener('click', () => drawer.open = true);
|
||||
@@ -46,10 +47,10 @@ Headers can be used to display titles and more. Use the `with-header` attribute
|
||||
|
||||
### Drawer with Footer
|
||||
|
||||
Footers can be used to display titles and more. Use the `with-footer` attribute to add a footer to the drawer.
|
||||
Footers can be used to display titles and more. Use the `footer` slot to add a footer to the drawer.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-footer class="drawer-footer">
|
||||
<wa-drawer label="Drawer" class="drawer-footer">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -69,7 +70,7 @@ Footers can be used to display titles and more. Use the `with-footer` attribute
|
||||
You can add the special `data-drawer="close"` attribute to a button inside the drawer to tell it to close without additional JavaScript. Alternatively, you can set the `open` property to `false` to close the drawer programmatically.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-dismiss">
|
||||
<wa-drawer label="Drawer" class="drawer-dismiss">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -89,7 +90,7 @@ You can add the special `data-drawer="close"` attribute to a button inside the d
|
||||
By default, drawers slide in from the end. To make the drawer slide in from the start, set the `placement` attribute to `start`.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer placement="start" class="drawer-placement-start">
|
||||
<wa-drawer label="Drawer" placement="start" class="drawer-placement-start">
|
||||
This drawer slides in from the start.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -109,7 +110,7 @@ By default, drawers slide in from the end. To make the drawer slide in from the
|
||||
To make the drawer slide in from the top, set the `placement` attribute to `top`.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer placement="top" class="drawer-placement-top">
|
||||
<wa-drawer label="Drawer" placement="top" class="drawer-placement-top">
|
||||
This drawer slides in from the top.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -129,7 +130,7 @@ To make the drawer slide in from the top, set the `placement` attribute to `top`
|
||||
To make the drawer slide in from the bottom, set the `placement` attribute to `bottom`.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer placement="bottom" class="drawer-placement-bottom">
|
||||
<wa-drawer label="Drawer" placement="bottom" class="drawer-placement-bottom">
|
||||
This drawer slides in from the bottom.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -149,7 +150,7 @@ To make the drawer slide in from the bottom, set the `placement` attribute to `b
|
||||
Use the `--size` custom property to set the drawer's size. This will be applied to the drawer's width or height depending on its `placement`.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-custom-size" style="--size: 50vw;">
|
||||
<wa-drawer label="Drawer" class="drawer-custom-size" style="--size: 50vw;">
|
||||
This drawer is always 50% of the viewport.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -169,7 +170,7 @@ Use the `--size` custom property to set the drawer's size. This will be applied
|
||||
By design, a drawer's height will never exceed 100% of its container. As such, drawers will not scroll with the page to ensure the header and footer are always accessible to the user.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-scrolling">
|
||||
<wa-drawer label="Drawer" class="drawer-scrolling">
|
||||
<div style="height: 150vh; border: dashed 2px var(--wa-color-surface-border); padding: 0 1rem;">
|
||||
<p>Scroll down and give it a try! 👇</p>
|
||||
</div>
|
||||
@@ -191,7 +192,7 @@ By design, a drawer's height will never exceed 100% of its container. As such, d
|
||||
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/docs/components/icon-button) if needed.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-header-actions">
|
||||
<wa-drawer label="Drawer" class="drawer-header-actions">
|
||||
<wa-icon-button class="new-window" slot="header-actions" name="arrow-up-right-from-square" variant="solid"></wa-icon-button>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
@@ -214,7 +215,7 @@ The header shows a functional close button by default. You can use the `header-a
|
||||
If you want the drawer to close when the user clicks on the overlay, add the `light-dismiss` attribute.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" light-dismiss with-header with-footer class="drawer-light-dismiss">
|
||||
<wa-drawer label="Drawer" light-dismiss class="drawer-light-dismiss">
|
||||
This drawer will close when you click on the overlay.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -238,7 +239,7 @@ To keep the drawer open in such cases, you can cancel the `wa-hide` event. When
|
||||
You can use `event.detail.source` to determine what triggered the request to close. This example prevents the drawer from closing when the overlay is clicked, but allows the close button or [[Escape]] to dismiss it.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-deny-close">
|
||||
<wa-drawer label="Drawer" class="drawer-deny-close">
|
||||
This drawer will only close when you click the button below.
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -261,12 +262,12 @@ You can use `event.detail.source` to determine what triggered the request to clo
|
||||
</script>
|
||||
```
|
||||
|
||||
### Customizing Initial Focus
|
||||
### Setting Initial Focus
|
||||
|
||||
By default, the drawer's panel will gain focus when opened. This allows a subsequent tab press to focus on the first tabbable element in the drawer. If you want a different element to have focus, add the `autofocus` attribute to it as shown below.
|
||||
To give focus to a specific element when the drawer opens, use the `autofocus` attribute.
|
||||
|
||||
```html {.example}
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-focus">
|
||||
<wa-drawer label="Drawer" class="drawer-focus">
|
||||
<wa-input autofocus placeholder="I will have focus when the drawer is opened"></wa-input>
|
||||
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
|
||||
</wa-drawer>
|
||||
|
||||
@@ -17,11 +17,14 @@ Not sure which icon to use? [Find the perfect icon over at Font Awesome!](https:
|
||||
|
||||
The default icon library is Font Awesome Free, which comes with two icon families: `classic` and `brands`. Use the `family` attribute to set the icon family.
|
||||
|
||||
Many Font Awesome Pro icon families have variants such as `thin`, `light`, `regular`, and `solid`. Font Awesome Pro users can [provide their kit code](/docs/#using-font-awesome-kit-codes) to unlock additional families, including `sharp` and `duotone`. For these icon families, use the `variant` attribute to set the variant.
|
||||
Many Font Awesome Pro icon families have variants such as `thin`, `light`, `regular`, and `solid`. Font Awesome Pro users can [provide their kit code](/docs/#using-font-awesome-kit-codes) to unlock additional families, including `sharp`, `duotone`, and `sharp-duotone`. For these icon families, use the `variant` attribute to set the variant.
|
||||
|
||||
```html {.example}
|
||||
<wa-icon family="brands" name="font-awesome"></wa-icon>
|
||||
<wa-icon family="brands" name="web-awesome"></wa-icon>
|
||||
<wa-icon family="brands" name="font-awesome"></wa-icon>
|
||||
<wa-icon family="brands" name="web-awesome"></wa-icon>
|
||||
<wa-icon family="classic" variant="light" name="sparkles"></wa-icon>
|
||||
<wa-icon family="sharp" variant="solid" name="fire"></wa-icon>
|
||||
<wa-icon family="duotone" variant="regular" name="cake-slice"></wa-icon>
|
||||
```
|
||||
|
||||
### Setting defaults via CSS
|
||||
|
||||
@@ -176,7 +176,7 @@ eleventyExcludeFromCollections: true
|
||||
</footer>
|
||||
<aside slot="aside">
|
||||
<h2 class="wa-heading-m">Discover More Birds</h2>
|
||||
<wa-card with-image>
|
||||
<wa-card>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1635254859323-65b78408dcca?q=20" alt="" />
|
||||
</div>
|
||||
@@ -185,7 +185,7 @@ eleventyExcludeFromCollections: true
|
||||
<span class="wa-caption-s" lang="la"><em>Asio otus</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-image>
|
||||
<wa-card>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1661350356618-f5915c7b6a3c?q=20" alt="" />
|
||||
</div>
|
||||
@@ -194,7 +194,7 @@ eleventyExcludeFromCollections: true
|
||||
<span class="wa-caption-s" lang="la"><em>Surnia ulula</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-image>
|
||||
<wa-card>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1660307777355-f08bced145d3?q=20" alt="" />
|
||||
</div>
|
||||
|
||||
@@ -168,7 +168,7 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
|
||||
</footer>
|
||||
<aside slot="aside" class="wa-desktop-only">
|
||||
<h2 class="wa-heading-m">Discover More Birds</h2>
|
||||
<wa-card with-image>
|
||||
<wa-card>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1635254859323-65b78408dcca?q=20" alt="" />
|
||||
</div>
|
||||
@@ -177,7 +177,7 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
|
||||
<span class="wa-caption-s" lang="la"><em>Asio otus</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-image>
|
||||
<wa-card>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1661350356618-f5915c7b6a3c?q=20" alt="" />
|
||||
</div>
|
||||
@@ -186,7 +186,7 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
|
||||
<span class="wa-caption-s" lang="la"><em>Surnia ulula</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-image>
|
||||
<wa-card>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1660307777355-f08bced145d3?q=20" alt="" />
|
||||
</div>
|
||||
|
||||
151
docs/docs/components/scroller.md
Normal file
151
docs/docs/components/scroller.md
Normal file
@@ -0,0 +1,151 @@
|
||||
---
|
||||
title: Scroller
|
||||
description: Scrollers create an accessible container while providing visual cues that help users identify and navigate through content that scrolls.
|
||||
layout: component
|
||||
tags: [organization]
|
||||
icon: scroller
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
<wa-scroller id="scroller__overview">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Party Role</th>
|
||||
<th>Combat Style</th>
|
||||
<th>Group Size</th>
|
||||
<th>Campaign Setting</th>
|
||||
<th>Signature Traits</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Warrior</td>
|
||||
<td>Melee Tank</td>
|
||||
<td>1-2</td>
|
||||
<td>Forgotten Realms</td>
|
||||
<td>Plate-armored swordmaster who taunts foes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rogue</td>
|
||||
<td>Stealth Striker</td>
|
||||
<td>1</td>
|
||||
<td>Eberron</td>
|
||||
<td>Shadowy lockpick with daggers and a secret gold stash.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Wizard</td>
|
||||
<td>Spell Slinger</td>
|
||||
<td>1</td>
|
||||
<td>Greyhawk</td>
|
||||
<td>Robe-clad mage hurling fireballs from a messy spellbook.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cleric</td>
|
||||
<td>Divine Support</td>
|
||||
<td>1</td>
|
||||
<td>Ravnica</td>
|
||||
<td>Holy healer with a glowing amulet and sneaky ale habit.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bard</td>
|
||||
<td>Charisma King</td>
|
||||
<td>1</td>
|
||||
<td>Dragonlance</td>
|
||||
<td>Lute-playing charmer with magical songs and bad puns.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</wa-scroller>
|
||||
|
||||
<style>
|
||||
#scroller__overview {
|
||||
table {
|
||||
margin-block: 0;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
th:nth-child(5),
|
||||
td:nth-child(5) {
|
||||
min-width: 50ch;
|
||||
white-space: wrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Adding Content
|
||||
|
||||
The scroller component automatically provides a scrollable container for any content that exceeds the available space. Simply add your content as children of the `<wa-scroller>` element, and it will handle the rest.
|
||||
|
||||
```html {.example}
|
||||
<wa-scroller>
|
||||
<div style="width: 1200px; padding: 1rem;">
|
||||
<h3>Superhero Team Roles Guide</h3>
|
||||
<div class="wa-grid" style="--wa-grid-columns: 4; --wa-grid-gap: var(--wa-spacing-l);">
|
||||
<div>
|
||||
<h4>Team Leaders</h4>
|
||||
<p>Charismatic captains like Captain America or Cyclops are the heart of any superteam, rallying everyone with epic speeches and killer strategies. They’re the ones calling the shots in a cosmic showdown, keeping the squad focused when Thanos or Magneto crashes the party.</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Heavy Hitters</h4>
|
||||
<p>Powerhouses like Thor or Hulk bring the boom, smashing through villain lairs or alien armadas. Their job is to land the big punches, but they gotta pace themselves to avoid stealing the spotlight from sneakier teammates.</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Tech Geniuses</h4>
|
||||
<p>Brainiacs like Iron Man or Mr. Fantastic keep the team one step ahead with gadgets and gizmos. They’re crafting quinjets or hacking evil AI, always ready with a snarky quip while saving the day from a computer terminal.</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Stealth Specialists</h4>
|
||||
<p>Ninja-like heroes like Black Widow or Nightcrawler slip through the shadows, gathering intel or pulling off surprise attacks. They’re the glue that makes risky plans work, coordinating with the team to flip a losing fight into a win.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</wa-scroller>
|
||||
```
|
||||
|
||||
### Orientation
|
||||
|
||||
Set the `orientation` attribute to `vertical` and provide a height to create a vertical scroller.
|
||||
|
||||
```html {.example}
|
||||
<wa-scroller orientation="vertical" style="max-height: 300px;">
|
||||
<p>Superhero movies are the ultimate popcorn-fueled thrill rides, turning comic book pages into cinematic rollercoasters. Back in the early 2000s, films like X-Men and Spider-Man kicked open the door, proving tights and teamwork could pack theaters. Those early flicks leaned on practical effects and heart—like Tobey Maguire’s earnest web-slinger saving a train—making us believe a guy in spandex could be a hero. They weren’t perfect, but they set the stage for the genre to become a cultural juggernaut.</p>
|
||||
<p>By the 2010s, the Marvel Cinematic Universe turned superhero films into a shared saga, like a comic crossover event on steroids. The Avengers in 2012 was a game-changer, tossing Iron Man’s snark, Thor’s hammer, and Cap’s shield into one epic brawl. Directors learned to balance humor, heart, and explosions, while studios figured out how to make every movie feel like a chapter in a bigger story. Even standalone hits like Wonder Woman brought fresh vibes, with Gal Gadot’s lasso-wielding warrior stealing hearts and smashing box office records.</p>
|
||||
<p>Today, superhero flicks are a global obsession, from Deadpool’s chimichanga-fueled chaos to Black Panther’s Wakandan pride. They’re not just about powers—they’re about characters we root for, like Rocket Raccoon’s scrappy loyalty or Harley Quinn’s wild energy. Fans dissect trailers like detectives, theorizing about multiverses and cameos, while memes of sad Affleck or dancing Groot flood the internet. Whether it’s a gritty Joker origin or a cosmic Guardians adventure, these movies keep us glued to our seats, dreaming of heroism and one-liners that’d make even Tony Stark jealous.</p>
|
||||
</wa-scroller>
|
||||
```
|
||||
|
||||
### Without a Shadow
|
||||
|
||||
Use the `without-shadow` attribute to remove the fading shadow effect at the edges of the scroller, which typically indicates more content is available.
|
||||
|
||||
```html {.example}
|
||||
<wa-scroller without-shadow>
|
||||
<div style="width: 1500px;">
|
||||
<p>Gaming consoles are like time machines for nerds, zapping us from pixelated 2D adventures to jaw-dropping cinematic worlds. Back in the ‘90s, the Super Nintendo was the cool kid on the block, using a 16-bit chip to pull off tricks like Mode 7, which made Mario Kart’s tracks feel like they were zooming right at you. It was like wizardry for a kid with a chunky controller, turning flat sprites into pseudo-3D races that had us yelling at our TVs when we got hit by a red shell.</p>
|
||||
<p>Fast-forward to today, and consoles like the PlayStation 5 and Xbox Series X are basically supercomputers in sleek boxes. They’re packing enough power to make games look like Hollywood blockbusters, with lighting so real you can practically feel the sun glare in Spider-Man: Miles Morales. These machines can handle massive open worlds, like the sprawling lands of Elden Ring, without breaking a sweat, letting you swing swords or race cars while your living room feels like a sci-fi movie set. It’s a far cry from the SNES days, but the vibe’s the same: pure, controller-gripping fun.</p>
|
||||
<p>What makes consoles the heart of gaming culture is how they bring everyone together, from casual players to hardcore speedrunners. Whether it’s your uncle fumbling through Super Mario World in ‘92 or your best friend screaming during a late-night Call of Duty match, consoles are the ultimate couch co-op machines. Modern systems even let you stream your clutch Fortnite wins to the world or jump into crossplay with PC pals. From the GameCube’s quirky handle to the Switch’s grab-and-go joy-cons, every console’s got its own personality, making every era of gaming feel like a legendary chapter in a never-ending quest.</p>
|
||||
</div>
|
||||
</wa-scroller>
|
||||
```
|
||||
|
||||
### Without a Scrollbar
|
||||
|
||||
Use the `without-scrollbar` attribute to hide the scrollbar while maintaining scroll functionality. This creates a cleaner visual appearance but may reduce usability on content that needs a clear scrolling indicator.
|
||||
|
||||
```html {.example}
|
||||
<wa-scroller without-scrollbar>
|
||||
<div style="width: 1500px;">
|
||||
<p>Dungeons & Dragons 5e is the blockbuster superhero flick of tabletop RPGs, turning every session into an epic tavern brawl or dragon-slaying saga. Unlike the old 3.5e days, where you’d stack +30 bonuses like a mathlete on a mission, 5e keeps things chill with skill checks capping around +11—like a +5 from your slick Charisma and +6 from being a pro at persuasion. This means even a squad of scrappy kobolds can give your level 10 barbarian a bad day if you roll poorly. It’s like the game’s saying, “Sure, you’re a hero, but don’t get cocky!”</p>
|
||||
<p>The advantage and disadvantage system is 5e’s secret sauce, making every dice roll feel like a movie cliffhanger. Instead of juggling a dozen modifiers, you just roll two d20s and take the better (or worse) one, which shakes out to about a +5 or -5 vibe shift. It’s like your rogue’s got a lucky charm when sneaking past guards or a cursed boot when dodging a fireball. This keeps the game’s flow snappy, so you’re not stuck crunching numbers when you could be roleplaying a dramatic speech to charm a dragon or bluffing your way out of a bandit ambush.</p>
|
||||
<p>5e’s world is built for storytelling, not just stat sheets, and that’s why it’s the king of game nights. The rules are flexible enough for your DM to whip up a haunted forest crawl or a pirate ship heist without needing a PhD in game design. Classes like the warlock let you make shady pacts with cosmic entities, while feats like Tavern Brawler turn your monk into a bar-fighting legend who can knock out goblins with a chair. Whether you’re a newbie rolling your first d20 or a veteran plotting a castle siege, 5e’s vibe is all about epic moments—like when your party’s wizard crits on a fireball and you all cheer like you just won the Super Bowl.</p>
|
||||
</div>
|
||||
</wa-scroller>
|
||||
```
|
||||
|
||||
:::warning
|
||||
Hiding scrollbars can negatively impact accessibility. Users who rely on visible scrollbars to navigate content may have difficulty recognizing that content is scrollable or controlling their scrolling position. Consider the needs of all users when implementing this option.
|
||||
:::
|
||||
@@ -129,7 +129,7 @@ Set a matching width and height to make a circle, square, or rounded avatar skel
|
||||
|
||||
<style>
|
||||
.skeleton-avatars wa-skeleton {
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
margin-right: 0.5rem;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
title: Viewport Demo
|
||||
description: Viewport demos can be used to display an iframe as a resizable, zoomable preview.
|
||||
tags: component
|
||||
noAlpha: true
|
||||
isPro: true
|
||||
unpublished: true
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -68,4 +68,4 @@ It goes without saying that this list is a rough plan and subject to change.
|
||||
- Non-linear zoom scale
|
||||
- Extend to general content, not just iframes
|
||||
- Styles for mobile and tablet frames and an attribute to switch between them
|
||||
- Automatic iframe height
|
||||
- Automatic iframe height
|
||||
@@ -501,13 +501,13 @@ hasOutline: false
|
||||
</div>
|
||||
<wa-select name="theme" label="Pick a theme to start!" value="default">
|
||||
<wa-option value="default">Default</wa-option>
|
||||
<wa-option data-alpha="remove" value="awesome">Awesome</wa-option>
|
||||
<wa-option data-alpha="remove" value="premium">Premium</wa-option>
|
||||
<wa-option data-alpha="remove" value="playful">Playful</wa-option>
|
||||
<wa-option data-alpha="remove" value="brutalist">Brutalist</wa-option>
|
||||
<wa-option data-alpha="remove" value="tailspin">Tailspin</wa-option>
|
||||
<wa-option data-alpha="remove" value="glossy">Glossy</wa-option>
|
||||
<wa-option data-alpha="remove" value="active">Active</wa-option>
|
||||
<wa-option value="awesome">Awesome</wa-option>
|
||||
<wa-option value="premium">Premium</wa-option>
|
||||
<wa-option value="playful">Playful</wa-option>
|
||||
<wa-option value="brutalist">Brutalist</wa-option>
|
||||
<wa-option value="tailspin">Tailspin</wa-option>
|
||||
<wa-option value="glossy">Glossy</wa-option>
|
||||
<wa-option value="active">Active</wa-option>
|
||||
<wa-option value="classic">Classic</wa-option>
|
||||
</wa-select>
|
||||
</div>
|
||||
@@ -667,7 +667,7 @@ hasOutline: false
|
||||
</wa-details>
|
||||
</form>
|
||||
|
||||
<wa-dialog id="icon-chooser" label="Browse Icons" with-header>
|
||||
<wa-dialog id="icon-chooser" label="Browse Icons">
|
||||
<div style="display: grid; grid-template-rows: minmax(0, auto) minmax(0, 1fr); height: 100%; gap: 1rem;">
|
||||
<div style="display: flex; gap: 1.25rem;">
|
||||
<wa-input name="icon-search" autofocus placeholder="Search Icons" clearable style="flex: 1 1 auto;">
|
||||
@@ -2139,7 +2139,7 @@ hasOutline: false
|
||||
</div>
|
||||
</section>
|
||||
<section class="strata message-composer">
|
||||
<wa-card with-header with-footer class="card-header card-footer">
|
||||
<wa-card class="card-header card-footer">
|
||||
<div slot="header">
|
||||
<div class="grouped-buttons">
|
||||
<wa-icon-button id="bold" name="bold" label="Bold"></wa-icon-button>
|
||||
|
||||
@@ -4,7 +4,6 @@ description: Callouts are used to display important messages inline.
|
||||
component: callout
|
||||
icon: callout
|
||||
snippets: '.wa-callout'
|
||||
noAlpha: true
|
||||
file: styles/native/callout.css
|
||||
---
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ file: styles/native/radio.css
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-cluster">
|
||||
<label><input type="radio" name="radio" value="1"> Option 1</label>
|
||||
<label><input type="radio" name="radio" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="a" value="1" checked> Option 1</label>
|
||||
<label><input type="radio" name="a" value="2"> Option 2</label>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -24,9 +24,9 @@ To set the initial value and checked state, use the `checked` attribute on the c
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-cluster">
|
||||
<label><input type="radio" name="radio" value="1"> Option 1</label>
|
||||
<label><input type="radio" name="radio" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="radio" value="3" checked> Option 3</label>
|
||||
<label><input type="radio" name="b" value="1" checked> Option 1</label>
|
||||
<label><input type="radio" name="b" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="b" value="3"> Option 3</label>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -36,9 +36,9 @@ Use the `disabled` attribute to disable a radio.
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-cluster">
|
||||
<label><input type="radio" name="radio" value="1"> Option 1</label>
|
||||
<label><input type="radio" name="radio" value="2" disabled> Option 2</label>
|
||||
<label><input type="radio" name="radio" value="3"> Option 3</label>
|
||||
<label><input type="radio" name="c" value="1" checked> Option 1</label>
|
||||
<label><input type="radio" name="c" value="2" disabled> Option 2</label>
|
||||
<label><input type="radio" name="c" value="3"> Option 3</label>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -49,26 +49,26 @@ Use the [size utilities](/docs/utilities/size) to change the radios' size.
|
||||
```html {.example}
|
||||
<fieldset class="wa-size-s wa-cluster">
|
||||
<legend>Small</legend>
|
||||
<label><input type="radio" name="radio" value="1"> Option 1</label>
|
||||
<label><input type="radio" name="radio" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="radio" value="3"> Option 3</label>
|
||||
<label><input type="radio" name="d" value="1" checked> Option 1</label>
|
||||
<label><input type="radio" name="d" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="d" value="3"> Option 3</label>
|
||||
</fieldset>
|
||||
|
||||
<br />
|
||||
<fieldset class="wa-size-m wa-cluster">
|
||||
<legend>Medium</legend>
|
||||
<label><input type="radio" name="radio" value="1"> Option 1</label>
|
||||
<label><input type="radio" name="radio" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="radio" value="3"> Option 3</label>
|
||||
<label><input type="radio" name="e" value="1" checked> Option 1</label>
|
||||
<label><input type="radio" name="e" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="e" value="3"> Option 3</label>
|
||||
</fieldset>
|
||||
|
||||
<br />
|
||||
|
||||
<fieldset class="wa-size-l wa-cluster">
|
||||
<legend>Large</legend>
|
||||
<label><input type="radio" name="radio" value="1"> Option 1</label>
|
||||
<label><input type="radio" name="radio" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="radio" value="3"> Option 3</label>
|
||||
<label><input type="radio" name="f" value="1" checked> Option 1</label>
|
||||
<label><input type="radio" name="f" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="f" value="3"> Option 3</label>
|
||||
</fieldset>
|
||||
```
|
||||
|
||||
@@ -78,16 +78,16 @@ You can wrap native radios in a flex container to give them a horizontal or vert
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-cluster">
|
||||
<label><input type="radio" name="radio" value="1"> Option 1</label>
|
||||
<label><input type="radio" name="radio" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="radio" value="3" checked> Option 3</label>
|
||||
<label><input type="radio" name="g" value="1" checked> Option 1</label>
|
||||
<label><input type="radio" name="g" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="g" value="3"> Option 3</label>
|
||||
</div>
|
||||
```
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack">
|
||||
<label><input type="radio" name="radio" value="1"> Option 1</label>
|
||||
<label><input type="radio" name="radio" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="radio" value="3" checked> Option 3</label>
|
||||
<label><input type="radio" name="h" value="1" checked> Option 1</label>
|
||||
<label><input type="radio" name="h" value="2"> Option 2</label>
|
||||
<label><input type="radio" name="h" value="3"> Option 3</label>
|
||||
</div>
|
||||
```
|
||||
|
||||
32
docs/docs/palettes/data.js.njk
Normal file
32
docs/docs/palettes/data.js.njk
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
layout: null
|
||||
permalink: '/docs/palettes/data.js'
|
||||
eleventyExcludeFromCollections: true
|
||||
---
|
||||
export default {
|
||||
{%- for palette in collections.palette | sort %}
|
||||
{%- if not palette.data.unlisted %}
|
||||
{% set paletteId = palette.fileSlug -%}
|
||||
{%- set colors = palettes[paletteId] -%}
|
||||
'{{ paletteId }}': {
|
||||
id: '{{ paletteId }}',
|
||||
title: '{{ palette.data.title }}',
|
||||
colors: {
|
||||
{% for hue, tints in colors -%}
|
||||
'{{ hue }}': {
|
||||
{% for tint, value in tints -%}
|
||||
{%- if tint != '05' -%}
|
||||
'{{ '05' if tint == '5' else tint }}': '{{ value | safe }}',
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
|
||||
get key() {
|
||||
return this[this.maxChromaTint];
|
||||
}
|
||||
},
|
||||
{% endfor -%} // end colors
|
||||
}
|
||||
}, // end palette
|
||||
{%- endif -%}
|
||||
{% endfor %}
|
||||
};
|
||||
@@ -1,6 +1,4 @@
|
||||
:root {
|
||||
--fa-sliders-simple: '\f1de';
|
||||
}
|
||||
@import url('/assets/styles/ui.css');
|
||||
|
||||
.core-column {
|
||||
position: relative;
|
||||
@@ -86,17 +84,6 @@ wa-dropdown > .color.swatch {
|
||||
margin-top: var(--wa-space-m);
|
||||
}
|
||||
|
||||
.popup {
|
||||
background: var(--wa-color-surface-default);
|
||||
border: 1px solid var(--wa-color-surface-border);
|
||||
padding: var(--wa-space-xl);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
|
||||
code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.color-scale {
|
||||
th {
|
||||
white-space: nowrap;
|
||||
@@ -182,24 +169,3 @@ wa-dropdown > .color.swatch {
|
||||
[v-if^='tweaked'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.core-color {
|
||||
wa-radio-button::part(base) {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
padding: 0;
|
||||
border-radius: var(--wa-border-radius-circle);
|
||||
background: var(--color);
|
||||
background-clip: border-box;
|
||||
}
|
||||
|
||||
wa-radio-button:is([checked], :state(checked))::part(base) {
|
||||
box-shadow:
|
||||
inset 0 0 0 var(--indicator-width) var(--indicator-color),
|
||||
inset 0 0 0 calc(var(--indicator-width) + 1.5px) var(--wa-color-surface-default);
|
||||
}
|
||||
|
||||
&::part(form-control-input) {
|
||||
gap: var(--wa-space-xs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
// TODO move these to local imports
|
||||
import Color from 'https://colorjs.io/dist/color.js';
|
||||
import { createApp, nextTick } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
|
||||
import { cdnUrl, hueRanges, hues, Permalink, tints } from '../../assets/scripts/tweak.js';
|
||||
import { maxGrayChroma, moreHue, selectors, themeConfig } from '../../assets/data/index.js';
|
||||
import { cdnUrl, hueRanges, hues, tints } from '../../assets/scripts/tweak.js';
|
||||
import { cssImport, cssLiteral, cssRule } from '../../assets/scripts/tweak/code.js';
|
||||
import { maxGrayChroma, moreHue, selectors, urls } from '../../assets/scripts/tweak/data.js';
|
||||
import { subtractAngles } from '../../assets/scripts/tweak/util.js';
|
||||
import Prism from '/assets/scripts/prism.js';
|
||||
import content from '/assets/scripts/vue/directives/content.js';
|
||||
import savedMixin from '/assets/scripts/vue/mixins/saved.js';
|
||||
import { SwatchSelect } from '/assets/vue/components/index.js';
|
||||
import content from '/assets/vue/directives/content.js';
|
||||
import savedMixin from '/assets/vue/mixins/saved.js';
|
||||
|
||||
await Promise.all(['wa-slider'].map(tag => customElements.whenDefined(tag)));
|
||||
|
||||
@@ -64,7 +65,7 @@ let paletteAppSpec = {
|
||||
|
||||
created() {
|
||||
// Non-reactive variables to expose
|
||||
Object.assign(this, { moreHue });
|
||||
Object.assign(this, { moreHue, hues });
|
||||
|
||||
this.grayChroma = this.originalGrayChroma;
|
||||
this.grayColor = this.originalGrayColor;
|
||||
@@ -121,7 +122,11 @@ let paletteAppSpec = {
|
||||
code() {
|
||||
let ret = {};
|
||||
for (let language of ['html', 'css']) {
|
||||
let code = getPaletteCode(this.id, this.colors, this.tweaked, { language, cdnUrl });
|
||||
let code = getPaletteCode(this.id, this.colors, this.tweaked, {
|
||||
language,
|
||||
cdnUrl,
|
||||
attributes: ' class="wa-palette',
|
||||
});
|
||||
ret[language] = {
|
||||
raw: code,
|
||||
highlighted: Prism.highlight(code, Prism.languages[language], language),
|
||||
@@ -345,6 +350,10 @@ let paletteAppSpec = {
|
||||
content,
|
||||
},
|
||||
|
||||
components: {
|
||||
SwatchSelect,
|
||||
},
|
||||
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('wa-'),
|
||||
},
|
||||
@@ -368,7 +377,7 @@ export function getPaletteCode(paletteId, colors, tweaked, options) {
|
||||
let imports = [];
|
||||
|
||||
if (paletteId) {
|
||||
imports.push(urls.palette(paletteId));
|
||||
imports.push(themeConfig.palette.url(paletteId));
|
||||
}
|
||||
|
||||
let css = '';
|
||||
|
||||
@@ -40,7 +40,10 @@ isPro: true
|
||||
<h3 id="auto-renew-label" class="wa-heading-m">Auto-renew</h3>
|
||||
<wa-switch size="large" aria-labelledby="auto-renew-label"></wa-switch>
|
||||
</div>
|
||||
<p class="wa-body-s">Automatically renew your subscription using your preferred payment method. We'll send you a reminder 30 days before we draft your account.</p>
|
||||
<p class="wa-body-s">
|
||||
Automatically renew your subscription using your preferred payment method. We'll send you a reminder 30 days
|
||||
before we draft your account.
|
||||
</p>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
@@ -50,7 +53,10 @@ isPro: true
|
||||
```html {.example}
|
||||
<wa-card style="margin: 0 auto; max-width: 45ch;">
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1532202802379-df93d543bac3?q=80&w=2574&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile-image"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1532202802379-df93d543bac3?q=80&w=2574&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile-image"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-heading-s">Super Dog</span>
|
||||
@@ -67,4 +73,4 @@ isPro: true
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Activity Log
|
||||
description: 'Track and organize recent user actions or events.'
|
||||
|
||||
---
|
||||
|
||||
## Simple
|
||||
@@ -107,9 +106,7 @@ description: 'Track and organize recent user actions or events.'
|
||||
<h3 class="wa-heading-m">Monthly Activity</h3>
|
||||
<div class="wa-stack">
|
||||
<wa-details>
|
||||
<span class="wa-heading-m" slot="summary">
|
||||
February
|
||||
</span>
|
||||
<span class="wa-heading-m" slot="summary"> February </span>
|
||||
<div class="wa-stack">
|
||||
<article class="wa-flank">
|
||||
<wa-icon style="font-size: var(--wa-font-size-l)" name="envelope" fixed-width></wa-icon>
|
||||
@@ -129,9 +126,7 @@ description: 'Track and organize recent user actions or events.'
|
||||
<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 class="wa-cluster wa-gap-2xs"><a href="#">Artur Fleck</a><span>for 1 hour</span></div>
|
||||
</div>
|
||||
<wa-format-date date="2025-02-23" month="short" day="numeric" class="wa-caption-m"></wa-format-date>
|
||||
</div>
|
||||
@@ -139,18 +134,14 @@ description: 'Track and organize recent user actions or events.'
|
||||
</div>
|
||||
</wa-details>
|
||||
<wa-details>
|
||||
<span class="wa-heading-m" slot="summary">
|
||||
March
|
||||
</span>
|
||||
<span class="wa-heading-m" slot="summary"> March </span>
|
||||
<div class="wa-stack">
|
||||
<article class="wa-flank">
|
||||
<wa-icon style="font-size: var(--wa-font-size-l)" name="video" fixed-width></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 class="wa-cluster wa-gap-2xs"><a href="#">Axel Foley</a><span>for 47 minutes</span></div>
|
||||
</div>
|
||||
<wa-format-date date="2025-03-15" month="short" day="numeric" class="wa-caption-m"></wa-format-date>
|
||||
</div>
|
||||
@@ -171,18 +162,14 @@ description: 'Track and organize recent user actions or events.'
|
||||
</div>
|
||||
</wa-details>
|
||||
<wa-details>
|
||||
<span class="wa-heading-m" slot="summary">
|
||||
April
|
||||
</span>
|
||||
<span class="wa-heading-m" slot="summary"> April </span>
|
||||
<div class="wa-stack">
|
||||
<article class="wa-flank">
|
||||
<wa-icon style="font-size: var(--wa-font-size-l)" family="brands" name="intercom" fixed-width></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 class="wa-cluster wa-gap-2xs"><a href="#">Jack Carter</a><span>on Intercom switchboard</span></div>
|
||||
</div>
|
||||
<wa-format-date date="2025-04-18" month="short" day="numeric" class="wa-caption-m"></wa-format-date>
|
||||
</div>
|
||||
@@ -205,13 +192,18 @@ description: 'Track and organize recent user actions or events.'
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
|
||||
## Card Separated
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack" style="max-width: 45ch; margin: 0 auto;">
|
||||
<div class="wa-stack">
|
||||
<wa-card>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile image"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<div class="wa-split">
|
||||
<span class="wa-heading-s">Isaiah Hamilton</span>
|
||||
@@ -228,47 +220,53 @@ description: 'Track and organize recent user actions or events.'
|
||||
<div class="wa-flank wa-gap-xl">
|
||||
<wa-divider vertical style="height: auto; align-self: stretch"></wa-divider>
|
||||
<ul class="wa-stack">
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<wa-card>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1645288059073-af3e9eb62a29?q=80&w=2936&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile image"></wa-avatar>
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<div class="wa-split">
|
||||
<span class="wa-heading-s">Melvin Hurst</span>
|
||||
<wa-relative-time class="wa-caption-s" date="2025-02-15T09:17:00-04:00"></wa-relative-time>
|
||||
</div>
|
||||
<p>What's on second?</p>
|
||||
<a href="#" class="wa-cluster wa-gap-2xs">
|
||||
<wa-icon name="reply" family="sharp" variant="regular"></wa-icon>
|
||||
<span>Reply</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
</li>
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<wa-card>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1674044494331-8db2ecf18d46?q=80&w=3019&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile image"></wa-avatar>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-split">
|
||||
<span class="wa-heading-s">Vanessa Wright</span>
|
||||
</div>
|
||||
<wa-textarea size="small" aria-label="Add Your Comment"></wa-textarea>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
</li>
|
||||
</ul>
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<wa-card>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1645288059073-af3e9eb62a29?q=80&w=2936&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<div class="wa-split">
|
||||
<span class="wa-heading-s">Melvin Hurst</span>
|
||||
<wa-relative-time class="wa-caption-s" date="2025-02-15T09:17:00-04:00"></wa-relative-time>
|
||||
</div>
|
||||
<p>What's on second?</p>
|
||||
<a href="#" class="wa-cluster wa-gap-2xs">
|
||||
<wa-icon name="reply" family="sharp" variant="regular"></wa-icon>
|
||||
<span>Reply</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
</li>
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<wa-card>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1674044494331-8db2ecf18d46?q=80&w=3019&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-split">
|
||||
<span class="wa-heading-s">Vanessa Wright</span>
|
||||
</div>
|
||||
<wa-textarea size="small" aria-label="Add Your Comment"></wa-textarea>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Divider Separated
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-header style="max-width: 54ch; margin: 0 auto;">
|
||||
<wa-card style="max-width: 54ch; margin: 0 auto;">
|
||||
<div slot="header" class="wa-split">
|
||||
<div>
|
||||
<span>Notifications</span>
|
||||
@@ -279,7 +277,10 @@ description: 'Track and organize recent user actions or events.'
|
||||
<div class="wa-stack">
|
||||
<article>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1614807547811-4174d3582092?q=80&w=2932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile image"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1614807547811-4174d3582092?q=80&w=2932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-split">
|
||||
<span><strong>Happy</strong> commented in <a href="#">Reporting Dashboard</a></span>
|
||||
@@ -298,7 +299,10 @@ description: 'Track and organize recent user actions or events.'
|
||||
</article>
|
||||
<article>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile image"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-split">
|
||||
<span><strong>Charlotte</strong> followed you</span>
|
||||
@@ -314,7 +318,10 @@ description: 'Track and organize recent user actions or events.'
|
||||
</article>
|
||||
<article>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1645288059073-af3e9eb62a29?q=80&w=2936&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="Profile image"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1645288059073-af3e9eb62a29?q=80&w=2936&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="Profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-split">
|
||||
<span><strong>Tavitian</strong> invited you to <a href="#">Homepage Redesign</a></span>
|
||||
@@ -333,4 +340,4 @@ description: 'Track and organize recent user actions or events.'
|
||||
</article>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -39,10 +39,16 @@ isPro: true
|
||||
<wa-avatar initials="RF" label="User avatar"></wa-avatar>
|
||||
<div class="wa-cluster">
|
||||
<strong>Robert Fox</strong>
|
||||
<span class="wa-caption-m">commented <wa-relative-time date="2025-03-31T09:17:00-04:00"></wa-relative-time></span>
|
||||
<span class="wa-caption-m"
|
||||
>commented <wa-relative-time date="2025-03-31T09:17:00-04:00"></wa-relative-time
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
<p>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.</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</li>
|
||||
<div class="wa-flank wa-gap-xl">
|
||||
<wa-divider vertical style="height: auto; align-self: stretch"></wa-divider>
|
||||
@@ -52,10 +58,15 @@ isPro: true
|
||||
<wa-avatar initials="VF" label="User avatar"></wa-avatar>
|
||||
<div class="wa-cluster">
|
||||
<strong>Virginia Woolf</strong>
|
||||
<span class="wa-caption-m">commented <wa-relative-time date="2025-03-31T12:32:00-04:00"></wa-relative-time></span>
|
||||
<span class="wa-caption-m"
|
||||
>commented <wa-relative-time date="2025-03-31T12:32:00-04:00"></wa-relative-time
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras convallis mollis nunc, vel tempor sem faucibus nec.</p>
|
||||
<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">
|
||||
@@ -65,7 +76,10 @@ isPro: true
|
||||
<span class="wa-caption-m">commented <wa-relative-time></wa-relative-time></span>
|
||||
</div>
|
||||
</div>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras convallis mollis nunc, vel tempor sem faucibus nec.</p>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras convallis mollis nunc, vel tempor sem
|
||||
faucibus nec.
|
||||
</p>
|
||||
</li>
|
||||
<li class="wa-cluster">
|
||||
<wa-icon name="reply"></wa-icon>
|
||||
@@ -82,7 +96,10 @@ isPro: true
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-align-items-start wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?q=80&w=2670&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="User avatar"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?q=80&w=2670&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="User avatar"
|
||||
></wa-avatar>
|
||||
<div class="wa-stack wa-gap-s">
|
||||
<wa-textarea placeholder="Add to the conversation..." aria-label="Add comment"></wa-textarea>
|
||||
<div class="wa-split">
|
||||
@@ -101,7 +118,7 @@ isPro: true
|
||||
## Rich Card with Multiple Actions
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-header with-footer style="max-width: 60ch; margin: auto">
|
||||
<wa-card style="max-width: 60ch; margin: auto">
|
||||
<div slot="header">
|
||||
<h3 class="wa-heading-s">I watched...</h3>
|
||||
</div>
|
||||
@@ -119,7 +136,14 @@ isPro: true
|
||||
<dl class="wa-split">
|
||||
<dt>Date</dt>
|
||||
<dd>
|
||||
<wa-format-date date="2025-03-13T00:00:00.000-04:00" weekday="long" month="long" day="numeric" year="numeric" class="wa-caption-m"></wa-format-date>
|
||||
<wa-format-date
|
||||
date="2025-03-13T00:00:00.000-04:00"
|
||||
weekday="long"
|
||||
month="long"
|
||||
day="numeric"
|
||||
year="numeric"
|
||||
class="wa-caption-m"
|
||||
></wa-format-date>
|
||||
</dd>
|
||||
</dl>
|
||||
<wa-divider></wa-divider>
|
||||
@@ -136,10 +160,12 @@ isPro: true
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
|
||||
## With Preview Pane
|
||||
|
||||
```html{.example}
|
||||
<div style="max-width: 60ch; margin: 0 auto;">
|
||||
<wa-card class="wa-border-radius-square" with-footer>
|
||||
<wa-card class="wa-border-radius-square">
|
||||
<h3 class="wa-heading-m">Add a comment</h3>
|
||||
<wa-tab-group>
|
||||
<wa-tab panel="write">Write</wa-tab>
|
||||
@@ -162,4 +188,4 @@ isPro: true
|
||||
</wa-card>
|
||||
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -4,8 +4,8 @@ description: 'Convey insights, metrics, and aggregate data at a glance.'
|
||||
isPro: true
|
||||
---
|
||||
|
||||
|
||||
## Simple
|
||||
|
||||
```html {.example}
|
||||
<wa-card>
|
||||
<div class="wa-grid wa-gap-3xl" style="--min-column-size: 24ch;">
|
||||
@@ -20,8 +20,13 @@ isPro: true
|
||||
<wa-format-number class="wa-heading-s" type="percent" value=".475"></wa-format-number>
|
||||
</div>
|
||||
</div>
|
||||
<wa-format-number class="wa-heading-xl" type="currency" currency="USD" value="175000000" lang="en-US"></wa-format-number>
|
||||
|
||||
<wa-format-number
|
||||
class="wa-heading-xl"
|
||||
type="currency"
|
||||
currency="USD"
|
||||
value="175000000"
|
||||
lang="en-US"
|
||||
></wa-format-number>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<div class="wa-split">
|
||||
@@ -29,12 +34,19 @@ isPro: true
|
||||
<wa-icon name="credit-card"></wa-icon>
|
||||
<span>Expenses</span>
|
||||
</div>
|
||||
<div class="wa-cluster wa-gap-xs" style="color: var(--wa-color-red);">
|
||||
<div class="wa-cluster wa-gap-xs" style="color: var(--wa-color-red);">
|
||||
<wa-icon name="arrow-trend-down"></wa-icon>
|
||||
<wa-format-number class="wa-heading-s" type="percent" value=".27"></wa-format-number>
|
||||
</div>
|
||||
</div>
|
||||
<wa-format-number class="wa-heading-xl" class="wa-heading-xl" type="currency" currency="USD" value="289472" lang="en-US"></wa-format-number>
|
||||
<wa-format-number
|
||||
class="wa-heading-xl"
|
||||
class="wa-heading-xl"
|
||||
type="currency"
|
||||
currency="USD"
|
||||
value="289472"
|
||||
lang="en-US"
|
||||
></wa-format-number>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<div class="wa-split">
|
||||
@@ -47,7 +59,14 @@ isPro: true
|
||||
<wa-format-number class="wa-heading-s" type="percent" value=".14"></wa-format-number>
|
||||
</div>
|
||||
</div>
|
||||
<wa-format-number class="wa-heading-xl" class="wa-heading-xl" type="currency" currency="USD" value="569213" lang="en-US"></wa-format-number>
|
||||
<wa-format-number
|
||||
class="wa-heading-xl"
|
||||
class="wa-heading-xl"
|
||||
type="currency"
|
||||
currency="USD"
|
||||
value="569213"
|
||||
lang="en-US"
|
||||
></wa-format-number>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<div class="wa-split">
|
||||
@@ -56,19 +75,27 @@ isPro: true
|
||||
<span>Mortgages & Loans</span>
|
||||
</div>
|
||||
</div>
|
||||
<wa-format-number class="wa-heading-xl" class="wa-heading-xl" type="currency" currency="USD" value="23904" lang="en-US"></wa-format-number>
|
||||
<wa-format-number
|
||||
class="wa-heading-xl"
|
||||
class="wa-heading-xl"
|
||||
type="currency"
|
||||
currency="USD"
|
||||
value="23904"
|
||||
lang="en-US"
|
||||
></wa-format-number>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
|
||||
## Cards with Avatars
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-grid" style="--min-column-size: 30ch">
|
||||
<wa-card>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
<wa-avatar shape="rounded">
|
||||
<wa-icon slot="icon" name="user-group"></wa-icon>
|
||||
<wa-icon slot="icon" name="user-group"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<h3 class="wa-caption-m">Total Subscribers</h3>
|
||||
@@ -85,7 +112,7 @@ isPro: true
|
||||
<wa-card>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
<wa-avatar shape="rounded">
|
||||
<wa-icon slot="icon" name="envelope-open"></wa-icon>
|
||||
<wa-icon slot="icon" name="envelope-open"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<h3 class="wa-caption-m">Open Rate</h3>
|
||||
@@ -102,7 +129,7 @@ isPro: true
|
||||
<wa-card>
|
||||
<div class="wa-flank wa-align-items-start">
|
||||
<wa-avatar shape="rounded">
|
||||
<wa-icon slot="icon" name="arrow-pointer"></wa-icon>
|
||||
<wa-icon slot="icon" name="arrow-pointer"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<h3 class="wa-caption-m">Click Rate</h3>
|
||||
@@ -136,12 +163,16 @@ isPro: true
|
||||
<wa-progress-ring value="12.3" style="--size: 1em; --track-width: 0.125em"></wa-progress-ring>
|
||||
<span>12.3%</span>
|
||||
</div>
|
||||
<wa-badge appearance="filled outlined" variant="danger"><wa-icon name="arrow-down"></wa-icon> down from 19.6%</wa-badge>
|
||||
<wa-badge appearance="filled outlined" variant="danger"
|
||||
><wa-icon name="arrow-down"></wa-icon> down from 19.6%</wa-badge
|
||||
>
|
||||
</article>
|
||||
<article class="wa-stack wa-gap-xs wa-align-items-end">
|
||||
<h4 class="wa-caption-l">Max CHR</h4>
|
||||
<span class="wa-heading-2xl">72.6%</span>
|
||||
<wa-badge appearance="filled outlined" variant="success"><wa-icon name="sparkles"></wa-icon> CHR Impact +5.4%</wa-badge>
|
||||
<wa-badge appearance="filled outlined" variant="success"
|
||||
><wa-icon name="sparkles"></wa-icon> CHR Impact +5.4%</wa-badge
|
||||
>
|
||||
</article>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
@@ -171,4 +202,4 @@ isPro: true
|
||||
</article>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -30,7 +30,10 @@ isPro: true
|
||||
</div>
|
||||
<div class="wa-flank wa-align-items-start" style="--flank-size: 20ch;">
|
||||
<dt>About</dt>
|
||||
<dd>After being lost in action and brainwashed into becoming Hydra's ruthless assassin, my journey is one of redemption, healing, and reclaiming my true self. Though burdened with the weight of the past, I remain a fierce warrior, loyal to those I love, and I'm always striving to atone for those dark days as the Winter Soldier.
|
||||
<dd>
|
||||
After being lost in action and brainwashed into becoming Hydra's ruthless assassin, my journey is one of
|
||||
redemption, healing, and reclaiming my true self. Though burdened with the weight of the past, I remain a fierce
|
||||
warrior, loyal to those I love, and I'm always striving to atone for those dark days as the Winter Soldier.
|
||||
</dd>
|
||||
</div>
|
||||
<div class="wa-flank wa-align-items-start" style="--flank-size: 20ch;">
|
||||
@@ -169,7 +172,12 @@ isPro: true
|
||||
<div class="wa-flank wa-align-items-start" style="--flank-size: 20ch;">
|
||||
<dt>About</dt>
|
||||
<div class="wa-flank:end">
|
||||
<dd>After being lost in action and brainwashed into becoming Hydra's ruthless assassin, my journey is one of redemption, healing, and reclaiming my true self. Though burdened with the weight of the past, I remain a fierce warrior, loyal to those I love, and I'm always striving to atone for those dark days as the Winter Soldier.</dd>
|
||||
<dd>
|
||||
After being lost in action and brainwashed into becoming Hydra's ruthless assassin, my journey is one of
|
||||
redemption, healing, and reclaiming my true self. Though burdened with the weight of the past, I remain a
|
||||
fierce warrior, loyal to those I love, and I'm always striving to atone for those dark days as the Winter
|
||||
Soldier.
|
||||
</dd>
|
||||
<wa-button appearance="plain" variant="brand" size="small">Edit</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -250,4 +258,4 @@ isPro: true
|
||||
</a>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -31,24 +31,27 @@ isPro: true
|
||||
## With Templates
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-header with-footer style="max-width: 70ch; margin: auto">
|
||||
<wa-card style="max-width: 70ch; margin: auto">
|
||||
<div slot="header" class="wa-stack wa-gap-xs">
|
||||
<h2 class="wa-heading-m">Projects</h2>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xl">
|
||||
<p class="wa-caption-m">You haven’t created a project yet. Get started by selecting a template or start with a blank canvas.</p>
|
||||
<p class="wa-caption-m">
|
||||
You haven’t created a project yet. Get started by selecting a template or start with a blank canvas.
|
||||
</p>
|
||||
<div class="wa-grid wa-gap-xl" style="--min-column-size: 30ch;">
|
||||
<a href="" class="wa-flank wa-align-items-start wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-yellow-90);color: var(--wa-color-yellow-40);">
|
||||
<wa-avatar
|
||||
shape="rounded"
|
||||
style="--background-color: var(--wa-color-yellow-90);color: var(--wa-color-yellow-40);"
|
||||
>
|
||||
<wa-icon slot="icon" name="note-sticky"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Create a Quick Note <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
Jot down any idea. Will it make sense later? Who knows.
|
||||
</p>
|
||||
<p class="wa-caption-m">Jot down any idea. Will it make sense later? Who knows.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="" class="wa-flank wa-align-items-start wa-link-plain">
|
||||
@@ -59,48 +62,49 @@ isPro: true
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Create a Checklist <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
The ultimate tool for looking busy.
|
||||
</p>
|
||||
<p class="wa-caption-m">The ultimate tool for looking busy.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href=""class="wa-flank wa-align-items-start wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-purple-90);color: var(--wa-color-purple-40);">
|
||||
<a href="" class="wa-flank wa-align-items-start wa-link-plain">
|
||||
<wa-avatar
|
||||
shape="rounded"
|
||||
style="--background-color: var(--wa-color-purple-90);color: var(--wa-color-purple-40);"
|
||||
>
|
||||
<wa-icon slot="icon" name="table-cells"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Create a Spreadsheet <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
Endless rows and columns of tiny, soul-crushing numbers.
|
||||
</p>
|
||||
<p class="wa-caption-m">Endless rows and columns of tiny, soul-crushing numbers.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="" class="wa-flank wa-align-items-start wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-orange-90);color: var(--wa-color-orange-40);">
|
||||
<wa-avatar
|
||||
shape="rounded"
|
||||
style="--background-color: var(--wa-color-orange-90);color: var(--wa-color-orange-40);"
|
||||
>
|
||||
<wa-icon slot="icon" name="presentation-screen"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Create a Slideshow <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
Dramatic transitions make everything seem more official.
|
||||
</p>
|
||||
<p class="wa-caption-m">Dramatic transitions make everything seem more official.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="" class="wa-flank wa-align-items-start wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-green-90);color: var(--wa-color-green-40);">
|
||||
<wa-avatar
|
||||
shape="rounded"
|
||||
style="--background-color: var(--wa-color-green-90);color: var(--wa-color-green-40);"
|
||||
>
|
||||
<wa-icon slot="icon" name="pen-field"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Create a Form <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
Collect the deepest personal details and darkest secrets.
|
||||
</p>
|
||||
<p class="wa-caption-m">Collect the deepest personal details and darkest secrets.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="" class="wa-flank wa-align-items-start wa-link-plain">
|
||||
@@ -111,9 +115,7 @@ isPro: true
|
||||
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
|
||||
Create a Photo Album <wa-icon name="arrow-right"></wa-icon>
|
||||
</span>
|
||||
<p class="wa-caption-m">
|
||||
Curate your best memories or most basic food pictures.
|
||||
</p>
|
||||
<p class="wa-caption-m">Curate your best memories or most basic food pictures.</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@@ -126,82 +128,95 @@ isPro: true
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
|
||||
## Add people
|
||||
|
||||
```html {.example}
|
||||
<wa-card style="max-width: 60ch; margin: 0 auto;">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<h3 class="wa-heading-m">Add team members</h3>
|
||||
<p>This project is awful lonely. Invite some team members to liven up the joint.</p>
|
||||
<div class="wa-flank:end wa-gap-xs">
|
||||
<wa-input></wa-input><wa-button>Invite</wa-button>
|
||||
</div>
|
||||
<div class="wa-flank:end wa-gap-xs"><wa-input></wa-input><wa-button>Invite</wa-button></div>
|
||||
<div class="wa-stack">
|
||||
<em class="wa-caption-l">Team members previously added to projects</em>
|
||||
<wa-divider></wa-divider>
|
||||
<section>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1614807547811-4174d3582092?q=80&w=2932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile image"></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Earl Upton</span>
|
||||
<span class="wa-caption-m">DevOps</span>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1614807547811-4174d3582092?q=80&w=2932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Earl Upton</span>
|
||||
<span class="wa-caption-m">DevOps</span>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="user-plus" slot="prefix"></wa-icon>
|
||||
Invite
|
||||
</wa-button>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="user-plus" slot="prefix"></wa-icon>
|
||||
Invite
|
||||
</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
</section>
|
||||
<section>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" lable="profile image"></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Steamboat Willie</span>
|
||||
<span class="wa-caption-m">Captain</span>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
lable="profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Steamboat Willie</span>
|
||||
<span class="wa-caption-m">Captain</span>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="user-plus" slot="prefix"></wa-icon>
|
||||
Invite
|
||||
</wa-button>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="user-plus" slot="prefix"></wa-icon>
|
||||
Invite
|
||||
</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
</section>
|
||||
<section>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1678582967399-bf558533f5eb?q=80&w=3029&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile image"></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Melissa Eckers</span>
|
||||
<span class="wa-caption-m">Cloud Engineer</span>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1678582967399-bf558533f5eb?q=80&w=3029&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Melissa Eckers</span>
|
||||
<span class="wa-caption-m">Cloud Engineer</span>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="user-plus" slot="prefix"></wa-icon>
|
||||
Invite
|
||||
</wa-button>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="user-plus" slot="prefix"></wa-icon>
|
||||
Invite
|
||||
</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
</section><section>
|
||||
</section>
|
||||
<section>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile image"></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Devin Shears</span>
|
||||
<span class="wa-caption-m">UX Writer</span>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-s">Devin Shears</span>
|
||||
<span class="wa-caption-m">UX Writer</span>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="user-plus" slot="prefix"></wa-icon>
|
||||
Invite
|
||||
</wa-button>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="user-plus" slot="prefix"></wa-icon>
|
||||
Invite
|
||||
</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -10,20 +10,32 @@ isPro: true
|
||||
<div class="wa-flank wa-align-items-start wa-gap-2xl" style="--flank-size: 35ch">
|
||||
<div>
|
||||
<h2>Frequently Asked Questions</h2>
|
||||
<p>Can’t find an answer? Reach out to your local <a href="">Operator</a>, or contact <a href="">the Oracle</a>, and enjoy a cookie. 🍪</p>
|
||||
<p>
|
||||
Can’t find an answer? Reach out to your local <a href="">Operator</a>, or contact <a href="">the Oracle</a>, and
|
||||
enjoy a cookie. 🍪
|
||||
</p>
|
||||
</div>
|
||||
<dl class="wa-stack wa-gap-2xl">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<dt>Is Zion actually real, or just another Matrix?</dt>
|
||||
<dd>Ah, the question that keeps redpills up at night. Sure, we escaped the first Matrix, but who’s to say Zion isn’t just another layer of the simulation?</dd>
|
||||
<dd>
|
||||
Ah, the question that keeps redpills up at night. Sure, we escaped the first Matrix, but who’s to say Zion isn’t
|
||||
just another layer of the simulation?
|
||||
</dd>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<dt>Why do the Agents always wear suits?</dt>
|
||||
<dd>Because nothing says "unstoppable digital enforcer" like a generic business professional aesthetic. Also, intimidation. You ever try fighting someone in sunglasses and a tie? It’s terrifying.</dd>
|
||||
<dd>
|
||||
Because nothing says "unstoppable digital enforcer" like a generic business professional aesthetic. Also,
|
||||
intimidation. You ever try fighting someone in sunglasses and a tie? It’s terrifying.
|
||||
</dd>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<dt>Can I go back into the Matrix once I’m out?</dt>
|
||||
<dd>Technically, yes—via hacking in. Emotionally? That depends on how well you handle the knowledge that nothing around you is real.</dd>
|
||||
<dd>
|
||||
Technically, yes—via hacking in. Emotionally? That depends on how well you handle the knowledge that nothing
|
||||
around you is real.
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
@@ -36,17 +48,20 @@ isPro: true
|
||||
<h2>Frequently Asked Questions</h2>
|
||||
<wa-details appearance="plain">
|
||||
<h3 slot="summary" class="wa-heading-m" style="margin: 0">Is Zion actually real, or just another Matrix?</h3>
|
||||
Ah, the question that keeps redpills up at night. Sure, we escaped the first Matrix, but who’s to say Zion isn’t just another layer of the simulation?
|
||||
Ah, the question that keeps redpills up at night. Sure, we escaped the first Matrix, but who’s to say Zion isn’t
|
||||
just another layer of the simulation?
|
||||
</wa-details>
|
||||
<wa-divider></wa-divider>
|
||||
<wa-details appearance="plain">
|
||||
<h3 slot="summary" class="wa-heading-m" style="margin: 0">Why do the Agents always wear suits?</h3>
|
||||
Because nothing says "unstoppable digital enforcer" like a generic business professional aesthetic. Also, intimidation. You ever try fighting someone in sunglasses and a tie? It’s terrifying.
|
||||
Because nothing says "unstoppable digital enforcer" like a generic business professional aesthetic. Also,
|
||||
intimidation. You ever try fighting someone in sunglasses and a tie? It’s terrifying.
|
||||
</wa-details>
|
||||
<wa-divider></wa-divider>
|
||||
<wa-details appearance="plain">
|
||||
<h3 slot="summary" class="wa-heading-m" style="margin: 0">Can I go back into the Matrix once I’m out?</h3>
|
||||
Technically, yes—via hacking in. Emotionally? That depends on how well you handle the knowledge that nothing around you is real.
|
||||
Technically, yes—via hacking in. Emotionally? That depends on how well you handle the knowledge that nothing around
|
||||
you is real.
|
||||
</wa-details>
|
||||
</div>
|
||||
```
|
||||
@@ -59,61 +74,86 @@ isPro: true
|
||||
<dl class="wa-stack wa-gap-2xl">
|
||||
<div class="wa-grid wa-gap-xs">
|
||||
<dt class="wa-heading-m">Is Zion actually real, or just another Matrix?</dt>
|
||||
<dd>Ah, the question that keeps redpills up at night. Sure, we escaped the first Matrix, but who’s to say Zion isn’t just another layer of the simulation?</dd>
|
||||
<dd>
|
||||
Ah, the question that keeps redpills up at night. Sure, we escaped the first Matrix, but who’s to say Zion isn’t
|
||||
just another layer of the simulation?
|
||||
</dd>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-grid wa-gap-xs">
|
||||
<dt class="wa-heading-m">Why do the Agents always wear suits?</dt>
|
||||
<dd>Because nothing says "unstoppable digital enforcer" like a generic business professional aesthetic. Also, intimidation. You ever try fighting someone in sunglasses and a tie? It’s terrifying.</dd>
|
||||
<dd>
|
||||
Because nothing says "unstoppable digital enforcer" like a generic business professional aesthetic. Also,
|
||||
intimidation. You ever try fighting someone in sunglasses and a tie? It’s terrifying.
|
||||
</dd>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-grid wa-gap-xs">
|
||||
<dt class="wa-heading-m">Can I go back into the Matrix once I’m out?</dt>
|
||||
<dd>Technically, yes—via hacking in. Emotionally? That depends on how well you handle the knowledge that nothing around you is real.</dd>
|
||||
<dd>
|
||||
Technically, yes—via hacking in. Emotionally? That depends on how well you handle the knowledge that nothing
|
||||
around you is real.
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Multiple Columns
|
||||
```html{.example}
|
||||
|
||||
```html {.example}
|
||||
<div>
|
||||
|
||||
<h2>Frequently Asked Questions</h2>
|
||||
|
||||
<h2>Frequently Asked Questions</h2>
|
||||
|
||||
<dl class="wa-grid wa-gap-m" style="--min-column-size: 30ch;">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<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>
|
||||
<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">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>
|
||||
<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">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 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>
|
||||
<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">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>
|
||||
<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 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>
|
||||
<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>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -8,7 +8,7 @@ isPro: true
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-grid" style="--min-column-size: 30ch;">
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
@@ -30,7 +30,7 @@ isPro: true
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
@@ -52,7 +52,7 @@ isPro: true
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<h3 class="wa-heading-s">Rex Tailwag</h3 class="wa-heading-s">
|
||||
@@ -71,7 +71,7 @@ isPro: true
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<h3 class="wa-heading-s">Luna Sniffington</h3 class="wa-heading-s">
|
||||
@@ -90,7 +90,7 @@ isPro: true
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<h3 class="wa-heading-s">Charlie Drooler</h3 class="wa-heading-s">
|
||||
@@ -109,7 +109,7 @@ isPro: true
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<h3 class="wa-heading-s">Daisy Zoomley</h3 class="wa-heading-s">
|
||||
@@ -135,13 +135,15 @@ isPro: true
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-grid" style="--min-column-size: 29ch;">
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-stack wa-align-items-center wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-circle">
|
||||
<img src="https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?q=80&w=2680&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
</div>
|
||||
<h2 class="wa-heading-m">Scott Summers</h2>
|
||||
<p class="wa-caption-l">DevOps</p>
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?q=80&w=2680&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<h2 class="wa-heading-m">Scott Summers</h2>
|
||||
<p class="wa-caption-l">DevOps</p>
|
||||
</div>
|
||||
<div slot="footer" class="wa-grid wa-gap-xs" style="--min-column-size: 10ch;">
|
||||
<wa-button appearance="outlined">
|
||||
@@ -154,13 +156,15 @@ isPro: true
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-stack wa-align-items-center wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-circle">
|
||||
<img src="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
</div>
|
||||
<h2 class="wa-heading-m">Kaitlin Moore</h2>
|
||||
<p class="wa-caption-l">Systems Engineer</p>
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<h2 class="wa-heading-m">Kaitlin Moore</h2>
|
||||
<p class="wa-caption-l">Systems Engineer</p>
|
||||
</div>
|
||||
<div slot="footer" class="wa-grid wa-gap-xs" style="--min-column-size: 10ch;">
|
||||
<wa-button appearance="outlined">
|
||||
@@ -173,13 +177,15 @@ isPro: true
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-stack wa-align-items-center wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-circle">
|
||||
<img src="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
</div>
|
||||
<h2 class="wa-heading-m">Nessa Riley</h2>
|
||||
<p class="wa-caption-l">Cloud Engineer</p>
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<h2 class="wa-heading-m">Nessa Riley</h2>
|
||||
<p class="wa-caption-l">Cloud Engineer</p>
|
||||
</div>
|
||||
<div slot="footer" class="wa-grid wa-gap-xs" style="--min-column-size: 10ch;">
|
||||
<wa-button appearance="outlined">
|
||||
@@ -192,13 +198,15 @@ isPro: true
|
||||
</wa-button>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-footer>
|
||||
<wa-card>
|
||||
<div class="wa-stack wa-align-items-center wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-circle">
|
||||
<img src="https://images.unsplash.com/photo-1645288059073-af3e9eb62a29?q=80&w=2936&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
</div>
|
||||
<h2 class="wa-heading-m">Veronica Staley</h2>
|
||||
<p class="wa-caption-l">Machine Learning Engineer</p>
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1645288059073-af3e9eb62a29?q=80&w=2936&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<h2 class="wa-heading-m">Veronica Staley</h2>
|
||||
<p class="wa-caption-l">Machine Learning Engineer</p>
|
||||
</div>
|
||||
<div slot="footer" class="wa-grid wa-gap-xs" style="--min-column-size: 10ch;">
|
||||
<wa-button appearance="outlined">
|
||||
@@ -213,12 +221,16 @@ isPro: true
|
||||
</wa-card>
|
||||
</div>
|
||||
```
|
||||
|
||||
## with Images
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-grid">
|
||||
<article class="wa-stack">
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img src="https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?q=80&w=2680&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?q=80&w=2680&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span>Jeff Hanks</span>
|
||||
@@ -231,7 +243,9 @@ isPro: true
|
||||
</article>
|
||||
<article class="wa-stack">
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img src="https://images.unsplash.com/photo-1674044494331-8db2ecf18d46?q=80&w=3019&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1674044494331-8db2ecf18d46?q=80&w=3019&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span>Allen Bryant</span>
|
||||
@@ -244,7 +258,9 @@ isPro: true
|
||||
</article>
|
||||
<article class="wa-stack">
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img src="https://images.unsplash.com/photo-1645288059073-af3e9eb62a29?q=80&w=2936&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1645288059073-af3e9eb62a29?q=80&w=2936&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span>Mariah Greene</span>
|
||||
@@ -257,7 +273,9 @@ isPro: true
|
||||
</article>
|
||||
<article class="wa-stack">
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img src="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span>Beverly Winslow</span>
|
||||
@@ -270,7 +288,9 @@ isPro: true
|
||||
</article>
|
||||
<article class="wa-stack">
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img src="https://images.unsplash.com/photo-1614807547811-4174d3582092?q=80&w=2932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1614807547811-4174d3582092?q=80&w=2932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span>Eric Masterson</span>
|
||||
@@ -283,7 +303,9 @@ isPro: true
|
||||
</article>
|
||||
<article class="wa-stack">
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img src="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span>Stephen Coffee</span>
|
||||
@@ -296,14 +318,18 @@ isPro: true
|
||||
</article>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Linked Cards with Options Menu
|
||||
|
||||
```html{.example}
|
||||
```html {.example}
|
||||
<div class="wa-grid" style="--min-column-size: 25ch">
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<a href="" class="wa-flank wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-yellow-80); --text-color: var(--wa-color-yellow-40)">
|
||||
<wa-avatar
|
||||
shape="rounded"
|
||||
style="--background-color: var(--wa-color-yellow-80); --text-color: var(--wa-color-yellow-40)"
|
||||
>
|
||||
<wa-icon slot="icon" name="pancakes"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-gap-2xs wa-stack">
|
||||
@@ -312,7 +338,12 @@ isPro: true
|
||||
</div>
|
||||
</a>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="more-actions-1" slot="trigger" name="ellipsis-vertical" label="More actions"></wa-icon-button>
|
||||
<wa-icon-button
|
||||
id="more-actions-1"
|
||||
slot="trigger"
|
||||
name="ellipsis-vertical"
|
||||
label="More actions"
|
||||
></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
@@ -325,7 +356,10 @@ isPro: true
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<a href="" class="wa-flank wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-orange-80); --text-color: var(--wa-color-orange-40)">
|
||||
<wa-avatar
|
||||
shape="rounded"
|
||||
style="--background-color: var(--wa-color-orange-80); --text-color: var(--wa-color-orange-40)"
|
||||
>
|
||||
<wa-icon slot="icon" name="burger-cheese"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-gap-2xs wa-stack">
|
||||
@@ -334,7 +368,12 @@ isPro: true
|
||||
</div>
|
||||
</a>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="more-actions-2" slot="trigger" name="ellipsis-vertical" label="More actions"></wa-icon-button>
|
||||
<wa-icon-button
|
||||
id="more-actions-2"
|
||||
slot="trigger"
|
||||
name="ellipsis-vertical"
|
||||
label="More actions"
|
||||
></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
@@ -347,7 +386,10 @@ isPro: true
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<a href="" class="wa-flank wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-indigo-80); --text-color: var(--wa-color-indigo-40)">
|
||||
<wa-avatar
|
||||
shape="rounded"
|
||||
style="--background-color: var(--wa-color-indigo-80); --text-color: var(--wa-color-indigo-40)"
|
||||
>
|
||||
<wa-icon slot="icon" name="martini-glass-citrus"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-gap-2xs wa-stack">
|
||||
@@ -356,7 +398,12 @@ isPro: true
|
||||
</div>
|
||||
</a>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="more-actions-3" slot="trigger" name="ellipsis-vertical" label="More actions"></wa-icon-button>
|
||||
<wa-icon-button
|
||||
id="more-actions-3"
|
||||
slot="trigger"
|
||||
name="ellipsis-vertical"
|
||||
label="More actions"
|
||||
></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
@@ -369,7 +416,10 @@ isPro: true
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<a href="" class="wa-flank wa-link-plain">
|
||||
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-pink-80); --text-color: var(--wa-color-pink-40)">
|
||||
<wa-avatar
|
||||
shape="rounded"
|
||||
style="--background-color: var(--wa-color-pink-80); --text-color: var(--wa-color-pink-40)"
|
||||
>
|
||||
<wa-icon slot="icon" name="cake-slice"></wa-icon>
|
||||
</wa-avatar>
|
||||
<div class="wa-gap-2xs wa-stack">
|
||||
@@ -378,7 +428,12 @@ isPro: true
|
||||
</div>
|
||||
</a>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="more-actions-4" slot="trigger" name="ellipsis-vertical" label="More actions"></wa-icon-button>
|
||||
<wa-icon-button
|
||||
id="more-actions-4"
|
||||
slot="trigger"
|
||||
name="ellipsis-vertical"
|
||||
label="More actions"
|
||||
></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
@@ -390,136 +445,146 @@ isPro: true
|
||||
</wa-card>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Kanban
|
||||
|
||||
```html {.example}
|
||||
<div>
|
||||
<h2>Project #487</h2>
|
||||
<div class="wa-grid wa-gap-2xl">
|
||||
<div class="wa-stack">
|
||||
<div class="wa-cluster wa-gap-s"><span>Draft</span> <wa-badge appearance="filled outlined" variant="neutral">1</wa-badge></div>
|
||||
<div class="wa-cluster wa-gap-s">
|
||||
<span>Draft</span> <wa-badge appearance="filled outlined" variant="neutral">1</wa-badge>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<span class="wa-heading-s">Unit Testing</span>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="task-action-4" slot="trigger" name="ellipsis" label="More actions"></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
<wa-menu-item>Move to trash</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
<wa-tooltip for="task-action-4">More actions</wa-tooltip>
|
||||
</div>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<wa-badge appearance="outlined" pill>DevOps</wa-badge> <wa-badge variant="neutral" appearance="outlined" pill>Priority: Low</wa-badge>
|
||||
</div>
|
||||
</div>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"></wa-avatar>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<span class="wa-heading-s">Unit Testing</span>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="task-action-4" slot="trigger" name="ellipsis" label="More actions"></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
<wa-menu-item>Move to trash</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
<wa-tooltip for="task-action-4">More actions</wa-tooltip>
|
||||
</div>
|
||||
</wa-card>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<wa-badge appearance="outlined" pill>DevOps</wa-badge>
|
||||
<wa-badge variant="neutral" appearance="outlined" pill>Priority: Low</wa-badge>
|
||||
</div>
|
||||
</div>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1559188286-a173792c8340?q=80&w=2906&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="plus"></wa-icon>
|
||||
Add Task
|
||||
</wa-button>
|
||||
|
||||
</wa-button>
|
||||
</div>
|
||||
|
||||
<div class="wa-stack">
|
||||
<div class="wa-cluster wa-gap-s"><span>In Progress</span> <wa-badge appearance="filled outlined" variant="neutral">2</wa-badge></div>
|
||||
<div class="wa-cluster wa-gap-s">
|
||||
<span>In Progress</span> <wa-badge appearance="filled outlined" variant="neutral">2</wa-badge>
|
||||
</div>
|
||||
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<span class="wa-heading-s">UX Audit</span>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="task-action-2" slot="trigger" name="ellipsis" label="More actions"></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
<wa-menu-item>Move to trash</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
<wa-tooltip for="task-action-2">More actions</wa-tooltip>
|
||||
</div>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<wa-badge appearance="outlined" pill>Design</wa-badge> <wa-badge variant="warning" appearance="outlined" pill>Priority: Medium</wa-badge>
|
||||
</div>
|
||||
</div>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"></wa-avatar>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<span class="wa-heading-s">UX Audit</span>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="task-action-2" slot="trigger" name="ellipsis" label="More actions"></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
<wa-menu-item>Move to trash</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
<wa-tooltip for="task-action-2">More actions</wa-tooltip>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<span class="wa-heading-s">Visual Testing</span>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="task-action-3" slot="trigger" name="ellipsis" label="More actions"></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
<wa-menu-item>Move to trash</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
<wa-tooltip for="task-action-3">More actions</wa-tooltip>
|
||||
</div>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<wa-badge appearance="outlined" pill>Design</wa-badge> <wa-badge variant="danger" appearance="outlined" pill>Priority: High</wa-badge>
|
||||
</div>
|
||||
</div>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1614807547811-4174d3582092?q=80&w=2932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="profile image"></wa-avatar>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<wa-badge appearance="outlined" pill>Design</wa-badge>
|
||||
<wa-badge variant="warning" appearance="outlined" pill>Priority: Medium</wa-badge>
|
||||
</div>
|
||||
</wa-card>
|
||||
</div>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1613428800237-c86372070fab?q=80&w=3017&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<span class="wa-heading-s">Visual Testing</span>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="task-action-3" slot="trigger" name="ellipsis" label="More actions"></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
<wa-menu-item>Move to trash</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
<wa-tooltip for="task-action-3">More actions</wa-tooltip>
|
||||
</div>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<wa-badge appearance="outlined" pill>Design</wa-badge>
|
||||
<wa-badge variant="danger" appearance="outlined" pill>Priority: High</wa-badge>
|
||||
</div>
|
||||
</div>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1614807547811-4174d3582092?q=80&w=2932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="profile image"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="plus"></wa-icon>
|
||||
Add Task
|
||||
</wa-button>
|
||||
|
||||
</wa-button>
|
||||
</div>
|
||||
|
||||
<div class="wa-stack">
|
||||
<div class="wa-cluster wa-gap-s"><span>Ready for Review</span> <wa-badge appearance="filled outlined" variant="neutral">1</wa-badge></div>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<span class="wa-heading-s">Deploy Bug Fixes</span>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="task-action-1" slot="trigger" name="ellipsis" label="More actions"></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
<wa-menu-item>Move to trash</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
<wa-tooltip for="task-action-1">More actions</wa-tooltip>
|
||||
</div>
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<wa-badge appearance="outlined" pill>Development</wa-badge> <wa-badge variant="warning" appearance="outlined" pill>Priority: Medium</wa-badge>
|
||||
</div>
|
||||
</div>
|
||||
<wa-avatar initials="KK" label="Avatar with initials: KK"></wa-avatar>
|
||||
<div class="wa-cluster wa-gap-s">
|
||||
<span>Ready for Review</span> <wa-badge appearance="filled outlined" variant="neutral">1</wa-badge>
|
||||
</div>
|
||||
<wa-card>
|
||||
<div class="wa-flank:end">
|
||||
<div class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<span class="wa-heading-s">Deploy Bug Fixes</span>
|
||||
<wa-dropdown>
|
||||
<wa-icon-button id="task-action-1" slot="trigger" name="ellipsis" label="More actions"></wa-icon-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Copy link</wa-menu-item>
|
||||
<wa-menu-item>Rename</wa-menu-item>
|
||||
<wa-menu-item>Move to trash</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
<wa-tooltip for="task-action-1">More actions</wa-tooltip>
|
||||
</div>
|
||||
</wa-card>
|
||||
|
||||
<div class="wa-cluster wa-gap-2xs">
|
||||
<wa-badge appearance="outlined" pill>Development</wa-badge>
|
||||
<wa-badge variant="warning" appearance="outlined" pill>Priority: Medium</wa-badge>
|
||||
</div>
|
||||
</div>
|
||||
<wa-avatar initials="KK" label="Avatar with initials: KK"></wa-avatar>
|
||||
</div>
|
||||
</wa-card>
|
||||
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon name="plus"></wa-icon>
|
||||
Add Task
|
||||
</wa-button>
|
||||
|
||||
</wa-button>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -140,7 +140,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="1" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1620428268482-cf1851a36764?q=80&w=3418&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1620428268482-cf1851a36764?q=80&w=3418&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>mitsuwo</span>
|
||||
@@ -151,7 +154,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="2" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1639628735078-ed2f038a193e?q=80&w=3348&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1639628735078-ed2f038a193e?q=80&w=3348&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>knowledgeninja</span>
|
||||
@@ -162,7 +168,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="3" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1638803040283-7a5ffd48dad5?q=80&w=2592&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1638803040283-7a5ffd48dad5?q=80&w=2592&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>NxtLvl</span>
|
||||
@@ -173,7 +182,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="4" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1630549316063-7ae02749d2cc?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1630549316063-7ae02749d2cc?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>brainiac</span>
|
||||
@@ -184,7 +196,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="5" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1582845512747-e42001c95638?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1582845512747-e42001c95638?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>eduexplorer</span>
|
||||
@@ -207,7 +222,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="1" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1630549316063-7ae02749d2cc?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1630549316063-7ae02749d2cc?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>brainiac</span>
|
||||
@@ -218,7 +236,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="2" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1546776230-bb86256870ce?q=80&w=3368&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1546776230-bb86256870ce?q=80&w=3368&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>LessonLegend</span>
|
||||
@@ -229,7 +250,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="3" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1620428268482-cf1851a36764?q=80&w=3418&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1620428268482-cf1851a36764?q=80&w=3418&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>mitsuwo</span>
|
||||
@@ -240,7 +264,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="4" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1586374579358-9d19d632b6df?q=80&w=3387&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1586374579358-9d19d632b6df?q=80&w=3387&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>wiswiz</span>
|
||||
@@ -251,7 +278,10 @@ isPro: true
|
||||
<li class="wa-flank">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="5" fixed-width></wa-icon>
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1639628735078-ed2f038a193e?q=80&w=3348&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" shape="rounded"></wa-avatar>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1639628735078-ed2f038a193e?q=80&w=3348&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
shape="rounded"
|
||||
></wa-avatar>
|
||||
</div>
|
||||
<div class="wa-split wa-gap-xs">
|
||||
<span>knowledgeninja</span>
|
||||
@@ -263,4 +293,4 @@ isPro: true
|
||||
</wa-card>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -49,4 +49,4 @@ isPro: true
|
||||
</wa-button-group>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -5,8 +5,9 @@ isPro: true
|
||||
---
|
||||
|
||||
## With Form Inputs
|
||||
```html{.example}
|
||||
<wa-card with-header style="max-width: 72ch; margin: 0 auto;">
|
||||
|
||||
```html {.example}
|
||||
<wa-card style="max-width: 72ch; margin: 0 auto;">
|
||||
<div slot="header" class="wa-split">
|
||||
<h2 class="wa-heading-m">Invite Team Members</h2>
|
||||
<wa-icon name="close"></wa-icon>
|
||||
@@ -21,7 +22,10 @@ isPro: true
|
||||
<span class="wa-heading-s">Project Members</span>
|
||||
<div class="wa-stack wa-gap-xl">
|
||||
<div class="wa-flank">
|
||||
<wa-avatar label="User avatar" image="https://images.unsplash.com/photo-1580489944761-15a19d654956?q=80&w=1961&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></wa-avatar>
|
||||
<wa-avatar
|
||||
label="User avatar"
|
||||
image="https://images.unsplash.com/photo-1580489944761-15a19d654956?q=80&w=1961&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-xs">Jessica Jones</span>
|
||||
@@ -36,7 +40,10 @@ isPro: true
|
||||
</div>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar label="User avatar" image="https://images.unsplash.com/photo-1566492031773-4f4e44671857?q=80&w=2487&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></wa-avatar>
|
||||
<wa-avatar
|
||||
label="User avatar"
|
||||
image="https://images.unsplash.com/photo-1566492031773-4f4e44671857?q=80&w=2487&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-xs">Foggy Nelson</span>
|
||||
@@ -51,7 +58,10 @@ isPro: true
|
||||
</div>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar label="User avatar" image="https://images.unsplash.com/photo-1494790108377-be9c29b29330?q=80&w=2487&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></wa-avatar>
|
||||
<wa-avatar
|
||||
label="User avatar"
|
||||
image="https://images.unsplash.com/photo-1494790108377-be9c29b29330?q=80&w=2487&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-xs">Karen Page</span>
|
||||
@@ -66,7 +76,10 @@ isPro: true
|
||||
</div>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar label="User avatar" image="https://images.unsplash.com/photo-1599566150163-29194dcaad36?q=80&w=2487&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></wa-avatar>
|
||||
<wa-avatar
|
||||
label="User avatar"
|
||||
image="https://images.unsplash.com/photo-1599566150163-29194dcaad36?q=80&w=2487&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span class="wa-heading-xs">Matt Murdock</span>
|
||||
@@ -95,135 +108,141 @@ isPro: true
|
||||
```
|
||||
|
||||
## Link Settings
|
||||
|
||||
```html {.example}
|
||||
<wa-card style="max-width: 45ch; margin: 0 auto;">
|
||||
<div class="wa-stack">
|
||||
<h2 class="wa-heading-m">Manage Link</h2>
|
||||
<h2 class="wa-heading-m">Manage Link</h2>
|
||||
<wa-input label="Expiration Date" type="date"></wa-input>
|
||||
<wa-radio-group
|
||||
label="Share Limit"
|
||||
orientation="horizontal"
|
||||
name="share-limit"
|
||||
value="0"
|
||||
>
|
||||
<wa-radio-group label="Share Limit" orientation="horizontal" name="share-limit" value="0">
|
||||
<wa-radio-button value="0">None</wa-radio-button>
|
||||
<wa-radio-button value="5">5</wa-radio-button>
|
||||
<wa-radio-button value="10">10</wa-radio-button>
|
||||
<wa-radio-button value="50">50</wa-radio-button>
|
||||
<wa-radio-button value="100">100</wa-radio-button>
|
||||
</wa-radio-group>
|
||||
<wa-divider></wa-divider>
|
||||
<wa-divider></wa-divider>
|
||||
<wa-switch hint="Members are removed after logging out." checked>Temporary Access</wa-switch>
|
||||
<div class="wa-cluster wa-gap-xs" style="justify-content: flex-end">
|
||||
<wa-button size="small" appearance="outlined" pill>Cancel</wa-button>
|
||||
<wa-button size="small" variant="brand" pill>Generate</wa-button>
|
||||
<wa-button size="small" appearance="outlined" pill>Cancel</wa-button>
|
||||
<wa-button size="small" variant="brand" pill>Generate</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</wa-card>
|
||||
```
|
||||
|
||||
## Role Settings
|
||||
|
||||
```html {.example}
|
||||
<div style="max-width: 78ch; margin: 0 auto;">
|
||||
<h2>Settings</h2>
|
||||
<p>Update settings for this server.</p>
|
||||
<wa-tab-group>
|
||||
<wa-tab panel="general">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="user"></wa-icon>
|
||||
<span>User Permissions</span>
|
||||
</div>
|
||||
</wa-tab>
|
||||
<wa-tab-panel name="general">
|
||||
<wa-card>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1741289308283-feba56f857cc?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTl8fGJlYXJkfGVufDB8MnwwfHx8Mg%3D%3D" alt="image avatar"></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span class="wa-heading-s">Kris Kringle</span>
|
||||
<span class="wa-caption-m">Admin</span>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon slot="prefix" name="edit"></wa-icon>
|
||||
Edit Profile
|
||||
</wa-button>
|
||||
</div>
|
||||
<wa-tab panel="general">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="user"></wa-icon>
|
||||
<span>User Permissions</span>
|
||||
</div>
|
||||
</wa-card>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Role</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1579824894326-77ec5aaf8703?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NDJ8fHJlaW5kZWVyfGVufDB8MnwwfHx8Mg%3D%3D"></wa-avatar>
|
||||
<span class="wa-caption-m">Dasher</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<wa-select value="moderator">
|
||||
<wa-option value="moderator">Moderator</wa-option>
|
||||
<wa-option value="contributor">Contributor</wa-option>
|
||||
<wa-option value="reader">Reader</wa-option>
|
||||
</wa-select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
</wa-tab>
|
||||
<wa-tab-panel name="general">
|
||||
<wa-card>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1691065686144-916ff29d1b4f?q=80&w=2666&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></wa-avatar>
|
||||
<span class="wa-caption-m">Dancer</span>
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1741289308283-feba56f857cc?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTl8fGJlYXJkfGVufDB8MnwwfHx8Mg%3D%3D"
|
||||
alt="image avatar"
|
||||
></wa-avatar>
|
||||
<div class="wa-split">
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span class="wa-heading-s">Kris Kringle</span>
|
||||
<span class="wa-caption-m">Admin</span>
|
||||
</div>
|
||||
<wa-button appearance="plain">
|
||||
<wa-icon slot="prefix" name="edit"></wa-icon>
|
||||
Edit Profile
|
||||
</wa-button>
|
||||
</div>
|
||||
</td>
|
||||
</div>
|
||||
</wa-card>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Role</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1579824894326-77ec5aaf8703?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NDJ8fHJlaW5kZWVyfGVufDB8MnwwfHx8Mg%3D%3D"
|
||||
></wa-avatar>
|
||||
<span class="wa-caption-m">Dasher</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<wa-select value="moderator">
|
||||
<wa-option value="moderator">Moderator</wa-option>
|
||||
<wa-option value="contributor">Contributor</wa-option>
|
||||
<wa-option value="reader">Reader</wa-option>
|
||||
</wa-select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1691065686144-916ff29d1b4f?q=80&w=2666&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
></wa-avatar>
|
||||
<span class="wa-caption-m">Dancer</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<wa-select value="moderator">
|
||||
<wa-option value="moderator">Moderator</wa-option>
|
||||
<wa-option value="contributor">Contributor</wa-option>
|
||||
<wa-option value="reader">Reader</wa-option>
|
||||
</wa-select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1616742618872-9e8a890d90b2?q=80&w=2712&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></wa-avatar>
|
||||
<span class="wa-caption-m">Prancer</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<wa-select value="contributor">
|
||||
<wa-option value="moderator">Moderator</wa-option>
|
||||
<wa-option value="contributor">Contributor</wa-option>
|
||||
<wa-option value="reader">Reader</wa-option>
|
||||
</wa-select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1728290403857-1b7909db2baa?q=80&w=2680&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></wa-avatar>
|
||||
<span class="wa-caption-m">Vixen</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<wa-select value="reader">
|
||||
<wa-option value="moderator">Moderator</wa-option>
|
||||
<wa-option value="contributor">Contributor</wa-option>
|
||||
<wa-option value="reader">Reader</wa-option>
|
||||
</wa-select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</wa-tab-panel>
|
||||
|
||||
</wa-tab-group>
|
||||
<td>
|
||||
<wa-select value="moderator">
|
||||
<wa-option value="moderator">Moderator</wa-option>
|
||||
<wa-option value="contributor">Contributor</wa-option>
|
||||
<wa-option value="reader">Reader</wa-option>
|
||||
</wa-select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1616742618872-9e8a890d90b2?q=80&w=2712&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
></wa-avatar>
|
||||
<span class="wa-caption-m">Prancer</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<wa-select value="contributor">
|
||||
<wa-option value="moderator">Moderator</wa-option>
|
||||
<wa-option value="contributor">Contributor</wa-option>
|
||||
<wa-option value="reader">Reader</wa-option>
|
||||
</wa-select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1728290403857-1b7909db2baa?q=80&w=2680&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
></wa-avatar>
|
||||
<span class="wa-caption-m">Vixen</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<wa-select value="reader">
|
||||
<wa-option value="moderator">Moderator</wa-option>
|
||||
<wa-option value="contributor">Contributor</wa-option>
|
||||
<wa-option value="reader">Reader</wa-option>
|
||||
</wa-select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</wa-tab-panel>
|
||||
</wa-tab-group>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -6,7 +6,7 @@ isPro: true
|
||||
|
||||
## Three Tiers
|
||||
|
||||
```html{.example}
|
||||
```html {.example}
|
||||
<div class="wa-grid">
|
||||
<wa-card>
|
||||
<div class="wa-stack">
|
||||
@@ -130,7 +130,9 @@ isPro: true
|
||||
<div class="wa-grid">
|
||||
<div class="wa-stack">
|
||||
<h3 class="wa-heading-l">Lifetime Membership</h3>
|
||||
<p>Learn at your own pace with expert-led content, exclusive resources, and a community of like-minded learners.</p>
|
||||
<p>
|
||||
Learn at your own pace with expert-led content, exclusive resources, and a community of like-minded learners.
|
||||
</p>
|
||||
<wa-divider></wa-divider>
|
||||
<h4 class="wa-heading-s">Membership Includes:</h4>
|
||||
<div class="wa-grid">
|
||||
@@ -165,4 +167,4 @@ isPro: true
|
||||
</wa-callout>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
```
|
||||
|
||||
55
docs/docs/patterns/blog-news/call-to-action.md
Normal file
55
docs/docs/patterns/blog-news/call-to-action.md
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: Call To Action
|
||||
description: 'Solicits a user to take action.'
|
||||
parent: blog-news
|
||||
icon: call-to-action
|
||||
tags: blog-news
|
||||
---
|
||||
|
||||
## Simple
|
||||
|
||||
```html {.example}
|
||||
<div style="margin-block: var(--wa-space-4xl);">
|
||||
<h2 class="wa-heading-3xl">Unlock Your Future: <br />Start Learning Web Development Today!</h2>
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
<wa-button>Get Started</wa-button>
|
||||
<wa-button appearance="plain">Find out more <wa-icon slot="suffix" name="arrow-right"></wa-icon></wa-button>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Centered
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack wa-align-items-center wa-gap-xl" style="margin-block: var(--wa-space-4xl);">
|
||||
<h2 class="wa-heading-3xl" style="text-align: center">
|
||||
Unlock Your Future: <br />Start Learning Web Development Today!
|
||||
</h2>
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
<wa-button>Get Started</wa-button>
|
||||
<wa-button appearance="plain">Find out more <wa-icon slot="suffix" name="arrow-right"></wa-icon></wa-button>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## 2 Column
|
||||
|
||||
```html {.example}
|
||||
<div style="margin-block: var(--wa-space-4xl);">
|
||||
<div class="wa-grid wa-align-items-center wa-gap-3xl">
|
||||
<div class="wa-stack wa-gap-3xl">
|
||||
<h2 class="wa-heading-3xl">Unlock Your Future: <br />Start Learning Web Development Today!</h2>
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
<wa-button>Get Started</wa-button>
|
||||
<wa-button appearance="plain">Find out more <wa-icon slot="suffix" name="arrow-right"></wa-icon></wa-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1586864387634-2f33030dab41?q=80&w=2670&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
143
docs/docs/patterns/blog-news/category-list.md
Normal file
143
docs/docs/patterns/blog-news/category-list.md
Normal file
@@ -0,0 +1,143 @@
|
||||
---
|
||||
title: Category List
|
||||
description: 'Organize your site and allow readers to find the information they want.'
|
||||
parent: blog-news
|
||||
icon: category-list
|
||||
tags: blog-news
|
||||
---
|
||||
|
||||
## Grid
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack wa-gap-2xl wa-align-items-center">
|
||||
<h2 class="wa-heading-2xl">Discover the Latest in...</h2>
|
||||
<div>
|
||||
<div class="wa-split">
|
||||
<h3 class="wa-heading-l">Customer Service</h3>
|
||||
<a class="wa-cluster wa-gap-2xs" href="#"><span>View More</span> <wa-icon name="arrow-right"></wa-icon></a>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-grid">
|
||||
<a href="#">
|
||||
<wa-card with-image style="height: 100%">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1560264357-8d9202250f21?q=80&w=3000&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Group of customer service reps working on computers in a shared office space"
|
||||
/>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span class="wa-caption-l">Articles</span>
|
||||
<span class="wa-heading-m">Creating Memorable Customer Moments: The Secret Sauce to Loyalty</span>
|
||||
</div>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="#">
|
||||
<wa-card with-image style="height: 100%">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1531403009284-440f080d1e12?q=80&w=5070&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="A hand pinching a pin on string, making connections between data on a corkboard"
|
||||
/>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span class="wa-caption-l">Software & Systems</span>
|
||||
<span class="wa-heading-m">Crafting a Seamless Customer Journey</span>
|
||||
</div>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="#">
|
||||
<wa-card with-image style="height: 100%">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1561323587-7464f7689886?q=80&w=5070&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="A chess board with all pieces in starting position"
|
||||
/>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span class="wa-caption-l">Engagement</span>
|
||||
<span class="wa-heading-m">Customer Delight vs. Satisfaction: What’s the Real Goal?</span>
|
||||
</div>
|
||||
</wa-card>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="wa-split">
|
||||
<h3 class="wa-heading-l">Growth & Culture</h3>
|
||||
<a class="wa-cluster wa-gap-2xs" href="#"><span>View More</span> <wa-icon name="arrow-right"></wa-icon></a>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-grid">
|
||||
<a href="#">
|
||||
<wa-card with-image style="height: 100%">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1493599124325-e628361046af?q=80&w=4470&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Viewpoint from the middle of a forest, looking upwards towards the canopy of towering evergreen"
|
||||
/>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span class="wa-caption-l">Hiring & Culture</span>
|
||||
<span class="wa-heading-m">Scaling with Soul: How to Grow Without Losing Your Culture</span>
|
||||
</div>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="#">
|
||||
<wa-card with-image style="height: 100%">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1466629437334-b4f6603563c5?q=80&w=4478&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Sunset over a vast grassy field with many prominent wind turbines"
|
||||
/>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span class="wa-caption-l">Articles</span>
|
||||
<span class="wa-heading-m">Culture Is Your Growth Engine: Why Values Drive Performance</span>
|
||||
</div>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="#">
|
||||
<wa-card with-image style="height: 100%">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1455849318743-b2233052fcff?q=80&w=4469&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Viewpoint of two people side-by-side looking down towards their shoes, PASSION LED US HERE written on the sidewalk"
|
||||
/>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<span class="wa-caption-l">Behind the Scenes</span>
|
||||
<span class="wa-heading-m">From Start-Up to Standout: Building a Culture That Attracts Top Talent</span>
|
||||
</div>
|
||||
</wa-card>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Links with Background Images
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack wa-align">
|
||||
<h2 class="wa-heading-2xl">Recipes</h2>
|
||||
<div class="wa-grid">
|
||||
<a
|
||||
href="#"
|
||||
class="wa-frame wa-align-items-center wa-border-radius-m wa-link-plain wa-heading-xl wa-dark"
|
||||
style="padding: var(--wa-space-3xl);background-image:linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('https://images.unsplash.com/photo-1548340748-6d2b7d7da280?q=80&w=3027&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D');background-size: cover;background-position: center; text-align: center;"
|
||||
>
|
||||
Appetizers and Snacks
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="wa-frame wa-align-items-center wa-border-radius-m wa-link-plain wa-heading-xl wa-dark"
|
||||
style="padding: var(--wa-space-3xl);background-image:linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('https://images.unsplash.com/photo-1644704265419-96ddaf628e71?q=80&w=5340&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D');background-size: cover;background-position: center; text-align: center"
|
||||
>
|
||||
Main Dishes
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="wa-frame wa-align-items-center wa-border-radius-m wa-link-plain wa-heading-xl wa-dark"
|
||||
style="padding: var(--wa-space-3xl);background-image:linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('https://images.unsplash.com/photo-1551024506-0bccd828d307?q=80&w=3200&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D');background-size: cover;background-position: center; text-align: center;"
|
||||
>
|
||||
Desserts
|
||||
</a>
|
||||
</div>
|
||||
<wa-button appearance="plain"><wa-icon slot="suffix" name="arrow-right"></wa-icon>View More Recipes</wa-button>
|
||||
</div>
|
||||
```
|
||||
167
docs/docs/patterns/blog-news/featured-post.md
Normal file
167
docs/docs/patterns/blog-news/featured-post.md
Normal file
@@ -0,0 +1,167 @@
|
||||
---
|
||||
title: Featured Post
|
||||
description: 'Highlight important, timely, or high-impact content.'
|
||||
parent: blog-news
|
||||
tags:
|
||||
---
|
||||
|
||||
## Single Column
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack wa-gap-2xl" style="max-width: 90ch; margin: 0 auto;">
|
||||
<article class="wa-stack">
|
||||
<div class="wa-grid wa-gap-2xl">
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1673255745677-e36f618550d1?q=80&w=5000&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="Futuristic humanoid robot holding a metallic brain in its right hand"
|
||||
/>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<span><a href="#">Catherine Rigby</a> wrote</span>
|
||||
<h2 class="wa-heading-3xl">How Artificial Intelligence Is Quietly Transforming Your Daily Life</h2>
|
||||
<span>
|
||||
<wa-format-date month="long" day="numeric" year="numeric"></wa-format-date> in
|
||||
<a href="#">Artificial Intelligence</a>, <a href="#">Large Language Model</a>,
|
||||
<a href="#">Machine Learning</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>From your morning playlist to your grocery list, AI is everywhere—and you might not even notice it.</p>
|
||||
<wa-button href="#" appearance="filled" variant="brand">
|
||||
Continue reading
|
||||
<wa-icon name="arrow-right" slot="suffix"></wa-icon>
|
||||
</wa-button>
|
||||
</article>
|
||||
<wa-divider></wa-divider>
|
||||
<article class="wa-stack">
|
||||
<span>
|
||||
<a href="#">Freddie Smith</a><wa-format-date month="long" day="numeric" year="numeric"></wa-format-date> in
|
||||
<a href="#">Artificial Intelligence</a>, <a href="#">Large Language Model</a>,
|
||||
<a href="#">Machine Learning</a>
|
||||
</span>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1654110455429-cf322b40a906?q=80&w=3178&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="Avatar of author"
|
||||
></wa-avatar>
|
||||
<h2 class="wa-heading-l">What Generative AI Means for Creativity, Work, and the Future of Content</h2>
|
||||
</div>
|
||||
</article>
|
||||
<wa-divider></wa-divider>
|
||||
<article class="wa-stack">
|
||||
<span>
|
||||
<a href="#">Michelle Starling</a><wa-format-date month="long" day="numeric" year="numeric"></wa-format-date> in
|
||||
<a href="#">Artificial Intelligence</a>, <a href="#">Large Language Model</a>,
|
||||
<a href="#">Machine Learning</a>
|
||||
</span>
|
||||
<div class="wa-flank">
|
||||
<wa-avatar
|
||||
image="https://images.unsplash.com/photo-1586297135537-94bc9ba060aa?q=80&w=4000&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
label="Avatar of author"
|
||||
></wa-avatar>
|
||||
<h2 class="wa-heading-l">The Ethics of Intelligence: Who’s Accountable When AI Gets It Wrong</h2>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Two Column
|
||||
|
||||
```html {.example}
|
||||
<div style="max-width: 84ch; margin: 0 auto;">
|
||||
<div class="wa-gap-3xl wa-grid">
|
||||
<div class="wa-stack">
|
||||
<div class="wa-frame wa-border-radius-l">
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1741208296373-27b4438d0654?q=80&w=2794&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="wa-heading-l">Masters and Movements: A Journey Through Art History’s Most Defining Eras</h2>
|
||||
<p class="wa-caption-l">
|
||||
Discover the pivotal artists, styles, and moments that shaped the world of fine art—from the Renaissance to
|
||||
the rise of modernism.
|
||||
</p>
|
||||
<span class="wa-cluster">
|
||||
<a href="#">Stephanie Howard</a>
|
||||
<wa-format-date month="long" day="numeric" date="2020-07-15T09:17:00-04:00"></wa-format-date> |
|
||||
<wa-icon name="comment"></wa-icon> 3
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<span>Top Stories</span>
|
||||
<ol class="wa-stack">
|
||||
<li class="wa-stack">
|
||||
<div class="wa-flank:end" style="--flank-size: 8ch">
|
||||
<h3 class="wa-heading-m">How Fine Art Captures Emotion Beyond Words</h3>
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1717501219402-4444fcef55e7?q=80&w=4096&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="article thumbnail"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-cluster">
|
||||
<a href="#">Emma Wilson</a>
|
||||
<wa-format-date month="long" day="numeric" date="2020-05-15T09:17:00-04:00"></wa-format-date> |
|
||||
<wa-icon name="comment"></wa-icon> 20
|
||||
</span>
|
||||
</li>
|
||||
<wa-divider></wa-divider>
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-flank:end" style="--flank-size: 8ch">
|
||||
<h3 class="wa-heading-m">From Brush to Pixel: The Evolving Identity of Fine Art in the Digital Age</h3>
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1697560415980-8cc04e055cdb?q=80&w=3600&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="article thumbnail"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-cluster">
|
||||
<a href="#">Eddie Kane</a>
|
||||
<wa-format-date month="long" day="numeric" date="2020-04-15T09:17:00-04:00"></wa-format-date> |
|
||||
<wa-icon name="comment"></wa-icon> 12
|
||||
</span>
|
||||
</li>
|
||||
<wa-divider></wa-divider>
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-flank:end" style="--flank-size: 8ch">
|
||||
<h3 class="wa-heading-m">What Makes It ‘Fine’? Unpacking the Line Between Art and Craft</h3>
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1738533614668-0a1a2501a138?q=80&w=3464&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="article thumbnail"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-cluster">
|
||||
<a href="#">Gill Scott</a>
|
||||
<wa-format-date month="long" day="numeric" date="2020-03-20T09:17:00-04:00"></wa-format-date> |
|
||||
<wa-icon name="comment"></wa-icon> 8
|
||||
</span>
|
||||
</li>
|
||||
<wa-divider></wa-divider>
|
||||
<li class="wa-stack wa-gap-2xs">
|
||||
<div class="wa-flank:end" style="--flank-size: 8ch">
|
||||
<h3 class="wa-heading-m">Studio Stories: Inside the Creative Rituals of Contemporary Fine Artists</h3>
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1600999116700-5a50973983e8?q=80&w=2292&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
alt="article thumbnail"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span class="wa-cluster">
|
||||
<a href="#">Festus Armond</a>
|
||||
<wa-format-date month="long" day="numeric" date="2020-02-20T09:17:00-04:00"></wa-format-date> |
|
||||
<wa-icon name="comment"></wa-icon> 16
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
162
docs/docs/patterns/blog-news/footer.md
Normal file
162
docs/docs/patterns/blog-news/footer.md
Normal file
@@ -0,0 +1,162 @@
|
||||
---
|
||||
title: Footer
|
||||
description: 'Provide useful information at the bottom of a webpage.'
|
||||
parent: blog-news
|
||||
tags: blog-news
|
||||
---
|
||||
|
||||
## Simple
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack wa-gap-xl">
|
||||
<div class="wa-split">
|
||||
<div class="wa-cluster wa-gap-xs wa-heading-xl">
|
||||
<wa-icon name="gears"></wa-icon>
|
||||
<span>Widget UI</span>
|
||||
</div>
|
||||
<form class="wa-flank:end wa-gap-xs wa-align-items-end">
|
||||
<wa-input placeholder="Enter your email" label="Stay in the Know" type="email"></wa-input>
|
||||
<wa-button>Subscribe</wa-button>
|
||||
</form>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<p style="text-align: right">© 2025 All rights reserved.</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Centered
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack wa-align-items-center">
|
||||
<div class="wa-cluster wa-gap-xl">
|
||||
<a href="#">Home</a>
|
||||
<a href="#">Get Started</a>
|
||||
<a href="#">Services</a>
|
||||
<a href="#">Portfolio</a>
|
||||
</div>
|
||||
<div class="wa-cluster wa-gap-s">
|
||||
<a href="#"
|
||||
><wa-icon-button
|
||||
style="font-size: var(--wa-font-size-l);"
|
||||
name="facebook"
|
||||
family="brands"
|
||||
label="Follow on Facebook"
|
||||
href="#"
|
||||
target="_blank"
|
||||
></wa-icon-button
|
||||
></a>
|
||||
<a href="#"
|
||||
><wa-icon-button
|
||||
style="font-size: var(--wa-font-size-l);"
|
||||
name="bluesky"
|
||||
family="brands"
|
||||
label="Follow on Bluesky"
|
||||
href="#"
|
||||
target="_blank"
|
||||
></wa-icon-button
|
||||
></a>
|
||||
<a href="#"
|
||||
><wa-icon-button
|
||||
style="font-size: var(--wa-font-size-l);"
|
||||
name="linkedin"
|
||||
family="brands"
|
||||
label="Follow on LinkedIn"
|
||||
href="#"
|
||||
target="_blank"
|
||||
></wa-icon-button
|
||||
></a>
|
||||
<a href="#"
|
||||
><wa-icon-button
|
||||
style="font-size: var(--wa-font-size-l);"
|
||||
name="envelope-open"
|
||||
label="Email us"
|
||||
href="#"
|
||||
target="_blank"
|
||||
></wa-icon-button
|
||||
></a>
|
||||
</div>
|
||||
<p>© 2025 All Rights reserved.</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Corporate
|
||||
|
||||
```html {.example}
|
||||
<div>
|
||||
<div class="wa-flank wa-align-items-baseline wa-gap-3xl" style="--flank-size: 36ch;">
|
||||
<p>
|
||||
We are committed to providing you with the best products and services. If you have any questions or need
|
||||
assistance, feel free to reach out to our team. Stay connected with us through our social media channels for
|
||||
updates, news, and more. Your satisfaction is our top priority, and we look forward to serving you again soon!
|
||||
</p>
|
||||
<div class="wa-grid">
|
||||
<section class="wa-stack wa-gap-xs">
|
||||
<h2 class="wa-heading-s">Links</h2>
|
||||
<a href="#">Home</a>
|
||||
<a href="#">Get Started</a>
|
||||
<a href="#">Services</a>
|
||||
<a href="#">Portfolio</a>
|
||||
</section>
|
||||
<section class="wa-stack wa-gap-xs">
|
||||
<h2 class="wa-heading-s">Others</h2>
|
||||
<a href="#">Corporate</a>
|
||||
<a href="#">Terms of Service</a>
|
||||
<a href="#">Privacy Policy</a>
|
||||
</section>
|
||||
<section class="wa-stack">
|
||||
<h2 class="wa-heading-s">Social</h2>
|
||||
<div class="wa-cluster">
|
||||
<a href="#">
|
||||
<wa-icon-button
|
||||
style="font-size: var(--wa-font-size-l);"
|
||||
name="facebook"
|
||||
family="brands"
|
||||
label="Follow on Facebook"
|
||||
href="#"
|
||||
target="_blank"
|
||||
></wa-icon-button>
|
||||
</a>
|
||||
<a href="#">
|
||||
<wa-icon-button
|
||||
style="font-size: var(--wa-font-size-l);"
|
||||
name="bluesky"
|
||||
family="brands"
|
||||
label="Follow on Bluesky"
|
||||
href="#"
|
||||
target="_blank"
|
||||
></wa-icon-button>
|
||||
</a>
|
||||
<a href="#">
|
||||
<wa-icon-button
|
||||
style="font-size: var(--wa-font-size-l);"
|
||||
name="linkedin"
|
||||
family="brands"
|
||||
label="Follow on LinkedIn"
|
||||
href="#"
|
||||
target="_blank"
|
||||
></wa-icon-button>
|
||||
</a>
|
||||
<a href="#">
|
||||
<wa-icon-button
|
||||
style="font-size: var(--wa-font-size-l);"
|
||||
name="envelope-open"
|
||||
label="Email us"
|
||||
href="#"
|
||||
target="_blank"
|
||||
></wa-icon-button>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-split">
|
||||
<p>© 2025 All rights reserved.</p>
|
||||
<wa-select label="Language" value="english">
|
||||
<wa-option value="english">English</wa-option>
|
||||
<wa-option value="spanish">Spanish</wa-option>
|
||||
<wa-option value="french">French</wa-option>
|
||||
</wa-select>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user