- {% for page in collections[tag] | sort %}
- {% if not page.data.parent -%}
+ {% for page in children %}
{% include 'sidebar-link.njk' %}
- {%- endif %}
{% endfor %}
diff --git a/docs/_includes/sidebar-link.njk b/docs/_includes/sidebar-link.njk
index dab3e32a0..d44628b07 100644
--- a/docs/_includes/sidebar-link.njk
+++ b/docs/_includes/sidebar-link.njk
@@ -1,4 +1,4 @@
-{% if not (isAlpha and page.data.noAlpha) and page.fileSlug != tag and not page.data.unlisted -%}
+{% if page | show -%}
-{% set allPages = collections[forTag] %}
+{% set allPages = allPages or collections[forTag] %}
+{% if allPages and allPages.length > 0 %}
{% include "grouped-pages.njk" %}
+{% endif %}
diff --git a/docs/_layouts/page.njk b/docs/_layouts/page.njk
index a55a02c21..203527a44 100644
--- a/docs/_layouts/page.njk
+++ b/docs/_layouts/page.njk
@@ -1,4 +1,9 @@
-{% set hasSidebar = true %}
-{% set hasOutline = false %}
+{% if hasSidebar == undefined %}
+ {% set hasSidebar = true %}
+{% endif %}
+
+{% if hasOutline == undefined %}
+ {% set hasOutline = false %}
+{% endif %}
{% extends "../_includes/base.njk" %}
diff --git a/docs/_layouts/theme.njk b/docs/_layouts/theme.njk
index 97c737f41..63693354c 100644
--- a/docs/_layouts/theme.njk
+++ b/docs/_layouts/theme.njk
@@ -68,7 +68,7 @@ wa_data.palettes = {
- {% include "svgs/" + (palette.data.icon or "thumbnail-placeholder") + ".njk" %}
+ {% include "svgs/" + (palette.data.icon or "thumbnail-placeholder") + ".njk" ignore missing %}
{{ palette.data.title }}
diff --git a/docs/_utils/filters.js b/docs/_utils/filters.js
index 912b5dbb1..9747a78b3 100644
--- a/docs/_utils/filters.js
+++ b/docs/_utils/filters.js
@@ -29,6 +29,9 @@ function getCollection(name) {
}
export function getCollectionItemFromUrl(url, collection) {
+ if (!url) {
+ return null;
+ }
collection ??= getCollection.call(this, 'all') || [];
return collection.find(item => item.url === url);
}
@@ -42,35 +45,33 @@ export function split(text, separator) {
return (text + '').split(separator).filter(Boolean);
}
-export function breadcrumbs(url, { withCurrent = false } = {}) {
- const parts = split(url, '/');
- const ret = [];
+export function ancestors(url, { withCurrent = false, withRoot = false } = {}) {
+ let ret = [];
+ let currentUrl = url;
+ let currentItem = getCollectionItemFromUrl.call(this, url);
- while (parts.length) {
- let partialUrl = '/' + parts.join('/') + '/';
- let item = getCollectionItemFromUrl.call(this, partialUrl);
-
- if (item && (partialUrl !== url || withCurrent)) {
- let title = item.data.title;
- if (title) {
- ret.unshift({ url: partialUrl, title });
- }
- }
-
- parts.pop();
-
- if (item?.data.parent) {
- let parentURL = item.data.parent;
- if (!item.data.parent.startsWith('/')) {
- // Parent is in the same directory
- parts.push(item.data.parent);
- parentURL = '/' + parts.join('/') + '/';
- }
-
- let parentBreadcrumbs = breadcrumbs.call(this, parentURL, { withCurrent: true });
- return [...parentBreadcrumbs, ...ret];
+ if (!currentItem) {
+ // Might have eleventyExcludeFromCollections, jump to parent
+ let parentUrl = this.ctx.parentUrl;
+ if (parentUrl) {
+ url = parentUrl;
}
}
+
+ for (let item; (item = getCollectionItemFromUrl.call(this, url)); url = item.data.parentUrl) {
+ ret.unshift(item);
+ }
+
+ if (!withRoot && ret[0]?.page.url === '/') {
+ // Remove root
+ ret.shift();
+ }
+
+ if (!withCurrent && ret.at(-1)?.page.url === currentUrl) {
+ // Remove current page
+ ret.pop();
+ }
+
return ret;
}
@@ -177,72 +178,196 @@ export function sort(arr, by = { 'data.order': 1, 'data.title': '' }) {
});
}
+export function show(page) {
+ return !(page.data.noAlpha && page.data.isAlpha) && !page.data.unlisted;
+}
+
/**
* Group an 11ty collection (or any array of objects with a `data.tags` property) by certain tags.
* @param {object[]} collection
- * @param { Object | (string | Object)[]} [tags] The tags to group by. If not provided/empty, defaults to grouping by all tags.
- * @returns { Object. } An object with keys for each tag, and an array of items for each tag.
+ * @param { Object | string[]} [options] Options object or array of tags to group by.
+ * @param {string[] | true} [options.tags] Tags to group by. If true, groups by all tags.
+ * If not provided/empty, defaults to grouping by page hierarchy, with any pages with more than 1 children becoming groups.
+ * @param {string[]} [options.groups] The groups to use if only a subset or a specific order is desired. Defaults to `options.tags`.
+ * @param {string[]} [options.titles] Any title overrides for groups.
+ * @param {string | false} [options.other="Other"] The title to use for the "Other" group. If `false`, the "Other" group is removed..
+ * @returns { Object. } An object of group ids to arrays of page objects.
*/
-export function groupByTags(collection, tags) {
+export function groupPages(collection, options = {}, page) {
if (!collection) {
- console.error(`Empty collection passed to groupByTags() to group by ${JSON.stringify(tags)}`);
- }
- if (!tags) {
- // Default to grouping by union of all tags
- tags = Array.from(new Set(collection.flatMap(item => item.data.tags)));
- } else if (Array.isArray(tags)) {
- // May contain objects of one-off tag -> label mappings
- tags = tags.map(tag => (typeof tag === 'object' ? Object.keys(tag)[0] : tag));
- } else if (typeof tags === 'object') {
- // tags is an object of tags to labels, so we just want the keys
- tags = Object.keys(tags);
+ console.error(`Empty collection passed to groupPages() to group by ${JSON.stringify(options)}`);
}
- let ret = Object.fromEntries(tags.map(tag => [tag, []]));
- ret.other = [];
+ if (Array.isArray(options)) {
+ options = { tags: options };
+ }
+
+ let { tags, groups, titles = {}, other = 'Other', filter = show } = options;
+
+ if (groups === undefined && Array.isArray(tags)) {
+ groups = tags;
+ }
+
+ let grouping;
+
+ if (tags) {
+ grouping = {
+ isGroup: item => undefined,
+ getCandidateGroups: item => item.data.tags,
+ getGroupMeta: group => ({}),
+ };
+ } else {
+ grouping = {
+ isGroup: item => (item.data.children.length >= 2 ? item.page.url : undefined),
+ getCandidateGroups: item => {
+ let parentUrl = item.data.parentUrl;
+ if (page?.url === parentUrl) {
+ return [];
+ }
+ return [parentUrl];
+ },
+ getGroupMeta: group => {
+ let item = byUrl[group] || getCollectionItemFromUrl.call(this, group);
+ return {
+ title: item?.data.title,
+ url: group,
+ item,
+ };
+ },
+ sortGroups: groups => sort(groups.map(url => byUrl[url]).filter(Boolean)).map(item => item.page.url),
+ };
+ }
+
+ let byUrl = {};
+ let byParentUrl = {};
+
+ if (filter) {
+ collection = collection.filter(filter);
+ }
for (let item of collection) {
- let categorized = false;
+ let url = item.page.url;
+ let parentUrl = item.data.parentUrl;
- for (let tag of tags) {
- if (item.data.tags.includes(tag)) {
- ret[tag].push(item);
- categorized = true;
- }
- }
+ byUrl[url] = item;
- if (!categorized) {
- ret.other.push(item);
+ if (parentUrl) {
+ byParentUrl[parentUrl] ??= [];
+ byParentUrl[parentUrl].push(item);
}
}
- // Remove empty categories
- for (let category in ret) {
- if (ret[category].length === 0) {
- delete ret[category];
+ let urlToGroups = {};
+
+ for (let item of collection) {
+ let url = item.page.url;
+ let parentUrl = item.data.parentUrl;
+
+ if (grouping.isGroup(item)) {
+ continue;
+ }
+
+ let parentItem = byUrl[parentUrl];
+ if (parentItem && !grouping.isGroup(parentItem)) {
+ // Their parent is also here and is not a group
+ continue;
+ }
+
+ let candidateGroups = grouping.getCandidateGroups(item);
+
+ if (groups) {
+ candidateGroups = candidateGroups.filter(group => groups.includes(group));
+ }
+
+ urlToGroups[url] ??= [];
+
+ for (let group of candidateGroups) {
+ urlToGroups[url].push(group);
+ }
+ }
+
+ let ret = {};
+
+ for (let url in urlToGroups) {
+ let groups = urlToGroups[url];
+ let item = byUrl[url];
+
+ if (groups.length === 0) {
+ // Not filtered out but also not categorized
+ groups = ['other'];
+ }
+
+ for (let group of groups) {
+ ret[group] ??= [];
+ ret[group].push(item);
+
+ if (!ret[group].meta) {
+ if (group === 'other') {
+ ret[group].meta = { title: other };
+ } else {
+ ret[group].meta = grouping.getGroupMeta(group);
+ ret[group].meta.title = titles[group] ?? ret[group].meta.title ?? capitalize(group);
+ }
+ }
+ }
+ }
+
+ if (other === false) {
+ delete ret.other;
+ }
+
+ // Sort
+ let sortedGroups = groups ?? grouping.sortGroups?.(Object.keys(ret));
+
+ if (sortedGroups) {
+ ret = sortObject(ret, sortedGroups);
+ } else {
+ // At least make sure other is last
+ if (ret.other) {
+ let otherGroup = ret.other;
+ delete ret.other;
+ ret.other = otherGroup;
+ }
+ }
+
+ Object.defineProperty(ret, 'meta', {
+ value: {
+ groupCount: Object.keys(ret).length,
+ },
+ enumerable: false,
+ });
+
+ return ret;
+}
+
+/**
+ * Sort an object by its keys
+ * @param {*} obj
+ * @param {function | string[]} order
+ */
+function sortObject(obj, order) {
+ let ret = {};
+ let sortedKeys = Array.isArray(order) ? order : Object.keys(obj).sort(order);
+
+ for (let key of sortedKeys) {
+ if (key in obj) {
+ ret[key] = obj[key];
+ }
+ }
+
+ // Add any keys that weren't in the order
+ for (let key in obj) {
+ if (!(key in ret)) {
+ ret[key] = obj[key];
}
}
return ret;
}
-export function getCategoryTitle(category, categories) {
- let title;
- if (Array.isArray(categories)) {
- // Find relevant entry
- // [{id: "Title"}, id2, ...]
- title = categories.find(entry => typeof entry === 'object' && entry?.[category])?.[category];
- } else if (typeof categories === 'object') {
- // {id: "Title", id2: "Title 2", ...}
- title = categories[category];
- }
-
- if (title) {
- return title;
- }
-
- // Capitalized
- return category.charAt(0).toUpperCase() + category.slice(1);
+function capitalize(str) {
+ str += '';
+ return str.charAt(0).toUpperCase() + str.slice(1);
}
const IDENTITY = x => x;
diff --git a/docs/_utils/outline.js b/docs/_utils/outline.js
index 0281ee66b..026a59e00 100644
--- a/docs/_utils/outline.js
+++ b/docs/_utils/outline.js
@@ -39,7 +39,7 @@ export function outlinePlugin(options = {}) {
}
// Create a clone of the heading so we can remove links and [data-no-outline] elements from the text content
- clone.querySelectorAll('a').forEach(a => a.remove());
+ clone.querySelectorAll('.wa-visually-hidden, [hidden], [aria-hidden="true"]').forEach(el => el.remove());
clone.querySelectorAll('[data-no-outline]').forEach(el => el.remove());
// Generate the link
diff --git a/docs/assets/components/scoped.js b/docs/assets/components/scoped.js
new file mode 100644
index 000000000..e97e62096
--- /dev/null
+++ b/docs/assets/components/scoped.js
@@ -0,0 +1,169 @@
+/**
+ * Low-level utility to encapsulate a bit of HTML (mainly to apply certain stylesheets to it without them leaking to the rest of the page)
+ * Usage:
+ */
+
+// Map of elements to any global
```
@@ -65,9 +55,9 @@ If using SSR, you need to also use the `with-header` attribute to add a header t
```html {.example}
-
+
Header Title
-
+
This card has a header. You can put all sorts of things in it!
@@ -78,19 +68,9 @@ If using SSR, you need to also use the `with-header` attribute to add a header t
max-width: 300px;
}
- .card-header [slot='header'] {
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
-
.card-header h3 {
margin: 0;
}
-
- .card-header wa-icon-button {
- font-size: var(--wa-font-size-m);
- }
```
@@ -103,7 +83,7 @@ If using SSR, you need to also use the `with-footer` attribute to add a footer t
This card has a footer. You can put all sorts of things in it!
-
+
Preview
@@ -113,12 +93,6 @@ If using SSR, you need to also use the `with-footer` attribute to add a footer t
.card-footer {
max-width: 300px;
}
-
- .card-footer [slot='footer'] {
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
```
@@ -153,7 +127,7 @@ Use the `size` attribute to change a card's size.
This is a small card.
-
-
```
-
+### Appearance
+
+Use the `appearance` attribute to change the card's visual appearance.
+
+```html {.example}
+
+
+
+
Outlined (default)
+ Card content.
+
+{% for appearance in ['outlined filled', 'outlined accent', 'plain', 'filled', 'accent'] -%}
+
+
+
{{ appearance | capitalize }}
+ Card content.
+
+{%- endfor %}
+
+```
diff --git a/docs/docs/components/details.md b/docs/docs/components/details.md
index 07cd53b33..9f6d94107 100644
--- a/docs/docs/components/details.md
+++ b/docs/docs/components/details.md
@@ -77,6 +77,31 @@ The details component automatically adapts to right-to-left languages:
```
+### Appearance
+
+Use the `appearance` attribute to change the element’s visual appearance.
+
+```html {.example}
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+
+
+```
+
### Grouping Details
Details are designed to function independently, but you can simulate a group or "accordion" where only one is shown at a time by listening for the `wa-show` event.
diff --git a/docs/docs/components/index.njk b/docs/docs/components/index.njk
index f5d19614d..64ddf6e40 100644
--- a/docs/docs/components/index.njk
+++ b/docs/docs/components/index.njk
@@ -2,13 +2,10 @@
title: Components
description: Components are the essential building blocks to create intuitive, cohesive experiences. Browse the library of customizable, framework-friendly web components included in Web Awesome.
layout: overview
-categories:
- - actions
- - feedback: 'Feedback & Status'
- - imagery
- - inputs
- - navigation
- - organization
- - helpers: 'Utilities'
override:tags: []
+categories:
+ tags: [actions, feedback, imagery, inputs, navigation, organization, helpers]
+ titles:
+ feedback: 'Feedback & Status'
+ helpers: 'Utilities'
---
diff --git a/docs/docs/docs.11tydata.js b/docs/docs/docs.11tydata.js
index 7ed1011e1..2232f7e53 100644
--- a/docs/docs/docs.11tydata.js
+++ b/docs/docs/docs.11tydata.js
@@ -1,10 +1,80 @@
+/**
+ * Global data for all pages
+ */
+import { sort } from '../_utils/filters.js';
+
export default {
eleventyComputed: {
- children(data) {
- let mainTag = data.tags?.[0];
- let collection = data.collections[mainTag] ?? [];
+ // Default parent. Can be overridden by explicitly setting parent in the data.
+ // parent can refer to either an ancestor page in the URL or another page in the same directory
+ parent(data) {
+ let { parent, page } = data;
- return collection.filter(item => item.data.parent === data.page.fileSlug);
+ if (parent) {
+ return parent;
+ }
+
+ return page.url.split('/').filter(Boolean).at(-2);
+ },
+
+ parentUrl(data) {
+ let { parent, page } = data;
+ return getParentUrl(page.url, parent);
+ },
+
+ parentItem(data) {
+ let { parentUrl } = data;
+ return data.collections.all.find(item => item.url === parentUrl);
+ },
+
+ children(data) {
+ let { collections, page, parentOf } = data;
+
+ if (parentOf) {
+ return collections[parentOf];
+ }
+
+ let collection = collections.all ?? [];
+ let url = page.url;
+
+ let ret = collection.filter(item => {
+ return item.data.parentUrl === url;
+ });
+
+ sort(ret);
+
+ return ret;
},
},
};
+
+function getParentUrl(url, parent) {
+ let parts = url.split('/').filter(Boolean);
+ let ancestorIndex = parts.findLastIndex(part => part === parent);
+ let retParts = parts.slice();
+
+ if (ancestorIndex > -1) {
+ // parent is an ancestor
+ retParts.splice(ancestorIndex + 1);
+ } else {
+ // parent is a sibling in the same directory
+ retParts.splice(-1, 1, parent);
+ }
+
+ let ret = retParts.join('/');
+
+ if (url.startsWith('/')) {
+ ret = '/' + ret;
+ }
+
+ if (!retParts.at(-1).includes('.') && !ret.endsWith('/')) {
+ // If no extension, make sure to end with a slash
+ ret += '/';
+ }
+
+ if (ret === '/docs/') {
+ ret = '/';
+ }
+
+ return ret;
+}
diff --git a/docs/docs/experimental/clamped-colors.njk b/docs/docs/experimental/clamped-colors.njk
index fac431d52..27797832d 100644
--- a/docs/docs/experimental/clamped-colors.njk
+++ b/docs/docs/experimental/clamped-colors.njk
@@ -1,13 +1,10 @@
---
-title: Clamped brand tokens
+title: Clamped Color Tokens
layout: block
---
-{% set tints = ['40-max', '50-max', '60-max', '40-min', '50-min', '60-min'] %}
-
-{% for hue in hues %}
-
-{% endfor %}
+{% set tints = ['max-50', 'max-60', 'max-70', 'min-50', 'min-60', 'min-70'] %}
+{% set hues = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'indigo', 'purple', 'pink', 'gray'] %}
@@ -20,18 +17,18 @@ layout: block
{% for hue in hues -%}
-
+
{{ hue | capitalize }}
-
+
{{ palettes[paletteId][hue].maxChromaTint }}
-
+
{% for tint in tints -%}
-
-
+
+
{%- endfor -%}
@@ -41,7 +38,7 @@ layout: block
+
\ No newline at end of file
diff --git a/docs/docs/installation.md b/docs/docs/installation.md
index 473e4ab1f..b142497bc 100644
--- a/docs/docs/installation.md
+++ b/docs/docs/installation.md
@@ -37,10 +37,6 @@ This snippet includes three parts:
Now you can [start using Web Awesome!](/docs/usage)
-:::info
-While convenient, autoloading may lead to a [Flash of Undefined Custom Elements](https://www.abeautifulsite.net/posts/flash-of-undefined-custom-elements/). The linked article describes some ways to alleviate it.
-:::
-
---
## Using Font Awesome Kit Codes
diff --git a/docs/docs/layout.njk b/docs/docs/layout.njk
index 67d8f8778..57af8bc94 100644
--- a/docs/docs/layout.njk
+++ b/docs/docs/layout.njk
@@ -2,6 +2,7 @@
title: Layout
description: Layout components and utility classes help you organize content that can adapt to any device or screen size. See the [installation instructions](#installation) to use Web Awesome's layout tools in your project.
layout: overview
+parentOf: layout
categories: ["components", "utilities"]
override:tags: []
---
@@ -22,4 +23,4 @@ Or, you can choose to import _only_ the utilities:
```html
```
-{% endmarkdown %}
\ No newline at end of file
+{% endmarkdown %}
diff --git a/docs/docs/native/button.md b/docs/docs/native/button.md
index b9740a711..3c050199f 100644
--- a/docs/docs/native/button.md
+++ b/docs/docs/native/button.md
@@ -33,7 +33,7 @@ Use the [variant utility classes](../utilities/color.md) to set the button's sem
### Appearance
-Use the [appearance utility classes](../utilities/appearance.md) to change the button's visual appearance:
+Use the [appearance utility classes](/docs/utilities/appearance) to change the button's visual appearance:
```html {.example}
diff --git a/docs/docs/native/callout.md b/docs/docs/native/callout.md
index e3ef62b88..ae8a5cdbf 100644
--- a/docs/docs/native/callout.md
+++ b/docs/docs/native/callout.md
@@ -57,7 +57,7 @@ Use the [variant utility classes](../utilities/color.md) to set the callout's co
### Appearance
-Use the [appearance utility classes](../utilities/appearance.md) to change the callout's visual appearance (the default is `outlined filled`).
+Use the [appearance utility classes](/docs/utilities/appearance) to change the callout's visual appearance (the default is `outlined filled`).
```html {.example}
diff --git a/docs/docs/native/details.md b/docs/docs/native/details.md
index 767904bc2..d633e8430 100644
--- a/docs/docs/native/details.md
+++ b/docs/docs/native/details.md
@@ -19,6 +19,35 @@ file: styles/native/details.css
## Examples
+### Appearance
+
+Use the [appearance utility classes](/docs/utilities/appearance) to change the element's visual appearance:
+
+```html {.example}
+
+
+ Outlined (default)
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+
+
+ Filled
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+
+
+ Filled + Outlined
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+
+
+ Plain
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+
+
+```
+
### Right-to-Left Languages
The details styling automatically adapts to right-to-left languages:
diff --git a/docs/docs/native/input.md b/docs/docs/native/input.md
index c7c11f0dc..ef7c483e5 100644
--- a/docs/docs/native/input.md
+++ b/docs/docs/native/input.md
@@ -42,6 +42,14 @@ wa-code-demo::part(preview) {
```
+## Pill shaped text fields
+
+Add the `wa-pill` class to an `` to make it pill-shaped.
+
+```html {.example}
+
+```
+
## Color Picker
Basic:
diff --git a/docs/docs/palettes/index.njk b/docs/docs/palettes/index.njk
index 9f3eb51f4..36a41a6c3 100644
--- a/docs/docs/palettes/index.njk
+++ b/docs/docs/palettes/index.njk
@@ -5,6 +5,6 @@ layout: overview
override:tags: []
forTag: palette
categories:
+ tags: [other, pro]
other: Free
- pro: Pro
---
diff --git a/docs/docs/patterns/index.njk b/docs/docs/patterns/index.njk
index fee915547..e51a1f6ce 100644
--- a/docs/docs/patterns/index.njk
+++ b/docs/docs/patterns/index.njk
@@ -2,7 +2,5 @@
title: Patterns
description: Patterns are reusable solutions to common design problems.
layout: overview
-categories: ["e-commerce"]
-listChildren: true
override:tags: []
---
diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md
index 4a19dad86..cbe062787 100644
--- a/docs/docs/resources/changelog.md
+++ b/docs/docs/resources/changelog.md
@@ -18,6 +18,22 @@ During the alpha period, things might break! We take breaking changes very serio
- Removed close watcher logic to backdrop hide animation bugs in `` and ``; this logic is already handled and we'll revisit `CloseWatcher` when browser support is better and behaviors are consistent
- Revert `` structure and CSS to fix clipped content in dialogs (WA-A #123) and light dismiss in iOS Safari (WA-A #201)
+### Enhancements
+
+- Added `appearance` to [``](/docs/components/details) and [``](/docs/components/card) and support for the [appearance utilities](/docs/utilities/appearance/) in the [`` native styles](/docs/native/details).
+- Added an `orange` scale to all color palettes
+- Added the `.wa-cloak` utility to prevent FOUCE
+- Added the `allDefined()` utility for awaiting component registration
+
+### Bugfixes
+
+- Specifying inherited CSS properties on `` now works as expected ([thanks Dennis!](https://github.com/shoelace-style/webawesome-alpha/discussions/203))
+- Fixed a bug in `` that made it hard to use with VueJS, Svelte, and many other frameworks
+- Fixed the `wa-pill` class for text fields
+- Fixed `pill` style for `` elements
+- Fixed a bug in `` that prevented light dismiss from working when clicking immediately above the color picker dropdown
+- Fixed a bug in `` that sometimes resulted in empty `