diff --git a/.gitignore b/.gitignore
index e7f19329c..b0a6ab872 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,8 @@ package.json
package-lock.json
dist
docs/assets/images/sprite.svg
+docs/public/pagefind
node_modules
src/react
cdn
+.astro
diff --git a/docs/.vscode/extensions.json b/docs/.vscode/extensions.json
new file mode 100644
index 000000000..22a15055d
--- /dev/null
+++ b/docs/.vscode/extensions.json
@@ -0,0 +1,4 @@
+{
+ "recommendations": ["astro-build.astro-vscode"],
+ "unwantedRecommendations": []
+}
diff --git a/docs/.vscode/launch.json b/docs/.vscode/launch.json
new file mode 100644
index 000000000..d64220976
--- /dev/null
+++ b/docs/.vscode/launch.json
@@ -0,0 +1,11 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "command": "./node_modules/.bin/astro dev",
+ "name": "Development server",
+ "request": "launch",
+ "type": "node-terminal"
+ }
+ ]
+}
diff --git a/docs/_includes/component.njk b/docs/_includes/component.njk
deleted file mode 100644
index 709082471..000000000
--- a/docs/_includes/component.njk
+++ /dev/null
@@ -1,349 +0,0 @@
-{% extends "default.njk" %}
-
-{# Find the component based on the `tag` front matter #}
-{% set component = getComponent('wa-' + page.fileSlug) %}
-
-{% block content %}
- {# Determine the badge variant #}
- {% if component.status == 'stable' %}
- {% set badgeVariant = 'brand' %}
- {% elseif component.status == 'experimental' %}
- {% set badgeVariant = 'warning' %}
- {% elseif component.status == 'planned' %}
- {% set badgeVariant = 'neutral' %}
- {% elseif component.status == 'deprecated' %}
- {% set badgeVariant = 'danger' %}
- {% else %}
- {% set badgeVariant = 'neutral' %}
- {% endif %}
-
- {# Header #}
-
-
-
- {% if component.summary %}
- {{ component.summary | markdownInline | safe }}
- {% endif %}
-
-
- {# Markdown content #}
- {{ content | safe }}
-
- {# Importing #}
- Importing
-
- If you're using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use
- any of the following snippets to cherry pick this component.
-
-
-
- Script
- Import
- Bundler
- React
-
-
-
- To import this component from the CDN
- using a script tag:
-
- <script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/{{ meta.cdndir }}/{{ component.path }}"></script>
-
-
-
-
- To import this component from the CDN
- using a JavaScript import:
-
- import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/{{ meta.cdndir }}/{{ component.path }}';
-
-
-
-
- To import this component using a bundler :
-
- import '@shoelace-style/shoelace/{{ meta.npmdir }}/{{ component.path }}';
-
-
-
-
- To import this component as a React component :
-
- import {{ component.name }} from '@shoelace-style/shoelace/{{ meta.npmdir }}/react/{{ component.tagNameWithoutPrefix }}';
-
-
-
- {# Slots #}
- {% if component.slots.length %}
- Slots
-
-
-
-
- Name
- Description
-
-
-
- {% for slot in component.slots %}
-
-
- {% if slot.name %}
- {{ slot.name }}
- {% else %}
- (default)
- {% endif %}
-
- {{ slot.description | markdownInline | safe }}
-
- {% endfor %}
-
-
-
- Learn more about using slots .
- {% endif %}
-
- {# Properties #}
- {% if component.properties.length %}
- Properties
-
-
-
-
- Name
- Description
- Reflects
- Type
- Default
-
-
-
- {% for prop in component.properties %}
-
-
- {{ prop.name }}
- {% if prop.attribute | length > 0 %}
- {% if prop.attribute != prop.name %}
-
-
-
-
- {{ prop.attribute }}
-
-
-
- {% endif %}
- {% endif %}
-
-
- {{ prop.description | markdownInline | safe }}
-
-
- {% if prop.reflects %}
-
- {% endif %}
-
-
- {% if prop.type.text %}
- {{ prop.type.text | trimPipes | markdownInline | safe }}
- {% else %}
- -
- {% endif %}
-
-
- {% if prop.default %}
- {{ prop.default | markdownInline | safe }}
- {% else %}
- -
- {% endif %}
-
-
- {% endfor %}
-
- updateComplete
-
- A read-only promise that resolves when the component has
- finished updating .
-
-
-
-
-
-
-
-
- Learn more about attributes and properties .
- {% endif %}
-
- {# Events #}
- {% if component.events.length %}
- Events
-
-
-
-
- Name
- React Event
- Description
- Event Detail
-
-
-
- {% for event in component.events %}
-
- {{ event.name }}
- {{ event.reactName }}
- {{ event.description | markdownInline | safe }}
-
- {% if event.type.text %}
- {{ event.type.text | trimPipes }}
- {% else %}
- -
- {% endif %}
-
-
- {% endfor %}
-
-
-
- Learn more about events .
- {% endif %}
-
- {# Methods #}
- {% if component.methods.length %}
- Methods
-
-
-
-
- Name
- Description
- Arguments
-
-
-
- {% for method in component.methods %}
-
- {{ method.name }}()
- {{ method.description | markdownInline | safe }}
-
- {% if method.parameters.length %}
-
- {% for param in method.parameters %}
- {{ param.name }}: {{ param.type.text | trimPipes }}{% if not loop.last %},{% endif %}
- {% endfor %}
-
- {% else %}
- -
- {% endif %}
-
-
- {% endfor %}
-
-
-
- Learn more about methods .
- {% endif %}
-
- {# Custom Properties #}
- {% if component.cssProperties.length %}
- Custom Properties
-
-
-
-
- Name
- Description
- Default
-
-
-
- {% for cssProperty in component.cssProperties %}
-
- {{ cssProperty.name }}
- {{ cssProperty.description | markdownInline | safe }}
- {{ cssProperty.default }}
-
- {% endfor %}
-
-
-
- Learn more about customizing CSS custom properties .
- {% endif %}
-
- {# CSS Parts #}
- {% if component.cssParts.length %}
- Parts
-
-
-
-
- Name
- Description
-
-
-
- {% for cssPart in component.cssParts %}
-
- {{ cssPart.name }}
- {{ cssPart.description | markdownInline | safe }}
-
- {% endfor %}
-
-
-
- Learn more about customizing CSS parts .
- {% endif %}
-
- {# Animations #}
- {% if component.animations.length %}
- Animations
-
-
-
-
- Name
- Description
-
-
-
- {% for animation in component.animations %}
-
- {{ animation.name }}
- {{ animation.description | markdownInline | safe }}
-
- {% endfor %}
-
-
-
- Learn more about customizing animations .
- {% endif %}
-
- {# Dependencies #}
- {% if component.dependencies.length %}
- Dependencies
-
- This component automatically imports the following dependencies.
-
-
- {% for dependency in component.dependencies %}
- <{{ dependency }}>
- {% endfor %}
-
- {% endif %}
-{% endblock %}
diff --git a/docs/_includes/default.njk b/docs/_includes/default.njk
deleted file mode 100644
index b9db3c213..000000000
--- a/docs/_includes/default.njk
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
- {# Metadata #}
-
-
-
- {{ meta.title }}
-
- {# Opt out of Turbo caching #}
-
-
- {# Stylesheets #}
-
-
-
-
- {# Favicons #}
-
-
- {# Twitter Cards #}
-
-
-
-
- {# OpenGraph #}
-
-
-
-
-
- {# Web Awesome #}
-
-
-
-
-
- {# Set the initial theme and menu states here to prevent flashing #}
-
-
- {# Web Fonts #}
-
-
-
-
- {# Turbo + Scroll positioning #}
-
-
-
-
-
-
-
-
- Skip to main content
-
-
- {# Menu toggle #}
-
-
-
-
- {# Content #}
-
-
-
- {% if toc %}
-
- {% endif %}
-
-
- {% block content %}
- {{ content | safe }}
- {% endblock %}
-
-
-
-
-
diff --git a/docs/_includes/sidebar.njk b/docs/_includes/sidebar.njk
deleted file mode 100644
index 121c033e8..000000000
--- a/docs/_includes/sidebar.njk
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
- Experimental
-
-
-
- Getting Started
-
-
-
- Frameworks
-
-
-
- Resources
-
-
-
- Components
-
-
-
- Design Tokens
-
-
-
- Tutorials
-
-
-
diff --git a/docs/_utilities/active-links.cjs b/docs/_utilities/active-links.cjs
deleted file mode 100644
index 7a998054e..000000000
--- a/docs/_utilities/active-links.cjs
+++ /dev/null
@@ -1,35 +0,0 @@
-function normalizePathname(pathname) {
- // Remove /index.html
- if (pathname.endsWith('/index.html')) {
- pathname = pathname.replace(/\/index\.html/, '');
- }
-
- // Remove trailing slashes
- return pathname.replace(/\/$/, '');
-}
-
-/**
- * Adds a class name to links that are currently active.
- */
-module.exports = function (doc, options) {
- options = {
- className: 'active-link', // the class to add to active links
- pathname: undefined, // the current pathname to compare
- within: 'body', // element containing the target links
- ...options
- };
-
- const within = doc.querySelector(options.within);
-
- if (!within) {
- return doc;
- }
-
- within.querySelectorAll('a').forEach(link => {
- if (normalizePathname(options.pathname) === normalizePathname(link.pathname)) {
- link.classList.add(options.className);
- }
- });
-
- return doc;
-};
diff --git a/docs/_utilities/anchor-headings.cjs b/docs/_utilities/anchor-headings.cjs
deleted file mode 100644
index 64a71668a..000000000
--- a/docs/_utilities/anchor-headings.cjs
+++ /dev/null
@@ -1,64 +0,0 @@
-const { createSlug } = require('./strings.cjs');
-
-/**
- * Turns headings into clickable, deep linkable anchors. The provided doc should be a document object provided by JSDOM.
- * The same document will be returned with the appropriate DOM manipulations.
- */
-module.exports = function (doc, options) {
- options = {
- levels: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'], // the headings to convert
- className: 'anchor-heading', // the class name to add
- within: 'body', // the element containing the target headings
- ...options
- };
-
- const within = doc.querySelector(options.within);
-
- if (!within) {
- return doc;
- }
-
- within.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach(heading => {
- const hasAnchor = heading.querySelector('a');
- const anchor = doc.createElement('a');
- let id = heading.textContent ?? '';
- let suffix = 0;
-
- // Skip heading levels we don't care about
- if (!options.levels?.includes(heading.tagName.toLowerCase())) {
- return;
- }
-
- // Convert dots to underscores
- id = id.replace(/\./g, '_');
-
- // Turn it into a slug
- id = createSlug(id);
-
- // Make sure it starts with a letter
- if (!/^[a-z]/i.test(id)) {
- id = `id_${id}`;
- }
-
- // Make sure the id is unique
- const originalId = id;
- while (doc.getElementById(id) !== null) {
- id = `${originalId}-${++suffix}`;
- }
-
- if (hasAnchor || !id) return;
-
- heading.setAttribute('id', id);
- anchor.setAttribute('href', `#${encodeURIComponent(id)}`);
- anchor.setAttribute('aria-label', `Direct link to "${heading.textContent}"`);
-
- if (options.className) {
- heading.classList.add(options.className);
- }
-
- // Append the anchor
- heading.append(anchor);
- });
-
- return doc;
-};
diff --git a/docs/_utilities/code-previews.cjs b/docs/_utilities/code-previews.cjs
deleted file mode 100644
index 59daefcce..000000000
--- a/docs/_utilities/code-previews.cjs
+++ /dev/null
@@ -1,138 +0,0 @@
-let count = 1;
-
-function escapeHtml(str) {
- return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
-}
-
-/**
- * Turns code fields with the :preview suffix into interactive code previews.
- */
-module.exports = function (doc, options) {
- options = {
- within: 'body', // the element containing the code fields to convert
- ...options
- };
-
- const within = doc.querySelector(options.within);
- if (!within) {
- return doc;
- }
-
- within.querySelectorAll('[class*=":preview"]').forEach(code => {
- const pre = code.closest('pre');
- if (!pre) {
- return;
- }
- const adjacentPre = pre.nextElementSibling?.tagName.toLowerCase() === 'pre' ? pre.nextElementSibling : null;
- const reactCode = adjacentPre?.querySelector('code[class$="react"]');
- const sourceGroupId = `code-preview-source-group-${count}`;
- const isExpanded = code.getAttribute('class').includes(':expanded');
- const noCodePen = code.getAttribute('class').includes(':no-codepen');
-
- count++;
-
- const htmlButton = `
-
- HTML
-
- `;
-
- const reactButton = `
-
- React
-
- `;
-
- const codePenButton = `
-
-
-
-
-
- `;
-
- const codePreview = `
-
-
- ${code.textContent}
-
-
-
-
-
-
-
-
${escapeHtml(code.textContent)}
-
-
- ${
- reactCode
- ? `
-
-
${escapeHtml(reactCode.textContent)}
-
- `
- : ''
- }
-
-
-
-
- `;
-
- pre.insertAdjacentHTML('afterend', codePreview);
- pre.remove();
-
- if (adjacentPre) {
- adjacentPre.remove();
- }
- });
-
- // Wrap code preview scripts in anonymous functions so they don't run in the global scope
- doc.querySelectorAll('.code-preview__preview script').forEach(script => {
- if (script.type === 'module') {
- // Modules are already scoped
- script.textContent = script.innerHTML;
- } else {
- // Wrap non-modules in an anonymous function so they don't run in the global scope
- script.textContent = `(() => { ${script.innerHTML} })();`;
- }
- });
-
- return doc;
-};
diff --git a/docs/_utilities/copy-code-buttons.cjs b/docs/_utilities/copy-code-buttons.cjs
deleted file mode 100644
index be2784604..000000000
--- a/docs/_utilities/copy-code-buttons.cjs
+++ /dev/null
@@ -1,23 +0,0 @@
-let codeBlockId = 0;
-
-/**
- * Adds copy code buttons to code fields. The provided doc should be a document object provided by JSDOM. The same
- * document will be returned with the appropriate DOM manipulations.
- */
-module.exports = function (doc) {
- doc.querySelectorAll('pre > code').forEach(code => {
- const pre = code.closest('pre');
- const button = doc.createElement('wa-copy-button');
-
- if (!code.id) {
- code.id = `code-block-${++codeBlockId}`;
- }
-
- button.classList.add('copy-code-button');
- button.setAttribute('from', code.id);
-
- pre.append(button);
- });
-
- return doc;
-};
diff --git a/docs/_utilities/external-links.cjs b/docs/_utilities/external-links.cjs
deleted file mode 100644
index 36a95898a..000000000
--- a/docs/_utilities/external-links.cjs
+++ /dev/null
@@ -1,41 +0,0 @@
-const { isExternalLink } = require('./strings.cjs');
-
-/**
- * Transforms external links to make them safer and optionally add a target. The provided doc should be a document
- * object provided by JSDOM. The same document will be returned with the appropriate DOM manipulations.
- */
-module.exports = function (doc, options) {
- options = {
- className: 'external-link', // the class name to add to links
- noopener: true, // sets rel="noopener"
- noreferrer: true, // sets rel="noreferrer"
- ignore: () => false, // callback function to filter links that should be ignored
- within: 'body', // element that contains the target links
- target: '', // sets the target attribute
- ...options
- };
-
- const within = doc.querySelector(options.within);
-
- if (within) {
- within.querySelectorAll('a').forEach(link => {
- if (isExternalLink(link) && !options.ignore(link)) {
- link.classList.add(options.className);
-
- const rel = [];
- if (options.noopener) rel.push('noopener');
- if (options.noreferrer) rel.push('noreferrer');
-
- if (rel.length) {
- link.setAttribute('rel', rel.join(' '));
- }
-
- if (options.target) {
- link.setAttribute('target', options.target);
- }
- }
- });
- }
-
- return doc;
-};
diff --git a/docs/_utilities/highlight-code.cjs b/docs/_utilities/highlight-code.cjs
deleted file mode 100644
index bb4c01f09..000000000
--- a/docs/_utilities/highlight-code.cjs
+++ /dev/null
@@ -1,63 +0,0 @@
-const Prism = require('prismjs');
-const PrismLoader = require('prismjs/components/index.js');
-
-PrismLoader('diff');
-PrismLoader.silent = true;
-
-/** Highlights a code string. */
-function highlight(code, language) {
- const alias = language.replace(/^diff-/, '');
- const isDiff = /^diff-/i.test(language);
-
- // Auto-load the target language
- if (!Prism.languages[alias]) {
- PrismLoader(alias);
-
- if (!Prism.languages[alias]) {
- throw new Error(`Unsupported language for code highlighting: "${language}"`);
- }
- }
-
- // Register diff-* languages to use the diff grammar
- if (isDiff) {
- Prism.languages[language] = Prism.languages.diff;
- }
-
- return Prism.highlight(code, Prism.languages[language], language);
-}
-
-/**
- * Highlights all code fields that have a language parameter. If the language has a colon in its name, the first chunk
- * will be the language used and additional chunks will be applied as classes to the ``. For example, a code field
- * tagged with "html:preview" will be rendered as ``.
- *
- * The provided doc should be a document object provided by JSDOM. The same document will be returned with the
- * appropriate DOM manipulations.
- */
-module.exports = function (doc) {
- doc.querySelectorAll('pre > code[class]').forEach(code => {
- // Look for class="language-*" and split colons into separate classes
- code.classList.forEach(className => {
- if (className.startsWith('language-')) {
- //
- // We use certain suffixes to indicate code previews, expanded states, etc. The class might look something like
- // this:
- //
- // class="language-html:preview:expanded"
- //
- // The language will always come first, so we need to drop the "language-" prefix and everything after the first
- // color to get the highlighter language.
- //
- const language = className.replace(/^language-/, '').split(':')[0];
-
- try {
- code.innerHTML = highlight(code.textContent ?? '', language);
- } catch (err) {
- // Language not found, skip it
- }
- }
- });
- });
-
- return doc;
-};
diff --git a/docs/_utilities/markdown.cjs b/docs/_utilities/markdown.cjs
deleted file mode 100644
index 7cd6386be..000000000
--- a/docs/_utilities/markdown.cjs
+++ /dev/null
@@ -1,75 +0,0 @@
-const MarkdownIt = require('markdown-it');
-const markdownItContainer = require('markdown-it-container');
-const markdownItIns = require('markdown-it-ins');
-const markdownItKbd = require('markdown-it-kbd');
-const markdownItMark = require('markdown-it-mark');
-const markdownItReplaceIt = require('markdown-it-replace-it');
-
-const markdown = MarkdownIt({
- html: true,
- xhtmlOut: false,
- breaks: false,
- langPrefix: 'language-',
- linkify: false,
- typographer: false
-});
-
-// Third-party plugins
-markdown.use(markdownItContainer);
-markdown.use(markdownItIns);
-markdown.use(markdownItKbd);
-markdown.use(markdownItMark);
-markdown.use(markdownItReplaceIt);
-
-// Callouts
-['tip', 'warning', 'danger'].forEach(type => {
- const variant = type === 'tip' ? 'brand' : type;
- let icon = 'circle-info';
- if (type === 'warning') icon = 'triangle-exclamation';
- if (type === 'danger') icon = 'circle-exclamation';
-
- markdown.use(markdownItContainer, type, {
- render: function (tokens, idx) {
- if (tokens[idx].nesting === 1) {
- return `
-
-
- `;
- }
- return ' \n';
- }
- });
-});
-
-// Asides
-markdown.use(markdownItContainer, 'aside', {
- render: function (tokens, idx) {
- if (tokens[idx].nesting === 1) {
- return `\n';
- }
-});
-
-// Details
-markdown.use(markdownItContainer, 'details', {
- validate: params => params.trim().match(/^details\s+(.*)$/),
- render: (tokens, idx) => {
- const m = tokens[idx].info.trim().match(/^details\s+(.*)$/);
- if (tokens[idx].nesting === 1) {
- return `\n${markdown.utils.escapeHtml(m[1])} \n`;
- }
- return ' \n';
- }
-});
-
-// Replace [#1234] with a link to GitHub issues
-markdownItReplaceIt.replacements.push({
- name: 'github-issues',
- re: /\[#([0-9]+)\]/gs,
- sub: '#$1 ',
- html: true,
- default: true
-});
-
-module.exports = markdown;
diff --git a/docs/_utilities/prettier.cjs b/docs/_utilities/prettier.cjs
deleted file mode 100644
index db18fba40..000000000
--- a/docs/_utilities/prettier.cjs
+++ /dev/null
@@ -1,26 +0,0 @@
-const { format } = require('prettier');
-
-/** Formats markup using prettier. */
-module.exports = function (content, options) {
- options = {
- arrowParens: 'avoid',
- bracketSpacing: true,
- htmlWhitespaceSensitivity: 'css',
- insertPragma: false,
- bracketSameLine: false,
- jsxSingleQuote: false,
- parser: 'html',
- printWidth: 120,
- proseWrap: 'preserve',
- quoteProps: 'as-needed',
- requirePragma: false,
- semi: true,
- singleQuote: true,
- tabWidth: 2,
- trailingComma: 'none',
- useTabs: false,
- ...options
- };
-
- return format(content, options);
-};
diff --git a/docs/_utilities/replacer.cjs b/docs/_utilities/replacer.cjs
deleted file mode 100644
index d2036ce7e..000000000
--- a/docs/_utilities/replacer.cjs
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * @typedef {object} Replacement
- * @property {string | RegExp} pattern
- * @property {string} replacement
- */
-
-/**
- * @typedef {Array} Replacements
- */
-
-/**
- * @param {Document} content
- * @param {Replacements} replacements
- */
-module.exports = function (content, replacements) {
- /** This seems trivial, but by assigning to a string first, THEN using innerHTML after iterating over every replacement, we reduce the calculations of JSDOM. At the time of writing benchmarks show a reduction from 9seconds to 3 seconds by doing so. */
- let html = content.body.innerHTML;
-
- replacements.forEach(replacement => {
- html = html.replaceAll(replacement.pattern, replacement.replacement);
- });
-
- content.body.innerHTML = html;
-};
diff --git a/docs/_utilities/scrolling-tables.cjs b/docs/_utilities/scrolling-tables.cjs
deleted file mode 100644
index 148248dbe..000000000
--- a/docs/_utilities/scrolling-tables.cjs
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Turns headings into clickable, deep linkable anchors. The provided doc should be a document object provided by JSDOM.
- * The same document will be returned with the appropriate DOM manipulations.
- */
-module.exports = function (doc, options) {
- const tables = [...doc.querySelectorAll('table')];
-
- options = {
- className: 'table-scroll', // the class name to add to the table's container
- ...options
- };
-
- tables.forEach(table => {
- const div = doc.createElement('div');
- div.classList.add(options.className);
- table.insertAdjacentElement('beforebegin', div);
- div.append(table);
- });
-
- return doc;
-};
diff --git a/docs/_utilities/strings.cjs b/docs/_utilities/strings.cjs
deleted file mode 100644
index 6831d66d9..000000000
--- a/docs/_utilities/strings.cjs
+++ /dev/null
@@ -1,16 +0,0 @@
-const slugify = require('slugify');
-
-/** Creates a slug from an arbitrary string of text. */
-module.exports.createSlug = function (text) {
- return slugify(String(text), {
- remove: /[^\w|\s]/g,
- lower: true
- });
-};
-
-/** Determines whether or not a link is external. */
-module.exports.isExternalLink = function (link) {
- // We use the "internal" hostname when initializing JSDOM so we know that those are local links
- if (!link.hostname || link.hostname === 'internal') return false;
- return true;
-};
diff --git a/docs/_utilities/table-of-contents.cjs b/docs/_utilities/table-of-contents.cjs
deleted file mode 100644
index 1ac04fd31..000000000
--- a/docs/_utilities/table-of-contents.cjs
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Generates an in-page table of contents based on headings.
- */
-module.exports = function (doc, options) {
- options = {
- levels: ['h2'], // headings to include (they must have an id)
- container: 'nav', // the container to append links to
- listItem: true, // if true, links will be wrapped in
- within: 'body', // the element containing the headings to summarize
- ...options
- };
-
- const container = doc.querySelector(options.container);
- const within = doc.querySelector(options.within);
- const headingSelector = options.levels.map(h => `${h}[id]`).join(', ');
-
- if (!container || !within) {
- return doc;
- }
-
- within.querySelectorAll(headingSelector).forEach(heading => {
- const listItem = doc.createElement('li');
- const link = doc.createElement('a');
- const level = heading.tagName.slice(1);
-
- link.href = `#${heading.id}`;
- link.textContent = heading.textContent;
-
- if (options.listItem) {
- // List item + link
- listItem.setAttribute('data-level', level);
- listItem.append(link);
- container.append(listItem);
- } else {
- // Link only
- link.setAttribute('data-level', level);
- container.append(link);
- }
- });
-
- return doc;
-};
diff --git a/docs/_utilities/typography.cjs b/docs/_utilities/typography.cjs
deleted file mode 100644
index 53fe84b61..000000000
--- a/docs/_utilities/typography.cjs
+++ /dev/null
@@ -1,23 +0,0 @@
-const smartquotes = require('smartquotes');
-
-smartquotes.replacements.push([/---/g, '\u2014']); // em dash
-smartquotes.replacements.push([/--/g, '\u2013']); // en dash
-smartquotes.replacements.push([/\.\.\./g, '\u2026']); // ellipsis
-smartquotes.replacements.push([/\(c\)/gi, '\u00A9']); // copyright
-smartquotes.replacements.push([/\(r\)/gi, '\u00AE']); // registered trademark
-smartquotes.replacements.push([/\?!/g, '\u2048']); // ?!
-smartquotes.replacements.push([/!!/g, '\u203C']); // !!
-smartquotes.replacements.push([/\?\?/g, '\u2047']); // ??
-smartquotes.replacements.push([/([0-9]\s?)-(\s?[0-9])/g, '$1\u2013$2']); // number ranges use en dash
-
-/**
- * Improves typography by adding smart quotes and similar corrections within the specified element(s).
- *
- * The provided doc should be a document object provided by JSDOM. The same document will be returned with the
- * appropriate DOM manipulations.
- */
-module.exports = function (doc, selector = 'body') {
- const elements = [...doc.querySelectorAll(selector)];
- elements.forEach(el => smartquotes.element(el));
- return doc;
-};
diff --git a/docs/assets/scripts/docs.js b/docs/assets/scripts/docs.js
deleted file mode 100644
index 9c3ae3099..000000000
--- a/docs/assets/scripts/docs.js
+++ /dev/null
@@ -1,206 +0,0 @@
-//
-// Sidebar
-//
-// When the sidebar is hidden, we apply the inert attribute to prevent focus from reaching it. Due to the many states
-// the sidebar can have (e.g. static, hidden, expanded), we test for visibility by checking to see if it's placed
-// offscreen or not. Then, on resize/transition we make sure to update the attribute accordingly.
-//
-(() => {
- function getSidebar() {
- return document.getElementById('sidebar');
- }
-
- function isSidebarOpen() {
- return document.documentElement.classList.contains('sidebar-open');
- }
-
- function isSidebarVisible() {
- return getSidebar().getBoundingClientRect().x >= 0;
- }
-
- function toggleSidebar(force) {
- const isOpen = typeof force === 'boolean' ? force : !isSidebarOpen();
- return document.documentElement.classList.toggle('sidebar-open', isOpen);
- }
-
- function updateInert() {
- getSidebar().inert = !isSidebarVisible();
- }
-
- // Toggle the menu
- document.addEventListener('click', event => {
- const menuToggle = event.target.closest('#menu-toggle');
- if (!menuToggle) return;
- toggleSidebar();
- });
-
- // Update the sidebar's inert state when the window resizes and when the sidebar transitions
- window.addEventListener('resize', () => toggleSidebar(false));
-
- document.addEventListener('transitionend', event => {
- const sidebar = event.target.closest('#sidebar');
- if (!sidebar) return;
- updateInert();
- });
-
- // Close when a menu item is selected on mobile
- document.addEventListener('click', event => {
- const sidebar = event.target.closest('#sidebar');
- const link = event.target.closest('a');
- if (!sidebar || !link) return;
-
- if (isSidebarOpen()) {
- toggleSidebar();
- }
- });
-
- // Close when open and escape is pressed
- document.addEventListener('keydown', event => {
- if (event.key === 'Escape' && isSidebarOpen()) {
- event.stopImmediatePropagation();
- toggleSidebar();
- }
- });
-
- // Close when clicking outside of the sidebar
- document.addEventListener('mousedown', event => {
- if (isSidebarOpen() & !event.target?.closest('#sidebar, #menu-toggle')) {
- event.stopImmediatePropagation();
- toggleSidebar();
- }
- });
-
- updateInert();
-})();
-
-//
-// Open details when printing
-//
-(() => {
- const detailsOpenOnPrint = new Set();
-
- window.addEventListener('beforeprint', () => {
- detailsOpenOnPrint.clear();
- document.querySelectorAll('details').forEach(details => {
- if (details.open) {
- detailsOpenOnPrint.add(details);
- }
- details.open = true;
- });
- });
-
- window.addEventListener('afterprint', () => {
- document.querySelectorAll('details').forEach(details => {
- details.open = detailsOpenOnPrint.has(details);
- });
- detailsOpenOnPrint.clear();
- });
-})();
-
-//
-// Smooth links
-//
-(() => {
- document.addEventListener('click', event => {
- const link = event.target.closest('a');
- const id = (link?.hash ?? '').substr(1);
- const isFragment = link?.hasAttribute('href') && link?.getAttribute('href').startsWith('#');
-
- if (!link || !isFragment || link.getAttribute('data-smooth-link') === 'false') {
- return;
- }
-
- // Scroll to the top
- if (link.hash === '') {
- event.preventDefault();
- window.scroll({ top: 0, behavior: 'smooth' });
- history.pushState(undefined, undefined, location.pathname);
- }
-
- // Scroll to an id
- if (id) {
- const target = document.getElementById(id);
-
- if (target) {
- event.preventDefault();
- window.scroll({ top: target.offsetTop, behavior: 'smooth' });
- history.pushState(undefined, undefined, `#${id}`);
- }
- }
- });
-})();
-
-//
-// Table of Contents scrollspy
-//
-(() => {
- // This will be stale if its not a function.
- const getLinks = () => [...document.querySelectorAll('.content__toc a')];
- const linkTargets = new WeakMap();
- const visibleTargets = new WeakSet();
- const observer = new IntersectionObserver(handleIntersect, { rootMargin: '0px 0px' });
- let debounce;
-
- function handleIntersect(entries) {
- entries.forEach(entry => {
- // Remember which targets are visible
- if (entry.isIntersecting) {
- visibleTargets.add(entry.target);
- } else {
- visibleTargets.delete(entry.target);
- }
- });
-
- updateActiveLinks();
- }
-
- function updateActiveLinks() {
- const links = getLinks();
- // Find the first visible target and activate the respective link
- links.find(link => {
- const target = linkTargets.get(link);
-
- if (target && visibleTargets.has(target)) {
- links.forEach(el => el.classList.toggle('active', el === link));
- return true;
- }
-
- return false;
- });
- }
-
- // Observe link targets
- function observeLinks() {
- getLinks().forEach(link => {
- const hash = link.hash.slice(1);
- const target = hash ? document.querySelector(`.content__body #${hash}`) : null;
-
- if (target) {
- linkTargets.set(link, target);
- observer.observe(target);
- }
- });
- }
-
- observeLinks();
-
- document.addEventListener('turbo:load', updateActiveLinks);
- document.addEventListener('turbo:load', observeLinks);
-})();
-
-//
-// Show custom versions in the sidebar
-//
-(() => {
- function updateVersion() {
- const el = document.querySelector('.sidebar-version');
- if (!el) return;
-
- if (location.hostname === 'next.shoelace.style') el.textContent = 'Next';
- if (location.hostname === 'localhost') el.textContent = 'Development';
- }
-
- updateVersion();
-
- document.addEventListener('turbo:load', updateVersion);
-})();
diff --git a/docs/assets/scripts/search.js b/docs/assets/scripts/search.js
deleted file mode 100644
index 7241e0bc3..000000000
--- a/docs/assets/scripts/search.js
+++ /dev/null
@@ -1,384 +0,0 @@
-(() => {
- // Append the search dialog to the body
- const siteSearch = document.createElement('div');
- const scrollbarWidth = Math.abs(window.innerWidth - document.documentElement.clientWidth);
-
- siteSearch.classList.add('search');
- siteSearch.innerHTML = `
-
-
-
-
- `;
-
- const overlay = siteSearch.querySelector('.search__overlay');
- const dialog = siteSearch.querySelector('.search__dialog');
- const input = siteSearch.querySelector('.search__input');
- const clearButton = siteSearch.querySelector('.search__clear-button');
- const results = siteSearch.querySelector('.search__results');
- const version = document.documentElement.getAttribute('data-wa-version');
- const key = `search_${version}`;
- const searchDebounce = 50;
- const animationDuration = 150;
- let isShowing = false;
- let searchTimeout;
- let searchIndex;
- let map;
-
- const loadSearchIndex = new Promise(resolve => {
- const cache = localStorage.getItem(key);
- const wait = 'requestIdleCallback' in window ? requestIdleCallback : requestAnimationFrame;
-
- // Cleanup older search indices (everything before this version)
- try {
- const items = { ...localStorage };
-
- Object.keys(items).forEach(k => {
- if (key > k) {
- localStorage.removeItem(k);
- }
- });
- } catch {
- /* do nothing */
- }
-
- // Look for a cached index
- try {
- if (cache) {
- const data = JSON.parse(cache);
-
- searchIndex = window.lunr.Index.load(data.searchIndex);
- map = data.map;
-
- return resolve();
- }
- } catch {
- /* do nothing */
- }
-
- // Wait until idle to fetch the index
- wait(() => {
- fetch('/assets/search.json')
- .then(res => res.json())
- .then(data => {
- if (!window.lunr) {
- console.error('The Lunr search client has not yet been loaded.');
- }
-
- searchIndex = window.lunr.Index.load(data.searchIndex);
- map = data.map;
-
- // Cache the search index for this version
- if (version) {
- try {
- localStorage.setItem(key, JSON.stringify(data));
- } catch (err) {
- console.warn(`Unable to cache the search index: ${err}`);
- }
- }
-
- resolve();
- });
- });
- });
-
- async function show() {
- isShowing = true;
- document.body.append(siteSearch);
- document.body.classList.add('search-visible');
- document.body.style.setProperty('--docs-search-scroll-lock-size', `${scrollbarWidth}px`);
- clearButton.hidden = true;
- requestAnimationFrame(() => input.focus());
- updateResults();
-
- dialog.showModal();
-
- await Promise.all([
- dialog.animate(
- [
- { opacity: 0, transform: 'scale(.9)', transformOrigin: 'top' },
- { opacity: 1, transform: 'scale(1)', transformOrigin: 'top' }
- ],
- { duration: animationDuration }
- ).finished,
- overlay.animate([{ opacity: 0 }, { opacity: 1 }], { duration: animationDuration }).finished
- ]);
-
- dialog.addEventListener('mousedown', handleMouseDown);
- dialog.addEventListener('keydown', handleKeyDown);
- }
-
- async function hide() {
- isShowing = false;
-
- await Promise.all([
- dialog.animate(
- [
- { opacity: 1, transform: 'scale(1)', transformOrigin: 'top' },
- { opacity: 0, transform: 'scale(.9)', transformOrigin: 'top' }
- ],
- { duration: animationDuration }
- ).finished,
- overlay.animate([{ opacity: 1 }, { opacity: 0 }], { duration: animationDuration }).finished
- ]);
-
- dialog.close();
-
- input.blur(); // otherwise Safari will scroll to the bottom of the page on close
- input.value = '';
- document.body.classList.remove('search-visible');
- document.body.style.removeProperty('--docs-search-scroll-lock-size');
- siteSearch.remove();
- updateResults();
-
- dialog.removeEventListener('mousedown', handleMouseDown);
- dialog.removeEventListener('keydown', handleKeyDown);
- }
-
- function handleInput() {
- clearButton.hidden = input.value === '';
-
- // Debounce search queries
- clearTimeout(searchTimeout);
- searchTimeout = setTimeout(() => updateResults(input.value), searchDebounce);
- }
-
- function handleClear() {
- clearButton.hidden = true;
- input.value = '';
- input.focus();
- updateResults();
- }
-
- function handleMouseDown(event) {
- if (!event.target.closest('.search__content')) {
- hide();
- }
- }
-
- function handleKeyDown(event) {
- // Close when pressing escape
- if (event.key === 'Escape') {
- event.preventDefault(); // prevent from closing immediately so it can animate
- event.stopImmediatePropagation();
- hide();
- return;
- }
-
- // Handle keyboard selections
- if (['ArrowDown', 'ArrowUp', 'Home', 'End', 'Enter'].includes(event.key)) {
- event.preventDefault();
-
- const currentEl = results.querySelector('[data-selected="true"]');
- const items = [...results.querySelectorAll('li')];
- const index = items.indexOf(currentEl);
- let nextEl;
-
- if (items.length === 0) {
- return;
- }
-
- switch (event.key) {
- case 'ArrowUp':
- nextEl = items[Math.max(0, index - 1)];
- break;
- case 'ArrowDown':
- nextEl = items[Math.min(items.length - 1, index + 1)];
- break;
- case 'Home':
- nextEl = items[0];
- break;
- case 'End':
- nextEl = items[items.length - 1];
- break;
- case 'Enter':
- currentEl?.querySelector('a')?.click();
- break;
- }
-
- // Update the selected item
- items.forEach(item => {
- if (item === nextEl) {
- input.setAttribute('aria-activedescendant', item.id);
- item.setAttribute('data-selected', 'true');
- nextEl.scrollIntoView({ block: 'nearest' });
- } else {
- item.setAttribute('data-selected', 'false');
- }
- });
- }
- }
-
- async function updateResults(query = '') {
- try {
- await loadSearchIndex;
-
- const hasQuery = query.length > 0;
- const searchTerms = query
- .split(' ')
- .map((term, index, arr) => {
- // Search API: https://lunrjs.com/guides/searching.html
- if (index === arr.length - 1) {
- // The last term is not mandatory and 1x fuzzy. We also duplicate it with a wildcard to match partial words
- // as the user types.
- return `${term}~1 ${term}*`;
- } else {
- // All other terms are mandatory and 1x fuzzy
- return `+${term}~1`;
- }
- })
- .join(' ');
- const matches = hasQuery ? searchIndex.search(searchTerms) : [];
- const hasResults = hasQuery && matches.length > 0;
-
- siteSearch.classList.toggle('search--has-results', hasQuery && hasResults);
- siteSearch.classList.toggle('search--no-results', hasQuery && !hasResults);
-
- input.setAttribute('aria-activedescendant', '');
- results.innerHTML = '';
-
- matches.forEach((match, index) => {
- const page = map[match.ref];
- const li = document.createElement('li');
- const a = document.createElement('a');
- const displayTitle = page.title ?? '';
- const displayDescription = page.description ?? '';
- const displayUrl = page.url.replace(/^\//, '').replace(/\/$/, '');
- let icon = 'file-text';
-
- a.setAttribute('role', 'option');
- a.setAttribute('id', `search-result-item-${match.ref}`);
-
- if (page.url.includes('getting-started/')) {
- icon = 'lightbulb';
- }
- if (page.url.includes('resources/')) {
- icon = 'book';
- }
- if (page.url.includes('components/')) {
- icon = 'puzzle-piece';
- }
- if (page.url.includes('tokens/')) {
- icon = 'swatchbook';
- }
- if (page.url.includes('utilities/')) {
- icon = 'wrench';
- }
- if (page.url.includes('tutorials/')) {
- icon = 'gamepad';
- }
-
- li.classList.add('search__result');
- li.setAttribute('role', 'option');
- li.setAttribute('id', `search-result-item-${match.ref}`);
- li.setAttribute('data-selected', index === 0 ? 'true' : 'false');
-
- a.href = page.url;
- a.innerHTML = `
-
-
-
-
- `;
- a.querySelector('.search__result-title').textContent = displayTitle;
- a.querySelector('.search__result-description').textContent = displayDescription;
- a.querySelector('.search__result-url').textContent = displayUrl;
-
- li.appendChild(a);
- results.appendChild(li);
- });
- } catch {
- // Ignore query errors as the user types
- }
- }
-
- // Show the search dialog when clicking on data-plugin="search"
- document.addEventListener('click', event => {
- const searchButton = event.target.closest('[data-plugin="search"]');
- if (searchButton) {
- show();
- }
- });
-
- // Show the search dialog when slash (or CMD+K) is pressed and focus is not inside a form element
- document.addEventListener('keydown', event => {
- if (
- !isShowing &&
- (event.key === '/' || (event.key === 'k' && (event.metaKey || event.ctrlKey))) &&
- !event.composedPath().some(el => ['input', 'textarea'].includes(el?.tagName?.toLowerCase()))
- ) {
- event.preventDefault();
- show();
- }
- });
-
- // Purge cache when we press CMD+CTRL+R
- document.addEventListener('keydown', event => {
- if ((event.metaKey || event.ctrlKey) && event.shiftKey && event.key === 'r') {
- localStorage.clear();
- }
- });
-
- input.addEventListener('input', handleInput);
- clearButton.addEventListener('click', handleClear);
-
- // Close when a result is selected
- results.addEventListener('click', event => {
- if (event.target.closest('a')) {
- hide();
- }
- });
-
- // We're using Turbo, so when a user searches for something, visits a result, and presses the back button, the search
- // UI will still be visible but not interactive. This removes the search UI when Turbo renders a page so they don't
- // get trapped.
- window.addEventListener('turbo:render', () => {
- document.body.classList.remove('search-visible');
- document.querySelectorAll('.search__overlay, .search__dialog').forEach(el => el.remove());
- });
-})();
diff --git a/docs/assets/scripts/turbo.js b/docs/assets/scripts/turbo.js
deleted file mode 100644
index 7075217f0..000000000
--- a/docs/assets/scripts/turbo.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import * as Turbo from 'https://cdn.jsdelivr.net/npm/@hotwired/turbo@7.3.0/+esm';
-
-(() => {
- if (!window.scrollPositions) {
- window.scrollPositions = {};
- }
-
- function preserveScroll() {
- document.querySelectorAll('[data-preserve-scroll').forEach(element => {
- scrollPositions[element.id] = element.scrollTop;
- });
- }
-
- function restoreScroll(event) {
- document.querySelectorAll('[data-preserve-scroll').forEach(element => {
- element.scrollTop = scrollPositions[element.id];
- });
-
- if (event.detail && event.detail.newBody) {
- event.detail.newBody.querySelectorAll('[data-preserve-scroll').forEach(element => {
- element.scrollTop = scrollPositions[element.id];
- });
- }
- }
-
- window.addEventListener('turbo:before-cache', preserveScroll);
- window.addEventListener('turbo:before-render', restoreScroll);
- window.addEventListener('turbo:render', restoreScroll);
-})();
diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs
new file mode 100644
index 000000000..258affdbf
--- /dev/null
+++ b/docs/astro.config.mjs
@@ -0,0 +1,142 @@
+import { defineConfig } from 'astro/config';
+import starlight from '@astrojs/starlight';
+import * as url from 'node:url';
+import * as path from 'node:path';
+// const __filename = url.fileURLToPath(import.meta.url);
+const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
+
+import FullReload from 'vite-plugin-full-reload';
+
+import { customElementsManifest } from './src/js/cem.js';
+import { RemarkPluginFindAndReplace } from 'remark-plugin-find-and-replace';
+import rehypeExternalLinks from 'rehype-external-links';
+import remarkCodeHighlighter from './src/plugins/prism';
+import GithubAutolink from './src/plugins/github-autolink.ts';
+
+const version = customElementsManifest().package.version;
+const cdndir = 'cdn';
+const npmdir = 'dist';
+
+function remarkFrontmatterPlugin() {
+ // All remark and rehype plugins return a separate function
+ return function (tree, file) {
+ const frontmatter = file.data.astro.frontmatter;
+
+ frontmatter.npmdir = npmdir;
+ frontmatter.cdndir = cdndir;
+ frontmatter.version = version;
+ };
+}
+
+// https://astro.build/config
+export default defineConfig({
+ server: {
+ open: true,
+ port: 4000,
+ host: true
+ },
+ vite: {
+ plugins: [
+ FullReload([
+ path.relative(__dirname, '../dist/custom-elements.json'),
+ path.relative(__dirname, './public/**/*.*')
+ ])
+ ]
+ },
+ outDir: '../_site',
+ site: 'https://shoelace.style',
+ markdown: {
+ syntaxHighlight: 'prism',
+ remarkPlugins: [
+ remarkFrontmatterPlugin,
+ RemarkPluginFindAndReplace({
+ replacements: [
+ { pattern: '%VERSION%', replacement: version },
+ { pattern: '%CDNDIR%', replacement: cdndir },
+ { pattern: '%NPMDIR%', replacement: npmdir }
+ ]
+ }),
+ GithubAutolink,
+ remarkCodeHighlighter
+ ],
+ rehypePlugins: [
+ () =>
+ rehypeExternalLinks({
+ rel: ['nofollow', 'noopener', 'noreferrer'],
+ target: ['_blank'],
+ properties: {
+ class: 'external-link'
+ }
+ })
+ ]
+ },
+ integrations: [
+ starlight({
+ expressiveCode: false,
+ title: 'Web Awesome',
+ social: {
+ github: 'https://github.com/shoelace-style/shoelace',
+ twitter: 'https://twitter.com/shoelace_style'
+ },
+ sidebar: [
+ {
+ label: 'Experimental',
+ autogenerate: { directory: 'experimental' }
+ },
+ {
+ label: 'Getting Started',
+ autogenerate: { directory: 'getting-started' }
+ },
+ {
+ label: 'Frameworks',
+ autogenerate: { directory: 'frameworks' }
+ },
+ {
+ label: 'Resources',
+ autogenerate: { directory: 'resources' },
+ items: [
+ {
+ label: 'Community',
+ link: '/resources/community'
+ },
+ {
+ label: 'Help & Support',
+ link: 'https://github.com/shoelace-style/shoelace/discussions'
+ },
+ {
+ label: 'Accessibility',
+ link: '/resources/accessibility'
+ },
+ {
+ label: 'Contributing',
+ link: '/resources/contributing'
+ },
+ {
+ label: 'Changelog',
+ link: '/resources/changelog'
+ }
+ ]
+ },
+ {
+ label: 'Components',
+ autogenerate: { directory: 'components' }
+ },
+ {
+ label: 'Design Tokens',
+ autogenerate: { directory: 'tokens' }
+ },
+ {
+ label: 'Tutorials',
+ autogenerate: { directory: 'tutorials' }
+ }
+ ],
+ // Component overrides
+ components: {
+ // Override the default `Head` component.
+ Head: './src/components/overrides/Head.astro',
+ TableOfContents: './src/components/overrides/TableOfContents.astro',
+ Search: './src/components/overrides/Search.astro'
+ }
+ })
+ ]
+});
diff --git a/docs/eleventy.config.cjs b/docs/eleventy.config.cjs
deleted file mode 100644
index 6f4172e93..000000000
--- a/docs/eleventy.config.cjs
+++ /dev/null
@@ -1,246 +0,0 @@
-/* eslint-disable no-invalid-this */
-const fs = require('fs');
-const path = require('path');
-const lunr = require('lunr');
-const { capitalCase } = require('change-case');
-const { JSDOM } = require('jsdom');
-const { customElementsManifest, getAllComponents } = require('./_utilities/cem.cjs');
-const webAwesomeFlavoredMarkdown = require('./_utilities/markdown.cjs');
-const activeLinks = require('./_utilities/active-links.cjs');
-const anchorHeadings = require('./_utilities/anchor-headings.cjs');
-const codePreviews = require('./_utilities/code-previews.cjs');
-const copyCodeButtons = require('./_utilities/copy-code-buttons.cjs');
-const externalLinks = require('./_utilities/external-links.cjs');
-const highlightCodeBlocks = require('./_utilities/highlight-code.cjs');
-const tableOfContents = require('./_utilities/table-of-contents.cjs');
-const prettier = require('./_utilities/prettier.cjs');
-const scrollingTables = require('./_utilities/scrolling-tables.cjs');
-const typography = require('./_utilities/typography.cjs');
-const replacer = require('./_utilities/replacer.cjs');
-
-const assetsDir = 'assets';
-const cdndir = 'cdn';
-const npmdir = 'dist';
-const allComponents = getAllComponents();
-let hasBuiltSearchIndex = false;
-
-module.exports = function (eleventyConfig) {
- //
- // Global data
- //
- eleventyConfig.addGlobalData('baseUrl', 'https://shoelace.style/'); // the production URL
- eleventyConfig.addGlobalData('layout', 'default'); // make 'default' the default layout
- eleventyConfig.addGlobalData('toc', true); // enable the table of contents
- eleventyConfig.addGlobalData('meta', {
- title: 'Web Awesome',
- description: 'A forward-thinking library of web components.',
- image: 'images/og-image.png',
- version: customElementsManifest.package.version,
- components: allComponents,
- cdndir,
- npmdir
- });
-
- //
- // Layout aliases
- //
- eleventyConfig.addLayoutAlias('default', 'default.njk');
-
- //
- // Copy assets
- //
- eleventyConfig.addPassthroughCopy(assetsDir);
- eleventyConfig.setServerPassthroughCopyBehavior('passthrough'); // emulates passthrough copy during --serve
-
- //
- // Functions
- //
-
- // Generates a URL relative to the site's root
- eleventyConfig.addNunjucksGlobal('rootUrl', (value = '', absolute = false) => {
- value = path.join('/', value);
- return absolute ? new URL(value, eleventyConfig.globalData.baseUrl).toString() : value;
- });
-
- // Generates a URL relative to the site's asset directory
- eleventyConfig.addNunjucksGlobal('assetUrl', (value = '', absolute = false) => {
- value = path.join(`/${assetsDir}`, value);
- return absolute ? new URL(value, eleventyConfig.globalData.baseUrl).toString() : value;
- });
-
- // Fetches a specific component's metadata
- eleventyConfig.addNunjucksGlobal('getComponent', tagName => {
- const component = allComponents.find(c => c.tagName === tagName);
- if (!component) {
- throw new Error(
- `Unable to find a component called "${tagName}". Make sure the file name is the same as the component's tag ` +
- `name (minus the wa- prefix).`
- );
- }
- return component;
- });
-
- //
- // Custom markdown syntaxes
- //
- eleventyConfig.setLibrary('md', webAwesomeFlavoredMarkdown);
-
- //
- // Filters
- //
- eleventyConfig.addFilter('markdown', content => {
- return webAwesomeFlavoredMarkdown.render(content);
- });
-
- eleventyConfig.addFilter('markdownInline', content => {
- return webAwesomeFlavoredMarkdown.renderInline(content);
- });
-
- // Trims whitespace and pipes from the start and end of a string. Useful for CEM types, which can be pipe-delimited.
- // With Prettier 3, this means a leading pipe will exist if the line wraps.
- eleventyConfig.addFilter('trimPipes', content => {
- return typeof content === 'string' ? content.replace(/^(\s|\|)/g, '').replace(/(\s|\|)$/g, '') : content;
- });
-
- eleventyConfig.addFilter('classNameToComponentName', className => {
- let name = capitalCase(className.replace(/^Wa/, ''));
- if (name === 'Qr Code') name = 'QR Code'; // manual override
- return name;
- });
-
- eleventyConfig.addFilter('removeWaPrefix', tagName => {
- return tagName.replace(/^wa-/, '');
- });
-
- //
- // Transforms
- //
- eleventyConfig.addTransform('html-transform', function (content) {
- // Parse the template and get a Document object
- const doc = new JSDOM(content, {
- // We must set a default URL so links are parsed with a hostname. Let's use a bogus TLD so we can easily
- // identify which ones are internal and which ones are external.
- url: `https://internal/`
- }).window.document;
-
- // DOM transforms
- activeLinks(doc, { pathname: this.page.url });
- anchorHeadings(doc, {
- within: '#content .content__body',
- levels: ['h2', 'h3', 'h4', 'h5']
- });
- tableOfContents(doc, {
- levels: ['h2', 'h3'],
- container: '#content .content__toc > ul',
- within: '#content .content__body'
- });
- codePreviews(doc);
- externalLinks(doc, { target: '_blank' });
- highlightCodeBlocks(doc);
- scrollingTables(doc);
- copyCodeButtons(doc); // must be after codePreviews + highlightCodeBlocks
- typography(doc, '#content');
-
- replacer(doc, [
- { pattern: '%VERSION%', replacement: customElementsManifest.package.version },
- { pattern: '%CDNDIR%', replacement: cdndir },
- { pattern: '%NPMDIR%', replacement: npmdir }
- ]);
-
- // Serialize the Document object to an HTML string and prepend the doctype
- content = `\n${doc.documentElement.outerHTML}`;
-
- // String transforms
- content = prettier(content);
-
- return content;
- });
-
- //
- // Build a search index
- //
- eleventyConfig.on('eleventy.after', ({ results }) => {
- // We only want to build the search index on the first run so all pages get indexed.
- if (hasBuiltSearchIndex) {
- return;
- }
-
- const map = {};
- const searchIndexFilename = path.join(eleventyConfig.dir.output, assetsDir, 'search.json');
- const lunrInput = path.resolve('../node_modules/lunr/lunr.min.js');
- const lunrOutput = path.join(eleventyConfig.dir.output, assetsDir, 'scripts/lunr.js');
- const searchIndex = lunr(function () {
- // The search index uses these field names extensively, so shortening them can save some serious bytes. The
- // initial index file went from 468 KB => 401 KB by using single-character names!
- this.ref('id'); // id
- this.field('t', { boost: 50 }); // title
- this.field('h', { boost: 25 }); // headings
- this.field('c'); // content
-
- results.forEach((result, index) => {
- const url = path
- .join('/', path.relative(eleventyConfig.dir.output, result.outputPath))
- .replace(/\\/g, '/') // convert backslashes to forward slashes
- .replace(/\/index.html$/, '/'); // convert trailing /index.html to /
- const doc = new JSDOM(result.content, {
- // We must set a default URL so links are parsed with a hostname. Let's use a bogus TLD so we can easily
- // identify which ones are internal and which ones are external.
- url: `https://internal/`
- }).window.document;
- const content = doc.querySelector('#content');
-
- // Get title and headings
- const title = (doc.querySelector('title')?.textContent || path.basename(result.outputPath)).trim();
- const headings = [...content.querySelectorAll('h1, h2, h3, h4')]
- .map(heading => heading.textContent)
- .join(' ')
- .replace(/\s+/g, ' ')
- .trim();
-
- // Remove code blocks and whitespace from content
- [...content.querySelectorAll('code[class|=language]')].forEach(code => code.remove());
- const textContent = content.textContent.replace(/\s+/g, ' ').trim();
-
- // Update the index and map
- this.add({ id: index, t: title, h: headings, c: textContent });
- map[index] = { title, url };
- });
- });
-
- // Copy the Lunr search client and write the index
- fs.mkdirSync(path.dirname(lunrOutput), { recursive: true });
- fs.copyFileSync(lunrInput, lunrOutput);
- fs.writeFileSync(searchIndexFilename, JSON.stringify({ searchIndex, map }), 'utf-8');
-
- hasBuiltSearchIndex = true;
- });
-
- //
- // Send a signal to stdout that let's the build know we've reached this point
- //
- eleventyConfig.on('eleventy.after', () => {
- console.log('[eleventy.after]');
- });
-
- //
- // Dev server options (see https://www.11ty.dev/docs/dev-server/#options)
- //
- eleventyConfig.setServerOptions({
- domDiff: false, // disable dom diffing so custom elements don't break on reload,
- port: 4000, // if port 4000 is taken, 11ty will use the next one available
- watch: ['cdn/**/*'] // additional files to watch that will trigger server updates (array of paths or globs)
- });
-
- //
- // 11ty config
- //
- return {
- dir: {
- input: 'pages',
- output: '../_site',
- includes: '../_includes' // resolved relative to the input dir
- },
- markdownTemplateEngine: 'njk', // use Nunjucks instead of Liquid for markdown files
- templateEngineOverride: ['njk'] // just Nunjucks and then markdown
- };
-};
diff --git a/docs/pages/404.md b/docs/pages/404.md
deleted file mode 100644
index 085c8d42a..000000000
--- a/docs/pages/404.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-meta:
- title: Page Not Found
- description: "The page you were looking for couldn't be found."
-permalink: 404.html
-toc: false
----
-
-
-
-# Page Not Found
-
-
-
-The page you were looking for couldn't be found.
-
-Press [[/]] to search, or [head back to the homepage](/).
-
-
diff --git a/docs/assets/examples/carousel/field.jpg b/docs/public/assets/examples/carousel/field.jpg
similarity index 100%
rename from docs/assets/examples/carousel/field.jpg
rename to docs/public/assets/examples/carousel/field.jpg
diff --git a/docs/assets/examples/carousel/mountains.jpg b/docs/public/assets/examples/carousel/mountains.jpg
similarity index 100%
rename from docs/assets/examples/carousel/mountains.jpg
rename to docs/public/assets/examples/carousel/mountains.jpg
diff --git a/docs/assets/examples/carousel/sunset.jpg b/docs/public/assets/examples/carousel/sunset.jpg
similarity index 100%
rename from docs/assets/examples/carousel/sunset.jpg
rename to docs/public/assets/examples/carousel/sunset.jpg
diff --git a/docs/assets/examples/carousel/valley.jpg b/docs/public/assets/examples/carousel/valley.jpg
similarity index 100%
rename from docs/assets/examples/carousel/valley.jpg
rename to docs/public/assets/examples/carousel/valley.jpg
diff --git a/docs/assets/examples/carousel/waterfall.jpg b/docs/public/assets/examples/carousel/waterfall.jpg
similarity index 100%
rename from docs/assets/examples/carousel/waterfall.jpg
rename to docs/public/assets/examples/carousel/waterfall.jpg
diff --git a/docs/assets/examples/include.html b/docs/public/assets/examples/include.html
similarity index 100%
rename from docs/assets/examples/include.html
rename to docs/public/assets/examples/include.html
diff --git a/docs/assets/images/awesome.svg b/docs/public/assets/images/awesome.svg
similarity index 100%
rename from docs/assets/images/awesome.svg
rename to docs/public/assets/images/awesome.svg
diff --git a/docs/assets/images/chrome.png b/docs/public/assets/images/chrome.png
similarity index 100%
rename from docs/assets/images/chrome.png
rename to docs/public/assets/images/chrome.png
diff --git a/docs/assets/images/edge.png b/docs/public/assets/images/edge.png
similarity index 100%
rename from docs/assets/images/edge.png
rename to docs/public/assets/images/edge.png
diff --git a/docs/assets/images/firefox.png b/docs/public/assets/images/firefox.png
similarity index 100%
rename from docs/assets/images/firefox.png
rename to docs/public/assets/images/firefox.png
diff --git a/docs/assets/images/gitpod.svg b/docs/public/assets/images/gitpod.svg
similarity index 100%
rename from docs/assets/images/gitpod.svg
rename to docs/public/assets/images/gitpod.svg
diff --git a/docs/public/assets/images/houston.webp b/docs/public/assets/images/houston.webp
new file mode 100644
index 000000000..930c16497
Binary files /dev/null and b/docs/public/assets/images/houston.webp differ
diff --git a/docs/assets/images/logo.svg b/docs/public/assets/images/logo.svg
similarity index 100%
rename from docs/assets/images/logo.svg
rename to docs/public/assets/images/logo.svg
diff --git a/docs/assets/images/og-image.png b/docs/public/assets/images/og-image.png
similarity index 100%
rename from docs/assets/images/og-image.png
rename to docs/public/assets/images/og-image.png
diff --git a/docs/assets/images/opera.png b/docs/public/assets/images/opera.png
similarity index 100%
rename from docs/assets/images/opera.png
rename to docs/public/assets/images/opera.png
diff --git a/docs/assets/images/safari.png b/docs/public/assets/images/safari.png
similarity index 100%
rename from docs/assets/images/safari.png
rename to docs/public/assets/images/safari.png
diff --git a/docs/assets/images/shoe.svg b/docs/public/assets/images/shoe.svg
similarity index 100%
rename from docs/assets/images/shoe.svg
rename to docs/public/assets/images/shoe.svg
diff --git a/docs/public/assets/images/sprite.svg b/docs/public/assets/images/sprite.svg
new file mode 100644
index 000000000..217fb532c
--- /dev/null
+++ b/docs/public/assets/images/sprite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/assets/images/tie.webp b/docs/public/assets/images/tie.webp
similarity index 100%
rename from docs/assets/images/tie.webp
rename to docs/public/assets/images/tie.webp
diff --git a/docs/assets/images/touch-icon.png b/docs/public/assets/images/touch-icon.png
similarity index 100%
rename from docs/assets/images/touch-icon.png
rename to docs/public/assets/images/touch-icon.png
diff --git a/docs/assets/images/twitter-card.png b/docs/public/assets/images/twitter-card.png
similarity index 100%
rename from docs/assets/images/twitter-card.png
rename to docs/public/assets/images/twitter-card.png
diff --git a/docs/assets/images/undraw-content-team.svg b/docs/public/assets/images/undraw-content-team.svg
similarity index 100%
rename from docs/assets/images/undraw-content-team.svg
rename to docs/public/assets/images/undraw-content-team.svg
diff --git a/docs/assets/images/undraw-not-found.svg b/docs/public/assets/images/undraw-not-found.svg
similarity index 100%
rename from docs/assets/images/undraw-not-found.svg
rename to docs/public/assets/images/undraw-not-found.svg
diff --git a/docs/assets/images/undraw-taken.svg b/docs/public/assets/images/undraw-taken.svg
similarity index 100%
rename from docs/assets/images/undraw-taken.svg
rename to docs/public/assets/images/undraw-taken.svg
diff --git a/docs/assets/images/walk.gif b/docs/public/assets/images/walk.gif
similarity index 100%
rename from docs/assets/images/walk.gif
rename to docs/public/assets/images/walk.gif
diff --git a/docs/assets/images/wordmark.svg b/docs/public/assets/images/wordmark.svg
similarity index 100%
rename from docs/assets/images/wordmark.svg
rename to docs/public/assets/images/wordmark.svg
diff --git a/docs/assets/images/favicon.svg b/docs/public/favicon.svg
similarity index 100%
rename from docs/assets/images/favicon.svg
rename to docs/public/favicon.svg
diff --git a/docs/src/assets/houston.webp b/docs/src/assets/houston.webp
new file mode 100644
index 000000000..930c16497
Binary files /dev/null and b/docs/src/assets/houston.webp differ
diff --git a/docs/src/components/Docs.astro b/docs/src/components/Docs.astro
new file mode 100644
index 000000000..3a5f43756
--- /dev/null
+++ b/docs/src/components/Docs.astro
@@ -0,0 +1,125 @@
+---
+---
+
+
diff --git a/docs/_includes/logo.njk b/docs/src/components/Logo.astro
similarity index 99%
rename from docs/_includes/logo.njk
rename to docs/src/components/Logo.astro
index a4d891f64..d0fd4be1b 100644
--- a/docs/_includes/logo.njk
+++ b/docs/src/components/Logo.astro
@@ -1 +1,4 @@
+---
+---
+
diff --git a/docs/src/components/Search.astro b/docs/src/components/Search.astro
new file mode 100644
index 000000000..4a36d9524
--- /dev/null
+++ b/docs/src/components/Search.astro
@@ -0,0 +1,389 @@
+---
+---
+
+
diff --git a/docs/src/components/Turbo.astro b/docs/src/components/Turbo.astro
new file mode 100644
index 000000000..293a96bf7
--- /dev/null
+++ b/docs/src/components/Turbo.astro
@@ -0,0 +1,36 @@
+---
+---
+
+
diff --git a/docs/src/components/overrides/Head.astro b/docs/src/components/overrides/Head.astro
new file mode 100644
index 000000000..756537a3a
--- /dev/null
+++ b/docs/src/components/overrides/Head.astro
@@ -0,0 +1,55 @@
+---
+import type { Props } from '@astrojs/starlight/props';
+import { default as AstroHead } from '@astrojs/starlight/components/Head.astro';
+import Turbo from "../Turbo.astro"
+import Docs from "../Docs.astro"
+import Search from "../Search.astro"
+
+import '../../styles/global.css'
+import '../../styles/syntax-highlight.css'
+import '../../styles/code-previews.css'
+import { customElementsManifest } from '../../js/cem';
+
+const version = customElementsManifest().package.version
+---
+
+
+
+
+
+
+<>
+
+
+ {/* */}
+
+
+
+
+
+
+
+
+
+
+
+>
diff --git a/docs/src/components/overrides/Search.astro b/docs/src/components/overrides/Search.astro
new file mode 100644
index 000000000..0e3a157cb
--- /dev/null
+++ b/docs/src/components/overrides/Search.astro
@@ -0,0 +1,436 @@
+---
+import '@pagefind/default-ui/css/ui.css';
+import { Icon } from '@astrojs/starlight/components';
+import type { Props } from '@astrojs/starlight/props';
+
+const { labels } = Astro.props;
+
+const pagefindTranslations = {
+ placeholder: labels['search.label'],
+ ...Object.fromEntries(
+ Object.entries(labels)
+ .filter(([key]) => key.startsWith('pagefind.'))
+ .map(([key, value]) => [key.replace('pagefind.', ''), value])
+ ),
+};
+
+---
+
+
+
+ {
+ /* The span is `aria-hidden` because it is not shown on small screens. Instead, the icon label is used for accessibility purposes. */
+ }
+
+ {labels['search.label']}
+
+
+
+
+
+ {
+ /* TODO: Make the layout of this button flexible to accommodate different word lengths. Currently hard-coded for English: āCancelā */
+ }
+
+ {labels['search.cancelLabel']}
+
+ {
+
+ }
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/components/overrides/TableOfContents.astro b/docs/src/components/overrides/TableOfContents.astro
new file mode 100644
index 000000000..25abebbb7
--- /dev/null
+++ b/docs/src/components/overrides/TableOfContents.astro
@@ -0,0 +1,63 @@
+---
+import { default as StarlightTOC } from '@astrojs/starlight/components/TableOfContents.astro';
+import type { Props } from "@astrojs/starlight/props"
+const { labels, toc, slug, entry, id } = Astro.props;
+
+import { getComponentFromFileName } from "../../js/cem.js"
+
+if (slug.includes("components/")) {
+ const component = getComponentFromFileName(slug + ".md")
+
+ const {
+ hasSlots,
+ hasProperties,
+ hasEvents,
+ hasMethods,
+ hasCssProperties,
+ hasCssParts,
+ hasAnimations,
+ hasDependencies,
+ } = component
+
+ toc.items.push({
+ text: "Importing",
+ slug: "importing",
+ depth: 0,
+ children: []
+ })
+
+ const strToText = {
+ CssProperties: "Custom Properties",
+ CssParts: "Parts",
+ }
+
+ const strToId = {
+ CssProperties: "custom-properties",
+ CssParts: "parts",
+ }
+
+ ;[
+ "Slots",
+ "Properties",
+ "Events",
+ "Methods",
+ "CssProperties",
+ "CssParts",
+ "Animations",
+ "Dependencies",
+ ].forEach((str) => {
+ if (component[`has${str}`]) {
+ toc.items.push({
+ text: strToText[str] || str,
+ slug: strToId[str] || str.toLowerCase(),
+ depth: 0,
+ children: []
+ })
+ }
+ })
+
+}
+---
+
+
+
diff --git a/docs/src/content/config.ts b/docs/src/content/config.ts
new file mode 100644
index 000000000..95b5451cb
--- /dev/null
+++ b/docs/src/content/config.ts
@@ -0,0 +1,16 @@
+import { defineCollection, z } from 'astro:content';
+import { docsSchema, i18nSchema } from '@astrojs/starlight/schema';
+
+export const collections = {
+ docs: defineCollection({
+ schema: docsSchema({
+ extend: z.object({
+ // Add a new field to the schema.
+ category: z
+ .enum(['components', 'experimental', 'frameworks', 'getting-started', 'resources', 'tokens', 'tutorials'])
+ .optional()
+ })
+ })
+ }),
+ i18n: defineCollection({ type: 'data', schema: i18nSchema() })
+};
diff --git a/docs/src/content/docs/404.md b/docs/src/content/docs/404.md
new file mode 100644
index 000000000..70643dd4b
--- /dev/null
+++ b/docs/src/content/docs/404.md
@@ -0,0 +1,28 @@
+---
+title: Page Not Found
+description: "The page you were looking for couldn't be found."
+tableOfContents: false
+pageTitle: false
+---
+
+
+
+# Page Not Found
+
+
+
+The page you were looking for couldn't be found.
+
+Press / to search, or [head back to the homepage](/).
+
+
+
+
diff --git a/docs/pages/components/alert.md b/docs/src/content/docs/components/alert.md
similarity index 98%
rename from docs/pages/components/alert.md
rename to docs/src/content/docs/components/alert.md
index bd67a079e..41cb4acb0 100644
--- a/docs/pages/components/alert.md
+++ b/docs/src/content/docs/components/alert.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Alert
- description: Alerts are used to display important messages inline or as toast notifications.
-layout: component
+title: Alert
+description: Alerts are used to display important messages inline or as toast notifications.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -24,7 +23,7 @@ const App = () => (
);
```
-:::warning
+:::caution
Alerts will not be visible if the `open` attribute is not present.
:::
diff --git a/docs/pages/components/animated-image.md b/docs/src/content/docs/components/animated-image.md
similarity index 94%
rename from docs/pages/components/animated-image.md
rename to docs/src/content/docs/components/animated-image.md
index cc64b8dbf..c7b8381cf 100644
--- a/docs/pages/components/animated-image.md
+++ b/docs/src/content/docs/components/animated-image.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Animated Image
- description: A component for displaying animated GIFs and WEBPs that play and pause on interaction.
-layout: component
+title: Animated Image
+description: A component for displaying animated GIFs and WEBPs that play and pause on interaction.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -61,8 +60,6 @@ To set a custom size, apply a width and/or height to the host element.
```
-{% raw %}
-
```jsx:react
import WaAnimatedImage from '@shoelace-style/shoelace/dist/react/animated-image';
@@ -75,8 +72,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Customizing the Control Box
You can change the appearance and location of the control box by targeting the `control-box` part in your styles.
diff --git a/docs/pages/components/animation.md b/docs/src/content/docs/components/animation.md
similarity index 97%
rename from docs/pages/components/animation.md
rename to docs/src/content/docs/components/animation.md
index e5dc61b24..66d109a91 100644
--- a/docs/pages/components/animation.md
+++ b/docs/src/content/docs/components/animation.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Animation
- description: Animate elements declaratively with nearly 100 baked-in presets, or roll your own with custom keyframes.
-layout: component
+title: Animation
+description: Animate elements declaratively with nearly 100 baked-in presets, or roll your own with custom keyframes.
+layout: ../../../layouts/ComponentLayout.astro
---
To animate an element, wrap it in `` and set an animation `name`. The animation will not start until you add the `play` attribute. Refer to the [properties table](#properties) for a list of all animation options.
@@ -80,7 +79,8 @@ This example demonstrates all of the baked-in animations and easings. Animations
-
+
+
@@ -134,6 +134,10 @@ This example demonstrates all of the baked-in animations and easings. Animations
```
+```jsx:react
+
+```
+
### Using Intersection Observer
Use an [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to control the animation when an element enters or exits the viewport. For example, scroll the box below in and out of your screen. The animation stops when the box exits the viewport and restarts each time it enters the viewport.
diff --git a/docs/pages/components/avatar.md b/docs/src/content/docs/components/avatar.md
similarity index 98%
rename from docs/pages/components/avatar.md
rename to docs/src/content/docs/components/avatar.md
index f02fefc7d..54adf623f 100644
--- a/docs/pages/components/avatar.md
+++ b/docs/src/content/docs/components/avatar.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Avatar
- description: Avatars are used to represent a person or object.
-layout: component
+title: Avatar
+description: Avatars are used to represent a person or object.
+layout: ../../../layouts/ComponentLayout.astro
---
By default, a generic icon will be shown. You can personalize avatars by adding custom icons, initials, and images. You should always provide a `label` for assistive devices.
diff --git a/docs/pages/components/badge.md b/docs/src/content/docs/components/badge.md
similarity index 96%
rename from docs/pages/components/badge.md
rename to docs/src/content/docs/components/badge.md
index 37c04deaf..fde18079d 100644
--- a/docs/pages/components/badge.md
+++ b/docs/src/content/docs/components/badge.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Badge
- description: Badges are used to draw attention and display statuses or counts.
-layout: component
+title: Badge
+description: Badges are used to draw attention and display statuses or counts.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -154,8 +153,6 @@ One of the most common use cases for badges is attaching them to buttons. To mak
```
-{% raw %}
-
```jsx:react
import WaBadge from '@shoelace-style/shoelace/dist/react/badge';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -184,8 +181,6 @@ const App = () => (
);
```
-{% endraw %}
-
### With Menu Items
When including badges in menu items, use the `suffix` slot to make sure they're aligned correctly.
@@ -198,8 +193,6 @@ When including badges in menu items, use the `suffix` slot to make sure they're
```
-{% raw %}
-
```jsx:react
import WaBadge from '@shoelace-style/shoelace/dist/react/badge';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -227,5 +220,3 @@ const App = () => (
);
```
-
-{% endraw %}
diff --git a/docs/pages/components/breadcrumb-item.md b/docs/src/content/docs/components/breadcrumb-item.md
similarity index 85%
rename from docs/pages/components/breadcrumb-item.md
rename to docs/src/content/docs/components/breadcrumb-item.md
index 733d129ce..c86347171 100644
--- a/docs/pages/components/breadcrumb-item.md
+++ b/docs/src/content/docs/components/breadcrumb-item.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Breadcrumb Item
- description: Breadcrumb Items are used inside breadcrumbs to represent different links.
-layout: component
+title: Breadcrumb Item
+description: Breadcrumb Items are used inside breadcrumbs to represent different links.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/breadcrumb.md b/docs/src/content/docs/components/breadcrumb.md
similarity index 97%
rename from docs/pages/components/breadcrumb.md
rename to docs/src/content/docs/components/breadcrumb.md
index c897b5524..de36a25d8 100644
--- a/docs/pages/components/breadcrumb.md
+++ b/docs/src/content/docs/components/breadcrumb.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Breadcrumb
- description: Breadcrumbs provide a group of links so users can easily navigate a website's hierarchy.
-layout: component
+title: Breadcrumb
+description: Breadcrumbs provide a group of links so users can easily navigate a website's hierarchy.
+layout: ../../../layouts/ComponentLayout.astro
---
Breadcrumbs are usually placed before a page's main content with the current page shown last to indicate the user's position in the navigation.
diff --git a/docs/pages/components/button-group.md b/docs/src/content/docs/components/button-group.md
similarity index 98%
rename from docs/pages/components/button-group.md
rename to docs/src/content/docs/components/button-group.md
index 15976ca1d..8303fdda9 100644
--- a/docs/pages/components/button-group.md
+++ b/docs/src/content/docs/components/button-group.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Button Group
- description: Button groups can be used to group related buttons into sections.
-layout: component
+title: Button Group
+description: Button groups can be used to group related buttons into sections.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/button.md b/docs/src/content/docs/components/button.md
similarity index 98%
rename from docs/pages/components/button.md
rename to docs/src/content/docs/components/button.md
index beb0c413b..699285f20 100644
--- a/docs/pages/components/button.md
+++ b/docs/src/content/docs/components/button.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Button
- description: Buttons represent actions that are available to the user.
-layout: component
+title: Button
+description: Buttons represent actions that are available to the user.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -201,8 +200,6 @@ As expected, buttons can be given a custom width by setting the `width` attribut
Large
```
-{% raw %}
-
```jsx:react
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -221,8 +218,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Prefix and Suffix Icons
Use the `prefix` and `suffix` slots to add icons.
diff --git a/docs/pages/components/card.md b/docs/src/content/docs/components/card.md
similarity index 97%
rename from docs/pages/components/card.md
rename to docs/src/content/docs/components/card.md
index 56c67c1e8..9a2b95e9c 100644
--- a/docs/pages/components/card.md
+++ b/docs/src/content/docs/components/card.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Card
- description: Cards can be used to group related subjects in a container.
-layout: component
+title: Card
+description: Cards can be used to group related subjects in a container.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/carousel-item.md b/docs/src/content/docs/components/carousel-item.md
similarity index 94%
rename from docs/pages/components/carousel-item.md
rename to docs/src/content/docs/components/carousel-item.md
index 6fa5d36f5..05ea36154 100644
--- a/docs/pages/components/carousel-item.md
+++ b/docs/src/content/docs/components/carousel-item.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Carousel Item
- description: A carousel item represent a slide within a carousel.
-layout: component
+title: Carousel Item
+description: A carousel item represent a slide within a carousel.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/carousel.md b/docs/src/content/docs/components/carousel.md
similarity index 99%
rename from docs/pages/components/carousel.md
rename to docs/src/content/docs/components/carousel.md
index 6141cafe1..b8144306a 100644
--- a/docs/pages/components/carousel.md
+++ b/docs/src/content/docs/components/carousel.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Carousel
- description: Carousels display an arbitrary number of content slides along a horizontal or vertical axis.
-layout: component
+title: Carousel
+description: Carousels display an arbitrary number of content slides along a horizontal or vertical axis.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -527,8 +526,6 @@ The `slides-per-page` attribute makes it possible to display multiple slides at
```
-{% raw %}
-
```jsx:react
import WaCarousel from '@shoelace-style/shoelace/dist/react/carousel';
import WaCarouselItem from '@shoelace-style/shoelace/dist/react/carousel-item';
@@ -545,8 +542,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Adding and Removing Slides
The content of the carousel can be changed by adding or removing carousel items. The carousel will update itself automatically.
@@ -619,8 +614,6 @@ The content of the carousel can be changed by adding or removing carousel items.
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaCarousel from '@shoelace-style/shoelace/dist/react/carousel';
@@ -680,8 +673,6 @@ const App = () => {
};
```
-{% endraw %}
-
### Vertical Scrolling
Setting the `orientation` attribute to `vertical` will render the carousel in a vertical layout. If the content of your slides vary in height, you will need to set amn explicit `height` or `max-height` on the carousel using CSS.
@@ -859,8 +850,6 @@ Use the `--aspect-ratio` custom property to customize the size of the carousel's
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaCarousel from '@shoelace-style/shoelace/dist/react/carousel';
@@ -926,8 +915,6 @@ const App = () => {
};
```
-{% endraw %}
-
### Scroll Hint
Use the `--scroll-hint` custom property to add inline padding in horizontal carousels and block padding in vertical carousels. This will make the closest slides slightly visible, hinting that there are more items in the carousel.
@@ -967,8 +954,6 @@ Use the `--scroll-hint` custom property to add inline padding in horizontal caro
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaCarousel from '@shoelace-style/shoelace/dist/react/carousel';
@@ -1014,8 +999,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Gallery Example
The carousel has a robust API that makes it possible to extend and customize. This example syncs the active slide with a set of thumbnails, effectively creating a gallery-style carousel.
diff --git a/docs/pages/components/checkbox.md b/docs/src/content/docs/components/checkbox.md
similarity index 96%
rename from docs/pages/components/checkbox.md
rename to docs/src/content/docs/components/checkbox.md
index 75239f1bb..425f27305 100644
--- a/docs/pages/components/checkbox.md
+++ b/docs/src/content/docs/components/checkbox.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Checkbox
- description: Checkboxes allow the user to toggle an option on or off.
-layout: component
+title: Checkbox
+description: Checkboxes allow the user to toggle an option on or off.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -125,8 +124,6 @@ Use the `setCustomValidity()` method to set a custom validation message. This wi
```
-{% raw %}
-
```jsx:react
import { useEffect, useRef } from 'react';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -162,5 +159,3 @@ const App = () => {
);
};
```
-
-{% endraw %}
diff --git a/docs/pages/components/color-picker.md b/docs/src/content/docs/components/color-picker.md
similarity index 97%
rename from docs/pages/components/color-picker.md
rename to docs/src/content/docs/components/color-picker.md
index 3dd36d170..4ea60cfba 100644
--- a/docs/pages/components/color-picker.md
+++ b/docs/src/content/docs/components/color-picker.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Color Picker
- description: Color pickers allow the user to select a color.
-layout: component
+title: Color Picker
+description: Color pickers allow the user to select a color.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/copy-button.md b/docs/src/content/docs/components/copy-button.md
similarity index 98%
rename from docs/pages/components/copy-button.md
rename to docs/src/content/docs/components/copy-button.md
index 60f4c9e4f..352d7492d 100644
--- a/docs/pages/components/copy-button.md
+++ b/docs/src/content/docs/components/copy-button.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Copy Button
- description: Copies data to the clipboard when the user clicks the button.
-layout: component
+title: Copy Button
+description: Copies data to the clipboard when the user clicks the button.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/details.md b/docs/src/content/docs/components/details.md
similarity index 97%
rename from docs/pages/components/details.md
rename to docs/src/content/docs/components/details.md
index 429e5dbca..7e03bad70 100644
--- a/docs/pages/components/details.md
+++ b/docs/src/content/docs/components/details.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Details
- description: Details show a brief summary and expand to show additional content.
-layout: component
+title: Details
+description: Details show a brief summary and expand to show additional content.
+layout: ../../../layouts/ComponentLayout.astro
---
diff --git a/docs/pages/components/dialog.md b/docs/src/content/docs/components/dialog.md
similarity index 98%
rename from docs/pages/components/dialog.md
rename to docs/src/content/docs/components/dialog.md
index 159a8040b..d31dee2cd 100644
--- a/docs/pages/components/dialog.md
+++ b/docs/src/content/docs/components/dialog.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Dialog
- description: 'Dialogs, sometimes called "modals", appear above the page and require the user''s immediate attention.'
-layout: component
+title: Dialog
+description: 'Dialogs, sometimes called "modals", appear above the page and require the user''s immediate attention.'
+layout: ../../../layouts/ComponentLayout.astro
---
@@ -72,8 +71,6 @@ Use the `--width` custom property to set the dialog's width.
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -97,8 +94,6 @@ const App = () => {
};
```
-{% endraw %}
-
### Scrolling
By design, a dialog's height will never exceed that of the viewport. As such, dialogs will not scroll with the page ensuring the header and footer are always accessible to the user.
@@ -123,8 +118,6 @@ By design, a dialog's height will never exceed that of the viewport. As such, di
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -157,8 +150,6 @@ const App = () => {
};
```
-{% endraw %}
-
### Header Actions
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/components/icon-button) if needed.
diff --git a/docs/pages/components/divider.md b/docs/src/content/docs/components/divider.md
similarity index 86%
rename from docs/pages/components/divider.md
rename to docs/src/content/docs/components/divider.md
index 36344f917..caac024e3 100644
--- a/docs/pages/components/divider.md
+++ b/docs/src/content/docs/components/divider.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Divider
- description: Dividers are used to visually separate or group elements.
-layout: component
+title: Divider
+description: Dividers are used to visually separate or group elements.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -25,16 +24,12 @@ Use the `--width` custom property to change the width of the divider.
```
-{% raw %}
-
```jsx:react
import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
const App = () => ;
```
-{% endraw %}
-
### Color
Use the `--color` custom property to change the color of the divider.
@@ -43,16 +38,12 @@ Use the `--color` custom property to change the color of the divider.
```
-{% raw %}
-
```jsx:react
import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
const App = () => ;
```
-{% endraw %}
-
### Spacing
Use the `--spacing` custom property to change the amount of space between the divider and it's neighboring elements.
@@ -65,22 +56,6 @@ Use the `--spacing` custom property to change the amount of space between the di
```
-{% raw %}
-
-```jsx:react
-import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
-
-const App = () => (
- <>
- Above
-
- Below
- >
-);
-```
-
-{% endraw %}
-
### Vertical
Add the `vertical` attribute to draw the divider in a vertical orientation. The divider will span the full height of its container. Vertical dividers work especially well inside of a flex container.
@@ -95,8 +70,6 @@ Add the `vertical` attribute to draw the divider in a vertical orientation. The
```
-{% raw %}
-
```jsx:react
import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
@@ -117,8 +90,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Menu Dividers
Use dividers in [menus](/components/menu) to visually group menu items.
@@ -135,8 +106,6 @@ Use dividers in [menus](/components/menu) to visually group menu items.
```
-{% raw %}
-
```jsx:react
import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
import WaMenu from '@shoelace-style/shoelace/dist/react/menu';
@@ -154,5 +123,3 @@ const App = () => (
);
```
-
-{% endraw %}
diff --git a/docs/pages/components/drawer.md b/docs/src/content/docs/components/drawer.md
similarity index 98%
rename from docs/pages/components/drawer.md
rename to docs/src/content/docs/components/drawer.md
index 40a83ef5c..07f20b922 100644
--- a/docs/pages/components/drawer.md
+++ b/docs/src/content/docs/components/drawer.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Drawer
- description: Drawers slide in from a container to expose additional options and information.
-layout: component
+title: Drawer
+description: Drawers slide in from a container to expose additional options and information.
+layout: ../../../layouts/ComponentLayout.astro
---
@@ -215,8 +214,6 @@ Unlike normal drawers, contained drawers are not modal. This means they do not s
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -259,8 +256,6 @@ const App = () => {
};
```
-{% endraw %}
-
### Custom Size
Use the `--size` custom property to set the drawer's size. This will be applied to the drawer's width or height depending on its `placement`.
@@ -283,8 +278,6 @@ Use the `--size` custom property to set the drawer's size. This will be applied
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -308,8 +301,6 @@ const App = () => {
};
```
-{% endraw %}
-
### Scrolling
By design, a drawer's height will never exceed 100% of its container. As such, drawers will not scroll with the page to ensure the header and footer are always accessible to the user.
@@ -334,8 +325,6 @@ By design, a drawer's height will never exceed 100% of its container. As such, d
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -367,8 +356,6 @@ const App = () => {
};
```
-{% endraw %}
-
### Header Actions
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/components/icon-button) if needed.
diff --git a/docs/pages/components/dropdown.md b/docs/src/content/docs/components/dropdown.md
similarity index 98%
rename from docs/pages/components/dropdown.md
rename to docs/src/content/docs/components/dropdown.md
index cc22b7a1e..107c44221 100644
--- a/docs/pages/components/dropdown.md
+++ b/docs/src/content/docs/components/dropdown.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Dropdown
- description: 'Dropdowns expose additional content that "drops down" in a panel.'
-layout: component
+title: Dropdown
+description: 'Dropdowns expose additional content that "drops down" in a panel.'
+layout: ../../../layouts/ComponentLayout.astro
---
Dropdowns consist of a trigger and a panel. By default, activating the trigger will expose the panel and interacting outside of the panel will close it.
@@ -396,7 +395,7 @@ const App = () => (
);
```
-:::warning
+:::caution
As a UX best practice, avoid using more than one level of submenu when possible.
:::
diff --git a/docs/pages/components/format-bytes.md b/docs/src/content/docs/components/format-bytes.md
similarity index 96%
rename from docs/pages/components/format-bytes.md
rename to docs/src/content/docs/components/format-bytes.md
index 8df80988c..bda552edb 100644
--- a/docs/pages/components/format-bytes.md
+++ b/docs/src/content/docs/components/format-bytes.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Format Bytes
- description: Formats a number as a human readable bytes value.
-layout: component
+title: Format Bytes
+description: Formats a number as a human readable bytes value.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -20,8 +19,6 @@ layout: component
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -48,8 +45,6 @@ const App = () => {
};
```
-{% endraw %}
-
## Examples
### Formatting Bytes
diff --git a/docs/pages/components/format-date.md b/docs/src/content/docs/components/format-date.md
similarity index 96%
rename from docs/pages/components/format-date.md
rename to docs/src/content/docs/components/format-date.md
index fa701de87..d5b96f269 100644
--- a/docs/pages/components/format-date.md
+++ b/docs/src/content/docs/components/format-date.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Format Date
- description: Formats a date/time using the specified locale and options.
-layout: component
+title: Format Date
+description: Formats a date/time using the specified locale and options.
+layout: ../../../layouts/ComponentLayout.astro
---
Localization is handled by the browser's [`Intl.DateTimeFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat). No language packs are required.
diff --git a/docs/pages/components/format-number.md b/docs/src/content/docs/components/format-number.md
similarity index 96%
rename from docs/pages/components/format-number.md
rename to docs/src/content/docs/components/format-number.md
index 570c003f4..8d854439d 100644
--- a/docs/pages/components/format-number.md
+++ b/docs/src/content/docs/components/format-number.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Format Number
- description: Formats a number using the specified locale and options.
-layout: component
+title: Format Number
+description: Formats a number using the specified locale and options.
+layout: ../../../layouts/ComponentLayout.astro
---
Localization is handled by the browser's [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat). No language packs are required.
@@ -23,8 +22,6 @@ Localization is handled by the browser's [`Intl.NumberFormat` API](https://devel
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaFormatNumber from '@shoelace-style/shoelace/dist/react/format-number';
@@ -50,8 +47,6 @@ const App = () => {
};
```
-{% endraw %}
-
## Examples
### Percentages
diff --git a/docs/pages/components/icon-button.md b/docs/src/content/docs/components/icon-button.md
similarity index 95%
rename from docs/pages/components/icon-button.md
rename to docs/src/content/docs/components/icon-button.md
index 9106a5d4a..32de6b9db 100644
--- a/docs/pages/components/icon-button.md
+++ b/docs/src/content/docs/components/icon-button.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Icon Button
- description: Icons buttons are simple, icon-only buttons that can be used for actions and in toolbars.
-layout: component
+title: Icon Button
+description: Icons buttons are simple, icon-only buttons that can be used for actions and in toolbars.
+layout: ../../../layouts/ComponentLayout.astro
---
For a full list of icons that come bundled with Web Awesome, refer to the [icon component](/components/icon).
@@ -29,8 +28,6 @@ Icon buttons inherit their parent element's `font-size`.
```
-{% raw %}
-
```jsx:react
import WaIconButton from '@shoelace-style/shoelace/dist/react/icon-button';
@@ -43,8 +40,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Colors
Icon buttons are designed to have a uniform appearance, so their color is not inherited. However, you can still customize them by styling the `base` part.
diff --git a/docs/pages/components/icon.md b/docs/src/content/docs/components/icon.md
similarity index 99%
rename from docs/pages/components/icon.md
rename to docs/src/content/docs/components/icon.md
index 5428e8c38..24e9f2dd2 100644
--- a/docs/pages/components/icon.md
+++ b/docs/src/content/docs/components/icon.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Icon
- description: Icons are symbols that can be used to represent various options within an application.
-layout: component
+title: Icon
+description: Icons are symbols that can be used to represent various options within an application.
+layout: ../../../layouts/ComponentLayout.astro
---
Web Awesome comes bundled with over 1,500 icons courtesy of the [Bootstrap Icons](https://icons.getbootstrap.com/) project. These icons are part of the `default` icon library. If you prefer, you can register [custom icon libraries](#icon-libraries) as well.
@@ -55,8 +54,6 @@ Icons inherit their color from the current text color. Thus, you can set the `co
```
-{% raw %}
-
```jsx:react
import WaIcon from '@shoelace-style/shoelace/dist/react/icon';
@@ -90,8 +87,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Sizing
Icons are sized relative to the current font size. To change their size, set the `font-size` property on the icon itself or on a parent element as shown below.
@@ -117,8 +112,6 @@ Icons are sized relative to the current font size. To change their size, set the
```
-{% raw %}
-
```jsx:react
import WaIcon from '@shoelace-style/shoelace/dist/react/icon';
@@ -144,8 +137,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Labels
For non-decorative icons, use the `label` attribute to announce it to assistive devices.
@@ -168,16 +159,12 @@ Custom icons can be loaded individually with the `src` attribute. Only SVGs on a
```
-{% raw %}
-
```jsx:react
import WaIcon from '@shoelace-style/shoelace/dist/react/icon';
const App = () => ;
```
-{% endraw %}
-
## Icon Libraries
You can register additional icons to use with the `` component through icon libraries. Icon files can exist locally or on a CORS-enabled endpoint (e.g. a CDN). There is no limit to how many icon libraries you can register and there is no cost associated with registering them, as individual icons are only requested when they're used.
@@ -630,9 +617,7 @@ As always, make sure to benchmark these changes. When using HTTP/2, it may in fa
:::danger
When using sprite sheets, the `wa-load` and `wa-error` events will not fire.
-:::
-:::danger
For security reasons, browsers may apply the same-origin policy on `` elements located in the `` shadow DOM and may refuse to load a cross-origin URL. There is currently no defined way to set a cross-origin policy for `` elements. For this reason, sprite sheets should only be used if you're self-hosting them.
:::
diff --git a/docs/pages/components/image-comparer.md b/docs/src/content/docs/components/image-comparer.md
similarity index 94%
rename from docs/pages/components/image-comparer.md
rename to docs/src/content/docs/components/image-comparer.md
index 339c4499c..ca2ada423 100644
--- a/docs/pages/components/image-comparer.md
+++ b/docs/src/content/docs/components/image-comparer.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Image Comparer
- description: Compare visual differences between similar photos with a sliding panel.
-layout: component
+title: Image Comparer
+description: Compare visual differences between similar photos with a sliding panel.
+layout: ../../../layouts/ComponentLayout.astro
---
For best results, use images that share the same dimensions. The slider can be controlled by dragging or pressing the left and right arrow keys. (Tip: press shift + arrows to move the slider in larger intervals, or home + end to jump to the beginning or end.)
diff --git a/docs/pages/components/include.md b/docs/src/content/docs/components/include.md
similarity index 90%
rename from docs/pages/components/include.md
rename to docs/src/content/docs/components/include.md
index 602e65ba9..079ce1a9b 100644
--- a/docs/pages/components/include.md
+++ b/docs/src/content/docs/components/include.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Include
- description: Includes give you the power to embed external HTML files into the page.
-layout: component
+title: Include
+description: Includes give you the power to embed external HTML files into the page.
+layout: ../../../layouts/ComponentLayout.astro
---
Included files are asynchronously requested using `window.fetch()`. Requests are cached, so the same file can be included multiple times, but only one request will be made.
diff --git a/docs/pages/components/input.md b/docs/src/content/docs/components/input.md
similarity index 98%
rename from docs/pages/components/input.md
rename to docs/src/content/docs/components/input.md
index d9ca7afe2..5d90e779e 100644
--- a/docs/pages/components/input.md
+++ b/docs/src/content/docs/components/input.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Input
- description: Inputs collect data from the user.
-layout: component
+title: Input
+description: Inputs collect data from the user.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/menu-item.md b/docs/src/content/docs/components/menu-item.md
similarity index 96%
rename from docs/pages/components/menu-item.md
rename to docs/src/content/docs/components/menu-item.md
index 633415003..389eeb738 100644
--- a/docs/pages/components/menu-item.md
+++ b/docs/src/content/docs/components/menu-item.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Menu Item
- description: Menu items provide options for the user to pick from in a menu.
-layout: component
+title: Menu Item
+description: Menu items provide options for the user to pick from in a menu.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -25,8 +24,6 @@ layout: component
```
-{% raw %}
-
```jsx:react
import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
import WaIcon from '@shoelace-style/shoelace/dist/react/icon';
@@ -56,8 +53,6 @@ const App = () => (
);
```
-{% endraw %}
-
## Examples
### Prefix & Suffix
@@ -86,8 +81,6 @@ Add content to the start and end of menu items using the `prefix` and `suffix` s
```
-{% raw %}
-
```jsx:react
import WaBadge from '@shoelace-style/shoelace/dist/react/badge';
import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
@@ -120,8 +113,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Disabled
Add the `disabled` attribute to disable the menu item so it cannot be selected.
@@ -134,8 +125,6 @@ Add the `disabled` attribute to disable the menu item so it cannot be selected.
```
-{% raw %}
-
```jsx:react
import WaMenu from '@shoelace-style/shoelace/dist/react/menu';
import WaMenuItem from '@shoelace-style/shoelace/dist/react/menu-item';
@@ -149,8 +138,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Loading
Use the `loading` attribute to indicate that a menu item is busy. Like a disabled menu item, clicks will be suppressed until the loading state is removed.
@@ -163,8 +150,6 @@ Use the `loading` attribute to indicate that a menu item is busy. Like a disable
```
-{% raw %}
-
```jsx:react
import WaMenu from '@shoelace-style/shoelace/dist/react/menu';
import WaMenuItem from '@shoelace-style/shoelace/dist/react/menu-item';
@@ -178,8 +163,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Checkbox Menu Items
Set the `type` attribute to `checkbox` to create a menu item that will toggle on and off when selected. You can use the `checked` attribute to set the initial state.
@@ -194,8 +177,6 @@ Checkbox menu items are visually indistinguishable from regular menu items. Thei
```
-{% raw %}
-
```jsx:react
import WaMenu from '@shoelace-style/shoelace/dist/react/menu';
import WaMenuItem from '@shoelace-style/shoelace/dist/react/menu-item';
@@ -211,8 +192,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Value & Selection
The `value` attribute can be used to assign a hidden value, such as a unique identifier, to a menu item. When an item is selected, the `wa-select` event will be emitted and a reference to the item will be available at `event.detail.item`. You can use this reference to access the selected item's value, its checked state, and more.
@@ -244,8 +223,6 @@ The `value` attribute can be used to assign a hidden value, such as a unique ide
```
-{% raw %}
-
```jsx:react
import WaMenu from '@shoelace-style/shoelace/dist/react/menu';
import WaMenuItem from '@shoelace-style/shoelace/dist/react/menu-item';
@@ -270,5 +247,3 @@ const App = () => {
);
};
```
-
-{% endraw %}
diff --git a/docs/pages/components/menu-label.md b/docs/src/content/docs/components/menu-label.md
similarity index 90%
rename from docs/pages/components/menu-label.md
rename to docs/src/content/docs/components/menu-label.md
index f5fbefcd9..610243bf1 100644
--- a/docs/pages/components/menu-label.md
+++ b/docs/src/content/docs/components/menu-label.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Menu Label
- description: Menu labels are used to describe a group of menu items.
-layout: component
+title: Menu Label
+description: Menu labels are used to describe a group of menu items.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -19,8 +18,6 @@ layout: component
```
-{% raw %}
-
```jsx:react
import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
import WaMenu from '@shoelace-style/shoelace/dist/react/menu';
@@ -41,5 +38,3 @@ const App = () => (
);
```
-
-{% endraw %}
diff --git a/docs/pages/components/menu.md b/docs/src/content/docs/components/menu.md
similarity index 96%
rename from docs/pages/components/menu.md
rename to docs/src/content/docs/components/menu.md
index 5c9657e84..45b268627 100644
--- a/docs/pages/components/menu.md
+++ b/docs/src/content/docs/components/menu.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Menu
- description: Menus provide a list of options for the user to choose from.
-layout: component
+title: Menu
+description: Menus provide a list of options for the user to choose from.
+layout: ../../../layouts/ComponentLayout.astro
---
You can use [menu items](/components/menu-item), [menu labels](/components/menu-label), and [dividers](/components/divider) to compose a menu. Menus support keyboard interactions, including type-to-select an option.
@@ -19,8 +18,6 @@ You can use [menu items](/components/menu-item), [menu labels](/components/menu-
```
-{% raw %}
-
```jsx:react
import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
import WaMenu from '@shoelace-style/shoelace/dist/react/menu';
@@ -39,8 +36,6 @@ const App = () => (
);
```
-{% endraw %}
-
:::tip
Menus are intended for system menus (dropdown menus, select menus, context menus, etc.). They should not be mistaken for navigation menus which serve a different purpose and have a different semantic meaning. If you're building navigation, use `` and `` elements instead.
:::
@@ -112,8 +107,6 @@ To create a submenu, nest an `` in any [menu item](/comp
```
-{% raw %}
-
```jsx:react
import WaDivider from '@shoelace-style/shoelace/dist/react/divider';
import WaMenu from '@shoelace-style/shoelace/dist/react/menu';
@@ -148,8 +141,6 @@ const App = () => (
);
```
-:::warning
+:::caution
As a UX best practice, avoid using more than one level of submenus when possible.
:::
-
-{% endraw %}
diff --git a/docs/pages/components/mutation-observer.md b/docs/src/content/docs/components/mutation-observer.md
similarity index 96%
rename from docs/pages/components/mutation-observer.md
rename to docs/src/content/docs/components/mutation-observer.md
index 3961fbc5a..a90d16a58 100644
--- a/docs/pages/components/mutation-observer.md
+++ b/docs/src/content/docs/components/mutation-observer.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Mutation Observer
- description: The Mutation Observer component offers a thin, declarative interface to the MutationObserver API.
-layout: component
+title: Mutation Observer
+description: The Mutation Observer component offers a thin, declarative interface to the MutationObserver API.
+layout: ../../../layouts/ComponentLayout.astro
---
The mutation observer will report changes to the content it wraps through the `wa-mutation` event. When emitted, a collection of [MutationRecord](https://developer.mozilla.org/en-US/docs/Web/API/MutationRecord) objects will be attached to `event.detail` that contains information about how it changed.
diff --git a/docs/pages/components/option.md b/docs/src/content/docs/components/option.md
similarity index 93%
rename from docs/pages/components/option.md
rename to docs/src/content/docs/components/option.md
index ebf5b510d..0921ab45b 100644
--- a/docs/pages/components/option.md
+++ b/docs/src/content/docs/components/option.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Option
- description: Options define the selectable items within various form controls such as select.
-layout: component
+title: Option
+description: Options define the selectable items within various form controls such as select.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/popup.md b/docs/src/content/docs/components/popup.md
similarity index 99%
rename from docs/pages/components/popup.md
rename to docs/src/content/docs/components/popup.md
index 55ce7a54f..143a67c5d 100644
--- a/docs/pages/components/popup.md
+++ b/docs/src/content/docs/components/popup.md
@@ -1,15 +1,14 @@
---
-meta:
- title: Popup
- description: 'Popup is a utility that lets you declaratively anchor "popup" containers to another element.'
-layout: component
+title: Popup
+description: 'Popup is a utility that lets you declaratively anchor "popup" containers to another element.'
+layout: ../../../layouts/ComponentLayout.astro
---
This component's name is inspired by [``](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md). It uses [Floating UI](https://floating-ui.com/) under the hood to provide a well-tested, lightweight, and fully declarative positioning utility for tooltips, dropdowns, and more.
Popup doesn't provide any styles ā just positioning! The popup's preferred placement, distance, and skidding (offset) can be configured using attributes. An arrow that points to the anchor can be shown and customized to your liking. Additional positioning options are available and described in more detail below.
-:::warning
+:::caution
Popup is a low-level utility built specifically for positioning elements. Do not mistake it for a [tooltip](/components/tooltip) or similar because _it does not facilitate an accessible experience!_ Almost every correct usage of `` will involve building other components. It should rarely, if ever, occur directly in your HTML.
:::
diff --git a/docs/pages/components/progress-bar.md b/docs/src/content/docs/components/progress-bar.md
similarity index 95%
rename from docs/pages/components/progress-bar.md
rename to docs/src/content/docs/components/progress-bar.md
index 3352e2386..705994e67 100644
--- a/docs/pages/components/progress-bar.md
+++ b/docs/src/content/docs/components/progress-bar.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Progress Bar
- description: Progress bars are used to show the status of an ongoing operation.
-layout: component
+title: Progress Bar
+description: Progress bars are used to show the status of an ongoing operation.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -39,16 +38,12 @@ Use the `--height` custom property to set the progress bar's height.
```
-{% raw %}
-
```jsx:react
import WaProgressBar from '@shoelace-style/shoelace/dist/react/progress-bar';
const App = () => ;
```
-{% endraw %}
-
### Showing Values
Use the default slot to show a value.
diff --git a/docs/pages/components/progress-ring.md b/docs/src/content/docs/components/progress-ring.md
similarity index 93%
rename from docs/pages/components/progress-ring.md
rename to docs/src/content/docs/components/progress-ring.md
index 826bc3af0..f941a7a85 100644
--- a/docs/pages/components/progress-ring.md
+++ b/docs/src/content/docs/components/progress-ring.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Progress Ring
- description: Progress rings are used to show the progress of a determinate operation in a circular fashion.
-layout: component
+title: Progress Ring
+description: Progress rings are used to show the progress of a determinate operation in a circular fashion.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -25,16 +24,12 @@ Use the `--size` custom property to set the diameter of the progress ring.
```
-{% raw %}
-
```jsx:react
import WaProgressRing from '@shoelace-style/shoelace/dist/react/progress-ring';
const App = () => ;
```
-{% endraw %}
-
### Track and Indicator Width
Use the `--track-width` and `--indicator-width` custom properties to set the width of the progress ring's track and indicator.
@@ -43,16 +38,12 @@ Use the `--track-width` and `--indicator-width` custom properties to set the wid
```
-{% raw %}
-
```jsx:react
import WaProgressRing from '@shoelace-style/shoelace/dist/react/progress-ring';
const App = () => ;
```
-{% endraw %}
-
### Colors
To change the color, use the `--track-color` and `--indicator-color` custom properties.
@@ -67,8 +58,6 @@ To change the color, use the `--track-color` and `--indicator-color` custom prop
>
```
-{% raw %}
-
```jsx:react
import WaProgressRing from '@shoelace-style/shoelace/dist/react/progress-ring';
@@ -83,8 +72,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Labels
Use the `label` attribute to label the progress ring and tell assistive devices how to announce it.
@@ -130,8 +117,6 @@ Use the default slot to show a label inside the progress ring.
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaButton from '@shoelace-style/shoelace/dist/react/button';
@@ -167,5 +152,3 @@ const App = () => {
);
};
```
-
-{% endraw %}
diff --git a/docs/pages/components/qr-code.md b/docs/src/content/docs/components/qr-code.md
similarity index 97%
rename from docs/pages/components/qr-code.md
rename to docs/src/content/docs/components/qr-code.md
index 76aea6f6f..b2ada35f8 100644
--- a/docs/pages/components/qr-code.md
+++ b/docs/src/content/docs/components/qr-code.md
@@ -1,8 +1,7 @@
---
-meta:
- title: QR Code
- description: Generates a QR code and renders it using the Canvas API.
-layout: component
+title: QR Code
+description: Generates a QR code and renders it using the Canvas API.
+layout: ../../../layouts/ComponentLayout.astro
---
QR codes are useful for providing small pieces of information to users who can quickly scan them with a smartphone. Most smartphones have built-in QR code scanners, so simply pointing the camera at a QR code will decode it and allow the user to visit a website, dial a phone number, read a message, etc.
diff --git a/docs/pages/components/radio-button.md b/docs/src/content/docs/components/radio-button.md
similarity index 98%
rename from docs/pages/components/radio-button.md
rename to docs/src/content/docs/components/radio-button.md
index f25071839..5b8c32930 100644
--- a/docs/pages/components/radio-button.md
+++ b/docs/src/content/docs/components/radio-button.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Radio Button
- description: Radios buttons allow the user to select a single option from a group using a button-like control.
-layout: component
+title: Radio Button
+description: Radios buttons allow the user to select a single option from a group using a button-like control.
+layout: ../../../layouts/ComponentLayout.astro
---
Radio buttons are designed to be used with [radio groups](/components/radio-group). When a radio button has focus, the arrow keys can be used to change the selected option just like standard radio controls.
diff --git a/docs/pages/components/radio-group.md b/docs/src/content/docs/components/radio-group.md
similarity index 97%
rename from docs/pages/components/radio-group.md
rename to docs/src/content/docs/components/radio-group.md
index 783181ab3..e672fe30e 100644
--- a/docs/pages/components/radio-group.md
+++ b/docs/src/content/docs/components/radio-group.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Radio Group
- description: Radio groups are used to group multiple radios or radio buttons so they function as a single form control.
-layout: component
+title: Radio Group
+description: Radio groups are used to group multiple radios or radio buttons so they function as a single form control.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/radio.md b/docs/src/content/docs/components/radio.md
similarity index 96%
rename from docs/pages/components/radio.md
rename to docs/src/content/docs/components/radio.md
index ca5fb3889..307db7b62 100644
--- a/docs/pages/components/radio.md
+++ b/docs/src/content/docs/components/radio.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Radio
- description: Radios allow the user to select a single option from a group.
-layout: component
+title: Radio
+description: Radios allow the user to select a single option from a group.
+layout: ../../../layouts/ComponentLayout.astro
---
Radios are designed to be used with [radio groups](/components/radio-group).
diff --git a/docs/pages/components/range.md b/docs/src/content/docs/components/range.md
similarity index 95%
rename from docs/pages/components/range.md
rename to docs/src/content/docs/components/range.md
index 718ca5e5b..a0ba92b0b 100644
--- a/docs/pages/components/range.md
+++ b/docs/src/content/docs/components/range.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Range
- description: Ranges allow the user to select a single value within a given range using a slider.
-layout: component
+title: Range
+description: Ranges allow the user to select a single value within a given range using a slider.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -118,8 +117,6 @@ You can customize the active and inactive portions of the track using the `--tra
>
```
-{% raw %}
-
```jsx:react
import WaRange from '@shoelace-style/shoelace/dist/react/range';
@@ -133,8 +130,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Custom Track Offset
You can customize the initial offset of the active track using the `--track-active-offset` custom property.
@@ -151,8 +146,6 @@ You can customize the initial offset of the active track using the `--track-acti
>
```
-{% raw %}
-
```jsx:react
import WaRange from '@shoelace-style/shoelace/dist/react/range';
@@ -169,8 +162,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Custom Tooltip Formatter
You can change the tooltip's content by setting the `tooltipFormatter` property to a function that accepts the range's value as an argument.
diff --git a/docs/pages/components/rating.md b/docs/src/content/docs/components/rating.md
similarity index 97%
rename from docs/pages/components/rating.md
rename to docs/src/content/docs/components/rating.md
index 2b014d6ac..c693394bf 100644
--- a/docs/pages/components/rating.md
+++ b/docs/src/content/docs/components/rating.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Rating
- description: Ratings give users a way to quickly view and provide feedback.
-layout: component
+title: Rating
+description: Ratings give users a way to quickly view and provide feedback.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -67,16 +66,12 @@ Set the `--symbol-size` custom property to adjust the size.
```
-{% raw %}
-
```jsx:react
import WaRating from '@shoelace-style/shoelace/dist/react/rating';
const App = () => ;
```
-{% endraw %}
-
### Readonly
Use the `readonly` attribute to display a rating that users can't change.
@@ -211,8 +206,6 @@ You can provide custom icons by passing a function to the `getSymbol` property.
```
-{% raw %}
-
```jsx:react
import WaRating from '@shoelace-style/shoelace/dist/react/rating';
@@ -225,8 +218,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Value-based Icons
You can also use the `getSymbol` property to render different icons based on value.
diff --git a/docs/pages/components/relative-time.md b/docs/src/content/docs/components/relative-time.md
similarity index 96%
rename from docs/pages/components/relative-time.md
rename to docs/src/content/docs/components/relative-time.md
index 673bca980..f3db1a902 100644
--- a/docs/pages/components/relative-time.md
+++ b/docs/src/content/docs/components/relative-time.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Relative Time
- description: Outputs a localized time phrase relative to the current date and time.
-layout: component
+title: Relative Time
+description: Outputs a localized time phrase relative to the current date and time.
+layout: ../../../layouts/ComponentLayout.astro
---
Localization is handled by the browser's [`Intl.RelativeTimeFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat). No language packs are required.
diff --git a/docs/pages/components/resize-observer.md b/docs/src/content/docs/components/resize-observer.md
similarity index 90%
rename from docs/pages/components/resize-observer.md
rename to docs/src/content/docs/components/resize-observer.md
index 18486dcf1..bc361cd68 100644
--- a/docs/pages/components/resize-observer.md
+++ b/docs/src/content/docs/components/resize-observer.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Resize Observer
- description: The Resize Observer component offers a thin, declarative interface to the ResizeObserver API.
-layout: component
+title: Resize Observer
+description: The Resize Observer component offers a thin, declarative interface to the ResizeObserver API.
+layout: ../../../layouts/ComponentLayout.astro
---
The resize observer will report changes to the dimensions of the elements it wraps through the `wa-resize` event. When emitted, a collection of [`ResizeObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry) objects will be attached to `event.detail` that contains the target element and information about its dimensions.
diff --git a/docs/pages/components/select.md b/docs/src/content/docs/components/select.md
similarity index 99%
rename from docs/pages/components/select.md
rename to docs/src/content/docs/components/select.md
index 4f1f70bb9..c546c1b54 100644
--- a/docs/pages/components/select.md
+++ b/docs/src/content/docs/components/select.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Select
- description: Selects allow you to choose items from a menu of predefined options.
-layout: component
+title: Select
+description: Selects allow you to choose items from a menu of predefined options.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -499,6 +498,6 @@ Remember that custom tags are rendered in a shadow root. To style them, you can
```
-:::warning
+:::caution
Be sure you trust the content you are outputting! Passing unsanitized user input to `getTag()` can result in XSS vulnerabilities.
:::
diff --git a/docs/pages/components/skeleton.md b/docs/src/content/docs/components/skeleton.md
similarity index 98%
rename from docs/pages/components/skeleton.md
rename to docs/src/content/docs/components/skeleton.md
index 9610188ad..fcbb92fce 100644
--- a/docs/pages/components/skeleton.md
+++ b/docs/src/content/docs/components/skeleton.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Skeleton
- description: Skeletons are used to provide a visual representation of where content will eventually be drawn.
-layout: component
+title: Skeleton
+description: Skeletons are used to provide a visual representation of where content will eventually be drawn.
+layout: ../../../layouts/ComponentLayout.astro
---
These are simple containers for scaffolding layouts that mimic what users will see when content has finished loading. This prevents large areas of empty space during asynchronous operations.
@@ -420,8 +419,6 @@ Set the `--color` and `--sheen-color` custom properties to adjust the skeleton's
```
-{% raw %}
-
```jsx:react
import WaSkeleton from '@shoelace-style/shoelace/dist/react/skeleton';
@@ -444,5 +441,3 @@ const css = `
const App = () => ;
```
-
-{% endraw %}
diff --git a/docs/pages/components/spinner.md b/docs/src/content/docs/components/spinner.md
similarity index 89%
rename from docs/pages/components/spinner.md
rename to docs/src/content/docs/components/spinner.md
index 530190dea..350b03fc5 100644
--- a/docs/pages/components/spinner.md
+++ b/docs/src/content/docs/components/spinner.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Spinner
- description: Spinners are used to show the progress of an indeterminate operation.
-layout: component
+title: Spinner
+description: Spinners are used to show the progress of an indeterminate operation.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -27,8 +26,6 @@ Spinners are sized based on the current font size. To change their size, set the
```
-{% raw %}
-
```jsx:react
import WaSpinner from '@shoelace-style/shoelace/dist/react/spinner';
@@ -41,8 +38,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Track Width
The width of the spinner's track can be changed by setting the `--track-width` custom property.
@@ -51,8 +46,6 @@ The width of the spinner's track can be changed by setting the `--track-width` c
```
-{% raw %}
-
```jsx:react
import WaSpinner from '@shoelace-style/shoelace/dist/react/spinner';
@@ -66,8 +59,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Color
The spinner's colors can be changed by setting the `--indicator-color` and `--track-color` custom properties.
@@ -76,8 +67,6 @@ The spinner's colors can be changed by setting the `--indicator-color` and `--tr
```
-{% raw %}
-
```jsx:react
import WaSpinner from '@shoelace-style/shoelace/dist/react/spinner';
@@ -91,5 +80,3 @@ const App = () => (
/>
);
```
-
-{% endraw %}
diff --git a/docs/pages/components/split-panel.md b/docs/src/content/docs/components/split-panel.md
similarity index 98%
rename from docs/pages/components/split-panel.md
rename to docs/src/content/docs/components/split-panel.md
index cf3ff3862..865dc8b5a 100644
--- a/docs/pages/components/split-panel.md
+++ b/docs/src/content/docs/components/split-panel.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Split Panel
- description: Split panels display two adjacent panels, allowing the user to reposition them.
-layout: component
+title: Split Panel
+description: Split panels display two adjacent panels, allowing the user to reposition them.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -22,8 +21,6 @@ layout: component
```
-{% raw %}
-
```jsx:react
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
@@ -57,8 +54,6 @@ const App = () => (
);
```
-{% endraw %}
-
## Examples
### Initial Position
@@ -117,8 +112,6 @@ To set the initial position in pixels instead of a percentage, use the `position
```
-{% raw %}
-
```jsx:react
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
@@ -152,8 +145,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Vertical
Add the `vertical` attribute to render the split panel in a vertical orientation where the start and end panels are stacked. You also need to set a height when using the vertical orientation.
@@ -175,8 +166,6 @@ Add the `vertical` attribute to render the split panel in a vertical orientation
```
-{% raw %}
-
```jsx:react
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
@@ -210,8 +199,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Snapping
To snap panels at specific positions while dragging, add the `snap` attribute with one or more space-separated values. Values must be in pixels or percentages. For example, to snap the panel at `100px` and `50%`, use `snap="100px 50%"`. You can also customize how close the divider must be before snapping with the `snap-threshold` attribute.
@@ -263,8 +250,6 @@ To snap panels at specific positions while dragging, add the `snap` attribute wi
```
-{% raw %}
-
```jsx:react
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
@@ -332,8 +317,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Disabled
Add the `disabled` attribute to prevent the divider from being repositioned.
@@ -355,8 +338,6 @@ Add the `disabled` attribute to prevent the divider from being repositioned.
```
-{% raw %}
-
```jsx:react
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
@@ -390,8 +371,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Setting the Primary Panel
By default, both panels will grow or shrink proportionally when the host element is resized. If a primary panel is designated, it will maintain its size and the secondary panel will grow or shrink to fit the remaining space. You can set the primary panel to `start` or `end` using the `primary` attribute.
@@ -431,8 +410,6 @@ Try resizing the example below with each option and notice how the panels respon
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
@@ -486,8 +463,6 @@ const App = () => {
};
```
-{% endraw %}
-
### Min & Max
To set a minimum or maximum size of the primary panel, use the `--min` and `--max` custom properties. Since the secondary panel is flexible, size constraints can only be applied to the primary panel. If no primary panel is designated, these constraints will be applied to the `start` panel.
@@ -511,8 +486,6 @@ This examples demonstrates how you can ensure both panels are at least 150px usi
```
-{% raw %}
-
```jsx:react
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
@@ -546,8 +519,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Nested Split Panels
Create complex layouts that can be repositioned independently by nesting split panels.
@@ -579,8 +550,6 @@ Create complex layouts that can be repositioned independently by nesting split p
```
-{% raw %}
-
```jsx:react
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
@@ -630,8 +599,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Customizing the Divider
You can target the `divider` part to apply CSS properties to the divider. To add a custom handle, slot an icon into the `divider` slot. When customizing the divider, make sure to think about focus styles for keyboard users.
@@ -668,8 +635,6 @@ You can target the `divider` part to apply CSS properties to the divider. To add
```
-{% raw %}
-
```jsx:react
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
import WaIcon from '@shoelace-style/shoelace/dist/react/icon';
@@ -705,8 +670,6 @@ const App = () => (
);
```
-{% endraw %}
-
Here's a more elaborate example that changes the divider's color and width and adds a styled handle.
```html:preview
@@ -770,8 +733,6 @@ Here's a more elaborate example that changes the divider's color and width and a
```
-{% raw %}
-
```jsx:react
import WaSplitPanel from '@shoelace-style/shoelace/dist/react/split-panel';
import WaIcon from '@shoelace-style/shoelace/dist/react/icon';
@@ -839,5 +800,3 @@ const App = () => (
>
);
```
-
-{% endraw %}
diff --git a/docs/pages/components/switch.md b/docs/src/content/docs/components/switch.md
similarity index 93%
rename from docs/pages/components/switch.md
rename to docs/src/content/docs/components/switch.md
index 9adc13325..19b8f7b0a 100644
--- a/docs/pages/components/switch.md
+++ b/docs/src/content/docs/components/switch.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Switch
- description: Switches allow the user to toggle an option on or off.
-layout: component
+title: Switch
+description: Switches allow the user to toggle an option on or off.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -83,8 +82,6 @@ Use the available custom properties to change how the switch is styled.
Really big
```
-{% raw %}
-
```jsx:react
import WaSwitch from '@shoelace-style/shoelace/dist/react/switch';
@@ -98,5 +95,3 @@ const App = () => (
/>
);
```
-
-{% endraw %}
diff --git a/docs/pages/components/tab-group.md b/docs/src/content/docs/components/tab-group.md
similarity index 99%
rename from docs/pages/components/tab-group.md
rename to docs/src/content/docs/components/tab-group.md
index 32dd6ad06..9eedc4c2f 100644
--- a/docs/pages/components/tab-group.md
+++ b/docs/src/content/docs/components/tab-group.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Tab Group
- description: Tab groups organize content into a container that shows one section at a time.
-layout: component
+title: Tab Group
+description: Tab groups organize content into a container that shows one section at a time.
+layout: ../../../layouts/ComponentLayout.astro
---
Tab groups make use of [tabs](/components/tab) and [tab panels](/components/tab-panel). Each tab must be slotted into the `nav` slot and its `panel` must refer to a tab panel of the same name.
diff --git a/docs/pages/components/tab-panel.md b/docs/src/content/docs/components/tab-panel.md
similarity index 91%
rename from docs/pages/components/tab-panel.md
rename to docs/src/content/docs/components/tab-panel.md
index 828ae15f9..27950d416 100644
--- a/docs/pages/components/tab-panel.md
+++ b/docs/src/content/docs/components/tab-panel.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Tab Panel
- description: Tab panels are used inside tab groups to display tabbed content.
-layout: component
+title: Tab Panel
+description: Tab panels are used inside tab groups to display tabbed content.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/tab.md b/docs/src/content/docs/components/tab.md
similarity index 77%
rename from docs/pages/components/tab.md
rename to docs/src/content/docs/components/tab.md
index 8b265ef07..b43fba249 100644
--- a/docs/pages/components/tab.md
+++ b/docs/src/content/docs/components/tab.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Tab
- description: Tabs are used inside tab groups to represent and activate tab panels.
-layout: component
+title: Tab
+description: Tabs are used inside tab groups to represent and activate tab panels.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/tag.md b/docs/src/content/docs/components/tag.md
similarity index 95%
rename from docs/pages/components/tag.md
rename to docs/src/content/docs/components/tag.md
index 71fa83e50..c1222d952 100644
--- a/docs/pages/components/tag.md
+++ b/docs/src/content/docs/components/tag.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Tag
- description: Tags are used as labels to organize things or to indicate a selection.
-layout: component
+title: Tag
+description: Tags are used as labels to organize things or to indicate a selection.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/textarea.md b/docs/src/content/docs/components/textarea.md
similarity index 96%
rename from docs/pages/components/textarea.md
rename to docs/src/content/docs/components/textarea.md
index b5e5c7bf6..a5091b349 100644
--- a/docs/pages/components/textarea.md
+++ b/docs/src/content/docs/components/textarea.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Textarea
- description: Textareas collect data from the user and allow multiple lines of text.
-layout: component
+title: Textarea
+description: Textareas collect data from the user and allow multiple lines of text.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/tooltip.md b/docs/src/content/docs/components/tooltip.md
similarity index 98%
rename from docs/pages/components/tooltip.md
rename to docs/src/content/docs/components/tooltip.md
index 79046998c..e3cc12186 100644
--- a/docs/pages/components/tooltip.md
+++ b/docs/src/content/docs/components/tooltip.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Tooltip
- description: Tooltips display additional information based on a specific action.
-layout: component
+title: Tooltip
+description: Tooltips display additional information based on a specific action.
+layout: ../../../layouts/ComponentLayout.astro
---
A tooltip's target is its _first child element_, so you should only wrap one element inside of the tooltip. If you need the tooltip to show up for multiple elements, nest them inside a container first.
@@ -266,8 +265,6 @@ Tooltips can be controller programmatically by setting the `trigger` attribute t
```
-{% raw %}
-
```jsx:react
import { useState } from 'react';
import WaAvatar from '@shoelace-style/shoelace/dist/react/avatar';
@@ -291,8 +288,6 @@ const App = () => {
};
```
-{% endraw %}
-
### Removing Arrows
You can control the size of tooltip arrows by overriding the `--wa-tooltip-arrow-size` design token. To remove them, set the value to `0` as shown below.
@@ -303,8 +298,6 @@ You can control the size of tooltip arrows by overriding the `--wa-tooltip-arrow
```
-{% raw %}
-
```jsx:react
import WaButton from '@shoelace-style/shoelace/dist/react/button';
import WaTooltip from '@shoelace-style/shoelace/dist/react/tooltip';
@@ -322,8 +315,6 @@ const App = () => (
);
```
-{% endraw %}
-
To override it globally, set it in a root block in your stylesheet after the Web Awesome stylesheet is loaded.
```css
@@ -369,8 +360,6 @@ Use the `--max-width` custom property to change the width the tooltip can grow t
```
-{% raw %}
-
```jsx:react
import WaButton from '@shoelace-style/shoelace/dist/react/button';
import WaTooltip from '@shoelace-style/shoelace/dist/react/tooltip';
@@ -382,8 +371,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Hoisting
Tooltips will be clipped if they're inside a container that has `overflow: auto|hidden|scroll`. The `hoist` attribute forces the tooltip to use a fixed positioning strategy, allowing it to break out of the container. In this case, the tooltip will be positioned relative to its [containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#Identifying_the_containing_block), which is usually the viewport unless an ancestor uses a `transform`, `perspective`, or `filter`. [Refer to this page](https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed) for more details.
diff --git a/docs/pages/components/tree-item.md b/docs/src/content/docs/components/tree-item.md
similarity index 96%
rename from docs/pages/components/tree-item.md
rename to docs/src/content/docs/components/tree-item.md
index 02aedd7d0..90031edfc 100644
--- a/docs/pages/components/tree-item.md
+++ b/docs/src/content/docs/components/tree-item.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Tree Item
- description: A tree item serves as a hierarchical node that lives inside a tree.
-layout: component
+title: Tree Item
+description: A tree item serves as a hierarchical node that lives inside a tree.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
diff --git a/docs/pages/components/tree.md b/docs/src/content/docs/components/tree.md
similarity index 98%
rename from docs/pages/components/tree.md
rename to docs/src/content/docs/components/tree.md
index 670a65613..88d448933 100644
--- a/docs/pages/components/tree.md
+++ b/docs/src/content/docs/components/tree.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Tree
- description: Trees allow you to display a hierarchical list of selectable tree items. Items with children can be expanded and collapsed as desired by the user.
-layout: component
+title: Tree
+description: Trees allow you to display a hierarchical list of selectable tree items. Items with children can be expanded and collapsed as desired by the user.
+layout: ../../../layouts/ComponentLayout.astro
---
```html:preview
@@ -195,8 +194,6 @@ Indent guides can be drawn by setting `--indent-guide-width`. You can also chang
```
-{% raw %}
-
```jsx:react
import WaTree from '@shoelace-style/shoelace/dist/react/tree';
@@ -233,8 +230,6 @@ const App = () => (
);
```
-{% endraw %}
-
### Lazy Loading
Use the `lazy` attribute on a tree item to indicate that the content is not yet present and will be loaded later. When the user tries to expand the node, the `loading` state is set to `true` and the `wa-lazy-load` event will be emitted to allow you to load data asynchronously. The item will remain in a loading state until its content is changed.
diff --git a/docs/pages/components/visually-hidden.md b/docs/src/content/docs/components/visually-hidden.md
similarity index 90%
rename from docs/pages/components/visually-hidden.md
rename to docs/src/content/docs/components/visually-hidden.md
index ffea0e38b..2cf2fb345 100644
--- a/docs/pages/components/visually-hidden.md
+++ b/docs/src/content/docs/components/visually-hidden.md
@@ -1,8 +1,7 @@
---
-meta:
- title: Visually Hidden
- description: The visually hidden utility makes content accessible to assistive devices without displaying it on the screen.
-layout: component
+title: Visually Hidden
+description: The visually hidden utility makes content accessible to assistive devices without displaying it on the screen.
+layout: ../../../layouts/ComponentLayout.astro
---
According to [The A11Y Project](https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/), "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."
diff --git a/docs/pages/experimental/form-validation.md b/docs/src/content/docs/experimental/form-validation.md
similarity index 96%
rename from docs/pages/experimental/form-validation.md
rename to docs/src/content/docs/experimental/form-validation.md
index b7ac9c285..97452b5f7 100644
--- a/docs/pages/experimental/form-validation.md
+++ b/docs/src/content/docs/experimental/form-validation.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Form Control Validation
- description: TODO
+title: Form Control Validation
+description: TODO
---
-# Form Control Validation
-
Adding the `wa-valid` or `wa-invalid` class to a form control will change its appearance. This is useful for applying validation styles to server-rendered form controls.
diff --git a/docs/pages/experimental/sandbox.md b/docs/src/content/docs/experimental/sandbox.md
similarity index 96%
rename from docs/pages/experimental/sandbox.md
rename to docs/src/content/docs/experimental/sandbox.md
index adced0d9f..edd0bf2fd 100644
--- a/docs/pages/experimental/sandbox.md
+++ b/docs/src/content/docs/experimental/sandbox.md
@@ -1,12 +1,9 @@
---
-meta:
- title: Theming Sandbox
- description: TODO
+title: Theming Sandbox
+description: TODO
---
-# Theming Sandbox
-
-#### Card
+## Card
```html:preview
@@ -43,7 +40,7 @@ meta:
```
-#### Alerts
+## Alerts
```html:preview
@@ -77,7 +74,7 @@ meta:
```
-#### Badges and Tags
+## Badges and Tags
```html:preview
Brand
@@ -93,7 +90,7 @@ meta:
Danger
```
-#### Buttons
+## Buttons
```html:preview
Brand
@@ -111,7 +108,7 @@ meta:
Brand
```
-#### Form controls
+## Form controls
```html:preview
Unchecked
@@ -140,7 +137,7 @@ meta:
```
-#### Progress
+## Progress
```html:preview
@@ -148,7 +145,7 @@ meta:
```
-#### Shadows
+## Shadows
```html:preview
```
-:::warning
+:::caution
This example is meant to demonstrate the concept of providing your own error messages inline. It is not intended to scale to more complex forms. Users who want this functionality are encouraged to build a more appropriate validation solution using the techniques shown below. Depending on how you implement this feature, custom error messages may affect the accessibility of your form controls.
:::
diff --git a/docs/pages/getting-started/installation.md b/docs/src/content/docs/getting-started/installation.md
similarity index 98%
rename from docs/pages/getting-started/installation.md
rename to docs/src/content/docs/getting-started/installation.md
index 9d2aceb10..e9655dd4f 100644
--- a/docs/pages/getting-started/installation.md
+++ b/docs/src/content/docs/getting-started/installation.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Installation
- description: Choose the installation method that works best for you.
+title: Installation
+description: Choose the installation method that works best for you.
---
-# Installation
-
You can load Web Awesome via CDN or by installing it locally. If you're using a framework, make sure to check out the pages for [React](/frameworks/react), [Vue](/frameworks/vue), and [Angular](/frameworks/angular) for additional information.
## CDN Installation (Easiest)
@@ -153,7 +150,7 @@ Here's an example that loads only the button component. Again, if you're not usi
You can copy and paste the code to import a component from the "Importing" section of the component's documentation. Note that some components have dependencies that are automatically imported when you cherry pick. If a component has dependencies, they will be listed in the "Dependencies" section of its docs.
-:::warning
+:::caution
You will see files named `chunk.[hash].js` in the `chunks` directory. Never import these files directly, as they are generated and change from version to version.
:::
@@ -188,7 +185,7 @@ setBasePath('/path/to/shoelace/%NPMDIR%');
// , , , and are ready to use!
```
-:::warning
+:::caution
Component modules include side effects for registration purposes. Because of this, importing directly from `@shoelace-style/shoelace` may result in a larger bundle size than necessary. For optimal tree shaking, always cherry pick, i.e. import components and utilities from their respective files, as shown above.
:::
diff --git a/docs/pages/getting-started/localization.md b/docs/src/content/docs/getting-started/localization.md
similarity index 97%
rename from docs/pages/getting-started/localization.md
rename to docs/src/content/docs/getting-started/localization.md
index 1ba29d497..62587f39c 100644
--- a/docs/pages/getting-started/localization.md
+++ b/docs/src/content/docs/getting-started/localization.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Localization
- description: Discover how to localize Web Awesome with minimal effort.
+title: Localization
+description: Discover how to localize Web Awesome with minimal effort.
---
-# Localization
-
Components can be localized by importing the appropriate translation file and setting the desired [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) and/or [`dir` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir) on the `` element. Here's an example that renders Web Awesome components in Spanish.
```html
diff --git a/docs/pages/getting-started/themes.md b/docs/src/content/docs/getting-started/themes.md
similarity index 97%
rename from docs/pages/getting-started/themes.md
rename to docs/src/content/docs/getting-started/themes.md
index 11132aaf9..7e52113fc 100644
--- a/docs/pages/getting-started/themes.md
+++ b/docs/src/content/docs/getting-started/themes.md
@@ -1,17 +1,14 @@
---
-meta:
- title: Themes
- description: Everything you need to know about theming Web Awesome.
+title: Themes
+description: Everything you need to know about theming Web Awesome.
---
-# Themes
-
Web Awesome is designed to be highly customizable through pure CSS. Out of the box, you can choose from a light or dark theme. Alternatively, you can design your own theme.
A theme is nothing more than a stylesheet that uses the Web Awesome API to define design tokens and apply custom styles to components. To create a theme, you will need a decent understanding of CSS, including [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) and the [`::part` selector](https://developer.mozilla.org/en-US/docs/Web/CSS/::part).
:::tip
-For component developers, built-in themes are also available as JavaScript modules that export [Lit CSSResult](https://lit.dev/docs/api/styles/#CSSResult) objects. You can find them in `%NPMDIR%/themes/*.styles.js`.
+For component developers, built-in themes are also available as JavaScript modules that export [Lit CSSResult](https://lit.dev/docs/api/styles/#CSSResult) objects. You can find them in `/%NPMDIR%/themes/*.styles.js`.
:::
## Theme Basics
diff --git a/docs/pages/getting-started/usage.md b/docs/src/content/docs/getting-started/usage.md
similarity index 99%
rename from docs/pages/getting-started/usage.md
rename to docs/src/content/docs/getting-started/usage.md
index 94d19b14a..b1ba8a8e4 100644
--- a/docs/pages/getting-started/usage.md
+++ b/docs/src/content/docs/getting-started/usage.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Usage
- description: Learn more about using custom elements.
+title: Usage
+description: Learn more about using custom elements.
---
-# Usage
-
Web Awesome components are just regular HTML elements, or [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) to be precise. You can use them like any other element. Each component has detailed documentation that describes its full API, including properties, events, methods, and more.
If you're new to custom elements, often referred to as "web components," this section will familiarize you with how to use them.
diff --git a/docs/pages/index.md b/docs/src/content/docs/index.mdx
similarity index 88%
rename from docs/pages/index.md
rename to docs/src/content/docs/index.mdx
index 061391146..69a47821b 100644
--- a/docs/pages/index.md
+++ b/docs/src/content/docs/index.mdx
@@ -1,13 +1,16 @@
---
-meta:
- title: 'Web Awesome: A forward-thinking library of web components.'
- description: Hand-crafted custom elements for any occasion.
-toc: false
+title: 'Web Awesome: A forward-thinking library of web components.'
+description: Hand-crafted custom elements for any occasion.
---
+import Logo from '../../components/Logo.astro';
+
-
-{% include 'logo.njk' %}
+
+
+
+
+
# Web Awesome:
@@ -22,16 +25,19 @@ toc: false
- [More awesome than ever](https://blog.fontawesome.com/shoelace-joins-font-awesome/) 
-
-
-
+
+
-
[](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace)
[](https://www.npmjs.com/package/@shoelace-style/shoelace)
-[](https://github.com/shoelace-style/shoelace/blob/next/LICENSE.md)
+[](https://github.com/shoelace-style/shoelace/blob/next/LICENSE.md)
+
[](https://discord.gg/mg8f26C)
[](https://twitter.com/shoelace_style)
@@ -41,10 +47,15 @@ toc: false
Add the following code to your page.
-
```html
-
-
+
+
```
Now you have access to all of Web Awesome's components! Try adding a button:
@@ -93,11 +104,11 @@ Whether you use Web Awesome as a starting point for your organization's design s
Web Awesome is tested in the latest two versions of the following browsers.
-
-
-
-
-
+
+
+
+
+
Critical bug fixes in earlier versions will be addressed based on their severity and impact.
diff --git a/docs/pages/resources/accessibility.md b/docs/src/content/docs/resources/accessibility.md
similarity index 92%
rename from docs/pages/resources/accessibility.md
rename to docs/src/content/docs/resources/accessibility.md
index 2a0a12d04..ede6b5960 100644
--- a/docs/pages/resources/accessibility.md
+++ b/docs/src/content/docs/resources/accessibility.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Accessibility Commitment
- description: Web Awesome recognizes the need for all users to have undeterred access to the websites and applications that are created with it.
+title: Accessibility Commitment
+description: Web Awesome recognizes the need for all users to have undeterred access to the websites and applications that are created with it.
---
-# Accessibility Commitment
-
Web Awesome recognizes the need for all users, regardless of ability and device, to have undeterred access to the websites and applications that are created with it. This is an important goal of the project.
Oftentimes, people will ask āis Web Awesome accessible?ā Iām reluctant to answer because accessibility isnāt binary ā thereās no simple āyesā or ānoā response to provide. What seems accessible to a sighted user might be completely inaccessible to a non-sighted user. And even if you optimize for various screen readers, you still have to account for low-level vision, color blindness, hearing impairments, mobility impairments, and more.
diff --git a/docs/pages/resources/changelog.md b/docs/src/content/docs/resources/changelog.md
similarity index 99%
rename from docs/pages/resources/changelog.md
rename to docs/src/content/docs/resources/changelog.md
index baff1dd55..898b30c46 100644
--- a/docs/pages/resources/changelog.md
+++ b/docs/src/content/docs/resources/changelog.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Changelog
- description: Changes to each version of the project are documented here.
+title: Changelog
+description: Changes to each version of the project are documented here.
---
-# Changelog
-
Web Awesome follows [Semantic Versioning](https://semver.org/). Breaking changes in components with the
Stable badge will not be accepted until the next major version. As such, all contributions must consider the project's roadmap and take this into consideration. Features that are deemed no longer necessary will be deprecated but not removed.
Components with the
Experimental badge should not be used in production. They are made available as release candidates for development and testing purposes. As such, changes to experimental components will not be subject to semantic versioning.
@@ -161,7 +158,7 @@ This release [unbundles Lit](https://github.com/shoelace-style/shoelace/issues/5
1. `cdn/` āĀ a bundled, CDN-ready distribution
2. `dist/` ā an unbundled, npm-ready distribution
-:::warning
+:::caution
If you're a CDN user, you must update your path to point to `cdn/` instead of `dist/`. You can copy and paste the latest paths from the [installation page](/getting-started/installation).
:::
@@ -1333,7 +1330,7 @@ From now on, importing a component will register it automatically. The caveat is
This change in tooling addresses a number of longstanding bugs and limitations. It also gives us more control over the library and build process while streamlining development and maintenance. Instead of two different distributions, Web Awesome now offers a single, standards-compliant collection of ES modules. This may affect how you install and use the library, so please refer to the [installation page](/getting-started/installation) for details.
-:::warning
+:::caution
Due to the large number of internal changes, I would consider this update to be less stable than previous ones. If you're using Web Awesome in a production app, consider holding off until the next beta to allow for more exhaustive testing from the community. Please report any bugs you find on the [issue tracker](https://github.com/shoelace-style/shoelace/issues).
:::
diff --git a/docs/pages/resources/community.md b/docs/src/content/docs/resources/community.md
similarity index 93%
rename from docs/pages/resources/community.md
rename to docs/src/content/docs/resources/community.md
index 2c2ca75fc..7658db794 100644
--- a/docs/pages/resources/community.md
+++ b/docs/src/content/docs/resources/community.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Community
- description: Web Awesome has a growing community of designers and developers that are building amazing things with web components.
+title: Community
+description: Web Awesome has a growing community of designers and developers that are building amazing things with web components.
---
-# Community
-
Web Awesome has a growing community of designers and developers that are building amazing things with web components. We'd love for you to become a part of it!
Please be respectful of other users and remember that Web Awesome is an open source project. We'll try to help when we can, but there's no guarantee we'll be able solve your problem. Please manage your expectations and don't forget to contribute back to the conversation when you can!
diff --git a/docs/pages/resources/contributing.md b/docs/src/content/docs/resources/contributing.md
similarity index 98%
rename from docs/pages/resources/contributing.md
rename to docs/src/content/docs/resources/contributing.md
index 8d2a0311c..72a5f1baa 100644
--- a/docs/pages/resources/contributing.md
+++ b/docs/src/content/docs/resources/contributing.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Contributing
- description: Web Awesome is an open source project, meaning everyone can use it and contribute to its development.
+title: Contributing
+description: Web Awesome is an open source project, meaning everyone can use it and contribute to its development.
---
-# Contributing
-
Web Awesome is an open source project, meaning everyone can use it and contribute to its development. When you join our community, you'll find a friendly group of enthusiasts at all experience levels who are willing to chat about anything and everything related to Web Awesome.
The easiest way to get started contributing is to join the [community chat](https://discord.gg/mg8f26C). This is where we hang out, discuss new ideas, ask for feedback, and more!
@@ -200,8 +197,8 @@ Special callouts can be added using the following syntax.
This is a tip/informational callout
:::
-:::warning
-This is a warning callout
+:::caution
+This is a caution callout
:::
:::danger
@@ -209,26 +206,6 @@ This is a danger callout
:::
```
-#### Asides
-
-To place content that's indirectly related, use the following syntax.
-
-```
-:::aside
-This content is indirectly related and will appear in an `
` element.
-:::
-```
-
-#### Details
-
-To provide additional details that can be expanded/collapses, use the following syntax.
-
-```
-:::details Title Here
-The details here are expandable.
-:::
-```
-
#### GitHub Issues
To link to a GitHub issue, PR, or discussion, use the following syntax.
diff --git a/docs/pages/tokens/borders.md b/docs/src/content/docs/tokens/borders.md
similarity index 95%
rename from docs/pages/tokens/borders.md
rename to docs/src/content/docs/tokens/borders.md
index 9c08f8929..417890dec 100644
--- a/docs/pages/tokens/borders.md
+++ b/docs/src/content/docs/tokens/borders.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Border Tokens
- description: Border tokens are used to control borders and corners.
+title: Border Tokens
+description: Border tokens are used to control borders and corners.
---
-# Border Tokens
-
Border radius tokens are used to give sharp edges a more subtle, rounded effect. They use rem units so they scale with the base font size. The pixel values displayed are based on a 16px font size.
| Token | Value | Example |
diff --git a/docs/pages/tokens/color.md b/docs/src/content/docs/tokens/color.md
similarity index 98%
rename from docs/pages/tokens/color.md
rename to docs/src/content/docs/tokens/color.md
index 859a92bae..543b74379 100644
--- a/docs/pages/tokens/color.md
+++ b/docs/src/content/docs/tokens/color.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Color Tokens
- description: Color tokens help maintain consistent use of color throughout your app.
+title: Color Tokens
+description: Color tokens help maintain consistent use of color throughout your app.
---
-# Color Tokens
-
Color tokens help maintain consistent use of color throughout your app. Web Awesome provides palettes for theme colors and primitives that you can use as a foundation for your design system.
Color tokens are referenced using the `--wa-color-{name}-{n}` CSS custom property, where `{name}` is the name of the palette and `{n}` is the numeric value of the desired swatch.
diff --git a/docs/pages/tokens/more.md b/docs/src/content/docs/tokens/more.md
similarity index 92%
rename from docs/pages/tokens/more.md
rename to docs/src/content/docs/tokens/more.md
index ab80bc0a7..c3a071a69 100644
--- a/docs/pages/tokens/more.md
+++ b/docs/src/content/docs/tokens/more.md
@@ -1,11 +1,8 @@
---
-meta:
- title: More Design Tokens
- description: Additional design tokens can be found here.
+title: More Design Tokens
+description: Additional design tokens can be found here.
---
-# More Design Tokens
-
## Focus Rings
Focus ring tokens control the appearance of focus rings.
diff --git a/docs/pages/tokens/shadows.md b/docs/src/content/docs/tokens/shadows.md
similarity index 85%
rename from docs/pages/tokens/shadows.md
rename to docs/src/content/docs/tokens/shadows.md
index 620e9a5c6..318a1140f 100644
--- a/docs/pages/tokens/shadows.md
+++ b/docs/src/content/docs/tokens/shadows.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Shadows
- description: Shadow tokens are used to give elements the appearance of being raised off the page.
+title: Shadow Tokens
+description: Shadow tokens are used to give elements the appearance of being raised off the page.
---
-# Shadow Tokens
-
Shadow tokens are used to give elements the appearance of being raised off the page. Use them with the `box-shadow` property. These are especially useful for menus, popovers, and dialogs.
| Token | Example |
diff --git a/docs/pages/tokens/spacing.md b/docs/src/content/docs/tokens/spacing.md
similarity index 91%
rename from docs/pages/tokens/spacing.md
rename to docs/src/content/docs/tokens/spacing.md
index e808887c1..3c951a1e1 100644
--- a/docs/pages/tokens/spacing.md
+++ b/docs/src/content/docs/tokens/spacing.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Spacing Tokens
- description: Spacing tokens are used to provide consistent spacing between content in your app.
+title: Spacing Tokens
+description: Spacing tokens are used to provide consistent spacing between content in your app.
---
-# Spacing Tokens
-
Spacing tokens are used to provide consistent spacing between content in your app.
| Token | Value | Example |
diff --git a/docs/pages/tokens/transition.md b/docs/src/content/docs/tokens/transition.md
similarity index 83%
rename from docs/pages/tokens/transition.md
rename to docs/src/content/docs/tokens/transition.md
index 677e66704..7211ee777 100644
--- a/docs/pages/tokens/transition.md
+++ b/docs/src/content/docs/tokens/transition.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Transition Tokens
- description: Transition tokens are used to provide consistent transitions throughout your app.
+title: Transition Tokens
+description: Transition tokens are used to provide consistent transitions throughout your app.
---
-# Transition Tokens
-
Transition tokens are used to provide consistent transitions throughout your app.
| Token | Value | Example |
diff --git a/docs/pages/tokens/typography.md b/docs/src/content/docs/tokens/typography.md
similarity index 97%
rename from docs/pages/tokens/typography.md
rename to docs/src/content/docs/tokens/typography.md
index fe7118f4b..d5f2e927a 100644
--- a/docs/pages/tokens/typography.md
+++ b/docs/src/content/docs/tokens/typography.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Typography
- description: Typography tokens are used to maintain a consistent set of font styles throughout your app.
+title: Typography
+description: Typography tokens are used to maintain a consistent set of font styles throughout your app.
---
-# Typography Tokens
-
Typography tokens are used to maintain a consistent set of font styles throughout your app.
## Font Family
diff --git a/docs/pages/tokens/z-index.md b/docs/src/content/docs/tokens/z-index.md
similarity index 73%
rename from docs/pages/tokens/z-index.md
rename to docs/src/content/docs/tokens/z-index.md
index 62d36e3f0..107fd0767 100644
--- a/docs/pages/tokens/z-index.md
+++ b/docs/src/content/docs/tokens/z-index.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Z-Index Tokens
- description: Z-indexes are used to stack components in a logical manner.
+title: Z-Index Tokens
+description: Z-indexes are used to stack components in a logical manner.
---
-# Z-Index Tokens
-
Z-indexes are used to stack components in a logical manner.
| Token | Value |
diff --git a/docs/pages/tutorials/integrating-with-laravel.md b/docs/src/content/docs/tutorials/integrating-with-laravel.md
similarity index 96%
rename from docs/pages/tutorials/integrating-with-laravel.md
rename to docs/src/content/docs/tutorials/integrating-with-laravel.md
index 68e6c01f5..0b2fa47b9 100644
--- a/docs/pages/tutorials/integrating-with-laravel.md
+++ b/docs/src/content/docs/tutorials/integrating-with-laravel.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Integrating with Laravel
- description: This page explains how to integrate Web Awesome with a Laravel app.
+title: Integrating with Laravel
+description: This page explains how to integrate Web Awesome with a Laravel app.
---
-# Integrating with Laravel
-
This page explains how to integrate Web Awesome with a [Laravel 9](https://laravel.com) app using Vite. For additional details refer to the [Bundling Assets (Vite)](https://laravel.com/docs/9.x/vite) section in the official Laravel docs.
:::tip
diff --git a/docs/pages/tutorials/integrating-with-nextjs.md b/docs/src/content/docs/tutorials/integrating-with-nextjs.md
similarity index 97%
rename from docs/pages/tutorials/integrating-with-nextjs.md
rename to docs/src/content/docs/tutorials/integrating-with-nextjs.md
index 0cae39f02..9295fdea1 100644
--- a/docs/pages/tutorials/integrating-with-nextjs.md
+++ b/docs/src/content/docs/tutorials/integrating-with-nextjs.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Integrating with NextJS
- description: This page explains how to integrate Web Awesome with a NextJS app.
+title: Integrating with NextJS
+description: This page explains how to integrate Web Awesome with a NextJS app.
---
-# Integrating with NextJS
-
This page explains how to integrate Web Awesome with a NextJS app.
:::tip
diff --git a/docs/pages/tutorials/integrating-with-rails.md b/docs/src/content/docs/tutorials/integrating-with-rails.md
similarity index 95%
rename from docs/pages/tutorials/integrating-with-rails.md
rename to docs/src/content/docs/tutorials/integrating-with-rails.md
index e923b7e56..afeeedc53 100644
--- a/docs/pages/tutorials/integrating-with-rails.md
+++ b/docs/src/content/docs/tutorials/integrating-with-rails.md
@@ -1,11 +1,8 @@
---
-meta:
- title: Integrating with Rails
- description: This page explains how to integrate Web Awesome with a Rails app.
+title: Integrating with Rails
+description: This page explains how to integrate Web Awesome with a Rails app.
---
-# Integrating with Rails
-
This page explains how to integrate Web Awesome with a Rails app.
:::tip
diff --git a/docs/src/env.d.ts b/docs/src/env.d.ts
new file mode 100644
index 000000000..acef35f17
--- /dev/null
+++ b/docs/src/env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/docs/_utilities/cem.cjs b/docs/src/js/cem.js
similarity index 58%
rename from docs/_utilities/cem.cjs
rename to docs/src/js/cem.js
index 8fb1bc12a..04f9e6a30 100644
--- a/docs/_utilities/cem.cjs
+++ b/docs/src/js/cem.js
@@ -1,17 +1,20 @@
-const customElementsManifest = require('../../dist/custom-elements.json');
-
//
// Export it here so we can import it elsewhere and use the same version
//
-module.exports.customElementsManifest = customElementsManifest;
+import * as path from 'node:path';
+import * as fs from 'node:fs';
+
+// We make it a function to lazy evaluate for re-renders
+export const customElementsManifest = () =>
+ JSON.parse(fs.readFileSync(path.join(process.cwd(), '/../dist/custom-elements.json')), { encoding: 'utf-8' });
//
// Gets all components from custom-elements.json and returns them in a more documentation-friendly format.
//
-module.exports.getAllComponents = function () {
+export function getAllComponents() {
const allComponents = [];
- customElementsManifest.modules?.forEach(module => {
+ customElementsManifest().modules?.forEach(module => {
module.declarations?.forEach(declaration => {
if (declaration.customElement) {
// Generate the dist path based on the src path and attach it to the component
@@ -68,4 +71,31 @@ module.exports.getAllComponents = function () {
if (a.name > b.name) return 1;
return 0;
});
-};
+}
+
+export function getComponent(tagName) {
+ const allComponents = getAllComponents();
+ const component = allComponents.find(c => c.tagName === tagName);
+ if (!component) {
+ throw new Error(
+ `Unable to find a component called "${tagName}". Make sure the file name is the same as the component's tag ` +
+ `name (minus the wa- prefix). ${allComponents}`
+ );
+ }
+
+ component.hasSlots = Boolean(component.slots?.length);
+ component.hasProperties = Boolean(component.properties?.length);
+ component.hasEvents = Boolean(component.events?.length);
+ component.hasMethods = Boolean(component.methods?.length);
+ component.hasCssProperties = Boolean(component.cssProperties?.length);
+ component.hasCssParts = Boolean(component.cssParts?.length);
+ component.hasAnimations = Boolean(component.animations?.length);
+ component.hasDependencies = Boolean(component.dependencies?.length);
+ return component;
+}
+
+export function getComponentFromFileName(filename) {
+ const { name } = path.parse(filename);
+ const tagName = 'wa-' + name;
+ return getComponent(tagName);
+}
diff --git a/docs/assets/scripts/code-previews.js b/docs/src/js/code-previews.js
similarity index 90%
rename from docs/assets/scripts/code-previews.js
rename to docs/src/js/code-previews.js
index 5564ede72..6be1595e4 100644
--- a/docs/assets/scripts/code-previews.js
+++ b/docs/src/js/code-previews.js
@@ -8,33 +8,6 @@
return html;
}
- function getAdjacentExample(name, pre) {
- let currentPre = pre.nextElementSibling;
-
- while (currentPre?.tagName.toLowerCase() === 'pre') {
- if (currentPre?.getAttribute('data-lang').split(' ').includes(name)) {
- return currentPre;
- }
-
- currentPre = currentPre.nextElementSibling;
- }
-
- return null;
- }
-
- function runScript(script) {
- const newScript = document.createElement('script');
-
- if (script.type === 'module') {
- newScript.type = 'module';
- newScript.textContent = script.innerHTML;
- } else {
- newScript.appendChild(document.createTextNode(`(() => { ${script.innerHTML} })();`));
- }
-
- script.parentNode.replaceChild(newScript, script);
- }
-
function getFlavor() {
return sessionStorage.getItem('flavor') || 'html';
}
@@ -64,7 +37,7 @@
});
}
- const waVersion = document.documentElement.getAttribute('data-wa-version');
+ const waVersion = document.querySelector("meta[name='wa-version']").getAttribute('content');
const reactVersion = '18.2.0';
const cdndir = 'cdn';
const npmdir = 'dist';
@@ -240,4 +213,5 @@
// Set the initial flavor
window.addEventListener('turbo:load', syncFlavor);
+ syncFlavor();
})();
diff --git a/docs/src/js/generate-search.js b/docs/src/js/generate-search.js
new file mode 100644
index 000000000..e667a1813
--- /dev/null
+++ b/docs/src/js/generate-search.js
@@ -0,0 +1,37 @@
+import * as pagefind from 'pagefind';
+import * as path from 'node:path';
+
+// clean up once complete
+import { getCollection } from 'astro:content';
+
+export async function generateSearch() {
+ const { index } = await pagefind.createIndex({});
+ if (!index) return;
+
+ // Get all `src/content/docs/` entries
+ let allContent = await getCollection('docs');
+
+ allContent = allContent.filter(doc => {
+ return doc.data.pagefind !== false;
+ });
+
+ await Promise.allSettled(
+ allContent.map(async entry => {
+ const { category, title, description } = entry.data;
+ return await index?.addCustomRecord({
+ content: entry.body,
+ language: 'en',
+ url: entry.slug,
+ meta: {
+ category: category || '',
+ title,
+ description: description || ''
+ }
+ });
+ })
+ );
+
+ const { errors } = await index.writeFiles({
+ outputPath: path.join(process.cwd(), 'public', 'pagefind')
+ });
+}
diff --git a/docs/src/js/theme.js b/docs/src/js/theme.js
new file mode 100644
index 000000000..cc96b4e31
--- /dev/null
+++ b/docs/src/js/theme.js
@@ -0,0 +1,34 @@
+(() => {
+ function getTheme() {
+ return document.documentElement.getAttribute('data-theme');
+ }
+ function syncTheme() {
+ const theme = getTheme();
+ document.documentElement.classList.toggle('wa-theme-default-dark', theme === 'dark');
+ }
+
+ function handleThemeChange(e) {
+ if (e.target.closest('starlight-theme-select')) {
+ requestAnimationFrame(() => syncTheme());
+ }
+ }
+
+ function handleKeyDown(e) {
+ if (e.key === '\\' && !e.composedPath().some(el => ['input', 'textarea'].includes(el?.tagName?.toLowerCase()))) {
+ let theme = getTheme() === 'light' ? 'dark' : 'light';
+
+ const option = document.querySelector(`starlight-theme-select select option[value='${theme}']`);
+
+ option.selected = true;
+
+ option.dispatchEvent(new Event('change', { bubbles: true }));
+ }
+ }
+
+ document.addEventListener('keydown', handleKeyDown);
+
+ document.addEventListener('change', handleThemeChange);
+ document.addEventListener('input', handleThemeChange);
+ window.addEventListener('turbo:load', syncTheme);
+ syncTheme();
+})();
diff --git a/docs/src/layouts/ComponentLayout.astro b/docs/src/layouts/ComponentLayout.astro
new file mode 100644
index 000000000..fbe5af31d
--- /dev/null
+++ b/docs/src/layouts/ComponentLayout.astro
@@ -0,0 +1,406 @@
+---
+import { getComponentFromFileName } from "../js/cem.js"
+import { marked } from 'marked';
+import { highlight } from "../utilities/prism";
+
+const { file, frontmatter } = Astro.props
+const { version, npmdir, cdndir } = frontmatter
+
+const component = getComponentFromFileName(file)
+
+function rootUrl(url) {
+ return "/" + url
+}
+
+function variantToBadge() {
+ if (component.status === 'stable') {
+ return 'brand'
+ }
+
+ if (component.status === 'experimental') {
+ return 'warning'
+ }
+
+ if (component.status == 'planned') {
+ return 'neutral'
+ }
+
+ if (component.status == 'deprecated') {
+ return 'danger'
+ }
+
+ return 'neutral'
+}
+
+
+function capitalCase (str: string) {
+ return str.split(/\s+/).map((str) => str[0].toUpperCase() + str.slice(1)).join(" ")
+}
+
+function classNameToComponentName (className: string) {
+ let name = capitalCase(className.replace(/^Wa/, ''));
+ if (name === 'Qr Code') name = 'QR Code'; // manual override
+ return name;
+}
+
+const componentSummary = marked.parse(component.summary);
+
+const {
+ hasSlots,
+ hasProperties,
+ hasEvents,
+ hasMethods,
+ hasCssProperties,
+ hasCssParts,
+ hasAnimations,
+ hasDependencies,
+} = component
+---
+
+
+
+
+
+
+
+{/* Importing */}
+Importing
+
+ If you're using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use
+ any of the following snippets to cherry pick this component.
+
+
+
+ Script
+ Import
+ Bundler
+ React
+
+
+
+ To import this component from the CDN
+ using a script tag:
+
+ `)}>
+
+
+
+
+ To import this component from the CDN
+ using a JavaScript import:
+
+
+
+
+
+
+ To import this component using a bundler :
+
+
+
+
+
+
+ To import this component as a React component :
+
+
+
+
+
+{/* Slots */}
+{!hasSlots ? "" :
+ <>
+ Slots
+
+
+
+ Learn more about using slots .
+ >
+}
+
+{/* Properties */}
+{!hasProperties ? "" :
+ <>
+ Properties
+
+
+
+ Learn more about attributes and properties .
+ >
+}
+
+{/** Events */}
+{!hasEvents ? "" :
+ <>
+ Events
+
+
+
+ Learn more about events .
+ >
+}
+
+{/* Methods */}
+{!hasMethods ? "" :
+ <>
+ Methods
+
+
+ >
+ Learn more about methods .
+}
+
+{/** Custom Properties */}
+{!hasCssProperties ? "" :
+ <>
+ Custom Properties
+
+
+
+ Learn more about customizing CSS custom properties .
+ >
+}
+
+{/* CSS Parts */}
+{!hasCssParts ? "" :
+ <>
+ Parts
+
+
+
+ Learn more about customizing CSS parts .
+ >
+}
+
+{/* Animations */}
+{!hasAnimations ? "" :
+ <>
+ Animations
+
+
+
+ Learn more about customizing animations .
+ >
+}
+
+{/* Dependencies */}
+{!hasDependencies ? "" :
+ <>
+ Dependencies
+
+ This component automatically imports the following dependencies.
+
+
+ {component.dependencies.map((dependency) => <{ dependency }> )}
+
+ >
+}
+
diff --git a/docs/src/pages/pagefind-dev.json.ts b/docs/src/pages/pagefind-dev.json.ts
new file mode 100644
index 000000000..31593e9a9
--- /dev/null
+++ b/docs/src/pages/pagefind-dev.json.ts
@@ -0,0 +1,22 @@
+// import { APIContext } from "astro";
+
+import { generateSearch } from '../js/generate-search';
+
+if (process.env.DEV_SEARCH !== 'generated') {
+ await generateSearch();
+
+ process.env.DEV_SEARCH = 'generated';
+
+ // setTimeout(() => {
+ // process.env.DEV_SEARCH = ""
+ // }, 200)
+}
+
+export async function GET() {
+ return new Response(null, {
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+}
diff --git a/docs/src/plugins/github-autolink.ts b/docs/src/plugins/github-autolink.ts
new file mode 100644
index 000000000..6ce677c55
--- /dev/null
+++ b/docs/src/plugins/github-autolink.ts
@@ -0,0 +1,40 @@
+import type { Node } from './types.js';
+
+function transformNode(node: Node) {
+ if (!node.value) return;
+
+ const regex = /\B\[(#\d+)\]\B/g;
+
+ if (!node.value.match(regex)) {
+ return;
+ }
+
+ node.type = 'html';
+ node.value = node.value.replace(
+ regex,
+ `
+ $1
+ `
+ );
+}
+
+/**
+ * A function to turn Github Issues into that looks like this: `[#1550]` into proper links.
+ */
+export default function GithubAutolink() {
+ return function visit(node: Node) {
+ if (!node) return;
+
+ transformNode(node);
+
+ if (!node.children?.length) return;
+
+ for (const childNode of node.children) {
+ transformNode(childNode);
+
+ if (childNode.children?.length) {
+ visit(childNode);
+ }
+ }
+ };
+}
diff --git a/docs/src/plugins/prism.ts b/docs/src/plugins/prism.ts
new file mode 100644
index 000000000..32b9c72b3
--- /dev/null
+++ b/docs/src/plugins/prism.ts
@@ -0,0 +1,167 @@
+import { highlight } from '../utilities/prism.ts';
+import { visit } from 'unist-util-visit';
+import type { Transformer } from 'unified';
+import type { Node } from './types.js';
+
+const html = String.raw;
+
+let count = 0;
+
+export default function remarkCodeHighlighter(): Transformer {
+ return tree => {
+ visit(tree, 'code', (node: Node, index: number, parent: Node) => {
+ let { lang } = node;
+
+ if (!lang) {
+ return;
+ }
+
+ lang = lang.split(':')[0];
+
+ // We don't process JSX nodes.
+ if (lang === 'jsx') {
+ node.value = '';
+ node.type = 'html';
+ return;
+ }
+
+ const options = node.lang.split(':').slice(1);
+
+ node.type = 'html';
+
+ if (!options.includes('preview')) {
+ // we still want to generate code blocks for non-previews, just...different html.
+ generateCodeBlock(node);
+ return;
+ }
+
+ let reactCode = '';
+
+ // Need to look ahead at the next node and if its also code, check if it's React.
+ if (parent.children?.length) {
+ const nextNode = parent.children[index + 1];
+
+ if (nextNode && nextNode.lang && nextNode.lang.split(':')[0] === 'jsx') {
+ reactCode = nextNode.value;
+ }
+ }
+
+ node.value = generatePreviewCodeBlock(node, reactCode);
+ });
+ };
+}
+
+function escapeHtml(str: string) {
+ return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
+}
+
+function copyButton(id: string) {
+ return html` `;
+}
+
+function generateCodeBlock(node: Node) {
+ let language = node.lang?.split(':')[0];
+
+ if (!language) {
+ language = 'plaintext';
+ }
+
+ node.value = html`${highlight(
+ language,
+ node.value
+ )}${copyButton(`code-block-${count}`)} `;
+}
+
+function generatePreviewCodeBlock(node: Node, reactCode: string) {
+ const options = node.lang.split(':').slice(1);
+ const sourceGroupId = `code-preview-source-group-${++count}`;
+
+ // const lang = node.lang.split(":")[0]
+
+ const isExpanded = options.includes('expanded');
+ const noCodePen = options.includes('no-codepen');
+
+ count++;
+
+ const htmlButton = html`
+ HTML
+ `;
+
+ const reactButton = html`
+
+ React
+
+ `;
+
+ const codePenButton = html`
+
+
+
+
+
+ `;
+
+ const codePreview = html`
+
+
+ ${node.value.replaceAll(/