Compare commits

..

59 Commits

Author SHA1 Message Date
Kelsey Jackson
e0038c3125 Initial Commit 2025-01-09 10:59:33 -06:00
lindsaym-fa
aa915c3e28 Doc revisions 2025-01-09 11:57:35 -05:00
Lea Verou
c79457a607 Attempt at better style isolation between themes
Still doesn't quite fix #475 but might be a nudge in the right direction.
2025-01-09 11:57:35 -05:00
Lea Verou
419f0610e4 Template-tweaks
- Move breadcrumbs to separate template
- Rename `beforeContent` to `header`
- Move breadcrumbs inside header
2025-01-09 02:26:01 -05:00
Cory LaViska
7ab5ca8640 3.0.0-alpha.8 2025-01-08 18:30:48 -05:00
Cory LaViska
c39faff936 update version (#473) 2025-01-08 18:17:31 -05:00
Lindsay M
6d31db57f6 Revise and add showcase to Themes doc (#456)
* Initial progress

* Make responsive

* quick fix to show theme name/description

* Small styling tweaks

* Documentation updates

* Revisions and improvements

* Avoid using static URLs 'cause that's ridiculous

---------

Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
2025-01-08 17:33:09 -05:00
Lea Verou
21ed4f82b0 Improve UX of Layout section 2025-01-08 17:13:38 -05:00
Lea Verou
844e374a72 Fix #470 2025-01-08 16:23:34 -05:00
Lea Verou
e5f4c14608 Fix native select caret positioning, fixes #411 2025-01-08 15:58:33 -05:00
Lea Verou
1ad963f5ad wa-card styling fixes 2025-01-08 15:36:12 -05:00
Lea Verou
4476117932 Add default layout as a failsafe 2025-01-08 15:20:26 -05:00
Lindsay M
e52a7a5ce5 Pre-release theme touchup (#465)
* Fix themed card styles

* Improve lowered surface colors across themes
2025-01-08 15:04:27 -05:00
Lindsay M
fa66f4262d Fix mobile theme selector; fixes #440 (#446)
* Fix styling

* Fix mobile theme selector label
2025-01-08 15:01:20 -05:00
Lea Verou
a87f3627bb Fix #451 without changing logic/specificity 2025-01-08 15:00:45 -05:00
Cory LaViska
06e432589f change migration => tailspin (#463) 2025-01-08 13:59:27 -05:00
Cory LaViska
b4c4074ae1 fix mobile color picker bug (#462) 2025-01-08 13:49:57 -05:00
Lea Verou
19042fcca4 Decouple dark mode & theme, fixes #445 closes #385 (#457)
Co-authored-by: Lindsay M <126139086+lindsaym-fa@users.noreply.github.com>
2025-01-08 12:50:29 -05:00
Lea Verou
8541369ae1 Fix #437 regression (#458) 2025-01-08 12:33:19 -05:00
Kelsey Jackson
31cfdf5704 Fixed radio button styling regression (#443)
* fixed styling regression

* Import missing appearance utilities

* Fix up radio button theme styles

* tweaked based on feedback

---------

Co-authored-by: lindsaym-fa <dev@lindsaym.design>
2025-01-08 12:07:28 -05:00
Lindsay M
3511a60b93 Fix missing select styles, improve consistency (#450)
* Refactor for consistency, fix missing theme styles

* Remove unused custom properties from docs

* Add missing custom property to docs

* Add UI test case
2025-01-08 12:04:22 -05:00
Lindsay M
e55e091192 Fix caret color on slider tooltips (#448) 2025-01-08 12:03:16 -05:00
Lindsay M
09df23dff8 Use theme properties for color picker border (#449) 2025-01-08 10:02:18 -05:00
Lea Verou
f4a88c3b3a Harmonize updated() definitions
- Use proper type
- Use same argument name
- Ensure `super.updated()` is called
2025-01-07 17:39:56 -05:00
Cory LaViska
559efcd1d2 Fix switch's submitted value; fixes #409 (#442)
* fix switch's submitted value; fixes #409

* update tests
2025-01-07 17:01:27 -05:00
Lindsay M
e046015ed5 Theme cleanup (#414)
* formatting, docs tweaks

* FA theme cleanup

* Revert removal of `--wa-form-control-height-*`

* Classic theme cleanup

* Use consistent selectors for dark mode

* Clean slate for additional themes

* Retire depth stylesheets

* Move header styles for themer out of themes

* Missed instance of dark mode selector

* Migration theme cleanup

* Brutalist theme cleanup

* Changelog for new themes

* Playful theme cleanup

* Formatting

* Default theme update

* Add tests for form theming

* Fix test typo

* Change misnamed `multiplier` properties to `scale`

* Active theme cleanup

* Mellow theme cleanup

* Cleanup unused FA styles

* Glassy theme progress

* Add checked styles to glassy

* Fix typo

* Final FA theme cleanup

* Rename FA theme to 'Awesome', allow in alpha

* Final brutalist theme cleanup

* A few more brutalist tweaks

* One last brutalist tweak

* Final mellow theme cleanup

* Final Tailwind theme cleanup

* Final active theme cleanup

* Some classic theme cleanup

* Remove unused `--wa-form-control-height-*`

* Rename `--wa-form-control-resting-color` to `border-color`

* Touch up callout `appearance` styles

* Add more themes to alpha

* Add changelog for removal of `--wa-form-control-height-*`

* Clean up colors

* Final classic theme cleanup

* Add new themes to alpha build

* Re-add teal (used by Awesome theme)

* sync mobile/desktop theme pickers and don't dup IDs

* Remove `color/standard.css` (duplicates `/themes/default/color.css`)

* add view transition

* Add premium theme for later cleanup

* Accommodate new tag `appearance` styles

* Revise `--wa-form-control-height-*` changelog entry

Co-authored-by: Lea Verou <lea@verou.me>

* Improve `--wa-border-width-scale` description

Co-authored-by: Lea Verou <lea@verou.me>

* Better border docs

* Premium tweaks

---------

Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
Co-authored-by: Lea Verou <lea@verou.me>
2025-01-07 15:41:57 -05:00
Lea Verou
44dbdd14cc Separate WebAwesomeFormAssociatedElement (and friends) into a separate file 2025-01-07 14:23:20 -05:00
lindsaym-fa
5e3fed605e Add changelog 2025-01-07 11:56:19 -05:00
Lea Verou
4b4f2247c5 [Tag] Add appearance, closes #435 2025-01-07 11:56:19 -05:00
Lea Verou
eca15dc7fc Revamp <wa-card> HTML & CSS, fix #431 (#433)
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
2025-01-07 10:12:32 -05:00
Lea Verou
eca444bbaa [Callout] Add appearance & size, closes #422 (#432)
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
2025-01-07 09:38:28 -05:00
Lea Verou
f39308dbc5 Allow customization of outlined styles, fixes #412 (#426) 2025-01-06 17:35:57 -05:00
Lea Verou
fc84e1a50d Replace M form control height with size-dependent height (#425) 2025-01-06 17:10:11 -05:00
Lea Verou
ef7d47e2b9 [Docs] Move commonalities across blocks to a single base layout (#424) 2025-01-06 17:01:29 -05:00
Lea Verou
a9af3172ad Rename Range to Slider (#428) 2025-01-06 16:44:43 -05:00
konnorrogers
cde8bea97a test commit 2025-01-06 13:24:54 -05:00
Kelsey Jackson
33b4045dad tweaked the tag component (#407)
* tweaked the tag component

* updated based on feedback

* updated to remove span

* changed display to initial

* prettier

---------

Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
2025-01-06 13:23:47 -05:00
Cory LaViska
bc4ad39f2e Fix tests (#410)
* skip broken test

* add middleware to follow new stylesheet imports

* fix avatar tests

* update badge tests

* fix button tests

* skip carousel test

* fix checkbox tests

* fix details test

* update radio button tests

* fix input tests

* fix progress bar tests

* update

* fix range tests

* fix select tests

* restore wrapper div to pass a11y tests

* fix switch tests

* fix tag tests

* fix textarea tests

* fix tooltip tests

* skips

* fix tree item tests

* [DRAFT]: test fixes (#421)

* working on some stuff..

* add a small delay for menu-item

* prettier

* add a small delay for menu-item

* prettier

* add a small delay for menu-item

* add a small delay for menu-item

* add a small delay for menu-item

* prettier

* Empty commit

* add a small delay for menu-item

* always build with alpha

* always build with alpha

* move to alpha builds

---------

Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
2025-01-06 13:13:34 -05:00
Konnor Rogers
b868b1e8fc fix alpha builds (#423)
* fix alpha builds

* Update docs/_includes/sidebar-group.njk

Co-authored-by: Lea Verou <lea@verou.me>

* Update docs/_includes/sidebar-group.njk

Co-authored-by: Lea Verou <lea@verou.me>

---------

Co-authored-by: Lea Verou <lea@verou.me>
2025-01-06 12:53:47 -05:00
Lea Verou
e916d771b0 Ensure --box-shadow & --border-width defaults are always set on the root stylable element, fixes #419 2025-01-06 12:41:28 -05:00
lindsaym-fa
bd6fe74c7d Fix missing input value styles 2025-01-04 16:42:45 -05:00
Lea Verou
ac7437894a Automate all overviews, fix bugs with filtering 2025-01-03 20:17:19 -05:00
Lea Verou
55ebe6e20b Add e-commerce tag, for overview 2025-01-03 20:14:51 -05:00
Lea Verou
e6388e7671 Let sort filter provide missing values so we can specify large values to place elements at the end 2025-01-03 19:20:49 -05:00
Lea Verou
9a21ae6f52 Make sure unlisted page cards never show up 2025-01-03 19:02:31 -05:00
Lea Verou
cd3386ce78 Exclude unlisted pages properly 2025-01-03 18:51:16 -05:00
Lea Verou
26b9bbb515 Automate Theming listing 2025-01-03 18:44:11 -05:00
Lea Verou
bda0ec0313 Overviews don't need to be MD files
And having them as MD files can insert pointless `<p>` tags if we're not careful, which can cause weird bugs.
2025-01-03 18:27:07 -05:00
Lea Verou
2490fbeaca attr filter for nicer optional attributes 2025-01-03 18:12:41 -05:00
Lea Verou
297149021e Add {% markdown %} paired shortcode 2025-01-03 17:45:26 -05:00
Lea Verou
c700c3ec09 Components index doesn't actually need to be a MD file
And having it as a MD file can insert pointless `<p>` tags if we're not careful, which can cause weird bugs.
2025-01-03 16:13:02 -05:00
Lea Verou
b383d8bf2d Move e-commerce patterns under E-commerce
As discussed on Slack with @kelseythejackson
2025-01-03 16:08:24 -05:00
Lea Verou
1dcf895be1 Don’t render children on the top level as well 2025-01-03 16:00:36 -05:00
Lea Verou
19fd55ca97 fix: noAlpha, not isAlpha 2025-01-03 15:58:42 -05:00
Lea Verou
fa094d924d Automate sidebar listings 2025-01-03 15:52:58 -05:00
Lea Verou
2a957e6316 Add layout and isAlpha to pattern pages automatically 2025-01-03 15:52:27 -05:00
Lea Verou
90b6a9a8ac Add status as computed data on component pages 2025-01-03 15:02:36 -05:00
Lea Verou
99fdd90601 [Select] Remove leftover code
The select uses the appearance utils, so this is done automatically.
2025-01-03 14:23:09 -05:00
Lea Verou
ecaa461638 [Select] Remove leftover code, rel #413
This was meant to be deleted, since there’s already `min-height: var(--wa-form-control-height);` above it which already responds to size.
2025-01-03 14:14:39 -05:00
202 changed files with 4730 additions and 7366 deletions

View File

@@ -31,7 +31,7 @@ jobs:
- name: Lint
run: npm run prettier
- name: Build
run: npm run build
run: npm run build:alpha
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run CSR tests

View File

@@ -30,7 +30,7 @@ jobs:
run: npm run prettier
- name: Build
run: npm run build
run: npm run build:alpha
- name: Install Playwright
run: npx playwright install --with-deps

View File

@@ -20,6 +20,12 @@ const packageData = JSON.parse(await readFile('./package.json', 'utf-8'));
const isAlpha = process.argv.includes('--alpha');
const isDev = process.argv.includes('--develop');
const globalData = {
package: packageData,
isAlpha,
layout: 'page.njk',
};
export default function (eleventyConfig) {
// NOTE - alpha setting removes certain pages
if (isAlpha) {
@@ -32,8 +38,9 @@ export default function (eleventyConfig) {
}
// Add template data
eleventyConfig.addGlobalData('package', packageData);
eleventyConfig.addGlobalData('isAlpha', isAlpha);
for (let name in globalData) {
eleventyConfig.addGlobalData(name, globalData[name]);
}
// Template filters - {{ content | filter }}
eleventyConfig.addFilter('inlineMarkdown', content => markdown.renderInline(content || ''));
@@ -48,6 +55,9 @@ export default function (eleventyConfig) {
return `https://early.webawesome.com/webawesome@${packageData.version}/dist/` + location.replace(/^\//, '');
});
// Paired shortcodes - {% shortCode %}content{% endShortCode %}
eleventyConfig.addPairedShortcode('markdown', content => markdown.render(content || ''));
// Helpers
// Remove elements that have [data-alpha="remove"]

View File

@@ -24,7 +24,6 @@
<script type="module" src="/dist/webawesome.loader.js"></script>
<link rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/default.css" />
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/color/standard.css" />
<link rel="stylesheet" href="/dist/styles/forms.css" />
{# Docs styles #}
@@ -80,11 +79,12 @@
</details>
</nav>
{% block beforeContent %}{% endblock %}
{% block header %}
{% include 'breadcrumbs.njk' %}
<h1 class="title">{{ title }}</h1>
{% endblock %}
{% block content %}
<h1 class="title">{{ title }}</h1>
{{ content | safe }}
{% endblock %}

View File

@@ -76,16 +76,13 @@
newStylesheet.addEventListener("load", updateStylesheet)
document.documentElement.classList.toggle(
`wa-theme-${preset}-dark`,
isDark()
);
document.documentElement.classList.toggle(`wa-dark`, isDark());
</script>
</head>
<body class="layout-{{ layout | stripExtension }}">
<!-- use view="desktop" as default to reduce layout jank on desktop site. -->
<wa-page view="desktop" disable-navigation-toggle="">
<header slot="header">
<header slot="header" class="wa-split">
{# Logo #}
<div id="docs-branding">
{# Nav toggle #}
@@ -101,9 +98,9 @@
<wa-badge variant="warning" appearance="filled" class="only-desktop">Alpha</wa-badge>
</div>
<div id="docs-toolbar">
<div id="docs-toolbar" class="wa-cluster wa-gap-xs">
{# Desktop selectors #}
<div class="only-desktop">
<div class="only-desktop wa-cluster wa-gap-xs">
{% include "preset-theme-selector.njk" %}
{% include "color-scheme-selector.njk" %}
</div>
@@ -121,7 +118,7 @@
{% if hasSidebar %}
{# Mobile selectors #}
<div class="wa-mobile-only" slot="navigation-header">
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));">
<div class="wa-cluster wa-gap-xs">
{% include "preset-theme-selector.njk" %}
{% include "color-scheme-selector.njk" %}
</div>
@@ -149,22 +146,14 @@
</details>
</nav>
{% set breadcrumbs = page.url | breadcrumbs %}
{% if breadcrumbs.length > 0 %}
<wa-breadcrumb id="docs-breadcrumbs">
{% for crumb in breadcrumbs %}
<wa-breadcrumb-item href="{{ crumb.url }}">{{ crumb.title }}</wa-breadcrumb-item>
{% endfor %}
<wa-breadcrumb-item>{# Current page #}</wa-breadcrumb-item>
</wa-breadcrumb>
{% else %}
{% endif %}
{% block beforeContent %}{% endblock %}
{% block header %}
{% include 'breadcrumbs.njk' %}
<h1 class="title">{{ title }}</h1>
{% endblock %}
{% block content %}
<h1 class="title">{{ title }}</h1>
{{ content | safe }}
{% endblock %}

View File

@@ -0,0 +1,10 @@
{% set breadcrumbs = page.url | breadcrumbs %}
{% if breadcrumbs.length > 0 %}
<wa-breadcrumb id="docs-breadcrumbs">
{% for crumb in breadcrumbs %}
<wa-breadcrumb-item href="{{ crumb.url }}">{{ crumb.title }}</wa-breadcrumb-item>
{% endfor %}
<wa-breadcrumb-item>{# Current page #}</wa-breadcrumb-item>
</wa-breadcrumb>
{% else %}
{% endif %}

View File

@@ -1,5 +1,5 @@
{# Color scheme selector #}
<wa-dropdown id="color-scheme-selector">
<wa-dropdown class="color-scheme-selector">
<wa-button slot="trigger" appearance="filled" size="small" pill caret title="Press \ to toggle">
<wa-icon class="only-light" slot="prefix" name="sun" variant="regular"></wa-icon>
<wa-icon class="only-dark" slot="prefix" name="moon" variant="regular"></wa-icon>

View File

@@ -4,10 +4,9 @@
{% for category, pages in allPages | groupByTags(categories) -%}
<h2 class="index-category">{{ category | getCategoryTitle(categories) }}</h2>
{%- for page in pages -%}
{%- if not page.data.unlisted and not page.data.parent -%}
{%- if not page.data.parent or listChildren -%}
{% include "page-card.njk" %}
{%- endif -%}
{%- endfor -%}
{%- endfor -%}
</section>

View File

@@ -1,4 +1,5 @@
<a href="{{ page.url }}" data-keywords="{{ page.data.keywords }}">
{%- if not page.data.unlisted -%}
<a href="{{ page.url }}"{{ page.data.keywords | attr('data-keywords') }}>
<wa-card with-header>
<div slot="header">
{% include "svgs/" + (page.data.icon or "thumbnail-placeholder") + ".njk" %}
@@ -6,3 +7,4 @@
<span class="page-name">{{ page.data.title }}</span>
</wa-card>
</a>
{% endif %}

View File

@@ -1,18 +1,19 @@
{# Preset theme selector #}
<wa-dropdown id="preset-theme-selector">
<wa-dropdown class="preset-theme-selector">
<wa-button slot="trigger" appearance="filled" size="small" pill caret>
<wa-icon slot="prefix" name="paintbrush" variant="regular"></wa-icon>
<span id="preset-theme-selector__text">Default</span>
<span class="preset-theme-selector__text">Default</span>
</wa-button>
<wa-menu>
<wa-menu-item type="checkbox" value="default">Default</wa-menu-item>
<wa-menu-item type="checkbox" value="classic">Classic</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="fa">Font Awesome</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="active">Active</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="brutalist">Brutalism</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="glassy">Glassy</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="migration">Migration</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="playful">Playful</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="premium">Premium</wa-menu-item>
<wa-menu-item type="checkbox" value="default" data-description="Your trusty companion, like a perfectly broken-in pair of jeans.">Default</wa-menu-item>
<wa-menu-item type="checkbox" value="classic" data-description="Timeless elegance that never goes out of style.">Classic</wa-menu-item>
<wa-menu-item type="checkbox" value="awesome" data-description="Punchy and vibrant, the rockstar of themes.">Awesome</wa-menu-item>
<wa-menu-item type="checkbox" value="active" data-description="Energetic and tactile, always in motion.">Active</wa-menu-item>
<wa-menu-item type="checkbox" value="brutalist" data-description="Sharp, raw, and unapologetically bold.">Brutalist</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="glassy" data-description="TODO">Glassy</wa-menu-item>
<wa-menu-item type="checkbox" value="mellow" data-description="Soft and soothing, like a lazy Sunday morning.">Mellow</wa-menu-item>
<wa-menu-item type="checkbox" value="tailspin" data-description="Like a bird in flight, guiding you from there to here.">Tailspin</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="playful" data-description="TODO">Playful</wa-menu-item>
<wa-menu-item data-alpha="remove" type="checkbox" value="premium" data-description="TODO">Premium</wa-menu-item>
</wa-menu>
</wa-dropdown>

View File

@@ -0,0 +1,22 @@
{# Some collections (like "patterns") will not have any items in the alpha build for example. So this checks to make sure the collection exists. #}
{% if collections[tag] -%}
<wa-details {{ (tag in (tags or [])) | attr('open') }}>
<h2 slot="summary">
{% set groupUrl %}/docs/{{ tag }}/{% endset %}
{% if groupUrl | getCollectionItemFromUrl %}
<a href="{{ groupUrl }}" title="Overview">{{ title or (tag | capitalize) }}
<wa-icon name="grid-2"></wa-icon>
</a>
{% else %}
{{ title or (tag | capitalize) }}
{% endif %}
</h2>
<ul>
{% for page in collections[tag] | sort %}
{% if not page.data.parent -%}
{% include 'sidebar-link.njk' %}
{%- endif %}
{% endfor %}
</ul>
</wa-details>
{%- endif %}

View File

@@ -0,0 +1,16 @@
{% if not (isAlpha and page.data.noAlpha) and page.fileSlug != tag and not page.data.unlisted -%}
<li>
<a href="{{ page.url }}">{{ page.data.title }}</a>
{% if page.data.status == 'experimental' %}<wa-icon name="flask"></wa-icon>{% endif %}
{% if page.data.isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
{% set children = page.data.children %}
{% if children.length > 0 %}
<ul>
{% for page in children %}
{% include 'sidebar-link.njk' %}
{% endfor %}
</ul>
{% endif %}
</li>
{%- endif %}

View File

@@ -19,121 +19,13 @@
<li><a href="/docs/resources/changelog">Changelog</a></li>
</ul>
{# Components #}
<wa-details {{ 'open' if '/components/' in page.url }}>
<h2 slot=summary>
<a href="/docs/components/" title="Overview">Components
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
{% for component in collections.components | sort %}
{% if not component.data.parent and not (isAlpha and component.data.noAlpha) and not component.data.unlisted %}
<li>
<a href="/docs/components/{{ component.fileSlug }}">{{ component.data.title }}</a>
{% if components[component.fileSlug].status == 'experimental' %}<wa-icon name="flask"></wa-icon>{% endif %}
{% if component.data.isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
<ul>
{% for child in collections.components | sort %}
{% if child.data.parent == component.fileSlug and not (isAlpha and child.data.noAlpha) %}
<li>
<a href="/docs/components/{{ child.fileSlug }}">{{ child.data.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
</wa-details>
<wa-details {{ 'open' if '/native/' in page.url }}>
<h2 slot=summary>
<a href="/docs/native/" title="Overview">Native Styles
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
{% for page in collections.native | sort %}
{% if page.fileSlug != 'native' and not page.unlisted %}
<li>
<a href="/docs/native/{{ page.fileSlug }}">{{ page.data.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</wa-details>
<wa-details {{ 'open' if '/utilities/' in page.url }}>
<h2 slot=summary>
<a href="/docs/utilities/" title="Overview">Style Utilities
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
{% for page in collections.utilities | sort %}
{% if page.fileSlug != 'utilities' and not page.unlisted %}
<li>
<a href="/docs/utilities/{{ page.fileSlug }}">{{ page.data.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</wa-details>
{# Layout #}
<h2>
<a href="/docs/layout" title="Overview">Layout
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
{% for page in collections.layout | sort %}
{% if page.fileSlug != 'layout' and not page.unlisted %}
<li>
<a href="{{ page.url }}">{{ page.data.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
{# Patterns #}
{% if not isAlpha %}
<h2>Patterns</h2>
<ul>
<li><a href="/docs/patterns/app">Web App</a></li>
<li><a href="/docs/patterns/ecommerce">E-commerce</a>
<ul>
<li><a href="/docs/patterns/ecommerce-product-review">Product Reviews</a></li>
<li><a href="/docs/patterns/ecommerce-product-list">Product Lists</a></li>
<li><a href="/docs/patterns/ecommerce-category-preview">Category Previews</a></li>
<li><a href="/docs/patterns/ecommerce-shopping-cart">Shopping Carts</a></li>
<li><a href="/docs/patterns/ecommerce-category-filter">Category Filters</a></li>
<li><a href="/docs/patterns/ecommerce-product-detail">Product Detail</a></li>
<li><a href="/docs/patterns/ecommerce-order-summary">Order Summaries</a></li>
<li><a href="/docs/patterns/ecommerce-order-history">Order History</a></li>
</ul>
</li>
<li><a href="/docs/patterns/blog">Blog</a></li>
<li><a href="/docs/patterns/news">News</a></li>
</ul>
{% endif %}
{# Theming #}
<h2>
<a href="/docs/theming" title="Overview">Theming
<wa-icon name="grid-2"></wa-icon>
</a>
</h2>
<ul>
{% for page in collections.theming | sort %}
{% if page.fileSlug != 'theming' and not page.unlisted %}
<li>
<a href="/docs/theming/{{ page.fileSlug }}">{{ page.data.title }}</a>
</li>
{% endif %}
{% for tag, title in {
'components': 'Components',
'native': 'Native Styles',
'utilities': 'Style Utilities',
'layout': 'Layout',
'patterns': 'Patterns',
'theming': 'Theming'
} %}
{% include 'sidebar-group.njk' %}
{% endfor %}
</ul>

View File

Before

Width:  |  Height:  |  Size: 337 B

After

Width:  |  Height:  |  Size: 337 B

View File

@@ -48,15 +48,12 @@
stylesheet.href = `/dist/styles/themes/${preset}.css`
document.documentElement.classList.toggle(
`wa-theme-${preset}-dark`,
isDark()
);
document.documentElement.classList.toggle(`wa-dark`, isDark());
</script>
</head>
<body class="layout-{{ layout | stripExtension }}">
{% block beforeContent %}{% endblock %}
{% block header %}{% endblock %}
{% block content %}
{{ content | safe }}

38
docs/_layouts/block.njk Normal file
View File

@@ -0,0 +1,38 @@
{% set hasSidebar = true %}
{% set hasOutline = true %}
{% extends '../_includes/base.njk' %}
{# Component header #}
{% block header %}
{% include 'breadcrumbs.njk' %}
<h1 class="title">{{ title }}</h1>
<div class="block-info">
{% set snippets = (elements or element or snippets or snippet) | dict %}
{% for snippet, link in snippets %}
{% if snippet %}
<code class="class">
{%- if link -%}
<a href="{{ link }}">{{ snippet }}</a>
{%- else -%}
{{ snippet }}
{%- endif-%}
</code>
{%- endif %}
{% endfor %}
{% include '../_includes/status.njk' %}
</div>
{% if description %}
<p class="summary">
{{ description | inlineMarkdown | safe }}
</p>
{% endif %}
{% block notes %}{% endblock %}
{% endblock %}
{# Content #}
{% block content %}
{{ content | safe }}
{% endblock %}

View File

@@ -1,23 +1,8 @@
{% set hasSidebar = true %}
{% set hasOutline = true %}
{% extends '../_layouts/block.njk' %}
{% set component = components[page.fileSlug] %}
{% set description = component.summary %}
{% set status = component.status %}
{% set since = component.since %}
{% extends '../_includes/base.njk' %}
{# Component header #}
{% block beforeContent %}
<h1 class="title">{{ title }}</h1>
<div class="component-info">
<code class="tag">&lt;{{ component.tagName }}&gt;</code>
{% include '../_includes/status.njk' %}
</div>
<p class="summary">
{{ component.summary | inlineMarkdown | safe }}
</p>
{% block notes %}
{% if native %}
<wa-callout variant="success">
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
@@ -27,11 +12,6 @@
{% endif %}
{% endblock %}
{# Content #}
{% block content %}
{{ content | safe }}
{% endblock %}
{# Component API #}
{% block afterContent %}
{# Slots #}

View File

@@ -1,37 +1,18 @@
{% set hasSidebar = true %}
{% set hasOutline = true %}
{% extends '../_includes/base.njk' %}
{% extends '../_layouts/block.njk' %}
{# Component header #}
{% block beforeContent %}
<h1 class="title">{{ title }}</h1>
<div class="component-info">
{% for tag, url in elements %}
<code class="tag"><a href="{{ url }}">{{ tag }}</a></code>
{% endfor %}
{% include '../_includes/status.njk' %}
</div>
{% if description -%}
<p class="summary">{{ description | inlineMarkdown | safe }}</p>
{%- endif %}
{% block notes %}
{% if component %}
<wa-callout variant="success">
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
Want to do more?
Check out the {% for name in (component | toArray) -%}
Check out the {% for name in (component | toList) -%}
{{ ' and ' if loop.last and not loop.first }}<a href="/docs/components/{{ name }}"><code>&lt;wa-{{ name }}&gt;</code></a>{{ ', ' if not loop.last }}
{%- endfor %} component{{ 's' if (component | isArray) }}</a>!
{%- endfor %} component{{ 's' if (component | isList) }}</a>!
</wa-callout>
{% endif %}
{% endblock %}
{# Content #}
{% block content %}
{{ content | safe }}
{% endblock %}
{# Component API #}
{% block afterContent %}
{# Slots #}
{% if css_file %}

View File

@@ -0,0 +1,25 @@
---
layout: page-outline
tags: ["overview"]
---
{% set forTag = forTag or (page.url | split('/') | last) %}
{% if description %}
<div class="index-summary">{{ description | markdown | safe }}</div>
{% endif %}
<div id="block-filter">
<wa-input type="search" placeholder="Search {{ title }}" clearable autofocus>
<wa-icon slot="prefix" name="search"></wa-icon>
</wa-input>
</div>
{% set allPages = collections[forTag] %}
{% include "grouped-pages.njk" %}
<link href="/assets/styles/filter.css" rel="stylesheet">
<script type="module" src="/assets/scripts/filter.js"></script>
{% if content | trim %}
<br> {# Temp fix for spacing issue #}
{{ content | safe }}
{% endif %}

View File

@@ -1,4 +0,0 @@
{% set hasSidebar = true %}
{% set hasOutline = true %}
{% extends "../_includes/base.njk" %}

View File

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

View File

@@ -38,8 +38,12 @@ export function getTitleFromUrl(url, collection) {
return item?.data.title || '';
}
export function split(text, separator) {
return (text + '').split(separator).filter(Boolean);
}
export function breadcrumbs(url, { withCurrent = false } = {}) {
const parts = url.split('/').filter(Boolean);
const parts = split(url, '/');
const ret = [];
while (parts.length) {
@@ -70,12 +74,30 @@ export function breadcrumbs(url, { withCurrent = false } = {}) {
return ret;
}
export function isArray(value) {
return Array.isArray(value);
export function isObject(value) {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
export function toArray(value) {
return isArray(value) ? value : [value];
export function isList(value) {
return Array.isArray(value) || value instanceof Set;
}
/** Get an Array or Set */
export function toList(value) {
return isList(value) ? value : [value];
}
/**
* Convert any value to something that can be iterated over with a for key, value loop.
* Arrays and sets will be converted to a Map of value -> undefined
*/
export function dict(value) {
if (value instanceof Map || isObject(value)) {
return value;
}
let list = toList(value);
return new Map([...list].map(item => [item, undefined]));
}
export function deepValue(obj, key) {
@@ -83,11 +105,15 @@ export function deepValue(obj, key) {
return key.reduce((subObj, property) => subObj?.[property], obj);
}
function isNumeric(value) {
export function isNumeric(value) {
return typeof value === 'number' || (typeof value === 'string' && !isNaN(value));
}
function isEmpty(value) {
export function isString(value) {
return typeof value === 'string';
}
export function isEmpty(value) {
return value === null || value === undefined || value === '';
}
@@ -113,13 +139,13 @@ function compare(a, b) {
return (a + '').localeCompare(b);
}
/** Sort an array of objects */
export function sort(arr, keys = ['data.order', 'data.title']) {
keys = toArray(keys);
/** Sort an array of objects by one or more of their properties */
export function sort(arr, by = { 'data.order': 1, 'data.title': '' }) {
let keys = Array.isArray(by) ? by : Object.keys(by);
return arr.sort((a, b) => {
let aValues = keys.map(key => deepValue(a, key));
let bValues = keys.map(key => deepValue(b, key));
let aValues = keys.map(key => deepValue(a, key) ?? by[key]);
let bValues = keys.map(key => deepValue(b, key) ?? by[key]);
for (let i = 0; i < aValues.length; i++) {
let aVal = aValues[i];
@@ -198,3 +224,41 @@ export function getCategoryTitle(category, categories) {
// Capitalized
return category.charAt(0).toUpperCase() + category.slice(1);
}
const IDENTITY = x => x;
/**
* Helper to print out one or more HTML attributes, especially conditional ones.
* Usage in 11ty:
* - Single attribute: `<foo{{ value | attr(name) }}>`
* - Multiple attributes: `<foo{{ { name1: value1, name2: value2 } | attr }}>`
*
* @overload
* @param {any} value - The attribute value If falsey, the attribute is not printed. If `true` the attribute is printed without a value.
* @param {string} name - The name of the attribute
*
* @overload
* @param {Object<string, any>} obj - Map of attribute names to values
*
* @returns {string} The attribute string. No `| safe` is needed.
*/
export function attr(value, name) {
const safe = this?.env.filters.safe ?? IDENTITY;
if (arguments.length === 1 && value && typeof value === 'object') {
// Called with a single object argument of names to values
let ret = Object.entries(obj)
.map(([name, value]) => attr(value, name))
.join('');
return safe(ret);
}
if (!value) {
// false, "", null, undefined
return '';
}
let ret = ' ' + name + (value === true ? '' : `="${value}"`);
return safe(ret);
}

View File

Before

Width:  |  Height:  |  Size: 698 KiB

After

Width:  |  Height:  |  Size: 698 KiB

View File

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 241 KiB

View File

Before

Width:  |  Height:  |  Size: 786 KiB

After

Width:  |  Height:  |  Size: 786 KiB

View File

Before

Width:  |  Height:  |  Size: 716 KiB

After

Width:  |  Height:  |  Size: 716 KiB

View File

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

Before

Width:  |  Height:  |  Size: 438 KiB

After

Width:  |  Height:  |  Size: 438 KiB

View File

@@ -5,22 +5,24 @@
function setColorScheme(newColorScheme) {
colorScheme = newColorScheme;
localStorage.setItem('colorScheme', colorScheme);
const presetTheme = window.getPresetTheme();
// Update the UI
updateSelection();
// Toggle the dark mode class
document.documentElement.classList.toggle(`wa-theme-${presetTheme}-dark`, window.isDark());
document.documentElement.classList.toggle(`wa-dark`, window.isDark());
}
function updateSelection() {
const menu = document.querySelector('#color-scheme-selector wa-menu');
if (!menu) return;
[...menu.querySelectorAll('wa-menu-item')].forEach(async item => {
await customElements.whenDefined(item.localName);
await item.updateComplete;
item.checked = item.getAttribute('value') === colorScheme;
const menus = document.querySelectorAll('.color-scheme-selector wa-menu');
menus.forEach(menu => {
if (!menu) return;
[...menu.querySelectorAll('wa-menu-item')].forEach(async item => {
await customElements.whenDefined(item.localName);
await item.updateComplete;
item.checked = item.getAttribute('value') === colorScheme;
});
});
}
@@ -28,14 +30,16 @@
// Selection is not preserved when changing page, so update when opening dropdown
document.addEventListener('wa-show', event => {
const colorSchemeSelector = event.target.closest('#color-scheme-selector');
const colorSchemeSelector = event.target.closest('.color-scheme-selector');
if (!colorSchemeSelector) return;
updateSelection();
});
// Listen for selections
document.addEventListener('wa-select', event => {
const menu = event.target.closest('#color-scheme-selector wa-menu');
const selector = event.target.closest('.color-scheme-selector');
const menu = selector?.querySelector('wa-menu');
console.log(menu);
if (!menu) return;
setColorScheme(event.detail.item.value);
});

View File

@@ -0,0 +1,25 @@
function updateResults(input) {
const filter = input.value.toLowerCase().trim();
let filtered = Boolean(filter);
for (let grid of document.querySelectorAll('.index-grid')) {
grid.classList.toggle('filtered', filtered);
for (let item of grid.querySelectorAll('a:has(> wa-card)')) {
let isMatch = true;
if (filter) {
const content = item.textContent.toLowerCase() + ' ' + (item.getAttribute('data-keywords') + ' ');
isMatch = content.includes(filter);
}
item.hidden = !isMatch;
}
}
}
document.documentElement.addEventListener('wa-input', e => {
if (e.target?.matches('#block-filter wa-input')) {
updateResults(e.target);
}
});

View File

@@ -1,13 +1,17 @@
//
// Preset theme selector
//
(() => {
function applyThemeChange(stylesheet, newStylesheet) {
newStylesheet.rel = 'stylesheet';
newStylesheet.id = stylesheet.id;
requestAnimationFrame(() => {
stylesheet.remove();
});
}
function setPresetTheme(newPresetTheme) {
presetTheme = newPresetTheme;
localStorage.setItem('presetTheme', presetTheme);
const stylesheet = document.getElementById('theme-stylesheet');
const newStylesheet = Object.assign(document.createElement('link'), {
href: `/dist/styles/themes/${presetTheme}.css`,
rel: 'preload',
@@ -17,54 +21,78 @@
newStylesheet.addEventListener(
'load',
() => {
newStylesheet.rel = 'stylesheet';
newStylesheet.id = stylesheet.id;
requestAnimationFrame(() => {
stylesheet.remove();
});
const canUseViewTransitions =
document.startViewTransition && !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (canUseViewTransitions) {
document.startViewTransition(() => applyThemeChange(stylesheet, newStylesheet));
} else {
applyThemeChange(stylesheet, newStylesheet);
}
},
{ once: true },
);
document.head.append(newStylesheet);
// Update the UI
updateSelection();
// Toggle the dark mode class
document.documentElement.classList.toggle(`wa-theme-${presetTheme}-dark`, window.isDark());
document.documentElement.classList.toggle(`wa-dark`, window.isDark());
}
function updateSelection(container = document) {
const menu = container.querySelector('#preset-theme-selector wa-menu');
if (!menu) return;
[...menu.querySelectorAll('wa-menu-item')].forEach(async item => {
const isChecked = item.getAttribute('value') === presetTheme;
if (isChecked) {
container.querySelector('#preset-theme-selector__text').textContent = item.innerText;
const menus = container.querySelectorAll('.preset-theme-selector wa-menu');
if (!menus) return;
[...menus].forEach(menu => {
// Clear all checked states
[...menu.querySelectorAll('wa-menu-item')].forEach(async item => {
await customElements.whenDefined(item.localName);
await item.updateComplete;
item.checked = false; // Reset all items to unchecked first
});
// Then set only the selected item as checked
const selectedItem = menu.querySelector(`wa-menu-item[value="${presetTheme}"]`);
if (selectedItem) {
customElements.whenDefined(selectedItem.localName).then(async () => {
await selectedItem.updateComplete;
selectedItem.checked = true;
container.querySelectorAll('.preset-theme-selector__text').forEach(themeSelector => {
themeSelector.textContent = selectedItem.innerText;
});
});
}
await customElements.whenDefined(item.localName);
await item.updateComplete;
item.checked = isChecked;
});
}
// Updates any element on the page with [data-theme-name] and [data-theme-description] with the current themes info
function updateThemeNameAndDescription(name, description) {
document.querySelectorAll('[data-theme-name]').forEach(el => (el.textContent = name));
document.querySelectorAll('[data-theme-description]').forEach(el => (el.textContent = description));
}
let presetTheme = window.getPresetTheme();
// Selection is not preserved when changing page, so update when opening dropdown
document.addEventListener('wa-show', event => {
const presetThemeSelector = event.target.closest('#preset-theme-selector');
const presetThemeSelector = event.target.closest('.preset-theme-selector');
if (!presetThemeSelector) return;
updateSelection();
});
// Listen for selections
document.addEventListener('wa-select', event => {
const menu = event.target.closest('#preset-theme-selector wa-menu');
const menu = event.target.closest('.preset-theme-selector wa-menu');
if (!menu) return;
setPresetTheme(event.detail.item.value);
updateThemeNameAndDescription(event.detail.item.textContent, event.detail.item.getAttribute('data-description'));
});
// Set the initial preset name/description in the UI by grabbing it from the dropdown (ugly, but quick)
const currentTheme = document.querySelector(`.preset-theme-selector wa-menu-item[value="${presetTheme}"]`);
if (currentTheme) {
updateThemeNameAndDescription(currentTheme.textContent, currentTheme.getAttribute('data-description'));
}
// Update the color scheme when the preference changes
window.matchMedia('(prefers-preset-theme: dark)').addEventListener('change', () => setPresetTheme(presetTheme));
updateSelection();

View File

@@ -10,8 +10,8 @@
--wa-brand-grey: #30323b;
}
html.wa-theme-default-dark .only-light,
html:not(.wa-theme-default-dark) .only-dark {
.wa-dark .only-light,
.only-dark:not(.wa-dark, .wa-dark *) {
display: none;
}
@@ -22,7 +22,7 @@ wa-page {
/* Header */
wa-page::part(header) {
background-color: var(--wa-color-surface-default);
border-bottom: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
border-bottom: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-surface-border);
}
wa-page::part(body) {
@@ -34,10 +34,6 @@ wa-page::part(header-actions) {
}
wa-page > header {
flex: 1 1 auto;
display: flex;
align-items: center;
justify-content: space-between;
padding-inline: var(--wa-space-xl);
a[href='/'] {
@@ -81,7 +77,7 @@ wa-page > header {
}
wa-button#search-trigger {
--background-color: var(--wa-form-control-background-color);
--border-color: var(--wa-form-control-resting-color);
--border-color: var(--wa-form-control-border-color);
}
#search-trigger kbd {
font-size: var(--wa-font-size-2xs);
@@ -215,6 +211,20 @@ wa-page::part(menu) {
scrollbar-width: thin;
}
wa-page[view='mobile'] :is([slot='navigation-header'], [slot='navigation']) {
padding: 0;
& wa-details::part(icon) {
padding-inline: var(--wa-space-xs); /* aligns details icons with drawer close icon */
}
}
[slot='navigation-header'] wa-menu {
font-family: var(--wa-font-family-body);
font-size: var(--wa-font-size-m);
font-weight: var(--wa-font-weight-normal);
}
/* Main content */
wa-page > main {
max-width: 80ch;
@@ -230,7 +240,7 @@ h1.title wa-badge {
}
}
.component-info {
.block-info {
margin-block-end: var(--wa-flow-spacing);
}
@@ -326,16 +336,18 @@ wa-page > main:has(> .index-grid) {
a {
border-radius: var(--wa-border-radius-l);
text-decoration: none;
}
wa-card {
--box-shadow: none;
box-shadow: none;
--spacing: var(--wa-space-m);
inline-size: 100%;
&:hover {
--border-color: var(--wa-color-brand-border-loud);
--box-shadow: 0 0 0 var(--wa-border-width-s) var(--border-color);
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);
@@ -428,7 +440,7 @@ wa-page > main:has(> .index-grid) {
@media screen and not (max-width: 768px) {
/* Navigation sidebar */
wa-page::part(navigation) {
border-right: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
border-right: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-surface-border);
}
wa-page > #sidebar {

View File

@@ -0,0 +1,37 @@
wa-card#drawer-card::part(header) {
--spacing: 0;
justify-content: flex-end;
overflow: hidden;
}
#block-filter {
margin-block-end: var(--wa-space-xl);
}
.index-grid.filtered {
h2 {
/* Hide headings while filtering */
display: none;
}
&:not(:has(> a:not([hidden]))) {
/* Were filtering and there are no results */
&::before {
content: var(--empty-message);
grid-column: 1 / -1;
color: var(--wa-color-on-quiet);
font-style: italic;
font-weight: var(--wa-font-weight-action);
}
/* Show empty state when there's a search filter and no results */
&[data-empty] {
--empty-message: attr(data-empty);
}
&:not([data-empty]) {
--empty-message: 'No results';
}
}
}

View File

@@ -31,6 +31,9 @@
}
@media screen and (max-width: 1199px) {
wa-page [slot='aside'] {
display: none;
}
#outline {
padding-block: 0.25rem;
margin-block-end: -1rem;

View File

@@ -1,5 +1,14 @@
/* #region Custom Styles */
@container preview (min-width: 0) {
/* Theme Builder Headers
* These styles control the appearance of the header of the theme builder,
* allowing each theme to have a unique hero section.
*/
/* #region Default */
html.wa-theme-default .preview-container {
container-name: default-theme;
}
@container default-theme (min-width: 0) {
.hero-background {
height: 47rem;
background-color: var(--wa-color-brand-fill-loud);
@@ -22,7 +31,7 @@
}
.hero wa-button[variant='brand'] {
--background: var(--wa-color-neutral-fill-quiet);
--background-color: var(--wa-color-neutral-fill-quiet);
--text-color: var(--wa-color-neutral-on-normal);
}
@@ -41,10 +50,733 @@
}
/* responsive */
@container preview (min-width: 1040px) {
@container default-theme (min-width: 1040px) {
.hero-background::after {
background-position: right bottom;
background-size: 90%;
}
}
/* #endregion */
/* #region Tailspin */
html.wa-theme-tailspin .preview-container {
container-name: tailspin-theme;
}
@container tailspin-theme (min-width: 0) {
.project-header {
background: var(--wa-color-surface-default);
}
.hero {
--hero-background-color: var(--wa-color-surface-default);
--hero-lines-color: color-mix(in oklab, var(--wa-color-neutral-fill-normal), transparent 30%);
background: linear-gradient(to top, var(--wa-color-surface-lowered), transparent 40%),
radial-gradient(circle at 10% 70%, color-mix(in oklab, var(--wa-color-red-50) 16%, transparent), transparent 30%),
radial-gradient(
circle at 40% 50%,
color-mix(in oklab, var(--wa-color-indigo-40) 16%, transparent),
transparent 40%
),
radial-gradient(circle at 80% 25%, color-mix(in oklab, var(--wa-color-red-50) 8%, transparent), transparent 20%),
radial-gradient(
circle at 80% 80%,
color-mix(in oklab, var(--wa-color-indigo-40) 16%, transparent),
transparent 40%
),
radial-gradient(circle at 90% 30%, color-mix(in oklab, var(--wa-color-red-60) 8%, transparent), transparent 10%),
linear-gradient(176deg, var(--hero-background-color), transparent 6rem),
linear-gradient(90deg, var(--hero-background-color), transparent),
repeating-linear-gradient(
var(--hero-lines-color),
var(--hero-lines-color) 1px,
transparent 1px,
transparent 10rem,
var(--hero-lines-color) 10rem
),
repeating-linear-gradient(
90deg,
var(--hero-lines-color),
var(--hero-lines-color) 1px,
transparent 1px,
transparent 10rem,
var(--hero-lines-color) 10rem
),
var(--hero-background-color);
& .title {
padding-block: calc(var(--wa-space-3xl) * 2) calc(var(--wa-space-3xl) * 10);
& .hero-title {
font-size: calc((var(--wa-font-size-4xl) * 1.125) * 1.125);
margin-block: 0 var(--wa-space-3xl);
}
}
}
.badge-stock {
position: absolute;
top: var(--wa-space-l);
left: var(--wa-space-l);
}
.message-composer wa-card {
&::part(footer) {
border: none;
}
& wa-icon-button {
color: var(--wa-color-base-50);
}
}
.products {
margin-top: calc(var(--wa-space-3xl) * -8);
}
pre.codeblock {
background-color: var(--wa-color-neutral-fill-normal);
}
}
/* #endregion */
/* #region Brutalist */
html.wa-theme-brutalist .preview-container {
container-name: brutalist-theme;
}
@container brutalist-theme (min-width: 0) {
.overlap {
background: var(--wa-color-surface-lowered) url('/assets/images/themer/brutalist/hero.png') 50% 3% no-repeat;
}
.strata.hero {
height: 42rem;
padding-top: 8rem;
padding-right: 50%;
--wa-font-weight-heading: var(--wa-font-weight-normal);
}
.hero wa-button {
--background: var(--wa-color-neutral-fill-loud);
margin-block-start: var(--wa-space-xl);
font-size: var(--wa-font-size-l);
}
/* imitating the large button styles */
.hero wa-button::part(label) {
padding: 0 var(--wa-space-l);
}
.strata.products {
margin-top: -20rem;
padding-top: 10rem;
}
.product-card .badge-stock {
position: absolute;
top: 0;
left: 0;
}
.product-card::part(footer) {
--wa-shadow-offset-x-s: 0;
--wa-shadow-offset-y-s: 0;
border-width: 0;
text-align: right;
}
.product-card wa-button::part(prefix) {
padding-inline-start: var(--wa-space-xs);
}
.product-card wa-button::part(suffix) {
padding-inline-end: var(--wa-space-xs);
}
.product-card wa-button:not(:last-child) {
margin-inline-end: var(--wa-space-xs);
}
/* imitating the rounded avatar */
.blog wa-avatar {
background-color: transparent;
}
.blog wa-avatar::part(image) {
border: var(--wa-border-width-s) solid var(--wa-color-brand-fill-loud);
border-radius: var(--wa-border-radius-circle);
}
.blog .landscape-frame {
box-shadow: var(--wa-shadow-s);
border: var(--wa-panel-border-width) var(--wa-panel-border-style) var(--wa-color-surface-border);
margin-block-end: var(--wa-shadow-offset-y-s);
}
.post-meta .categories {
display: flex;
flex-direction: column;
}
.message-composer wa-card::part(header) {
background-color: var(--wa-color-neutral-fill-loud);
}
.message-composer .grouped-buttons {
--wa-color-neutral-border-quiet: color-mix(in oklab, var(--wa-color-gray-30), white 40%);
}
.message-composer [slot='header'] wa-icon-button::part(base) {
color: var(--wa-color-neutral-on-loud);
}
.message-composer .grouped-buttons wa-icon-button::part(base):hover {
background-color: var(--wa-color-neutral-fill-normal);
color: var(--wa-color-text-normal);
}
.message-composer wa-tooltip::part(body) {
background-color: var(--wa-color-brand-fill-loud);
color: var(--wa-color-brand-on-loud);
}
.message-composer wa-tooltip::part(base__arrow) {
--arrow-color: var(--wa-color-brand-fill-loud);
}
.message-composer wa-card::part(footer) {
border-width: 0;
--padding: 0 var(--wa-space-s) var(--wa-space-s) var(--wa-space-s);
}
.support-table th {
background-color: var(--wa-color-neutral-fill-loud);
color: var(--wa-color-neutral-on-loud);
}
.support-table th wa-checkbox {
--background: transparent;
--border-color: var(--wa-color-neutral-on-loud);
--border-color-checked: var(--wa-color-neutral-on-loud);
}
.checkout-form {
font-size: var(--wa-font-size-s);
}
.checkout-form .square-frame {
box-shadow: var(--wa-shadow-s);
border: var(--wa-panel-border-width) var(--wa-panel-border-style) var(--wa-color-surface-border);
}
.wa-theme-brutalist.wa-dark {
& p a::before {
background: var(--wa-color-yellow-40);
}
& wa-rating {
--symbol-color: color-mix(in oklab, var(--wa-color-base-80), transparent 50%);
--symbol-color-active: var(--wa-color-gray-80);
}
& wa-alert {
&[variant='brand'] {
--icon-color: var(--wa-color-brand-on-quiet);
}
&[variant='success'] {
--icon-color: var(--wa-color-success-on-quiet);
}
&[variant='warning'] {
--icon-color: var(--wa-color-warning-on-quiet);
}
&[variant='danger'] {
--icon-color: var(--wa-color-danger-on-quiet);
}
&[variant='neutral'] {
--icon-color: var(--wa-color-neutral-on-quiet);
}
}
}
.preview-container pre {
border-inline-start: var(--wa-panel-border-width) var(--wa-panel-border-style) var(--wa-color-neutral-border-quiet);
}
p a,
a.highlite-link {
position: relative;
--wa-link-decoration-default: none;
--wa-link-decoration-hover: none;
&:before {
position: absolute;
z-index: -1;
content: '';
background: var(--wa-color-yellow-80);
width: 100%;
bottom: 0;
height: 50%;
opacity: 0.7;
transition: all var(--wa-transition-fast) ease-in-out;
}
&:hover:before {
height: 100%;
}
}
}
@container brutalist-theme (min-width: 1040px) and (max-width: 1140px) {
.product-card wa-button {
font-size: 80%;
}
}
/* #endregion */
/* #region Playful */
html.wa-theme-playful .preview-container {
container-name: playful-theme;
}
@container playful-theme (min-width: 0) {
.project-header {
color: var(--wa-color-success-on-normal);
}
.hero-background {
position: absolute;
z-index: -1;
top: -60rem;
left: 50%;
width: 250rem;
height: 250rem;
transform: translate(-50%, -50%);
flex-shrink: 0;
border-radius: 50%;
background: linear-gradient(180deg, var(--wa-color-green-90) 69.42%, var(--wa-color-green-80) 100%);
}
.hero-background::after {
background: url(/assets/images/themer/playful/hero.png) 0 50% no-repeat;
content: '';
position: absolute;
width: 520px;
height: 600px;
transform: translateX(-50%);
left: 50%;
bottom: 33rem;
}
.strata.hero {
padding-top: 19rem;
text-align: center;
}
.hero .hero-title {
color: var(--wa-color-success-on-normal);
font-size: var(--wa-font-size-4xl);
}
.hero .hero-cta {
font-size: var(--wa-font-size-l);
}
.product-card .badge-stock {
position: absolute;
top: var(--wa-space-xl);
right: var(--wa-space-xl);
}
.product-card {
--wa-panel-border-radius: var(--wa-border-radius-l);
}
.product-card::part(footer) {
border-width: 0;
}
.product-card wa-button {
margin-inline-end: var(--wa-space-xs);
}
.blog wa-avatar {
--size: 2rem;
}
.blog .landscape-frame {
border-radius: var(--wa-border-radius-l);
box-shadow: var(--wa-shadow-s);
}
.message-composer wa-card {
--background: var(--wa-color-surface-raised);
}
.message-composer wa-card::part(header) {
--wa-color-neutral-border-quiet: var(--wa-color-gray-70);
border-width: 0;
background-color: var(--wa-color-neutral-fill-quiet);
}
&:not(.wa-theme-premium.wa-dark) .message-composer wa-card {
--wa-color-neutral-fill-quiet: var(--wa-color-gray-90);
}
.message-composer wa-icon-button {
color: var(--wa-text-color-normal);
font-size: var(--wa-font-size-l);
}
.message-composer wa-card::part(footer) {
padding-top: 0;
}
.product-detail .price {
font-weight: var(--wa-font-weight-bold);
}
.support-table wa-card {
background: var(--wa-color-surface-raised);
}
.support-table th {
font-size: var(--wa-font-size-s);
font-weight: var(--wa-font-weight-bold);
background-color: var(--wa-color-surface-lowered);
}
.support-table tr {
border-top-color: var(--wa-color-surface-lowered);
}
.support-table .excerpt {
color: var(--wa-color-text-quiet);
}
.order-item img {
border-radius: var(--wa-border-radius-m);
}
.checkout-form {
font-size: var(--wa-font-size-s);
}
.checkout-form h2 {
font-size: var(--wa-font-size-3xl);
}
.checkout-form wa-input::part(form-control-label),
.checkout-form wa-select::part(form-control-label) {
font-size: var(--wa-font-size-s);
padding-block-end: var(--wa-space-xs);
}
.wa-theme-playful.wa-dark {
& .hero-background {
background: linear-gradient(180deg, var(--wa-color-green-60) 69.42%, var(--wa-color-green-30) 100%);
}
& .message-composer wa-card {
border-color: var(--wa-color-gray-30);
}
& .message-composer wa-card::part(header) {
background: var(--wa-color-gray-40);
}
& .message-composer wa-card::part(footer) {
border-top: 0;
}
& .message-composer .tools .grouped-buttons:not(:last-of-type) {
--wa-color-neutral-border-quiet: var(--wa-color-gray-40);
}
& .support-table th {
background: var(--wa-color-surface-lowered);
}
}
}
/* responsive */
@container playful-theme (min-width: 1040px) and (max-width: 1140px) {
.product-card wa-button {
font-size: 80%;
margin-inline-end: 0;
}
}
/* #endregion */
/* #region Active */
html.wa-theme-active .preview-container {
container-name: active-theme;
}
@container active-theme (min-width: 0) {
.hero-background::after {
backdrop-filter: brightness(0.8);
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.hero-background {
background: linear-gradient(
var(--wa-color-green-80) 20%,
var(--wa-color-primary-80) 80.5%,
var(--wa-color-base-10) 80.5%,
var(--wa-color-primary-80) 100%
);
background: url(/assets/images/themer/active/hero.png) 50% 0px / cover no-repeat;
height: 40rem;
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: -1;
}
.strata.hero {
height: 24rem;
}
.hero .title {
text-align: right;
margin-inline-start: 55%;
}
.hero .hero-title {
font-style: italic;
font-weight: var(--wa-font-weight-black);
font-size: var(--wa-font-size-2xl);
}
.hero wa-button[variant='brand'] {
--background: var(--wa-color-neutral-fill-quiet);
--text-color: var(--wa-color-neutral-on-normal);
}
wa-rating {
--symbol-color-active: var(--wa-color-brand-on-quiet);
}
}
/* responsive */
@container preview (min-width: 1100px) {
.hero-background {
height: 47rem;
}
.strata.hero {
height: 30rem;
}
.hero .title {
margin-block-start: 10%;
}
}
/* #endregion */
/* #region Premium */
html.wa-theme-premium .preview-container {
container-name: premium-theme;
}
@container premium-theme (min-width: 0) {
.project-header {
background-color: var(--wa-color-warning-fill-normal);
}
.strata.hero {
height: 60rem;
background: var(--wa-color-warning-fill-normal) url('/assets/images/themer/premium/hero.png') -4rem 12rem no-repeat;
background-size: cover;
padding-top: var(--wa-space-2xl);
padding-left: var(--wa-space-s);
text-align: right;
}
.hero .hero-title {
color: var(--wa-color-warning-on-normal);
font-style: italic;
}
.blog wa-avatar {
border-radius: var(--wa-border-radius-circle);
overflow: hidden;
}
.strata.products {
margin-top: -25rem;
padding-top: 10rem;
background: linear-gradient(0deg, var(--wa-color-surface-lowered) 80%, rgba(255, 255, 255, 0) 100%);
}
.product-card .badge-stock {
position: absolute;
top: var(--wa-space-xl);
right: var(--wa-space-xl);
}
.product-card wa-rating {
--symbol-size: var(--wa-font-size-m);
}
.product-card .title {
font-size: var(--wa-font-size-2xl);
}
.product-card .description {
color: var(--wa-color-text-quiet);
}
.product-card::part(footer) {
border-width: 0;
}
.product-card wa-button:not(:last-child) {
margin-inline-end: var(--wa-space-xs);
}
.blog .authors a {
--wa-color-text-link: var(--wa-color-text-quiet);
--wa-link-decoration-default: none;
}
.message-composer wa-card {
background: var(--wa-color-surface-raised);
}
.message-composer wa-card::part(header) {
border-width: 0;
background-color: var(--wa-color-neutral-fill-quiet);
}
&:not(.wa-theme-premium.wa-dark) .message-composer wa-card {
--wa-color-neutral-fill-quiet: var(--wa-color-base-95);
}
.message-composer wa-card::part(footer) {
border-width: 0;
--padding: var(--wa-space-s) var(--wa-space-xl);
}
.message-composer .grouped-buttons wa-icon-button::part(base) {
block-size: var(--wa-form-control-height-s);
inline-size: var(--wa-form-control-height-s);
justify-content: center;
}
.message-composer .grouped-buttons wa-icon-button::part(base):hover {
background-color: var(--wa-color-neutral-fill-normal);
color: var(--wa-color-text-normal);
}
.support-table th {
text-transform: uppercase;
font-weight: var(--wa-font-weight-normal);
color: var(--wa-color-text-quiet);
background-color: var(--wa-color-surface-lowered);
}
.support-table th:first-child {
border-radius: var(--wa-border-radius-l) 0 0 0;
}
.support-table th:last-child {
border-radius: 0 var(--wa-border-radius-l) 0 0;
}
.support-table tr {
--wa-color-surface-border: var(--wa-color-surface-lowered);
}
.checkout-form wa-input::part(form-control-label),
.checkout-form wa-select::part(form-control-label) {
font-size: var(--wa-font-size-s);
margin-block-end: var(--wa-space-xs);
}
.order-item .finish {
color: var(--wa-color-text-quiet);
font-size: var(--wa-font-size-s);
font-style: italic;
}
.wa-theme-premium.wa-dark {
& .message-composer .tools .grouped-buttons:not(:last-of-type) {
--wa-color-neutral-border-quiet: var(--wa-color-base-40);
}
& .preview-container pre,
& .preview-container code {
background-color: var(--wa-color-base-20);
}
/* syntax highlighting */
& .token {
&.selector {
color: var(--wa-color-green-80);
}
&.tag {
color: var(--wa-color-primary-80);
}
&.punctuation {
color: var(--wa-color-base-95);
}
&.attr-name {
color: var(--wa-color-green-80);
}
&.attr-value {
color: var(--wa-color-yellow-80);
}
}
}
.preview-container pre,
.preview-container code {
background-color: var(--wa-color-base-90);
font-size: var(--font-size-m);
}
/* syntax highlighting */
.token {
&.selector {
color: var(--wa-color-green-30);
}
&.tag {
color: var(--wa-color-primary-30);
}
&.punctuation {
color: var(--wa-color-base-10);
}
&.attr-name {
color: var(--wa-color-green-30);
}
&.attr-value {
color: var(--wa-color-yellow-30);
}
}
}
/* responsive */
@container preview (min-width: 1040px) {
.strata.hero {
background: var(--wa-color-warning-fill-normal) url('/assets/images/themer/premium/hero.png') -4rem 35% no-repeat;
padding-top: 15rem;
padding-left: 50%;
}
.strata.products {
margin-top: -25rem;
padding-top: 10rem;
background: linear-gradient(0deg, var(--wa-color-surface-lowered) 60%, rgba(255, 255, 255, 0) 100%);
}
}
/* #endregion */

View File

@@ -58,6 +58,71 @@ Set the `variant` attribute to change the callout's variant.
</wa-callout>
```
### Appearance
Use the `appearance` attribute to change the callout's visual appearance (the default is `outlined filled`).
```html {.example}
<wa-callout variant="brand" appearance="outlined accent">
<wa-icon slot="icon" name="check-to-slot"></wa-icon>
This <strong>accent</strong> callout is also <strong>outlined</strong>
</wa-callout>
<br />
<wa-callout variant="brand" appearance="accent">
<wa-icon slot="icon" name="square-check"></wa-icon>
This <strong>accent</strong> callout draws attention without an outline
</wa-callout>
<br />
<wa-callout variant="brand" appearance="outlined filled">
<wa-icon slot="icon" name="fill-drip" variant="regular"></wa-icon>
This callout is both <strong>filled</strong> and <strong>outlined</strong>
</wa-callout>
<br />
<wa-callout variant="brand" appearance="filled">
<wa-icon slot="icon" name="fill" variant="regular"></wa-icon>
This callout is only <strong>filled</strong>
</wa-callout>
<br />
<wa-callout variant="brand" appearance="outlined">
<wa-icon slot="icon" name="lines-leaning" variant="regular"></wa-icon>
Here's an <strong>outlined</strong> callout
</wa-callout>
<br />
<wa-callout variant="brand" appearance="plain">
<wa-icon slot="icon" name="font" variant="regular"></wa-icon>
No bells and whistles on this <strong>plain</strong> callout
</wa-callout>
```
### Sizes
Use the `size` attribute to change a callout's size.
```html {.example}
<wa-callout variant="brand" appearance="outlined accent" size="large">
<wa-icon slot="icon" name="circle-info" variant="solid"></wa-icon>
This is meant to be very emphasized.
</wa-callout>
<wa-callout>
<wa-icon slot="icon" name="circle-info" variant="regular"></wa-icon>
Normal-sized callout.
</wa-callout>
<wa-callout variant="plain" appearance="plain" size="small">
<wa-icon slot="icon" name="circle-info" variant="regular"></wa-icon>
Just a small tip!
</wa-callout>
```
### Without Icons
Icons are optional. Simply omit the `icon` slot if you don't want them.

View File

@@ -60,7 +60,8 @@ Basic cards aren't very exciting, but they can display any content you want them
### Card with Header
Headers can be used to display titles and more. Use the `with-header` attribute to add a header to the card.
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">
@@ -95,7 +96,8 @@ Headers can be used to display titles and more. Use the `with-header` attribute
### Card with Footer
Footers can be used to display actions, summaries, or other relevant content. Use the `with-footer` attribute to add a footer to the card.
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">
@@ -122,7 +124,8 @@ Footers can be used to display actions, summaries, or other relevant content. Us
### Images
Card images are displayed atop the card and will stretch to fit. Use the `with-image` attribute to add an image to the card.
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">

View File

@@ -1,4 +1,11 @@
{
"layout": "component.njk",
"tags": ["components"]
"tags": ["components"],
"eleventyComputed": {
"component": "{{ components[page.fileSlug] }}",
"description": "{{ components[page.fileSlug].summary }}",
"status": "{{ components[page.fileSlug].status }}",
"since": "{{ components[page.fileSlug].since }}",
"element": "<{{ components[page.fileSlug].tagName }}>"
}
}

View File

@@ -1,81 +0,0 @@
---
title: Components
description: Components are the essential building blocks to create intuitive, cohesive experiences. Browse the library of customizable, framework-friendly web components included in Web Awesome.
layout: page-outline
categories:
- actions
- feedback: 'Feedback & Status'
- imagery
- inputs
- navigation
- organization
- helpers: 'Utilities'
override:tags: []
---
<div id="component-filter">
<wa-input type="search" placeholder="Search components" clearable autofocus></wa-input>
</div>
{% set allPages = collections.components %}
{% include "grouped-pages.njk" %}
<div id="component-filter-empty" hidden>
No results
</div>
<script type="module">
const container = document.getElementById('component-filter');
const empty = document.getElementById('component-filter-empty');
const grid = document.getElementById('content');
const input = container.querySelector('wa-input');
function updateResults() {
const filter = input.value.toLowerCase().trim();
// Hide headings while filtering
grid.querySelectorAll('h2').forEach(heading => {
heading.hidden = filter === '' ? false : true;
});
// Show matching components
grid.querySelectorAll('a:has(> wa-card)').forEach(link => {
console.log(link);
const content = link.textContent.toLowerCase();
const keywords = link.getAttribute('data-keywords') || '';
const isMatch = filter === '' || (content + keywords).includes(filter);
link.hidden = !isMatch;
});
// Show empty state when there's a search filter and no results
if (filter !== '' && grid.querySelector('a:not([hidden])') === null) {
empty.hidden = false;
} else {
empty.hidden = true;
}
}
input.addEventListener('wa-input', updateResults);
</script>
<style>
wa-card#drawer-card::part(header) {
--spacing: 0;
justify-content: flex-end;
overflow: hidden;
}
#component-filter {
margin-block-end: var(--wa-space-xl);
}
#component-filter-empty {
border: dashed var(--wa-border-width-m) var(--wa-color-neutral-border-quiet);
border-radius: var(--wa-border-radius-l);
font-size: var(--wa-font-size-l);
color: var(--wa-color-text-quiet);
text-align: center;
padding-block: var(--wa-space-2xl);
margin-block-start: 0
}
</style>

View File

@@ -0,0 +1,14 @@
---
title: Components
description: Components are the essential building blocks to create intuitive, cohesive experiences. Browse the library of customizable, framework-friendly web components included in Web Awesome.
layout: overview
categories:
- actions
- feedback: 'Feedback & Status'
- imagery
- inputs
- navigation
- organization
- helpers: 'Utilities'
override:tags: []
---

View File

@@ -127,7 +127,7 @@ eleventyExcludeFromCollections: true
</a>
</nav>
<header slot="main-header">
<div class="wa-flank:end wa-border-radius-l wa-theme-default-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
<div class="wa-flank:end wa-border-radius-l wa-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
<div class="wa-stack" style="margin: var(--wa-space-2xl);">
<h1>Great Horned Owl</h1>
<wa-divider></wa-divider>

View File

@@ -5,7 +5,7 @@ layout: blank
eleventyExcludeFromCollections: true
---
<wa-page class="wa-theme-default-dark">
<wa-page class="wa-dark">
<header slot="header">
<div class="wa-cluster">
<wa-icon-button name="bars" label="Menu" data-toggle-nav></wa-icon-button>

View File

@@ -3,7 +3,7 @@ title: Page
description: Pages offer an easy way to scaffold entire page layouts using minimal markup.
tags: [organization, layout]
isPro: true
order: 1
order: 0
# icon: page
---
@@ -119,7 +119,7 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
</a>
</nav>
<header slot="main-header">
<div class="wa-flank:end wa-border-radius-l wa-theme-default-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
<div class="wa-flank:end wa-border-radius-l wa-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
<div class="wa-stack" style="margin: var(--wa-space-2xl);">
<h1>Great Horned Owl</h1>
<wa-divider></wa-divider>
@@ -299,7 +299,7 @@ It can be opened using a button with `[data-toggle-nav]` that appears in the `su
A sample media app page using `header`, `navigation-header`, `main-header`, and `main-footer` along with the default slot. The navigation menu collapses into a drawer at the default `mobile-breakpoint` and can be opened using a button with `[data-toggle-nav]` that appears in the `header` slot.
```html {.example viewport="1600"}
<wa-page class="wa-theme-default-dark">
<wa-page class="wa-dark">
<header slot="header">
<div class="wa-cluster">
<wa-icon-button name="bars" label="Menu" data-toggle-nav></wa-icon-button>

View File

@@ -248,7 +248,7 @@ Use the `distance` attribute to change the distance between the popup and its an
<div class="box"></div>
</wa-popup>
<wa-range min="-50" max="50" step="1" value="0" label="Distance"></wa-range>
<wa-slider min="-50" max="50" step="1" value="0" label="Distance"></wa-slider>
</div>
<style>
@@ -267,7 +267,7 @@ Use the `distance` attribute to change the distance between the popup and its an
border-radius: var(--wa-border-radius-m);
}
.popup-distance wa-range {
.popup-distance wa-slider {
max-width: 260px;
}
</style>
@@ -275,7 +275,7 @@ Use the `distance` attribute to change the distance between the popup and its an
<script>
const container = document.querySelector('.popup-distance');
const popup = container.querySelector('wa-popup');
const distance = container.querySelector('wa-range');
const distance = container.querySelector('wa-slider');
distance.addEventListener('wa-input', () => (popup.distance = distance.value));
</script>
@@ -292,7 +292,7 @@ The `skidding` attribute is similar to `distance`, but instead allows you to off
<div class="box"></div>
</wa-popup>
<wa-range min="-50" max="50" step="1" value="0" label="Skidding"></wa-range>
<wa-slider min="-50" max="50" step="1" value="0" label="Skidding"></wa-slider>
</div>
<style>
@@ -311,7 +311,7 @@ The `skidding` attribute is similar to `distance`, but instead allows you to off
border-radius: var(--wa-border-radius-m);
}
.popup-skidding wa-range {
.popup-skidding wa-slider {
max-width: 260px;
}
</style>
@@ -319,7 +319,7 @@ The `skidding` attribute is similar to `distance`, but instead allows you to off
<script>
const container = document.querySelector('.popup-skidding');
const popup = container.querySelector('wa-popup');
const skidding = container.querySelector('wa-range');
const skidding = container.querySelector('wa-slider');
skidding.addEventListener('wa-input', () => (popup.skidding = skidding.value));
</script>
@@ -747,8 +747,8 @@ When a gap exists between the anchor and the popup element, this option will add
</wa-popup>
<br>
<wa-switch checked>Hover Bridge</wa-switch><br>
<wa-range min="0" max="50" step="1" value="10" label="Distance"></wa-range>
<wa-range min="-50" max="50" step="1" value="0" label="Skidding"></wa-range>
<wa-slider min="0" max="50" step="1" value="10" label="Distance"></wa-slider>
<wa-slider min="-50" max="50" step="1" value="0" label="Skidding"></wa-slider>
</div>
<style>
.popup-hover-bridge span[slot='anchor'] {
@@ -766,7 +766,7 @@ When a gap exists between the anchor and the popup element, this option will add
border-radius: var(--wa-border-radius-m);
}
.popup-hover-bridge wa-range {
.popup-hover-bridge wa-slider {
max-width: 260px;
margin-top: .5rem;
}
@@ -780,8 +780,8 @@ When a gap exists between the anchor and the popup element, this option will add
const container = document.querySelector('.popup-hover-bridge');
const popup = container.querySelector('wa-popup');
const hoverBridge = container.querySelector('wa-switch');
const distance = container.querySelector('wa-range[label="Distance"]');
const skidding = container.querySelector('wa-range[label="Skidding"]');
const distance = container.querySelector('wa-slider[label="Distance"]');
const skidding = container.querySelector('wa-slider[label="Skidding"]');
distance.addEventListener('wa-input', () => (popup.distance = distance.value));
skidding.addEventListener('wa-input', () => (popup.skidding = skidding.value));
hoverBridge.addEventListener('wa-change', () => (popup.hoverBridge = hoverBridge.checked));

View File

@@ -1,13 +1,13 @@
---
title: Range
title: Slider
description: Ranges allow the user to select a single value within a given range using a slider.
tags: [inputs, forms]
native: slider
icon: range
icon: slider
---
```html {.example}
<wa-range></wa-range>
<wa-slider></wa-slider>
```
:::info
@@ -21,7 +21,7 @@ This component works with standard `<form>` elements. Please refer to the sectio
Use the `label` attribute to give the range an accessible label. For labels that contain HTML, use the `label` slot instead.
```html {.example}
<wa-range label="Volume" min="0" max="100"></wa-range>
<wa-slider label="Volume" min="0" max="100"></wa-slider>
```
### Hint
@@ -29,7 +29,7 @@ Use the `label` attribute to give the range an accessible label. For labels that
Add descriptive hint to a range with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
```html {.example}
<wa-range label="Volume" hint="Controls the volume of the current song." min="0" max="100"></wa-range>
<wa-slider label="Volume" hint="Controls the volume of the current song." min="0" max="100"></wa-slider>
```
### Min, Max, and Step
@@ -37,7 +37,7 @@ Add descriptive hint to a range with the `hint` attribute. For hints that contai
Use the `min` and `max` attributes to set the range's minimum and maximum values, respectively. The `step` attribute determines the value's interval when increasing and decreasing.
```html {.example}
<wa-range min="0" max="10" step="1"></wa-range>
<wa-slider min="0" max="10" step="1"></wa-slider>
```
### Disabled
@@ -45,7 +45,7 @@ Use the `min` and `max` attributes to set the range's minimum and maximum values
Use the `disabled` attribute to disable a slider.
```html {.example}
<wa-range disabled></wa-range>
<wa-slider disabled></wa-slider>
```
### Tooltip Placement
@@ -53,7 +53,7 @@ Use the `disabled` attribute to disable a slider.
By default, the tooltip is shown on top. Set `tooltip` to `bottom` to show it below the slider.
```html {.example}
<wa-range tooltip="bottom"></wa-range>
<wa-slider tooltip="bottom"></wa-slider>
```
### Disable the Tooltip
@@ -61,7 +61,7 @@ By default, the tooltip is shown on top. Set `tooltip` to `bottom` to show it be
To disable the tooltip, set `tooltip` to `none`.
```html {.example}
<wa-range tooltip="none"></wa-range>
<wa-slider tooltip="none"></wa-slider>
```
### Custom Track Colors
@@ -69,12 +69,12 @@ To disable the tooltip, set `tooltip` to `none`.
You can customize the active and inactive portions of the track using the `--track-color-active` and `--track-color-inactive` custom properties.
```html {.example}
<wa-range
<wa-slider
style="
--track-color-active: var(--wa-color-brand-fill-loud);
--track-color-inactive: var(--wa-color-brand-fill-normal);
"
></wa-range>
></wa-slider>
```
### Custom Track Offset
@@ -82,7 +82,7 @@ You can customize the active and inactive portions of the track using the `--tra
You can customize the initial offset of the active track using the `--track-active-offset` custom property.
```html {.example}
<wa-range
<wa-slider
min="-100"
max="100"
style="
@@ -90,7 +90,7 @@ You can customize the initial offset of the active track using the `--track-acti
--track-color-inactive: var(--wa-color-brand-fill-normal);
--track-active-offset: 50%;
"
></wa-range>
></wa-slider>
```
### Custom Tooltip Formatter
@@ -98,7 +98,7 @@ You can customize the initial offset of the active track using the `--track-acti
You can change the tooltip's content by setting the `tooltipFormatter` property to a function that accepts the range's value as an argument.
```html {.example}
<wa-range min="0" max="100" step="1" class="range-with-custom-formatter"></wa-range>
<wa-slider min="0" max="100" step="1" class="range-with-custom-formatter"></wa-slider>
<script>
const range = document.querySelector('.range-with-custom-formatter');
@@ -111,8 +111,8 @@ You can change the tooltip's content by setting the `tooltipFormatter` property
The component adapts to right-to-left (RTL) languages as you would expect.
```html {.example}
<wa-range dir="rtl"
<wa-slider dir="rtl"
label="مقدار"
hint="التحكم في مستوى صوت الأغنية الحالية."
style="--track-color-active: var(--wa-color-brand-fill-loud)" value="10"></wa-range>
style="--track-color-active: var(--wa-color-brand-fill-loud)" value="10"></wa-slider>
```

View File

@@ -15,9 +15,50 @@ icon: tag
## Examples
### Appearance
Use the `size` attribute to change a tag's visual appearance.
The default appearance is `outlined filled`.
```html {.example}
<div class="wa-stack">
<p>
<wa-tag variant="brand" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="brand" appearance="accent">Accent</wa-tag>
<wa-tag variant="brand" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="brand" appearance="filled">Filled</wa-tag>
<wa-tag variant="brand" appearance="outlined filled">Outlined Filled</wa-tag>
</p>
<p>
<wa-tag variant="success" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="success" appearance="accent">Accent</wa-tag>
<wa-tag variant="success" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="success" appearance="filled">Filled</wa-tag>
<wa-tag variant="success" appearance="outlined filled">Outlined Filled</wa-tag>
<p>
<wa-tag variant="neutral" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="neutral" appearance="accent">Accent</wa-tag>
<wa-tag variant="neutral" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="neutral" appearance="filled">Filled</wa-tag>
<wa-tag variant="neutral" appearance="outlined filled">Outlined Filled</wa-tag>
<p>
<wa-tag variant="warning" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="warning" appearance="accent">Accent</wa-tag>
<wa-tag variant="warning" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="warning" appearance="filled">Filled</wa-tag>
<wa-tag variant="warning" appearance="outlined filled">Outlined Filled</wa-tag>
<p>
<wa-tag variant="danger" appearance="outlined accent">Outlined accent</wa-tag>
<wa-tag variant="danger" appearance="accent">Accent</wa-tag>
<wa-tag variant="danger" appearance="outlined">Outlined</wa-tag>
<wa-tag variant="danger" appearance="filled">Filled</wa-tag>
<wa-tag variant="danger" appearance="outlined filled">Outlined Filled</wa-tag>
</div>
```
### Sizes
Use the `size` attribute to change a tab's size.
Use the `size` attribute to change a tag's size.
```html {.example}
<wa-tag size="small">Small</wa-tag>

View File

@@ -17,7 +17,7 @@ To customize a theme, simply override any of these custom properties in your own
```css
:root,
:host,
.wa-theme-default-light {
.wa-theme-default {
/* Changes the brand color to violet across the library */
--wa-color-brand-fill-quiet: var(--wa-color-violet-95);
--wa-color-brand-fill-normal: var(--wa-color-violet-90);

View File

@@ -0,0 +1,10 @@
export default {
eleventyComputed: {
children(data) {
let mainTag = data.tags?.[0];
let collection = data.collections[mainTag] ?? [];
return collection.filter(item => item.data.parent === data.page.fileSlug);
},
},
};

View File

@@ -15,7 +15,7 @@ Adding the `wa-valid` or `wa-invalid` class to a form control will change its ap
<wa-option>Well, maybe two is OK</wa-option>
</wa-select>
<wa-textarea class="wa-valid" label="Bio" hint="Tell us about yourself" placeholder="Enter a bio"></wa-textarea><br>
<wa-range class="wa-valid" value="50" label="Volume" hint="Crank it up"></wa-range><br>
<wa-slider class="wa-valid" value="50" label="Volume" hint="Crank it up"></wa-slider><br>
<wa-checkbox class="wa-valid" checked>I am awesome</wa-checkbox><br>
<wa-checkbox class="wa-valid">So am I</wa-checkbox><br><br>
<wa-switch class="wa-valid" checked>Still awesome</wa-switch><br>
@@ -35,7 +35,7 @@ Adding the `wa-valid` or `wa-invalid` class to a form control will change its ap
<wa-option>Well, maybe two is OK</wa-option>
</wa-select>
<wa-textarea class="wa-invalid" label="Bio" hint="Tell us about yourself" placeholder="Enter a bio"></wa-textarea><br>
<wa-range class="wa-invalid" value="50" label="Volume" hint="Crank it up"></wa-range><br>
<wa-slider class="wa-invalid" value="50" label="Volume" hint="Crank it up"></wa-slider><br>
<wa-checkbox class="wa-invalid" checked>I am awesome</wa-checkbox><br>
<wa-checkbox class="wa-invalid">So am I</wa-checkbox><br><br>
<wa-switch class="wa-invalid" checked>Still awesome</wa-switch><br>

View File

@@ -1,7 +1,7 @@
---
title: Theming Sandbox
description: TODO
layout: page
layout: page-outline
---
## Card
@@ -132,7 +132,7 @@ layout: page
<br />
<wa-switch checked>Switch on</wa-switch>
<br /><br />
<wa-range label="Range" hint="Here's a bit of handy content." min="0" max="100"></wa-range>
<wa-slider label="Range" hint="Here's a bit of handy content." min="0" max="100"></wa-slider>
<br /><br />
<wa-input label="Label" hint="Super helpful and/or contextual content" placeholder="Placeholder"></wa-input>
<br />
@@ -172,7 +172,7 @@ layout: page
<div class="shadow" style="box-shadow: var(--wa-shadow-l);"></div>
```
## Tests
## Alignment Tests
```html {.example}
<style>
@@ -239,17 +239,114 @@ layout: page
<wa-badge>OCBS</wa-badge>
<wa-avatar></wa-avatar>
<wa-rating></wa-rating>
<wa-range></wa-range>
<wa-slider></wa-slider>
<wa-icon-button name="gear" label="Settings"></wa-icon-button>
<wa-progress-bar value="50" style="width: 8rem;"></wa-progress-bar>
<wa-spinner></wa-spinner>
</div>
<div class="alignment">
<wa-input label="AaBbCc" hint="Lorem ipsum dolor"></wa-input>
<wa-select label="AaBbCc" value="ocbs" multiple hint="Lorem ipsum dolor">
<wa-input label="AaBbCc" hint="Ipsum"></wa-input>
<wa-select label="AaBbCc" value="ocbs" multiple hint="Ipsum">
<wa-option value="ocbs">OCBS</wa-option>
</wa-select>
<wa-color-picker label="AaBbCc" hint="Lorem ipsum dolor"></wa-color-picker>
<wa-color-picker label="AaBbCc" hint="Ipsum"></wa-color-picker>
</div>
</div>
```
## Custom Property Tests
```html {.example}
<style>
.wa-theme-test {
--wa-form-control-background-color: mistyrose;
--wa-form-control-border-style: dotted;
--wa-form-control-border-width: 3px;
--wa-form-control-border-radius: 12px;
--wa-form-control-activated-color: mediumvioletred;
--wa-form-control-border-color: palevioletred;
--wa-form-control-label-color: rosybrown;
--wa-form-control-label-font-weight: 900;
--wa-form-control-label-line-height: 1;
--wa-form-control-value-color: brown;
--wa-form-control-value-font-weight: 900;
--wa-form-control-value-line-height: 2;
--wa-form-control-placeholder-color: lightpink;
}
</style>
<div class="wa-theme-test" style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;">
<label>Native Input <input type="text" placeholder="placeholder"></label>
<wa-input label="WA Input" type="text" placeholder="placeholder"></wa-input>
<label>Native Input <input type="text" value="value"></label>
<wa-input label="WA Input" type="text" value="value"></wa-input>
<label>Native Textarea <textarea placeholder="placeholder"></textarea></label>
<wa-textarea label="WA Textarea" placeholder="placeholder"></wa-textarea>
<label>Native Textarea <textarea>value</textarea></label>
<wa-textarea label="WA Textarea" value="value"></wa-textarea>
<label><input type="checkbox" checked> Native Checkbox</label>
<wa-checkbox checked>WA Checkbox</wa-checkbox>
<label><input type="checkbox"> Native Checkbox</label>
<wa-checkbox>WA Checkbox</wa-checkbox>
<label><input type="radio" checked> Native Radio</label>
<wa-radio checked>WA Radio</wa-radio>
<label><input type="radio"> Native Radio</label>
<wa-radio>WA Radio</wa-radio>
<label>
Native Select
<select value="option-1">
<option value="option-1">Option 1</option>
<option value="option-2">Option 2</option>
<option value="option-3">Option 3</option>
<option value="option-4">Option 4</option>
</select>
</label>
<wa-select label="WA Select" value="option-1">
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
<wa-option value="option-4">Option 4</wa-option>
</wa-select>
</div>
```
## Text Controls Tests
```html {.example}
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;">
<label>Native Input <input type="text" value="value"></label>
<wa-input label="WA Input" type="text" value="value"></wa-input>
<label>
Native Select
<select value="option-1">
<option value="option-1">Option 1</option>
<option value="option-2">Option 2</option>
<option value="option-3">Option 3</option>
<option value="option-4">Option 4</option>
</select>
</label>
<wa-select label="WA Select" value="option-1">
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
<wa-option value="option-4">Option 4</wa-option>
</wa-select>
<label>Native Textarea <textarea>value</textarea></label>
<wa-textarea label="WA Textarea" value="value"></wa-textarea>
</div>
```

View File

@@ -5,6 +5,15 @@ layout: page
hasOutline: false
---
<script>
// Add stylesheet to set themed headers
const themeHeadersLink = document.createElement("link");
themeHeadersLink.type="text/css";
themeHeadersLink.rel="stylesheet";
themeHeadersLink.href="/assets/styles/theme-headers.css";
document.getElementsByTagName("head")[0].appendChild(themeHeadersLink);
</script>
<style>
/* turn off eleventy header anchors */
.anchor-heading a {
@@ -156,7 +165,7 @@ hasOutline: false
--wa-form-control-border-radius: var(--wa-border-radius-m);
--wa-form-control-activated-color: var(--wa-color-brand-fill-loud);
--wa-form-control-resting-color: var(--wa-color-neutral-border-normal);
--wa-form-control-border-color: var(--wa-color-neutral-border-normal);
--wa-form-control-label-color: var(--wa-color-text-normal);
--wa-form-control-label-font-weight: var(--wa-font-weight-normal);
@@ -168,16 +177,6 @@ hasOutline: false
--wa-form-control-placeholder-color: color-mix(in oklab, var(--wa-color-text-normal), transparent);
--wa-form-control-height-s: calc(
var(--wa-space-xs) * 2 + 1em * var(--wa-form-control-value-line-height)
);
--wa-form-control-height-m: calc(
var(--wa-space-s) * 2 + 1em * var(--wa-form-control-value-line-height)
);
--wa-form-control-height-l: calc(
var(--wa-space-m) * 2 + 1em * var(--wa-form-control-value-line-height)
);
--wa-form-control-required-content: '*';
--wa-form-control-required-content-color: inherit;
--wa-form-control-required-content-offset: -0.1em;
@@ -364,13 +363,13 @@ hasOutline: false
/* file uploader styles */
.file-uploader {
position: relative;
border: var(--wa-form-control-border-width) dashed var(--wa-form-control-resting-color);
border: var(--wa-form-control-border-width) dashed var(--wa-form-control-border-color);
border-radius: var(--wa-form-control-border-radius);
background: var(--wa-form-control-background-color);
cursor: pointer;
font-weight: var(--wa-font-weight-action);
height: calc(var(--wa-form-control-height-m) + var(--wa-border-width-s) * 2);
line-height: var(--wa-form-control-height-m);
height: calc(var(--wa-form-control-height) + var(--wa-border-width-s) * 2);
line-height: var(--wa-form-control-height);
text-align: center;
}
@@ -502,11 +501,11 @@ 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="fa">Font Awesome</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="migration">Migration</wa-option>
<wa-option data-alpha="remove" value="tailspin">Tailspin</wa-option>
<wa-option data-alpha="remove" value="glassy">Glassy</wa-option>
<wa-option data-alpha="remove" value="active">Active</wa-option>
<wa-option value="classic">Classic</wa-option>
@@ -661,10 +660,10 @@ hasOutline: false
<wa-option value="dotted">Dotted</wa-option>
<wa-option value="double">Double</wa-option>
</wa-select>
<wa-range name="border-width" label="Border width" min="1" max="5" value="1" step="1" tooltip="none"></wa-range>
<wa-range name="spacing" label="Spacing" min=".5" max="1.5" value="1" step="0.125" tooltip="none"></wa-range>
<wa-range name="corners" label="Corners" min="0" max="1.5" value=".25" step=".125" tooltip="none"></wa-range>
<wa-range name="depth" label="Depth" min="0" max="4" value="0" step="1" tooltip="none"></wa-range>
<wa-slider name="border-width" label="Border width" min="1" max="5" value="1" step="1" tooltip="none"></wa-slider>
<wa-slider name="spacing" label="Spacing" min=".5" max="1.5" value="1" step="0.125" tooltip="none"></wa-slider>
<wa-slider name="corners" label="Corners" min="0" max="1.5" value=".25" step=".125" tooltip="none"></wa-slider>
<wa-slider name="depth" label="Depth" min="0" max="4" value="0" step="1" tooltip="none"></wa-slider>
</wa-details>
</form>
@@ -877,10 +876,10 @@ hasOutline: false
switch(themeSelect.value) {
case 'classic':
case 'migration':
case 'tailspin':
colorPalette = 'classic';
break;
case 'fa':
case 'awesome':
colorPalette = 'bright';
break;
case 'playful':
@@ -1045,11 +1044,11 @@ hasOutline: false
switch(themeSelect.value) {
case 'premium':
case 'migration':
case 'tailspin':
case 'playful':
case 'brutalist':
case 'classic':
case 'fa':
case 'awesome':
case 'glassy':
case 'active':
assetFolder = themeSelect.value;
@@ -1245,7 +1244,7 @@ hasOutline: false
let presetLogoIcons;
switch(themeSelect.value) {
case 'fa':
case 'awesome':
presetLogoIcons = ['cupcake', 'camera-retro', 'rocket-launch', 'cookie-bite'];
break;
case 'premium':
@@ -1257,7 +1256,7 @@ hasOutline: false
case 'brutalist':
presetLogoIcons = ['leaf', 'mug-hot', 'book-open', 'landmark'];
break;
case 'migration':
case 'tailspin':
presetLogoIcons = ['wind', 'feather', 'lemon', 'wind-turbine'];
break;
case 'glassy':
@@ -1447,7 +1446,7 @@ hasOutline: false
function setPreferredIcons() {
switch(themeSelect.value) {
case 'fa':
case 'awesome':
iconFamily.value = 'fa-classic';
iconStyle.value = 'solid';
useFaIcons();
@@ -1491,7 +1490,7 @@ hasOutline: false
}
});
break;
case 'migration':
case 'tailspin':
iconFamily.value = 'fa-classic';
iconStyle.value = 'solid';
useFaIcons();
@@ -1664,7 +1663,7 @@ hasOutline: false
.preview-container {
background: var(--wa-color-surface-lowered);
container: preview / inline-size;
container-type: inline-size;
padding: 0;
max-inline-size: 1400px;
margin-inline: auto;
@@ -1743,7 +1742,7 @@ hasOutline: false
/* strata product cards */
.products wa-card::part(base) {
.products wa-card {
height: 100%;
}
@@ -2124,7 +2123,7 @@ hasOutline: false
<h3>Ontological Shock</h3>
<p>The allegory is related to Plato's theory of Forms, which holds that the true essence of an object is not what we perceive with our senses, but rather its quality, and that most people perceive only the shadow of the object and are thus limited to false perception.</p>
<pre class="codeblock">
<code class="language-html">&lt;html class="wa-theme-default-dark"&gt;
<code class="language-html">&lt;html class="wa-dark"&gt;
&lt;head&gt;
&lt;link rel="stylesheet" href="path/to/webawesome/dist/styles/themes/dark.css" /&gt;
&lt;/head&gt;

View File

@@ -1,27 +0,0 @@
---
title: Layout
description: Browse Web Awesome's components and utilities for creating responsive web layouts.
layout: page-outline
categories: ["components", "utilities"]
---
<style>
wa-page > main {
max-width: 120ch;
margin-inline: auto;
}
.index-grid wa-card::part(header) {
background-color: var(--wa-color-neutral-fill-quiet);
border-bottom: none;
}
wa-card .component-name,
wa-card .page-name {
font-size: var(--wa-font-size-s);
font-weight: var(--wa-font-weight-action);
}
</style>
<p style="max-width: 80ch">Layout components and utility classes help you organize content that can adapt to any device or screen size. Browse the collection of responsive layout tools included in Web Awesome Pro.</p>
{% set allPages = collections.layout %}
{% include "grouped-pages.njk" %}

7
docs/docs/layout.njk Normal file
View File

@@ -0,0 +1,7 @@
---
title: Layout
description: Layout components and utility classes help you organize content that can adapt to any device or screen size. Browse the collection of responsive layout tools included in Web Awesome Pro.
layout: overview
categories: ["components", "utilities"]
override:tags: []
---

View File

@@ -4,6 +4,9 @@ description: 'Button styles apply your Web Awesome theme to native HTML buttons.
tags: forms
component: button
icon: button
snippets:
'<button>': https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button
'.wa-button': false
---
```html {.example}

View File

@@ -1,20 +1,16 @@
---
title: Native Styles
description: Native Styles use your theme to style native HTML elements to match the look and feel of Web Awesome components.
layout: page-outline
layout: overview
categories: ['forms', 'apps', 'content']
override:tags: []
---
{% markdown %}
Web Awesome works _with_ the platform, rather than trying to reinvent it.
If all you need is styles, you dont need to use new `<wa-*>` elements!
We also provide styles that make native HTML elements look good so you can continue using what you know and gradually adopt Web Awesome as you see fit.
{% set allPages = collections.native %}
{% include "grouped-pages.njk" %}
<br> {# Temp fix for spacing issue #}
## Installation
To use all Web Awesome page styles (including [utilities](/docs/utilities/)), include the following stylesheet in your project:
@@ -86,3 +82,4 @@ E.g. to opt-out of `<details>` styling:
If you find yourself opting out of entire element types too much, you could consider only including the parts of Native Styles you need instead of the whole thing.
You can find instructions for how to do that on the individual Native Styles pages.
{% endmarkdown %}

View File

@@ -3,8 +3,8 @@ title: Slider
description: Sliders allow the user to select a single value within a given range using a slider.
tags: forms
layout: element
icon: range
component: range
icon: slider
component: slider
elements:
"<input type=range>": https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range
---

View File

@@ -1,7 +1,6 @@
---
title: App
description: TODO
layout: pattern.njk
---
TODO Page Description
@@ -1045,4 +1044,4 @@ TODO Page Description
```
### With templates
### With recommendations grid
### With recommendations grid

View File

@@ -1,7 +1,6 @@
---
title: Blog
description: TODO
layout: pattern.njk
---
TODO Page Description
@@ -367,4 +366,4 @@ TODO Page Description
}
</style>
```
```

View File

@@ -1,9 +1,8 @@
---
title: Business
description: TODO
layout: pattern.njk
---
TODO Page Description
## Examples
## Examples

View File

@@ -1,7 +1,8 @@
---
title: E-commerce - Category Filter
title: Category Filter
description: TODO
layout: pattern.njk
parent: ecommerce
tags: e-commerce
---
TODO Page Description
@@ -9,4 +10,4 @@ TODO Page Description
## With inline actions and expandable sidebar filters
```html{.example}
```
```

View File

@@ -1,11 +1,12 @@
---
title: E-commerce - Category Preview
title: Category Preview
description: TODO
layout: pattern.njk
parent: ecommerce
tags: e-commerce
---
TODO Page Description
## Three Column (WIP)
```
```

View File

@@ -1,7 +1,8 @@
---
title: E-commerce - Order History
title: Order History
description: TODO
layout: pattern.njk
parent: ecommerce
tags: e-commerce
---
TODO Page Description
@@ -10,4 +11,4 @@ TODO Page Description
```html{.example}
```
```

View File

@@ -1,7 +1,8 @@
---
title: E-commerce - Product List
title: Product List
description: TODO
layout: pattern.njk
parent: ecommerce
tags: e-commerce
---
TODO Page Description
@@ -9,4 +10,4 @@ TODO Page Description
## With split image
```html{.example}
```
```

View File

@@ -1,7 +1,8 @@
---
title: E-commerce - Product Detail
title: Product Detail
description: TODO
layout: pattern.njk
parent: ecommerce
tags: e-commerce
---
TODO Page Description

View File

@@ -1,7 +1,8 @@
---
title: E-commerce - Product Lists
title: Product Lists
description: TODO
layout: pattern.njk
parent: ecommerce
tags: e-commerce
---
TODO Page Description

View File

@@ -1,7 +1,8 @@
---
title: E-commerce - Product Reviews
title: Product Reviews
description: TODO
layout: pattern.njk
parent: ecommerce
tags: e-commerce
---
TODO Page Description

View File

@@ -1,9 +1,10 @@
---
title: E-commerce - Shopping Cart
title: Shopping Cart
description: TODO
layout: pattern.njk
parent: ecommerce
tags: e-commerce
---
TODO Page Description
## Examples
## Examples

View File

@@ -2,6 +2,7 @@
title: E-commerce
description: TODO
layout: page
tags: e-commerce
---
TODO Page Description

View File

@@ -1,9 +1,8 @@
---
title: Business
description: TODO
layout: pattern.njk
---
TODO Page Description
## Examples
## Examples

View File

@@ -1,9 +1,8 @@
---
title: Entertainment
description: TODO
layout: pattern.njk
---
TODO Page Description
## Examples
## Examples

View File

@@ -1,5 +0,0 @@
---
title: Patterns
description: Browse the library of customizable, framework-friendly web components included in Web Awesome.
layout: page-outline
---

View File

@@ -0,0 +1,8 @@
---
title: Patterns
description: Patterns are reusable solutions to common design problems.
layout: overview
categories: ["e-commerce"]
listChildren: true
override:tags: []
---

View File

@@ -1,9 +1,8 @@
---
title: Membership
description: TODO
layout: pattern.njk
---
TODO Page Description
## Examples
## Examples

View File

@@ -1,7 +1,6 @@
---
title: News
description: TODO
layout: pattern.njk
---
TODO Page Description
@@ -157,4 +156,4 @@ TODO Page Description
}
}
</style>
```
```

View File

@@ -1,9 +1,8 @@
---
title: Non-profit
description: TODO
layout: pattern.njk
---
TODO Page Description
## Examples
## Examples

View File

@@ -0,0 +1,5 @@
{
"layout": "block.njk",
"tags": ["patterns"],
"noAlpha": true
}

View File

@@ -1,9 +1,8 @@
---
title: Portfolio
description: TODO
layout: pattern.njk
---
TODO Page Description
## Examples
## Examples

View File

@@ -1,9 +1,8 @@
---
title: Product Landing
description: TODO
layout: pattern.njk
---
TODO Page Description
## Examples
## Examples

View File

@@ -12,15 +12,27 @@ Components with the <wa-badge variant="warning" pill>Experimental</wa-badge> bad
During the alpha period, things might break! We take breaking changes very seriously, but sometimes they're necessary to make the final product that much better. We appreciate your patience!
:::
## Next
## 3.0.0-alpha.8
- Simplified the internal structure and CSS properties of `<wa-card>`, removed `base` part.
- Added `appearance` to `<wa-callout>` and `<wa-tag>`
- Fixed a bug in `<wa-switch>` where it would not properly change its "checked" state when its property changed.
- Fixed a bug in `<wa-switch>` where the value would be incorrectly submitted as "on" when a value is provided and the switch is checked
- Fixed a bug in the `wa-split` CSS utility that caused it to behave incorrectly
- Improved performance of `<wa-select>` when using a large number of options
- Updated the Japanese translation
### Theming
- Added new themes:
- Awesome
- Active
- Brutalist
- Mellow
- Tailspin
- Playful
- Renamed `--wa-form-control-resting-color` to `--wa-form-control-border-color` for familiarity and accuracy
- Removed size-based `--wa-form-control-height-*` tokens in favor of `--wa-form-control-height` (see [size utilities](/docs/utilities/size/))
- Updated the `--wa-border-width-*` and `--wa-border-radius-*` scale for better DX
- Changed the value of `--wa-border-width-scale` to `1` and updated calculations of size-based `--wa-border-width-*` tokens
- Changed the value of `--wa-border-radius-scale` to `1` and updated calculations of size-based `--wa-border-radius-*` tokens
@@ -147,4 +159,4 @@ Here's a list of some of the things that have changed since Shoelace v2. For que
Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome-alpha/discussions)
Are you coming from Shoelace? [The 2.x changelog can be found here.](https://shoelace.style/resources/changelog/)
Are you coming from Shoelace? [The 2.x changelog can be found here.](https://shoelace.style/resources/changelog/)

View File

@@ -3,55 +3,327 @@ title: Themes
description: Everything you need to know about theming Web Awesome.
layout: page-outline
---
<style>
wa-page > main {
max-width: 140ch;
.max-line-length {
max-width: 80ch;
}
}
.theme-showcase {
container: showcase / inline-size;
background-color: var(--wa-color-surface-lowered);
border-radius: var(--wa-border-radius-l);
min-height: 16lh;
height: 65vh;
max-height: 21lh;
padding: var(--wa-space-xl);
overflow: hidden;
margin-block-end: var(--wa-space-xl);
&.wa-flank {
--content-percentage: 55%;
--flank-size: 20ch;
}
}
.showcase-examples-wrapper {
inline-size: 100%;
block-size: 100%;
}
.showcase-examples {
column-gap: var(--wa-space-xl);
& wa-card {
display: inline-block;
width: 100%;
&:has(+ wa-card) {
margin-block-end: var(--wa-space-xl);
}
}
}
@supports not (zoom: 1) {
.showcase-examples {
column-count: 1;
}
@container showcase (width > 700px) {
.showcase-examples {
column-count: 2;
}
}
@container showcase (width > 900px) {
.showcase-examples {
column-count: 3;
}
}
}
@supports (zoom: 1) {
.showcase-examples {
column-count: 2;
zoom: 40%;
}
@container showcase (width > 400px) {
.showcase-examples {
zoom: 55%;
}
}
@container showcase (width > 700px) {
.showcase-examples {
zoom: 70%;
}
}
@container showcase (width > 800px) {
.showcase-examples {
column-count: 3;
zoom: 70%;
}
}
}
</style>
<div class="theme-showcase wa-flank wa-gap-xl">
<div>
<h2 id="theme-showcase-name" data-theme-name></h2>
<p id="theme-showcase-description" data-theme-description></p>
</div>
<div class="showcase-examples-wrapper">
<div class="showcase-examples">
<wa-card with-header with-footer>
<div slot="header" class="wa-split">
<h3 class="wa-heading-m">Your Cart</h3>
<wa-icon-button name="xmark"></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>
<div class="wa-stack wa-gap-xs">
<div class="wa-split wa-gap-xs">
<strong>Initiate Saber</strong>
<strong>$179.99</strong>
</div>
<div class="wa-split wa-gap-xs wa-caption-m">
<span>Green</span>
<a href="#">Remove</a>
</div>
</div>
</div>
<wa-divider></wa-divider>
<div class="wa-flank">
<wa-avatar shape="rounded" style="--size: 3em; --background-color: var(--wa-color-teal-60); --text-color: var(--wa-color-teal-95);">
<wa-icon slot="icon" name="robot-astromech" family="duotone" style="font-size: 1.5em;"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-xs">
<div class="wa-split wa-gap-xs">
<strong>Repair Droid</strong>
<strong>$3,049.99</strong>
</div>
<div class="wa-split wa-gap-xs wa-caption-m">
<span>R-series</span>
<a href="#">Remove</a>
</div>
</div>
</div>
</div>
<div slot="footer" class="wa-stack">
<div class="wa-split">
<strong>Subtotal</strong>
<strong>$3,229.98</strong>
</div>
<span class="wa-caption-m">Shipping and taxes calculated at checkout.</span>
<wa-button variant="brand">
<wa-icon slot="prefix" name="shopping-bag"></wa-icon>
Checkout
</wa-button>
</div>
</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-avatar>
<p class="wa-body-l" style="margin: 0;">&ldquo;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.&rdquo;</p>
</wa-card>
<wa-card>
<div class="wa-stack">
<h3 class="wa-heading-m">Sign In</h3>
<wa-input label="Email" placeholder="ddjarin@mandalore.gov">
<wa-icon slot="prefix" name="envelope" variant="regular"></wa-icon>
</wa-input>
<wa-input label="Password" type="password">
<wa-icon slot="prefix" name="lock" variant="regular"></wa-icon>
</wa-input>
<wa-button variant="brand">Sign In</wa-button>
<a href="#" class="wa-body-s">I forgot my password</a>
</div>
</wa-card>
<wa-card with-footer>
<div class="wa-stack">
<div class="wa-split">
<h3 class="wa-heading-m">To-Do</h3>
<wa-icon-button name="plus" label="Add task"></wa-icon-button>
</div>
<wa-checkbox checked>Umbrella for Adelard</wa-checkbox>
<wa-checkbox checked>Waste-paper basket for Dora</wa-checkbox>
<wa-checkbox checked>Pen and ink for Milo</wa-checkbox>
<wa-checkbox>Mirror for Angelica</wa-checkbox>
<wa-checkbox>Silver spoons for Lobelia</wa-checkbox>
</div>
<div slot="footer">
<a href="">View all completed</a>
</div>
</wa-card>
<wa-card>
<div class="wa-stack">
<div class="wa-frame wa-border-radius-m" style="align-self: center; max-inline-size: 25ch;">
<img src="https://images.unsplash.com/photo-1667514627762-521b1c815a89?q=20" alt="Album art">
</div>
<div class="wa-flank:end wa-align-items-start">
<div class="wa-stack wa-gap-3xs">
<div class="wa-cluster wa-gap-xs" style="height: 2.25em;">
<strong>The Stone Troll</strong>
<small><wa-badge variant="neutral" appearance="filled">E</wa-badge></small>
</div>
<span class="wa-caption-m">Samwise G</span>
</div>
<wa-icon-button name="ellipsis" label="Options"></wa-icon-button>
</div>
<div class="wa-stack wa-gap-2xs">
<wa-progress-bar value="34" style="height: 0.5em"></wa-progress-bar>
<div class="wa-split">
<span class="wa-caption-xs">1:01</span>
<span class="wa-caption-xs">-1:58</span>
</div>
</div>
<div class="wa-grid wa-align-items-center" style="--min-column-size: 1em; justify-items: center;">
<wa-icon-button name="backward" label="Skip backward"></wa-icon-button>
<wa-icon-button name="pause" style="font-size: var(--wa-font-size-2xl);" label="Pause"></wa-icon-button>
<wa-icon-button name="forward" label="Skip forward"></wa-icon-button>
</div>
</div>
</wa-card>
<wa-card>
<div class="wa-stack">
<h3 class="wa-heading-m">Chalmun's Spaceport Cantina</h3>
<div class="wa-cluster wa-gap-xs">
<wa-rating value="4.6" read-only></wa-rating>
<strong>4.6</strong>
<span>(419 reviews)</span>
</div>
<div class="wa-cluster wa-gap-xs">
<div class="wa-cluster wa-gap-3xs">
<wa-icon name="dollar" style="color: var(--wa-color-green-60);"></wa-icon>
<wa-icon name="dollar" style="color: var(--wa-color-green-60);"></wa-icon>
<wa-icon name="dollar" style="color: var(--wa-color-green-60);"></wa-icon>
</div>
<span class="wa-caption-m">&bull;</span>
<wa-tag size="small">Cocktail Bar</wa-tag>
<wa-tag size="small">Gastropub</wa-tag>
<wa-tag size="small">Local Fare</wa-tag>
<wa-tag size="small">Gluten Free</wa-tag>
</div>
<div class="wa-flank wa-gap-xs">
<wa-icon name="location-dot"></wa-icon>
<a href="#" class="wa-caption-m">Mos Eisley, Tatooine</a>
</div>
</div>
</wa-card>
</div>
</div>
</div>
<div class="max-line-length">
Themes are collections of pre-defined CSS custom properties that thread through every Web Awesome component and pattern.
Web Awesome includes two pre-made themes:
- **Default** for a clean look that prioritizes accessibility and performance
- **Classic** for the look and feel of Shoelace with more accessible color pairings
Web Awesome Free includes these pre-made themes:
- **Default** (`default.css`) for a clean look that prioritizes accessibility and performance
- **Classic** (`classic.css`) for the look and feel of Shoelace with more accessible color pairings
- **Awesome** (`awesome.css`) for the familiar, vibrant styles from your friends at Font Awesome
Even more themes are available with Web Awesome <wa-badge>Pro</wa-badge>:
- **Active** (`active.css`)
- **Brutalist** (`brutalist.css`)
- **Mellow** (`mellow.css`)
- **Tailspin** (`tailspin.css`)
To get started right away, include the following in your project, replacing `default.css` at the end with your preferred pre-made theme:
```html
<link rel="stylesheet" href="{% cdnUrl 'styles/themes/default.css' %}" />
```
## What's a Theme?
Themes are a standard collection of [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) that cover all styles from colors to transitions. We use these custom properties throughout Web Awesome components to ensure a cohesive look and feel. Our [Theming pages](/docs/theming/) document these styles so that you can use them freely throughout your project and customize them as needed.
Themes are a collection of standardized [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) that cover a range of styles from colors to transitions. We use these custom properties throughout Web Awesome components for a cohesive look and feel. Our [Theming pages](/docs/theming/) document these styles so that you can use them freely throughout your project and customize them as needed.
Themes are scoped to unique classes for each color scheme, such as `wa-theme-default-light` and `wa-theme-default-dark`, and the `:host` selector. Scoping to unique classes allows you to import multiple themes and use them interchangeably without collisions, while scoping to `:host` ensures the styles are applied to the shadow roots of custom elements.
Themes are scoped to unique classes, such as `wa-theme-default` or `wa-theme-classic`. Scoping to unique classes allows you to import multiple themes and use them interchangeably without collisions.
Additionally, styles may be scoped to the `:root` selector to be activated automatically. For pre-made themes, *all* custom properties are scoped to both `:root` and the class for the light color scheme (`wa-theme-default-light` or `wa-theme-classic-light`), activating the light color scheme by default.
Each theme may also include both light and dark color schemes with the classes `wa-light` and `wa-dark`.
You can use these classes to apply a specific color scheme to an entire page or just a section.
In pre-made themes, we use a light color scheme by default.
Other themes or color schemes must be activated with the corresponding class, like the dark color scheme for pre-made themes (`wa-theme-default-dark` or `wa-theme-classic-dark`), which only defines a subset of custom properties for colors. This ensures that non-color styles only need to be defined once for the theme, regardless of whether the color scheme is light or dark.
Additionally, styles may be scope to the `:root` selector to be activated automatically.
For pre-made themes, *all* custom properties are scoped to `:where(:root)`, the theme class, and `wa-light`.
:::info
We use `:where(:root)` to give these styles 0 [specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) so that they can be easily overridden. If you plan on using multiple themes in your project, we recommend doing the same for your custom themes.
:::
Finally, we scope themes to `:host` and `:host-context()` to ensure the styles are applied to the shadow roots of custom elements.
For example, the default theme is set up like this:
```css
:root,
:where(:root),
:host,
.wa-theme-default-light {
.wa-theme-default,
.wa-light {
/* all CSS custom properties for color, typography, space, etc. */
}
.wa-theme-default-dark,
.wa-theme-default-dark :host {
/* subset of CSS custom properties for color */
.wa-dark,
:host-context(.wa-dark) {
/* subset of CSS custom properties for a dark color scheme */
}
```
## Using Themes
You can import the default and classic themes from the Web Awesome CDN. Simply add the following code to the `<head>` of your page to import the **default** theme:
You can import pre-made themes from the Web Awesome CDN. Simply add the following code to the `<head>` of your page to import the **default** theme:
```html
<link rel="stylesheet" href="https://early.webawesome.com/webawesome@3.0.0-alpha.4/dist/styles/themes/default.css" />
<link rel="stylesheet" href="{% cdnUrl 'styles/themes/default.css' %}" />
```
Or import the **classic** theme:
Or the **Classic** theme:
```html
<link rel="stylesheet" href="https://early.webawesome.com/webawesome@3.0.0-alpha.4/dist/styles/themes/classic.css" />
<link rel="stylesheet" href="{% cdnUrl 'styles/themes/classic.css' %}" />
```
Both the default and classic themes include both light and dark color schemes. When importing either theme, the light color scheme is activated by default. To activate the dark color scheme, apply the appropriate class (`wa-theme-default-dark` or `wa-theme-classic-dark`, depending on theme) to the `<html>` element on your page, like this example for the default theme:
Or any of our Pro themes, like **Brutalist**:
```html
<html class="wa-theme-default-dark">
<link rel="stylesheet" href="{% cdnUrl 'styles/themes/brutalist.css' %}" />
```
To activate the dark color scheme of any theme, apply the class `wa-dark` to the `<html>` element on your page, like this example for the default theme:
```html
<html class="wa-theme-default wa-dark">
<head>
<link rel="stylesheet" href="path/to/web-awesome/dist/styles/themes/default.css" />
<!-- other links, scripts, and metadata -->
@@ -62,7 +334,7 @@ Both the default and classic themes include both light and dark color schemes. W
</html>
```
Because themes are scoped to specific classes, you can activate different color schemes or entire themes on different containers throughout the page. This example uses the default theme with a dark sidebar.
Because themes are scoped to specific classes, you can use different color schemes or even different themes throughout the page. Here, we use the default theme with a dark sidebar:
```html
<html>
@@ -71,7 +343,7 @@ Because themes are scoped to specific classes, you can activate different color
</head>
<body>
<nav class="wa-theme-default-dark">
<nav class="wa-dark">
<!-- dark-themed sidebar -->
</nav>
@@ -93,7 +365,8 @@ If you're customizing the default light styles, scope your styles to the followi
```css
:root,
:host,
.wa-theme-default-light {
.wa-theme-default,
.wa-light {
/* your custom styles here */
}
```
@@ -101,13 +374,13 @@ If you're customizing the default light styles, scope your styles to the followi
If you're customizing the default dark styles, scope your styles to the following selectors.
```css
:host,
.wa-theme-default-dark {
.wa-dark,
:is(:host-context(.wa-dark)) {
/* your custom styles here */
}
```
By customizing a built-in theme, you'll maintain a smaller stylesheet containing only the changes you've made. Contrast this to [creating a new theme](#creating-a-new-theme), where you need to explicitly define every custom property required by the library. This approach is more "future-proof," as new design tokens that emerge in subsequent versions of Web Awesome will be accounted for by built-in themes.
By customizing a built-in theme, you'll maintain a smaller stylesheet containing only your changes. Contrast this to [creating a new theme](#creating-a-new-theme), where you need to explicitly define every custom property required by the library. This approach is more "future-proof," as new design tokens that emerge in subsequent versions of Web Awesome will be accounted for by built-in themes.
While this approach is easier to maintain, the drawback is that your theme can't be activated independently — it's tied to the built-in theme you're extending.
@@ -118,8 +391,10 @@ Creating a new theme is more of an undertaking than [customizing an existing one
Start by changing the selector to match your theme's name. Assuming your new theme is called "Purple Power", your theme should be scoped like this.
```css
:root,
:host,
.wa-theme-purple-power {
.wa-theme-purple-power,
.wa-light {
/* your custom styles here */
}
```
@@ -137,3 +412,4 @@ Web Awesome's default theme has both light and dark styles built in. However, We
- Remember the user's preference and restore it on subsequent logins
Web Awesome avoids using the `prefers-color-scheme` media query because not all apps support dark mode, and it would break things for the ones that don't.
</div>

View File

@@ -15,14 +15,15 @@ Border style controls the standard line shape of borders throughout Web Awesome.
Border widths use `rem` units in order to scale proportionately with the root font size.
Each border width value uses a `calc()` function with `--wa-border-width-scale` to scale all border widths at once. By default, this multiplier is `0.0625`. The table below lists the result of the calculation.
| Custom Property | Default Value | Preview |
| --------------------- | -------------------------------- | ------------------------------------------------------------------------- |
| `--wa-border-width-s` | `0.0625rem` <small>(1px)</small> | <div class="swatch" style="border-width: var(--wa-border-width-s)"></div> |
| `--wa-border-width-m` | `0.125rem` <small>(2px)</small> | <div class="swatch" style="border-width: var(--wa-border-width-m)"></div> |
| `--wa-border-width-l` | `0.1875rem` <small>(3px)</small> | <div class="swatch" style="border-width: var(--wa-border-width-l)"></div> |
To scale all borders at once, you can use the `--wa-border-width-scale` property which specifies a multiplier on `border-width`.
Values < 1 make all borders uniformly thinner, while values > 1 make them thicker.
## Radius
Border radius controls the corners of Web Awesome components.
@@ -37,10 +38,11 @@ Common border radius properties allow you to achieve specific shapes beyond your
Size-based border radius properties allow you to customize the overall roundness of Web Awesome components. These use `rem` units in order to scale proportionately with the root font size.
Each property uses a `calc()` function with `--wa-border-radius-scale` to uniformly scale all border radii. By default, this multiplier is `1`. The table below lists the result of the calculation.
| Custom Property | Default Value | Preview |
| ----------------------- | -------------------------------- | --------------------------------------------------------------------------- |
| `--wa-border-radius-s` | `0.1875rem` <small>(3px)</small> | <div class="swatch" style="border-radius: var(--wa-border-radius-s)"></div> |
| `--wa-border-radius-m` | `0.375rem` <small>(6px)</small> | <div class="swatch" style="border-radius: var(--wa-border-radius-m)"></div> |
| `--wa-border-radius-l` | `0.75rem` <small>(12px)</small> | <div class="swatch" style="border-radius: var(--wa-border-radius-l)"></div> |
| Custom Property | Default Value | Preview |
| ----------------------- | -------------------------------- | ---------------------------------------------------------------------------- |
| `--wa-border-radius-s` | `0.1875rem` <small>(3px)</small> | <div class="swatch" style="border-radius: var(--wa-border-radius-s)"></div> |
| `--wa-border-radius-m` | `0.375rem` <small>(6px)</small> | <div class="swatch" style="border-radius: var(--wa-border-radius-m)"></div> |
| `--wa-border-radius-l` | `0.75rem` <small>(12px)</small> | <div class="swatch" style="border-radius: var(--wa-border-radius-l)"></div> |
To scale all border radii at once, you can use the `--wa-border-radius-scale` property which specifies a multiplier on `border-radius`.
Values < 1 make corners sharper, while values > 1 make them rounder.

View File

@@ -210,6 +210,54 @@ Web Awesome defines seven literal colors each with 11 lightness values using the
</li>
</ul>
<div class="color-name">Teal</div>
<ul class="color-group">
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-95)"></div>
<small>95</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-90)"></div>
<small>90</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-80)"></div>
<small>80</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-70)"></div>
<small>70</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-60)"></div>
<small>60</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-50)"></div>
<small>50</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-40)"></div>
<small>40</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-30)"></div>
<small>30</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-20)"></div>
<small>20</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-10)"></div>
<small>10</small>
</li>
<li class="color-preview">
<div class="swatch" style="background-color: var(--wa-color-teal-05)"></div>
<small>05</small>
</li>
</ul>
<div class="color-name">Blue</div>
<ul class="color-group">
<li class="color-preview">

View File

@@ -1,6 +1,7 @@
---
title: Component Groups
description: Style groups of components that share similar qualities with these Web Awesome custom properties.
order: 9999
---
For components that share similar qualities, Web Awesome includes custom properties to change the appearance of these related components all at once.
@@ -14,11 +15,11 @@ Not every form control uses all of these custom properties. For example, `<wa-ra
| Custom Property | Default Value |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `--wa-form-control-background-color` | `var(--wa-color-surface-default)` |
| `--wa-form-control-border-color` | `var(--wa-color-neutral-border-loud)` |
| `--wa-form-control-border-style` | `var(--wa-border-style)` |
| `--wa-form-control-border-width` | `var(--wa-border-width-s)` |
| `--wa-form-control-border-radius` | `var(--wa-border-radius-m)` |
| `--wa-form-control-activated-color` | `var(--wa-color-brand-fill-loud)` |
| `--wa-form-control-resting-color` | `var(--wa-color-neutral-border-loud)` |
| `--wa-form-control-label-color` | `var(--wa-color-neutral-border-loud)` |
| `--wa-form-control-label-font-weight` | `var(--wa-font-weight-normal)` |
| `--wa-form-control-label-line-height` | `var(--wa-line-height-normal)` |
@@ -26,9 +27,6 @@ Not every form control uses all of these custom properties. For example, `<wa-ra
| `--wa-form-control-value-font-weight` | `var(--wa-font-weight-body)` |
| `--wa-form-control-value-line-height` | `var(--wa-line-height-condensed)` |
| `--wa-form-control-placeholder-color` | `var(--wa-color-gray-60)` |
| `--wa-form-control-height-s` | `calc(var(--wa-space-xs) * 2 + 1em * var(--wa-form-control-value-line-height))` |
| `--wa-form-control-height-m` | `calc(var(--wa-space-s) * 2 + 1em * var(--wa-form-control-value-line-height))` |
| `--wa-form-control-height-l` | `calc(var(--wa-space-m) * 2 + 1em * var(--wa-form-control-value-line-height))` |
| `--wa-form-control-required-content` | `'*'` |
| `--wa-form-control-required-content-color` | `inherit` |
| `--wa-form-control-required-content-offset` | `-0.1em` |
@@ -49,7 +47,7 @@ Not every form control uses all of these custom properties. For example, `<wa-ra
</wa-radio-group>
<wa-checkbox>Checkbox</wa-checkbox>
<wa-switch>Switch</wa-switch>
<wa-range label="Range"></wa-range>
<wa-slider label="Range"></wa-slider>
<wa-button>Button</wa-button>
</form>

View File

@@ -1,73 +0,0 @@
---
title: Theming
description: Browse the library of customizable, framework-friendly web components included in Web Awesome.
---
<p class="index-summary">A theme is a collection of pre-defined CSS custom properties that control global styles from color to shadows. These custom properties thread through all Web Awesome components for a consistent look and feel.</p>
<div class="index-grid">
<a href="/docs/theming/color">
<wa-card with-header>
<div slot="header">
{% include "svgs/theming/color.njk" %}
</div>
<span class="page-name">Color</span>
</wa-card>
</a>
<a href="/docs/theming/typography">
<wa-card with-header>
<div slot="header">
{% include "svgs/theming/typography.njk" %}
</div>
<span class="page-name">Typography</span>
</wa-card>
</a>
<a href="/docs/theming/space">
<wa-card with-header>
<div slot="header">
{% include "svgs/theming/space.njk" %}
</div>
<span class="page-name">Space</span>
</wa-card>
</a>
<a href="/docs/theming/borders">
<wa-card with-header>
<div slot="header">
{% include "svgs/theming/borders.njk" %}
</div>
<span class="page-name">Borders</span>
</wa-card>
</a>
<a href="/docs/theming/focus">
<wa-card with-header>
<div slot="header">
{% include "svgs/theming/focus.njk" %}
</div>
<span class="page-name">Focus</span>
</wa-card>
</a>
<a href="/docs/theming/shadows">
<wa-card with-header>
<div slot="header">
{% include "svgs/theming/shadows.njk" %}
</div>
<span class="page-name">Shadows</span>
</wa-card>
</a>
<a href="/docs/theming/transitions">
<wa-card with-header>
<div slot="header">
{% include "svgs/theming/transitions.njk" %}
</div>
<span class="page-name">Transitions</span>
</wa-card>
</a>
<a href="/docs/theming/component-groups">
<wa-card with-header>
<div slot="header">
{% include "svgs/theming/component-groups.njk" %}
</div>
<span class="page-name">Component Groups</span>
</wa-card>
</a>
</div>

View File

@@ -0,0 +1,6 @@
---
title: Theming
description: A theme is a collection of pre-defined CSS custom properties that control global styles from color to shadows. These custom properties thread through all Web Awesome components for a consistent look and feel.
layout: overview
override:tags: []
---

View File

@@ -1,4 +1,7 @@
{
"layout": "page-outline.njk",
"tags": ["theming"]
"tags": ["theming"],
"eleventyComputed": {
"icon": "theming/{{ page.fileSlug }}"
}
}

View File

@@ -1,11 +1,11 @@
---
title: Appearance Variants
description: Appearance utilities apply a collection of properties to achieve certain effects, like making elements accented, outlined, filled, or plain.
classes:
- wa-accent
- wa-outlined
- wa-filled
- wa-plain
snippets:
- .wa-accent
- .wa-outlined
- .wa-filled
- .wa-plain
---
Some Web Awesome components, like `<wa-button>`, allow you to change their overall style by using an `appearance` attribute:

View File

@@ -2,12 +2,12 @@
title: Color Variants
description: Color utilities allow you to apply the brand, neutral, success, warning, and danger colors from your theme to any element.
icon: theming/color
classes:
- wa-brand
- wa-neutral
- wa-success
- wa-warning
- wa-danger
snippets:
- .wa-brand
- .wa-neutral
- .wa-success
- .wa-warning
- .wa-danger
---
Some Web Awesome components, like `<wa-button>`, allow you to change the color by using a `variant` attribute:

View File

@@ -2,16 +2,12 @@
title: Style Utilities
description: Web Awesome provides a few style utilities to customize styles in ways that cannot necessarily be described by semantic HTML.
Some of these correspond to component attributes, but we also expose utility classes so you can apply these styles to native elements too.
layout: page-outline
override:tags: []
layout: overview
categories: ["layout"]
override:tags: []
---
{% set allPages = collections.utilities %}
{% include "grouped-pages.njk" %}
<br> {# Temp fix for spacing issue #}
{% markdown %}
## Installation
To use all Web Awesome page styles (including [native styles](/docs/native/)), include the following stylesheet in your project:
@@ -27,3 +23,4 @@ Or, to _only_ include utilities:
```
You can also include individual utilities following the instructions in their pages.
{% endmarkdown %}

View File

@@ -3,10 +3,10 @@ title: Size
description: Size utilities give elements one of three preset sizes (small, medium, or large).
icon: theming/space
status: experimental
classes:
- wa-size-s
- wa-size-m
- wa-size-l
snippets:
- .wa-size-s
- .wa-size-m
- .wa-size-l
---
Some Web Awesome components, like `<wa-button>`, allow you to change their size to one of three presets: `small`, `medium`, and `large` by using a `size` attribute:
@@ -24,6 +24,7 @@ You can create the same effect on any element by using the size utility classes:
Using these classes does two things:
- It sets `font-size` to one of the [size tokens](/docs/theming/typography/#font-size).
You can use CSS `em` units to reference that size in other properties.
- It calculates `--wa-form-control-height` based on the applied size, supporting consistent heights for elements like inputs and buttons.
- It aliases a bunch of other properties that CSS can use:
| Custom Property | Small | Medium | Large |
@@ -32,7 +33,6 @@ You can use CSS `em` units to reference that size in other properties.
| `--wa-size-smaller` | `--wa-font-size-xs` | `--wa-font-size-s` | `--wa-font-size-m` |
| `--wa-space` | `--wa-space-s` | `--wa-space-m` | `--wa-space-l` |
| `--wa-space-smaller` | `--wa-space-xs` | `--wa-space-s` | `--wa-space-m` |
| `--wa-form-control-height` | `--wa-form-control-height-s` | `--wa-form-control-height-m` | `--wa-form-control-height-l` |
For example, assume we wanted to make a custom `.tag` class with size variants.

View File

@@ -1,4 +1,4 @@
{
"layout": "utilities",
"layout": "block",
"tags": ["utilities"]
}

View File

@@ -2,9 +2,9 @@
title: Visually Hidden
description: The visually hidden utility makes content accessible to assistive devices without displaying it on the screen.
icon: visually-hidden
classes:
- wa-visually-hidden
- wa-visually-hidden-force
snippets:
- .wa-visually-hidden
- .wa-visually-hidden-force
---
> "there are real world situations where visually hiding content may be appropriate, while the content should remain available to assistive technologies, such as screen readers. For instance, hiding a search field's label as a common magnifying glass icon is used in its stead."

View File

@@ -268,7 +268,7 @@ layout: page
<h1 class="brand-font">Make something <span class="emphasis">awesome</span> with open-source web components</h1>
<div class="hero-cta">
<span><em>Psst!</em> You can pre-order Web Awesome Pro at a low, guaranteed-for-life price &mdash; but not for long. Get in while the gettins good.</span>
<wa-button class="wa-theme-default-dark" size="small" href="https://www.kickstarter.com/projects/fontawesome/web-awesome">
<wa-button class="wa-dark" size="small" href="https://www.kickstarter.com/projects/fontawesome/web-awesome">
<wa-icon slot="prefix" name="person-running"></wa-icon>
Pre-order WA Pro
</wa-button>

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@shoelace-style/webawesome",
"version": "3.0.0-alpha.7",
"version": "3.0.0-alpha.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@shoelace-style/webawesome",
"version": "3.0.0-alpha.7",
"version": "3.0.0-alpha.8",
"license": "MIT",
"dependencies": {
"@ctrl/tinycolor": "^4.1.0",

View File

@@ -1,7 +1,7 @@
{
"name": "@shoelace-style/webawesome",
"description": "A forward-thinking library of web components.",
"version": "3.0.0-alpha.7",
"version": "3.0.0-alpha.8",
"homepage": "https://webawesome.com/",
"author": "Web Awesome",
"license": "MIT",

View File

@@ -113,7 +113,15 @@ async function generateStyles() {
// Remove pro themes
const allThemes = await globby(join(cdnDir, 'styles/themes/**/*.css'));
const proThemes = allThemes.filter(file => {
if (file.includes('themes/classic') || file.includes('themes/default')) {
if (
file.includes('themes/classic') ||
file.includes('themes/default') ||
file.includes('themes/awesome') ||
file.includes('themes/active') ||
file.includes('themes/mellow') ||
file.includes('themes/tailspin') ||
file.includes('themes/brutalist')
) {
return false;
}
return true;

View File

@@ -3,8 +3,6 @@ import { html } from 'lit';
import { fixtures } from '../../internal/test/fixture.js';
import type WaAvatar from './avatar.js';
// The default avatar background just misses AA contrast, but the next step up is way too dark. Since avatars aren't
// used to display text, we're going to relax this rule.
const ignoredRules = ['color-contrast'];
describe('<wa-avatar>', () => {
@@ -22,9 +20,7 @@ describe('<wa-avatar>', () => {
});
it('should default to circle styling', () => {
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(el.getAttribute('shape')).to.eq('circle');
expect(part.classList.value.trim()).to.eq('avatar avatar--circle');
});
});
@@ -36,25 +32,12 @@ describe('<wa-avatar>', () => {
});
it('should pass accessibility tests', async () => {
/**
* The image element itself is ancillary, because it's parent container contains the
* aria-label which dictates what "wa-avatar" is. This also implies that label text will
* resolve to "" when not provided and ignored by readers. This is why we use alt="" on
* the image element to pass accessibility.
* https://html.spec.whatwg.org/multipage/images.html#ancillary-images
*/
await expect(el).to.be.accessible({ ignoredRules });
});
it('renders "image" part, with src and a role of presentation', () => {
it('renders "image" part with src and proper aria-label', () => {
const part = el.shadowRoot!.querySelector('[part~="image"]')!;
expect(part.getAttribute('src')).to.eq(image);
});
it('renders the label attribute in the "base" part', () => {
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.getAttribute('aria-label')).to.eq(label);
});
});
@@ -69,50 +52,10 @@ describe('<wa-avatar>', () => {
await expect(el).to.be.accessible({ ignoredRules });
});
it('renders "initials" part, with initials as the text node', () => {
it('renders "initials" part with initials and proper aria-label', () => {
const part = el.shadowRoot!.querySelector<HTMLElement>('[part~="initials"]')!;
expect(part.innerText).to.eq(initials);
});
});
describe('when image is present, the initials or icon part should not render', () => {
const initials = 'SL';
const image = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
const label = 'Small transparent square';
beforeEach(async () => {
el = await fixture<WaAvatar>(
html`<wa-avatar image="${image}" label="${label}" initials="${initials}"></wa-avatar>`,
);
});
it('should pass accessibility tests', async () => {
/**
* The image element itself is ancillary, because it's parent container contains the
* aria-label which dictates what "wa-avatar" is. This also implies that label text will
* resolve to "" when not provided and ignored by readers. This is why we use alt="" on
* the image element to pass accessibility.
* https://html.spec.whatwg.org/multipage/images.html#ancillary-images
*/
await expect(el).to.be.accessible({ ignoredRules });
});
it('renders "image" part, with src and a role of presentation', () => {
const part = el.shadowRoot!.querySelector('[part~="image"]')!;
expect(part.getAttribute('src')).to.eq(image);
});
it('should not render the initials part', () => {
const part = el.shadowRoot!.querySelector<HTMLElement>('[part~="initials"]')!;
expect(part).to.not.exist;
});
it('should not render the icon part', () => {
const slot = el.shadowRoot!.querySelector<HTMLSlotElement>('slot[name=icon]')!;
expect(slot).to.not.exist;
expect(part.getAttribute('aria-label')).to.eq('Avatar');
});
});
@@ -126,11 +69,8 @@ describe('<wa-avatar>', () => {
await expect(el).to.be.accessible({ ignoredRules });
});
it('appends the appropriate class on the "base" part', () => {
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
it('reflects the shape attribute', () => {
expect(el.getAttribute('shape')).to.eq(shape);
expect(part.classList.value.trim()).to.eq(`avatar avatar--${shape}`);
});
});
});
@@ -149,11 +89,8 @@ describe('<wa-avatar>', () => {
it('should accept as an assigned child in the shadow root', () => {
const slot = el.shadowRoot!.querySelector<HTMLSlotElement>('slot[name=icon]')!;
const childNodes = slot.assignedNodes({ flatten: true }) as HTMLElement[];
expect(childNodes.length).to.eq(1);
const span = childNodes[0];
expect(span.innerHTML).to.eq('random content');
expect(childNodes[0].innerHTML).to.eq('random content');
});
});
@@ -161,11 +98,9 @@ describe('<wa-avatar>', () => {
el = await fixture<WaAvatar>(html`<wa-avatar></wa-avatar>`);
el.image = 'bad_image';
await aTimeout(0);
await el.updateComplete;
await waitUntil(() => el.shadowRoot!.querySelector('img') === null);
expect(el.shadowRoot!.querySelector('img')).to.be.null;
await waitUntil(() => el.shadowRoot?.querySelector('img') === null);
expect(el.shadowRoot?.querySelector('img')).to.be.null;
});
it('should show a valid image after being passed an invalid image initially', async () => {
@@ -173,7 +108,6 @@ describe('<wa-avatar>', () => {
await aTimeout(0);
await el.updateComplete;
// await waitUntil(() => el.shadowRoot!.querySelector('img') === null);
expect(el.shadowRoot!.querySelector('img')).to.be.null;
el.image = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';

View File

@@ -66,7 +66,7 @@ export default class WaAvatar extends WebAwesomeElement {
class="image"
src="${this.image}"
loading="${this.loading}"
alt=""
role="img"
aria-label=${this.label}
@error="${this.handleImageLoadError}"
/>

View File

@@ -3,8 +3,6 @@ import { html } from 'lit';
import { fixtures } from '../../internal/test/fixture.js';
import type WaBadge from './badge.js';
// The default badge background just misses AA contrast, but the next step up is way too dark. We're going to relax this
// rule for now.
const ignoredRules = ['color-contrast'];
describe('<wa-badge>', () => {
@@ -16,7 +14,7 @@ describe('<wa-badge>', () => {
expect(el.innerText).to.eq('Badge');
});
it('should pass accessibility tests with a role of status on the base part.', async () => {
it('should pass accessibility tests with a role of status on the base part', async () => {
const el = await fixture<WaBadge>(html` <wa-badge>Badge</wa-badge> `);
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.getAttribute('role')).to.eq('status');
@@ -25,8 +23,7 @@ describe('<wa-badge>', () => {
it('should default to square styling, with the brand color', async () => {
const el = await fixture<WaBadge>(html` <wa-badge>Badge</wa-badge> `);
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.classList.value.trim()).to.eq('badge badge--brand');
expect(el.getAttribute('variant')).to.eq('brand');
});
});
@@ -36,10 +33,9 @@ describe('<wa-badge>', () => {
await expect(el).to.be.accessible({ ignoredRules });
});
it('should append the pill class to the classlist to render a pill', async () => {
it('should have the pill attribute', async () => {
const el = await fixture<WaBadge>(html` <wa-badge pill>Badge</wa-badge> `);
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.classList.value.trim()).to.eq('badge badge--brand badge--pill');
expect(el.hasAttribute('pill')).to.be.true;
});
});
@@ -50,10 +46,9 @@ describe('<wa-badge>', () => {
await aTimeout(1);
});
it('should append the pulse class to the classlist to render a pulse', async () => {
it('should have the pulse attribute', async () => {
const el = await fixture<WaBadge>(html` <wa-badge pulse>Badge</wa-badge> `);
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.classList.value.trim()).to.eq('badge badge--brand badge--pulse');
expect(el.hasAttribute('pulse')).to.be.true;
});
});
@@ -65,10 +60,9 @@ describe('<wa-badge>', () => {
await aTimeout(1);
});
it('should default to square styling, with the correct color', async () => {
it('should have the correct variant attribute', async () => {
const el = await fixture<WaBadge>(html`<wa-badge variant="${variant}">Badge</wa-badge>`);
const part = el.shadowRoot!.querySelector('[part~="base"]')!;
expect(part.classList.value.trim()).to.eq(`badge badge--${variant}`);
expect(el.getAttribute('variant')).to.eq(variant);
});
});
});

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