Compare commits
3 Commits
kj/blog-pa
...
esbuild-pl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a7fd7964f | ||
|
|
5a683300b2 | ||
|
|
20321f84d9 |
10
.eslintignore
Normal file
@@ -0,0 +1,10 @@
|
||||
.cache
|
||||
docs/dist
|
||||
docs/search.json
|
||||
docs/**/*.min.js
|
||||
dist
|
||||
examples
|
||||
node_modules
|
||||
src/react
|
||||
scripts
|
||||
|
||||
213
.eslintrc.cjs
Normal file
@@ -0,0 +1,213 @@
|
||||
/* eslint-env node */
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
'wc',
|
||||
'lit',
|
||||
'lit-a11y',
|
||||
'chai-expect',
|
||||
'chai-friendly',
|
||||
'import',
|
||||
'sort-imports-es6-autofix'
|
||||
],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:wc/recommended',
|
||||
'plugin:wc/best-practice',
|
||||
'plugin:lit/recommended',
|
||||
'plugin:lit-a11y/recommended'
|
||||
],
|
||||
env: {
|
||||
es2021: true,
|
||||
browser: true
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: 'module'
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
project: './tsconfig.json',
|
||||
tsconfigRootDir: __dirname
|
||||
},
|
||||
files: ['*.ts'],
|
||||
rules: {
|
||||
'default-param-last': 'off',
|
||||
'@typescript-eslint/default-param-last': 'error',
|
||||
'no-console': 'warn',
|
||||
'no-empty-function': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'warn',
|
||||
'no-implied-eval': 'off',
|
||||
'no-invalid-this': 'off',
|
||||
'no-shadow': 'off',
|
||||
'no-throw-literal': 'off',
|
||||
'no-unused-expressions': 'off',
|
||||
'lit-a11y/no-autofocus': 'off',
|
||||
'@typescript-eslint/no-implied-eval': 'error',
|
||||
'@typescript-eslint/no-invalid-this': 'error',
|
||||
'@typescript-eslint/no-throw-literal': 'error',
|
||||
'@typescript-eslint/no-shadow': 'error',
|
||||
'@typescript-eslint/prefer-regexp-exec': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': 'error',
|
||||
'@typescript-eslint/unbound-method': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/no-floating-promises': 'off',
|
||||
'@typescript-eslint/no-misused-promises': [
|
||||
'error',
|
||||
{
|
||||
checksVoidReturn: false
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/consistent-type-assertions': [
|
||||
'warn',
|
||||
{
|
||||
assertionStyle: 'as',
|
||||
objectLiteralTypeAssertions: 'never'
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/consistent-type-imports': 'warn',
|
||||
'@typescript-eslint/no-base-to-string': 'error',
|
||||
'@typescript-eslint/no-confusing-non-null-assertion': 'error',
|
||||
'@typescript-eslint/no-invalid-void-type': 'error',
|
||||
'@typescript-eslint/no-require-imports': 'error',
|
||||
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn',
|
||||
'@typescript-eslint/no-unnecessary-condition': 'off',
|
||||
'@typescript-eslint/no-unnecessary-qualifier': 'warn',
|
||||
'@typescript-eslint/non-nullable-type-assertion-style': 'warn',
|
||||
'@typescript-eslint/prefer-for-of': 'warn',
|
||||
'@typescript-eslint/prefer-optional-chain': 'warn',
|
||||
'@typescript-eslint/prefer-ts-expect-error': 'warn',
|
||||
'@typescript-eslint/prefer-return-this-type': 'error',
|
||||
'@typescript-eslint/prefer-string-starts-ends-with': 'warn',
|
||||
'@typescript-eslint/require-array-sort-compare': 'error',
|
||||
'@typescript-eslint/unified-signatures': 'warn',
|
||||
'@typescript-eslint/array-type': 'warn',
|
||||
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
||||
'@typescript-eslint/member-delimiter-style': 'warn',
|
||||
'@typescript-eslint/method-signature-style': 'warn',
|
||||
'@typescript-eslint/no-extraneous-class': 'error',
|
||||
'@typescript-eslint/no-redundant-type-constituents': 'off',
|
||||
'@typescript-eslint/parameter-properties': 'error',
|
||||
'@typescript-eslint/strict-boolean-expressions': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.cjs'],
|
||||
env: {
|
||||
node: true
|
||||
}
|
||||
},
|
||||
{
|
||||
extends: ['plugin:chai-expect/recommended', 'plugin:chai-friendly/recommended'],
|
||||
files: ['*.test.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': 'off'
|
||||
}
|
||||
}
|
||||
],
|
||||
rules: {
|
||||
'no-template-curly-in-string': 'error',
|
||||
'array-callback-return': 'error',
|
||||
'comma-dangle': 'off',
|
||||
'consistent-return': 'error',
|
||||
curly: 'off',
|
||||
'default-param-last': 'error',
|
||||
eqeqeq: 'error',
|
||||
'lit-a11y/click-events-have-key-events': 'off',
|
||||
'no-constructor-return': 'error',
|
||||
'no-empty-function': 'warn',
|
||||
'no-eval': 'error',
|
||||
'no-extend-native': 'error',
|
||||
'no-extra-bind': 'error',
|
||||
'no-floating-decimal': 'error',
|
||||
'no-implicit-coercion': 'off',
|
||||
'no-implicit-globals': 'error',
|
||||
'no-implied-eval': 'error',
|
||||
'no-invalid-this': 'off',
|
||||
'no-labels': 'error',
|
||||
'no-lone-blocks': 'error',
|
||||
'no-new': 'error',
|
||||
'no-new-func': 'error',
|
||||
'no-new-wrappers': 'error',
|
||||
'no-octal-escape': 'error',
|
||||
'no-proto': 'error',
|
||||
'no-return-assign': 'warn',
|
||||
'no-script-url': 'error',
|
||||
'no-self-compare': 'warn',
|
||||
'no-sequences': 'warn',
|
||||
'no-throw-literal': 'error',
|
||||
'no-unmodified-loop-condition': 'error',
|
||||
'no-unused-expressions': 'warn',
|
||||
'no-useless-call': 'error',
|
||||
'no-useless-concat': 'error',
|
||||
'no-useless-return': 'warn',
|
||||
'prefer-promise-reject-errors': 'error',
|
||||
radix: 'off',
|
||||
'require-await': 'error',
|
||||
'wrap-iife': ['warn', 'inside'],
|
||||
'no-shadow': 'error',
|
||||
'no-array-constructor': 'error',
|
||||
'no-bitwise': 'error',
|
||||
'no-multi-assign': 'warn',
|
||||
'no-new-object': 'error',
|
||||
'no-useless-computed-key': 'warn',
|
||||
'no-useless-rename': 'warn',
|
||||
'no-var': 'error',
|
||||
'prefer-const': 'warn',
|
||||
'prefer-numeric-literals': 'warn',
|
||||
'prefer-object-spread': 'warn',
|
||||
'prefer-rest-params': 'warn',
|
||||
'prefer-spread': 'warn',
|
||||
'prefer-template': 'off',
|
||||
'no-else-return': 'off',
|
||||
'func-names': ['warn', 'never'],
|
||||
'one-var': ['warn', 'never'],
|
||||
'operator-assignment': 'warn',
|
||||
'prefer-arrow-callback': 'warn',
|
||||
'no-restricted-imports': [
|
||||
'warn',
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: '.',
|
||||
message: 'Usage of local index imports is not allowed.'
|
||||
},
|
||||
{
|
||||
name: './index',
|
||||
message: 'Import from the source file instead.'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'always',
|
||||
{
|
||||
ignorePackages: true,
|
||||
pattern: {
|
||||
js: 'always',
|
||||
ts: 'never'
|
||||
}
|
||||
}
|
||||
],
|
||||
'import/no-duplicates': 'warn',
|
||||
'sort-imports-es6-autofix/sort-imports-es6': [
|
||||
2,
|
||||
{
|
||||
ignoreCase: true,
|
||||
ignoreMemberSort: false,
|
||||
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single']
|
||||
}
|
||||
],
|
||||
'wc/guard-super-call': 'off'
|
||||
}
|
||||
};
|
||||
4
.github/workflows/client_tests.js.yml
vendored
@@ -29,9 +29,9 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
run: npm run prettier
|
||||
run: npm run prettier && npm run lint
|
||||
- name: Build
|
||||
run: npm run build:alpha
|
||||
run: npm run build
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
- name: Run CSR tests
|
||||
|
||||
4
.github/workflows/ssr_tests.js.yml
vendored
@@ -27,10 +27,10 @@ jobs:
|
||||
run: npm ci
|
||||
# Just lint here too. Save some GH Action minutes and not need to use "depends_on" or anything.
|
||||
- name: Lint
|
||||
run: npm run prettier
|
||||
run: npm run prettier && npm run lint
|
||||
|
||||
- name: Build
|
||||
run: npm run build:alpha
|
||||
run: npm run build
|
||||
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
1
.vscode/extensions.json
vendored
@@ -3,6 +3,7 @@
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"bierner.lit-html",
|
||||
"bashmish.es6-string-css",
|
||||
"streetsidesoftware.code-spell-checker"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
"crutchcorn",
|
||||
"csspart",
|
||||
"cssproperty",
|
||||
"cssstate",
|
||||
"datetime",
|
||||
"describedby",
|
||||
"Docsify",
|
||||
@@ -47,7 +46,6 @@
|
||||
"dropdowns",
|
||||
"easings",
|
||||
"ecommerce",
|
||||
"endfor",
|
||||
"endraw",
|
||||
"endregion",
|
||||
"enterkeyhint",
|
||||
@@ -105,7 +103,6 @@
|
||||
"metaframeworks",
|
||||
"middlewares",
|
||||
"minlength",
|
||||
"minmax",
|
||||
"monospace",
|
||||
"mousedown",
|
||||
"mousemove",
|
||||
@@ -158,19 +155,16 @@
|
||||
"smartquotes",
|
||||
"spacebar",
|
||||
"stylesheet",
|
||||
"svgs",
|
||||
"Tabbable",
|
||||
"tabindex",
|
||||
"tabler",
|
||||
"tablist",
|
||||
"tabpanel",
|
||||
"tbody",
|
||||
"templating",
|
||||
"tera",
|
||||
"testid",
|
||||
"textareas",
|
||||
"textfield",
|
||||
"thead",
|
||||
"Themer",
|
||||
"tinycolor",
|
||||
"transitionend",
|
||||
|
||||
@@ -2,8 +2,8 @@ import { customElementJetBrainsPlugin } from 'custom-element-jet-brains-integrat
|
||||
import { customElementVsCodePlugin } from 'custom-element-vs-code-integration';
|
||||
// import { customElementVuejsPlugin } from 'custom-element-vuejs-integration';
|
||||
import { parse } from 'comment-parser';
|
||||
import fs from 'fs';
|
||||
import { pascalCase } from 'pascal-case';
|
||||
import fs from 'fs';
|
||||
|
||||
const packageData = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||
const { name, description, version, author, homepage, license } = packageData;
|
||||
@@ -28,7 +28,7 @@ export default {
|
||||
name: 'wa-package-data',
|
||||
packageLinkPhase({ customElementsManifest }) {
|
||||
customElementsManifest.package = { name, description, version, author, homepage, license };
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
// Parse custom jsDoc tags
|
||||
@@ -83,13 +83,13 @@ export default {
|
||||
classDoc[t.tag].push({
|
||||
name: t.name,
|
||||
description: t.description,
|
||||
type: t.type || undefined,
|
||||
type: t.type || undefined
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
@@ -109,7 +109,7 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
@@ -127,7 +127,7 @@ export default {
|
||||
//
|
||||
const terms = [
|
||||
{ from: /^src\//, to: '' }, // Strip the src/ prefix
|
||||
{ from: /\.(t|j)sx?$/, to: '.js' }, // Convert .ts to .js
|
||||
{ from: /\.(t|j)sx?$/, to: '.js' } // Convert .ts to .js
|
||||
];
|
||||
|
||||
mod.path = replace(mod.path, terms);
|
||||
@@ -146,7 +146,7 @@ export default {
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
// Generate custom VS Code data
|
||||
@@ -156,9 +156,9 @@ export default {
|
||||
referencesTemplate: (_, tag) => [
|
||||
{
|
||||
name: 'Documentation',
|
||||
url: `https://webawesome.com/docs/components/${tag.replace('wa-', '')}`,
|
||||
},
|
||||
],
|
||||
url: `https://webawesome.com/docs/components/${tag.replace('wa-', '')}`
|
||||
}
|
||||
]
|
||||
}),
|
||||
|
||||
customElementJetBrainsPlugin({
|
||||
@@ -168,10 +168,10 @@ export default {
|
||||
referencesTemplate: (_, tag) => {
|
||||
return {
|
||||
name: 'Documentation',
|
||||
url: `https://webawesome.com/docs/components/${tag.replace('wa-', '')}`,
|
||||
url: `https://webawesome.com/docs/components/${tag.replace('wa-', '')}`
|
||||
};
|
||||
},
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
||||
//
|
||||
// TODO - figure out why this broke when events were updated
|
||||
@@ -181,5 +181,5 @@ export default {
|
||||
// fileName: 'index.d.ts',
|
||||
// componentTypePath: (_, tag) => `../../components/${tag.replace('wa-', '')}/${tag.replace('wa-', '')}.js`
|
||||
// })
|
||||
],
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
import { parse } from 'path';
|
||||
import { markdown } from './_utils/markdown.js';
|
||||
import { anchorHeadingsPlugin } from './_utils/anchor-headings.js';
|
||||
import { codeExamplesPlugin } from './_utils/code-examples.js';
|
||||
import { copyCodePlugin } from './_utils/copy-code.js';
|
||||
import { removeDataAlphaElements } from './_utils/remove-data-alpha-elements.js';
|
||||
import { currentLink } from './_utils/current-link.js';
|
||||
import { highlightCodePlugin } from './_utils/highlight-code.js';
|
||||
import { markdown } from './_utils/markdown.js';
|
||||
import { removeDataAlphaElements } from './_utils/remove-data-alpha-elements.js';
|
||||
// import { formatCodePlugin } from './_utils/format-code.js';
|
||||
import litPlugin from '@lit-labs/eleventy-plugin-lit';
|
||||
import { readFile } from 'fs/promises';
|
||||
import componentList from './_data/componentList.js';
|
||||
import * as filters from './_utils/filters.js';
|
||||
import { outlinePlugin } from './_utils/outline.js';
|
||||
import { replaceTextPlugin } from './_utils/replace-text.js';
|
||||
import { searchPlugin } from './_utils/search.js';
|
||||
import { readFile } from 'fs/promises';
|
||||
import { outlinePlugin } from './_utils/outline.js';
|
||||
import componentList from './_data/componentList.js';
|
||||
import litPlugin from '@lit-labs/eleventy-plugin-lit';
|
||||
|
||||
import process from 'process';
|
||||
|
||||
const packageData = JSON.parse(await readFile('./package.json', 'utf-8'));
|
||||
const isAlpha = process.argv.includes('--alpha');
|
||||
const isDev = process.argv.includes('--develop');
|
||||
|
||||
const globalData = {
|
||||
package: packageData,
|
||||
isAlpha,
|
||||
layout: 'page.njk',
|
||||
};
|
||||
// const isDeveloping = process.argv.includes('--develop');
|
||||
|
||||
export default function (eleventyConfig) {
|
||||
// NOTE - alpha setting removes certain pages
|
||||
@@ -38,26 +32,26 @@ export default function (eleventyConfig) {
|
||||
}
|
||||
|
||||
// Add template data
|
||||
for (let name in globalData) {
|
||||
eleventyConfig.addGlobalData(name, globalData[name]);
|
||||
}
|
||||
eleventyConfig.addGlobalData('package', packageData);
|
||||
eleventyConfig.addGlobalData('isAlpha', isAlpha);
|
||||
|
||||
// Template filters - {{ content | filter }}
|
||||
eleventyConfig.addFilter('inlineMarkdown', content => markdown.renderInline(content || ''));
|
||||
eleventyConfig.addFilter('markdown', content => markdown.render(content || ''));
|
||||
|
||||
for (let name in filters) {
|
||||
eleventyConfig.addFilter(name, filters[name]);
|
||||
}
|
||||
eleventyConfig.addFilter('stripExtension', string => parse(string).name);
|
||||
eleventyConfig.addFilter('stripPrefix', content => content.replace(/^wa-/, ''));
|
||||
eleventyConfig.addFilter('trimPipes', 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 be present when the line wraps.
|
||||
return typeof content === 'string' ? content.replace(/^(\s|\|)/g, '').replace(/(\s|\|)$/g, '') : content;
|
||||
});
|
||||
eleventyConfig.addFilter('keys', obj => Object.keys(obj));
|
||||
|
||||
// Shortcodes - {% shortCode arg1, arg2 %}
|
||||
eleventyConfig.addShortcode('cdnUrl', location => {
|
||||
return `https://early.webawesome.com/webawesome@${packageData.version}/dist/` + location.replace(/^\//, '');
|
||||
});
|
||||
|
||||
// Paired shortcodes - {% shortCode %}content{% endShortCode %}
|
||||
eleventyConfig.addPairedShortcode('markdown', content => markdown.render(content || ''));
|
||||
|
||||
// Helpers
|
||||
|
||||
// Remove elements that have [data-alpha="remove"]
|
||||
@@ -77,8 +71,8 @@ export default function (eleventyConfig) {
|
||||
selector: 'h2, h3',
|
||||
ifEmpty: doc => {
|
||||
doc.querySelector('#outline')?.remove();
|
||||
},
|
||||
}),
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Add current link classes
|
||||
@@ -99,58 +93,54 @@ export default function (eleventyConfig) {
|
||||
// Replace [issue:1234] with a link to the issue on GitHub
|
||||
{
|
||||
replace: /\[pr:([0-9]+)\]/gs,
|
||||
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/pull/$1">#$1</a>',
|
||||
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/pull/$1">#$1</a>'
|
||||
},
|
||||
// Replace [pr:1234] with a link to the pull request on GitHub
|
||||
{
|
||||
replace: /\[issue:([0-9]+)\]/gs,
|
||||
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/issues/$1">#$1</a>',
|
||||
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/issues/$1">#$1</a>'
|
||||
},
|
||||
// Replace [discuss:1234] with a link to the discussion on GitHub
|
||||
{
|
||||
replace: /\[discuss:([0-9]+)\]/gs,
|
||||
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/discussions/$1">#$1</a>',
|
||||
},
|
||||
]),
|
||||
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/discussions/$1">#$1</a>'
|
||||
}
|
||||
])
|
||||
);
|
||||
|
||||
// SSR plugin
|
||||
if (!isDev) {
|
||||
//
|
||||
// Problematic components in SSR land:
|
||||
// - animation (breaks on navigation + ssr with Turbo)
|
||||
// - mutation-observer (why SSR this?)
|
||||
// - resize-observer (why SSR this?)
|
||||
// - tooltip (why SSR this?)
|
||||
//
|
||||
const omittedModules = [];
|
||||
const componentModules = componentList
|
||||
.filter(component => !omittedModules.includes(component.tagName.split(/wa-/)[1]))
|
||||
.map(component => {
|
||||
const name = component.tagName.split(/wa-/)[1];
|
||||
return `./dist/components/${name}/${name}.js`;
|
||||
});
|
||||
const omittedModules = [];
|
||||
|
||||
eleventyConfig.addPlugin(litPlugin, {
|
||||
mode: 'worker',
|
||||
componentModules,
|
||||
// problematic components:
|
||||
// animation (breaks on navigation + ssr with Turbo)
|
||||
// mutation-observer (why SSR this?)
|
||||
// resize-observer (why SSR this?)
|
||||
// tooltip (why SSR this?)
|
||||
const componentModules = componentList
|
||||
// .filter(component => !omittedModules.includes(component.tagName.split(/wa-/)[1]))
|
||||
.map(component => {
|
||||
const name = component.tagName.split(/wa-/)[1];
|
||||
return `./dist/components/${name}/${name}.js`;
|
||||
});
|
||||
}
|
||||
|
||||
eleventyConfig.addPlugin(litPlugin, {
|
||||
mode: 'worker',
|
||||
componentModules
|
||||
});
|
||||
|
||||
// Build the search index
|
||||
eleventyConfig.addPlugin(
|
||||
searchPlugin({
|
||||
filename: '',
|
||||
selectorsToIgnore: ['code.example'],
|
||||
getContent: doc => doc.querySelector('#content')?.textContent ?? '',
|
||||
}),
|
||||
getContent: doc => doc.querySelector('#content')?.textContent ?? ''
|
||||
})
|
||||
);
|
||||
|
||||
// Production-only plugins
|
||||
//
|
||||
// TODO - disabled because it takes about a minute to run now
|
||||
//
|
||||
// if (!isDev) {
|
||||
// if (!isDeveloping) {
|
||||
// // Run Prettier on each file (prod only because it can be slow)
|
||||
// eleventyConfig.addPlugin(formatCodePlugin());
|
||||
// }
|
||||
@@ -159,8 +149,8 @@ export default function (eleventyConfig) {
|
||||
markdownTemplateEngine: 'njk',
|
||||
dir: {
|
||||
includes: '_includes',
|
||||
layouts: '_layouts',
|
||||
layouts: '_layouts'
|
||||
},
|
||||
templateFormats: ['njk', 'md'],
|
||||
templateFormats: ['njk', 'md']
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* @module components Fetches components from custom-elements.json and exposes them in a saner format.
|
||||
*/
|
||||
import { readFileSync } from 'fs';
|
||||
import { dirname, resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
@@ -36,7 +36,7 @@ const components = manifest.modules.flatMap(module => {
|
||||
slug: declaration.tagName.replace(/^wa-/, ''),
|
||||
methods,
|
||||
attributes,
|
||||
properties,
|
||||
properties
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ const by = {
|
||||
event: {},
|
||||
method: {},
|
||||
cssPart: {},
|
||||
cssProperty: {},
|
||||
cssProperty: {}
|
||||
};
|
||||
|
||||
function getAll(component, type) {
|
||||
|
||||
@@ -22,9 +22,10 @@
|
||||
|
||||
{# Web Awesome #}
|
||||
<script type="module" src="/dist/webawesome.loader.js"></script>
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/default.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/forms.css" />
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="/dist/themes/default.css" />
|
||||
<link rel="stylesheet" href="/dist/themes/applied.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/color_standard.css" />
|
||||
<link rel="stylesheet" href="/dist/themes/forms.css" />
|
||||
|
||||
{# Docs styles #}
|
||||
<link rel="stylesheet" href="/assets/styles/docs.css" />
|
||||
@@ -42,7 +43,7 @@
|
||||
<wa-page>
|
||||
<header slot="header">
|
||||
{# Nav toggle #}
|
||||
<wa-button appearance="plain" data-toggle-nav>
|
||||
<wa-button variant="text" data-toggle-nav>
|
||||
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
|
||||
</wa-button>
|
||||
|
||||
@@ -79,12 +80,11 @@
|
||||
</details>
|
||||
</nav>
|
||||
|
||||
{% block header %}
|
||||
{% include 'breadcrumbs.njk' %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
{% endblock %}
|
||||
{% block beforeContent %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -31,10 +31,11 @@
|
||||
|
||||
{# Web Awesome #}
|
||||
<script type="module" src="/dist/webawesome.ssr-loader.js"></script>
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/default.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/utilities.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/forms.css" />
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="/dist/themes/default.css" />
|
||||
<link rel="stylesheet" href="/dist/themes/applied.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/layout.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/utilities.css" />
|
||||
<link rel="stylesheet" href="/dist/themes/forms.css" />
|
||||
|
||||
{# Docs styles #}
|
||||
<link rel="stylesheet" href="/assets/styles/docs.css" />
|
||||
@@ -62,7 +63,7 @@
|
||||
const newStylesheet = document.createElement("link")
|
||||
|
||||
let preset = getPresetTheme()
|
||||
newStylesheet.href = `/dist/styles/themes/${preset}.css`
|
||||
newStylesheet.href = `/dist/themes/${preset}.css`
|
||||
newStylesheet.rel = "preload"
|
||||
newStylesheet.as = "style"
|
||||
|
||||
@@ -76,31 +77,34 @@
|
||||
|
||||
newStylesheet.addEventListener("load", updateStylesheet)
|
||||
|
||||
document.documentElement.classList.toggle(`wa-dark`, isDark());
|
||||
document.documentElement.classList.toggle(
|
||||
`wa-theme-${preset}-dark`,
|
||||
isDark()
|
||||
);
|
||||
</script>
|
||||
</head>
|
||||
<body class="layout-{{ layout | stripExtension }}">
|
||||
<!-- use view="desktop" as default to reduce layout jank on desktop site. -->
|
||||
<wa-page view="desktop" disable-navigation-toggle="">
|
||||
<header slot="header" class="wa-split">
|
||||
<header slot="header">
|
||||
{# Logo #}
|
||||
<div id="docs-branding">
|
||||
{# Nav toggle #}
|
||||
<wa-button appearance="plain" size="small" data-toggle-nav>
|
||||
<wa-button appearance="text" size="small" data-toggle-nav>
|
||||
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
|
||||
</wa-button>
|
||||
|
||||
<a href="/" aria-label="Web Awesome">
|
||||
<span class="wa-desktop-only">{% include "logo.njk" %}</span>
|
||||
<span class="wa-mobile-only">{% include "logo-simple.njk" %}</span>
|
||||
<span class="only-desktop">{% include "logo.njk" %}</span>
|
||||
<span class="only-mobile">{% include "logo-simple.njk" %}</span>
|
||||
</a>
|
||||
<small id="version-number" class="only-desktop">{{ package.version }}</small>
|
||||
<wa-badge variant="warning" appearance="filled" class="only-desktop">Alpha</wa-badge>
|
||||
<wa-badge variant="warning" class="only-desktop">Alpha</wa-badge>
|
||||
</div>
|
||||
|
||||
<div id="docs-toolbar" class="wa-cluster wa-gap-xs">
|
||||
<div id="docs-toolbar">
|
||||
{# Desktop selectors #}
|
||||
<div class="only-desktop wa-cluster wa-gap-xs">
|
||||
<div class="only-desktop">
|
||||
{% include "preset-theme-selector.njk" %}
|
||||
{% include "color-scheme-selector.njk" %}
|
||||
</div>
|
||||
@@ -117,8 +121,8 @@
|
||||
{# Sidebar #}
|
||||
{% if hasSidebar %}
|
||||
{# Mobile selectors #}
|
||||
<div class="wa-mobile-only" slot="navigation-header">
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
<div class="only-mobile" slot="navigation-header">
|
||||
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));">
|
||||
{% include "preset-theme-selector.njk" %}
|
||||
{% include "color-scheme-selector.njk" %}
|
||||
</div>
|
||||
@@ -146,14 +150,11 @@
|
||||
</details>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
{% block header %}
|
||||
{% include 'breadcrumbs.njk' %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
{% endblock %}
|
||||
{% block beforeContent %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
{% set breadcrumbs = page.url | breadcrumbs %}
|
||||
{% if breadcrumbs.length > 0 %}
|
||||
<wa-breadcrumb id="docs-breadcrumbs">
|
||||
{% for crumb in breadcrumbs %}
|
||||
<wa-breadcrumb-item href="{{ crumb.url }}">{{ crumb.title }}</wa-breadcrumb-item>
|
||||
{% endfor %}
|
||||
<wa-breadcrumb-item>{# Current page #}</wa-breadcrumb-item>
|
||||
</wa-breadcrumb>
|
||||
{% else %}
|
||||
{% endif %}
|
||||
@@ -1,6 +1,6 @@
|
||||
{# Color scheme selector #}
|
||||
<wa-dropdown class="color-scheme-selector">
|
||||
<wa-button slot="trigger" appearance="filled" size="small" pill caret title="Press \ to toggle">
|
||||
<wa-dropdown id="color-scheme-selector">
|
||||
<wa-button slot="trigger" appearance="tinted" size="small" pill caret title="Press \ to toggle">
|
||||
<wa-icon class="only-light" slot="prefix" name="sun" variant="regular"></wa-icon>
|
||||
<wa-icon class="only-dark" slot="prefix" name="moon" variant="regular"></wa-icon>
|
||||
<span class="only-light">Light</span>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{# Cards for pages listed by category #}
|
||||
|
||||
<section id="grid" class="index-grid">
|
||||
{% for category, pages in allPages | groupByTags(categories) -%}
|
||||
<h2 class="index-category">{{ category | getCategoryTitle(categories) }}</h2>
|
||||
{%- for page in pages -%}
|
||||
{%- if not page.data.parent or listChildren -%}
|
||||
{% include "page-card.njk" %}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endfor -%}
|
||||
</section>
|
||||
@@ -1,10 +0,0 @@
|
||||
{%- if not page.data.unlisted -%}
|
||||
<a href="{{ page.url }}"{{ page.data.keywords | attr('data-keywords') }}>
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/" + (page.data.icon or "thumbnail-placeholder") + ".njk" %}
|
||||
</div>
|
||||
<span class="page-name">{{ page.data.title }}</span>
|
||||
</wa-card>
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -16,11 +16,7 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
<wa-viewport-demo viewport="1000">
|
||||
<iframe srcdoc="" id="page_slots_iframe"></iframe>
|
||||
<iframe srcdoc="" id="page_slots_iframe" data-turbo="false" data-turbo-temporary></iframe>
|
||||
</wa-viewport-demo>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
const cacheBust = new Date().toString()
|
||||
import(`/assets/examples/page-demo/demo.js?${cacheBust}`)
|
||||
</script>
|
||||
<script type=module src="/assets/examples/page-demo/demo.js"></script>
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
{# Preset theme selector #}
|
||||
<wa-dropdown class="preset-theme-selector">
|
||||
<wa-button slot="trigger" appearance="filled" size="small" pill caret>
|
||||
<wa-dropdown id="preset-theme-selector">
|
||||
<wa-button slot="trigger" appearance="tinted" size="small" pill caret>
|
||||
<wa-icon slot="prefix" name="paintbrush" variant="regular"></wa-icon>
|
||||
<span class="preset-theme-selector__text">Default</span>
|
||||
<span id="preset-theme-selector__text">Default</span>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item type="checkbox" value="default" data-description="Your trusty companion, like a perfectly broken-in pair of jeans.">Default</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="classic" data-description="Timeless elegance that never goes out of style.">Classic</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="awesome" data-description="Punchy and vibrant, the rockstar of themes.">Awesome</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="active" data-description="Energetic and tactile, always in motion.">Active</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="brutalist" data-description="Sharp, raw, and unapologetically bold.">Brutalist</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="glassy" data-description="TODO">Glassy</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="mellow" data-description="Soft and soothing, like a lazy Sunday morning.">Mellow</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="tailspin" data-description="Like a bird in flight, guiding you from there to here.">Tailspin</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="playful" data-description="TODO">Playful</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="premium" data-description="TODO">Premium</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="default">Default</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="classic">Classic</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="fa">Font Awesome</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="active">Active</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="brutalist">Brutalism</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="glassy">Glassy</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="migration">Migration</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="playful">Playful</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="premium">Premium</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<wa-input
|
||||
id="site-search-input"
|
||||
type="search"
|
||||
appearance="filled"
|
||||
filled
|
||||
size="large"
|
||||
clearable
|
||||
placeholder="Search"
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{# Some collections (like "patterns") will not have any items in the alpha build for example. So this checks to make sure the collection exists. #}
|
||||
{% if collections[tag] -%}
|
||||
<wa-details {{ (tag in (tags or [])) | attr('open') }}>
|
||||
<h2 slot="summary">
|
||||
{% set groupUrl %}/docs/{{ tag }}/{% endset %}
|
||||
{% if groupUrl | getCollectionItemFromUrl %}
|
||||
<a href="{{ groupUrl }}" title="Overview">{{ title or (tag | capitalize) }}
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
{% else %}
|
||||
{{ title or (tag | capitalize) }}
|
||||
{% endif %}
|
||||
</h2>
|
||||
<ul>
|
||||
{% for page in collections[tag] | sort %}
|
||||
{% if not page.data.parent -%}
|
||||
{% include 'sidebar-link.njk' %}
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</wa-details>
|
||||
{%- endif %}
|
||||
@@ -1,16 +0,0 @@
|
||||
{% if not (isAlpha and page.data.noAlpha) and page.fileSlug != tag and not page.data.unlisted -%}
|
||||
<li>
|
||||
<a href="{{ page.url }}">{{ page.data.title }}</a>
|
||||
{% if page.data.status == 'experimental' %}<wa-icon name="flask"></wa-icon>{% endif %}
|
||||
{% if page.data.isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
|
||||
|
||||
{% set children = page.data.children %}
|
||||
{% if children.length > 0 %}
|
||||
<ul>
|
||||
{% for page in children %}
|
||||
{% include 'sidebar-link.njk' %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{%- endif %}
|
||||
@@ -19,13 +19,298 @@
|
||||
<li><a href="/docs/resources/changelog">Changelog</a></li>
|
||||
</ul>
|
||||
|
||||
{% for tag, title in {
|
||||
'components': 'Components',
|
||||
'native': 'Native Styles',
|
||||
'utilities': 'Style Utilities',
|
||||
'layout': 'Layout',
|
||||
'patterns': 'Patterns',
|
||||
'theming': 'Theming'
|
||||
} %}
|
||||
{% include 'sidebar-group.njk' %}
|
||||
{% endfor %}
|
||||
{# Components #}
|
||||
<h2>
|
||||
<a href="/docs/components/" title="Overview">Components
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/components/animated-image">Animated Image</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/animation">Animation</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/avatar">Avatar</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/badge">Badge</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/breadcrumb">Breadcrumb</a>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/components/breadcrumb-item">Breadcrumb Item</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/button">Button</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/button-group">Button Group</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/callout">Callout</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/card">Card</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/carousel">Carousel</a>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/components/carousel-item">Carousel Item</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/checkbox">Checkbox</a>
|
||||
</li>
|
||||
{% if not isAlpha %}
|
||||
<li>
|
||||
<a href="/docs/components/code-demo">Code Demo</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="/docs/components/color-picker">Color Picker</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/copy-button">Copy Button</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/details">Details</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/dialog">Dialog</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/divider">Divider</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/drawer">Drawer</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/dropdown">Dropdown</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/format-bytes">Format Bytes</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/format-date">Format Date</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/format-number">Format Number</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/icon">Icon</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/icon-button">Icon Button</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/image-comparer">Image Comparer</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/include">Include</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/input">Input</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/menu">Menu</a>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/components/menu-item">Menu Item</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/menu-label">Menu Label</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/mutation-observer">Mutation Observer</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/page">Page</a>
|
||||
<wa-icon name="flask"></wa-icon>
|
||||
<wa-badge class="pro">PRO</wa-badge>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/popup">Popup</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/progress-bar">Progress Bar</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/progress-ring">Progress Ring</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/qr-code">QR Code</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/radio-group">Radio Group</a>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/components/radio">Radio</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/radio-button">Radio Button</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/range">Range</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/rating">Rating</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/relative-time">Relative Time</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/resize-observer">Resize Observer</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/select">Select</a>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/components/option">Option</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/skeleton">Skeleton</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/spinner">Spinner</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/split-panel">Split Panel</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/switch">Switch</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/tab-group">Tab Group</a>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/components/tab">Tab</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/tab-panel">Tab Panel</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/tag">Tag</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/textarea">Textarea</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/tooltip">Tooltip</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/components/tree">Tree</a>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/components/tree-item">Tree Item</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{% if not isAlpha %}
|
||||
<li>
|
||||
<a href="/docs/components/viewport-demo">Viewport Demo</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="/docs/components/visually-hidden">Visually Hidden</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{# Layout #}
|
||||
{% if not isAlpha %}
|
||||
<h2>
|
||||
<a href="/docs/layout" title="Overview">Layout
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
<ul>
|
||||
<li><a href="/docs/components/page">Page</a></li>
|
||||
<li><a href="/docs/layout/cluster">Cluster</a></li>
|
||||
<li><a href="/docs/layout/flank">Flank</a></li>
|
||||
<li><a href="/docs/layout/frame">Frame</a></li>
|
||||
<li><a href="/docs/layout/grid">Grid</a></li>
|
||||
<li><a href="/docs/layout/split">Split</a></li>
|
||||
<li><a href="/docs/layout/stack">Stack</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{# Patterns #}
|
||||
{% if not isAlpha %}
|
||||
<h2>Patterns</h2>
|
||||
<ul>
|
||||
<li><a href="/docs/patterns/app">Web App</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce">E-commerce</a>
|
||||
<ul>
|
||||
<li><a href="/docs/patterns/ecommerce-product-review">Product Reviews</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-product-list">Product Lists</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-category-preview">Category Previews</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-shopping-cart">Shopping Carts</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-category-filter">Category Filters</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-product-detail">Product Detail</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-order-summary">Order Summaries</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-order-history">Order History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="/docs/patterns/blog">Blog</a></li>
|
||||
<li><a href="/docs/patterns/news">News</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{# Theming #}
|
||||
<h2>
|
||||
<a href="/docs/theming" title="Overview">Theming
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/theming/color">Color</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/typography">Typography</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/space">Space</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/borders">Borders</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/focus">Focus</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/shadows">Shadows</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/transitions">Transitions</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/component-groups">Component Groups</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{# Style Utilities #}
|
||||
{% if not isAlpha %}
|
||||
<h2>Style Utilities</h2>
|
||||
<ul>
|
||||
<li><a href="/docs/style-utilities/align-items">Align Items</a></li>
|
||||
<li><a href="/docs/style-utilities/border-radius">Border Radius</a></li>
|
||||
<li><a href="/docs/style-utilities/gap">Gap</a></li>
|
||||
<li><a href="/docs/style-utilities/text">Text</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
{% if since -%}
|
||||
<wa-badge variant="neutral">Since {{ since }}</wa-badge>
|
||||
{%- endif %}
|
||||
|
||||
{% if status -%}
|
||||
{%- if status == "wip" %}
|
||||
<wa-badge variant="danger">
|
||||
<wa-icon name="pickaxe"></wa-icon>
|
||||
Work In Progress
|
||||
</wa-badge>
|
||||
{%- elif status == "experimental" -%}
|
||||
<wa-badge variant="warning">
|
||||
<wa-icon name="flask"></wa-icon>
|
||||
Experimental
|
||||
</wa-badge>
|
||||
{%- elif status == "stable" -%}
|
||||
<wa-badge variant="brand">Stable</wa-badge>
|
||||
{%- else %}
|
||||
<wa-badge>{{ status}}</wa-badge>
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
|
||||
{% if isPro -%}
|
||||
<wa-badge class="pro">PRO</wa-badge>
|
||||
{%- endif %}
|
||||
|
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 337 B |
@@ -21,9 +21,10 @@
|
||||
{# Web Awesome #}
|
||||
<script type="module" src="/dist/webawesome.ssr-loader.js"></script>
|
||||
<link rel="stylesheet" id="theme-stylesheet" />
|
||||
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/utilities.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/forms.css" />
|
||||
<link rel="stylesheet" href="/dist/themes/applied.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/layout.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/themes/utilities.css" />
|
||||
<link rel="stylesheet" href="/dist/themes/forms.css" />
|
||||
|
||||
{# Set the theme to prevent flashing #}
|
||||
<script>
|
||||
@@ -46,14 +47,17 @@
|
||||
const stylesheet = document.getElementById("theme-stylesheet")
|
||||
let preset = getPresetTheme()
|
||||
|
||||
stylesheet.href = `/dist/styles/themes/${preset}.css`
|
||||
stylesheet.href = `/dist/themes/${preset}.css`
|
||||
|
||||
document.documentElement.classList.toggle(`wa-dark`, isDark());
|
||||
document.documentElement.classList.toggle(
|
||||
`wa-theme-${preset}-dark`,
|
||||
isDark()
|
||||
);
|
||||
</script>
|
||||
</head>
|
||||
<body class="layout-{{ layout | stripExtension }}">
|
||||
|
||||
{% block header %}{% endblock %}
|
||||
{% block beforeContent %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ content | safe }}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
|
||||
{% extends '../_includes/base.njk' %}
|
||||
|
||||
{# Component header #}
|
||||
{% block header %}
|
||||
{% include 'breadcrumbs.njk' %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
<div class="block-info">
|
||||
{% set snippets = (elements or element or snippets or snippet) | dict %}
|
||||
|
||||
{% for snippet, link in snippets %}
|
||||
{% if snippet %}
|
||||
<code class="class">
|
||||
{%- if link -%}
|
||||
<a href="{{ link }}">{{ snippet }}</a>
|
||||
{%- else -%}
|
||||
{{ snippet }}
|
||||
{%- endif-%}
|
||||
</code>
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% include '../_includes/status.njk' %}
|
||||
</div>
|
||||
{% if description %}
|
||||
<p class="summary">
|
||||
{{ description | inlineMarkdown | safe }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% block notes %}{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{# Content #}
|
||||
{% block content %}
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
@@ -1,15 +1,35 @@
|
||||
{% extends '../_layouts/block.njk' %}
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
{% set component = components[page.fileSlug] %}
|
||||
{% set description = component.summary %}
|
||||
|
||||
{% extends '../_includes/base.njk' %}
|
||||
|
||||
{# Component header #}
|
||||
{% block notes %}
|
||||
{% if native %}
|
||||
<wa-callout variant="success">
|
||||
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
|
||||
Just want the styles?
|
||||
Check out the <a href="/docs/native/{{ native }}/">{{ ('/docs/native/' + native + '/') | getTitleFromUrl }} native styles</a>!
|
||||
</wa-callout>
|
||||
{% endif %}
|
||||
{% block beforeContent %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
<div class="component-info">
|
||||
<code class="component-tag"><{{ component.tagName }}></code>
|
||||
<wa-badge variant="neutral">Since {{ component.since }}</wa-badge>
|
||||
<wa-badge
|
||||
{% if component.status == 'stable' %}variant="brand"{% endif %}
|
||||
{% if component.status == 'experimental' %}variant="warning"{% endif %}
|
||||
>
|
||||
{{ component.status }}
|
||||
</wa-badge>
|
||||
{# TODO - add a pro flag for pro components #}
|
||||
{% if component.tagName == 'wa-page' %}
|
||||
<wa-badge class="pro">PRO</wa-badge>
|
||||
{% endif %}
|
||||
</div>
|
||||
<p class="component-summary">
|
||||
{{ component.summary | inlineMarkdown | safe }}
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
||||
{# Content #}
|
||||
{% block content %}
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
|
||||
{# Component API #}
|
||||
@@ -17,7 +37,6 @@
|
||||
{# Slots #}
|
||||
{% if component.slots.length %}
|
||||
<h2>Slots</h2>
|
||||
<p>Learn more about <a href="/docs/usage/#slots">using slots</a>.</p>
|
||||
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
@@ -48,7 +67,6 @@
|
||||
{# Properties #}
|
||||
{% if component.properties.length %}
|
||||
<h2>Attributes & Properties</h2>
|
||||
<p>Learn more about <a href="/docs/usage/#attributes-and-properties">attributes and properties</a>.</p>
|
||||
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
@@ -95,8 +113,6 @@
|
||||
{# Methods #}
|
||||
{% if component.methods.length %}
|
||||
<h2>Methods</h2>
|
||||
<p>Learn more about <a href="/docs/usage/#methods">methods</a>.</p>
|
||||
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
@@ -127,10 +143,34 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# States #}
|
||||
{% if component.states.length %}
|
||||
<h2>States</h2>
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="table-name">Name</th>
|
||||
<th class="table-description">Description</th>
|
||||
<th class="table-selector">CSS selector</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for state in component.states %}
|
||||
<tr>
|
||||
<td class="table-name"><code>{{ state.name }}</code></td>
|
||||
<td class="table-description">{{ state.description | inlineMarkdown | safe }}</td>
|
||||
<td class="table-selector"><code>[data-state-{{ state.name }}]</code></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Events #}
|
||||
{% if component.events.length %}
|
||||
<h2>Events</h2>
|
||||
<p>Learn more about <a href="/docs/usage/#events">events</a>.</p>
|
||||
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
@@ -157,7 +197,6 @@
|
||||
{# Custom Properties #}
|
||||
{% if component.cssProperties.length %}
|
||||
<h2>CSS custom properties</h2>
|
||||
<p>Learn more about <a href="/docs/customizing/#custom-properties">CSS custom properties</a>.</p>
|
||||
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
@@ -186,37 +225,9 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Custom States #}
|
||||
{% if component.cssStates.length %}
|
||||
<h2>Custom States</h2>
|
||||
<p>Learn more about <a href="/docs/customizing/#custom-states">custom states</a>.</p>
|
||||
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="table-name">Name</th>
|
||||
<th class="table-description">Description</th>
|
||||
<th class="table-selector">CSS selector</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for state in component.cssStates %}
|
||||
<tr>
|
||||
<td class="table-name"><code>{{ state.name }}</code></td>
|
||||
<td class="table-description">{{ state.description | inlineMarkdown | safe }}</td>
|
||||
<td class="table-selector"><code>:state({{ state.name }})</code></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# CSS Parts #}
|
||||
{% if component.cssParts.length %}
|
||||
<h2>CSS parts</h2>
|
||||
<p>Learn more about <a href="/docs/customizing/#css-parts">CSS parts</a>.</p>
|
||||
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
@@ -242,7 +253,7 @@
|
||||
{% if component.dependencies.length %}
|
||||
<h2>Dependencies</h2>
|
||||
<p>
|
||||
This component automatically imports the following elements. Sub-dependencies, if any exist, will also be included in this list.
|
||||
This component automatically imports the following elements. Subdependencies, if any exist, will also be included in this list.
|
||||
</p>
|
||||
|
||||
<ul class="dependency-list">
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
{% extends '../_layouts/block.njk' %}
|
||||
|
||||
{# Component header #}
|
||||
{% block notes %}
|
||||
{% if component %}
|
||||
<wa-callout variant="success">
|
||||
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
|
||||
Want to do more?
|
||||
Check out the {% for name in (component | toList) -%}
|
||||
{{ ' and ' if loop.last and not loop.first }}<a href="/docs/components/{{ name }}"><code><wa-{{ name }}></code></a>{{ ', ' if not loop.last }}
|
||||
{%- endfor %} component{{ 's' if (component | isList) }}</a>!
|
||||
</wa-callout>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block afterContent %}
|
||||
{# Slots #}
|
||||
{% if css_file %}
|
||||
<h2>Using these styles</h2>
|
||||
<p>If you want to use these styles without using the entirety of Web Awesome Native Styles, you can include the following CSS files:</p>
|
||||
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
layout: page-outline
|
||||
tags: ["overview"]
|
||||
---
|
||||
{% set forTag = forTag or (page.url | split('/') | last) %}
|
||||
{% if description %}
|
||||
<div class="index-summary">{{ description | markdown | safe }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="block-filter">
|
||||
<wa-input type="search" placeholder="Search {{ title }}" clearable autofocus>
|
||||
<wa-icon slot="prefix" name="search"></wa-icon>
|
||||
</wa-input>
|
||||
</div>
|
||||
|
||||
{% set allPages = collections[forTag] %}
|
||||
{% include "grouped-pages.njk" %}
|
||||
|
||||
<link href="/assets/styles/filter.css" rel="stylesheet">
|
||||
<script type="module" src="/assets/scripts/filter.js"></script>
|
||||
|
||||
{% if content | trim %}
|
||||
<br> {# Temp fix for spacing issue #}
|
||||
{{ content | safe }}
|
||||
{% endif %}
|
||||
4
docs/_layouts/pattern.njk
Normal file
@@ -0,0 +1,4 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
|
||||
{% extends "../_includes/base.njk" %}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { parse } from 'node-html-parser';
|
||||
import slugify from 'slugify';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import slugify from 'slugify';
|
||||
|
||||
function createId(text) {
|
||||
let slug = slugify(String(text), {
|
||||
remove: /[^\w|\s]/g,
|
||||
lower: true,
|
||||
lower: true
|
||||
});
|
||||
|
||||
// ids must start with a letter
|
||||
@@ -24,7 +24,7 @@ export function anchorHeadingsPlugin(options = {}) {
|
||||
container: 'body',
|
||||
headingSelector: 'h2, h3, h4, h5, h6',
|
||||
anchorLabel: 'Jump to heading',
|
||||
...options,
|
||||
...options
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
|
||||
@@ -53,7 +53,7 @@ const templates = {
|
||||
attributes = {
|
||||
open,
|
||||
include: `link[rel=stylesheet][href^='/dist/']`,
|
||||
...attributes,
|
||||
...attributes
|
||||
};
|
||||
|
||||
const attributesString = Object.entries(attributes)
|
||||
@@ -93,7 +93,7 @@ const templates = {
|
||||
${pre.outerHTML}
|
||||
</wa-code-demo>
|
||||
`;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -107,13 +107,13 @@ export function codeExamplesPlugin(eleventyConfig, options = {}) {
|
||||
outputPathIndex === 1 && // is first
|
||||
code.textContent.length < 500
|
||||
); // is short
|
||||
},
|
||||
}
|
||||
};
|
||||
options = { ...defaultOptions, ...options };
|
||||
|
||||
const stats = {
|
||||
inputPaths: {},
|
||||
outputPaths: {},
|
||||
outputPaths: {}
|
||||
};
|
||||
|
||||
eleventyConfig.addTransform('code-examples', function (content) {
|
||||
@@ -144,7 +144,7 @@ export function codeExamplesPlugin(eleventyConfig, options = {}) {
|
||||
edit: true,
|
||||
buttons: true,
|
||||
new: true, // comment this line to default back to the old demos
|
||||
attributes: {},
|
||||
attributes: {}
|
||||
};
|
||||
|
||||
for (const prop of ['new', 'open', 'buttons', 'edit']) {
|
||||
@@ -174,7 +174,7 @@ export function codeExamplesPlugin(eleventyConfig, options = {}) {
|
||||
localOptions.open = localOptions.defaultOpen(code, {
|
||||
pre,
|
||||
inputPathIndex: stats.inputPaths[inputPath],
|
||||
outputPathIndex: stats.outputPaths[outputPath],
|
||||
outputPathIndex: stats.outputPaths[outputPath]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { parse } from 'node-html-parser';
|
||||
export function copyCodePlugin(options = {}) {
|
||||
options = {
|
||||
container: 'body',
|
||||
...options,
|
||||
...options
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
|
||||
@@ -28,7 +28,7 @@ export function currentLink(options = {}) {
|
||||
options = {
|
||||
container: 'body',
|
||||
className: 'current',
|
||||
...options,
|
||||
...options
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
|
||||
@@ -1,264 +0,0 @@
|
||||
import { parse } from 'path';
|
||||
|
||||
export function stripExtension(string) {
|
||||
return parse(string).name;
|
||||
}
|
||||
|
||||
export function stripPrefix(content) {
|
||||
return content.replace(/^wa-/, '');
|
||||
}
|
||||
|
||||
// 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 be present when the line wraps.
|
||||
export function trimPipes(content) {
|
||||
return typeof content === 'string' ? content.replace(/^(\s|\|)/g, '').replace(/(\s|\|)$/g, '') : content;
|
||||
}
|
||||
|
||||
export function keys(obj) {
|
||||
return Object.keys(obj);
|
||||
}
|
||||
|
||||
export function log(firstArg, ...rest) {
|
||||
console.log(firstArg, ...rest);
|
||||
return firstArg;
|
||||
}
|
||||
|
||||
function getCollection(name) {
|
||||
// From https://github.com/11ty/eleventy/blob/d3d24ccddb804e6e14773501d8c4e07e2c4b9c2b/src/Filters/GetLocaleCollectionItem.js#L39-L43
|
||||
return this.collections?.[name] || this.ctx?.collections?.[name] || this.context?.environments?.collections?.[name];
|
||||
}
|
||||
|
||||
export function getCollectionItemFromUrl(url, collection) {
|
||||
collection ??= getCollection.call(this, 'all') || [];
|
||||
return collection.find(item => item.url === url);
|
||||
}
|
||||
|
||||
export function getTitleFromUrl(url, collection) {
|
||||
const item = getCollectionItemFromUrl.call(this, url, collection);
|
||||
return item?.data.title || '';
|
||||
}
|
||||
|
||||
export function split(text, separator) {
|
||||
return (text + '').split(separator).filter(Boolean);
|
||||
}
|
||||
|
||||
export function breadcrumbs(url, { withCurrent = false } = {}) {
|
||||
const parts = split(url, '/');
|
||||
const ret = [];
|
||||
|
||||
while (parts.length) {
|
||||
let partialUrl = '/' + parts.join('/') + '/';
|
||||
let item = getCollectionItemFromUrl.call(this, partialUrl);
|
||||
|
||||
if (item && (partialUrl !== url || withCurrent)) {
|
||||
let title = item.data.title;
|
||||
if (title) {
|
||||
ret.unshift({ url: partialUrl, title });
|
||||
}
|
||||
}
|
||||
|
||||
parts.pop();
|
||||
|
||||
if (item?.data.parent) {
|
||||
let parentURL = item.data.parent;
|
||||
if (!item.data.parent.startsWith('/')) {
|
||||
// Parent is in the same directory
|
||||
parts.push(item.data.parent);
|
||||
parentURL = '/' + parts.join('/') + '/';
|
||||
}
|
||||
|
||||
let parentBreadcrumbs = breadcrumbs.call(this, parentURL, { withCurrent: true });
|
||||
return [...parentBreadcrumbs, ...ret];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function isObject(value) {
|
||||
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
export function isList(value) {
|
||||
return Array.isArray(value) || value instanceof Set;
|
||||
}
|
||||
|
||||
/** Get an Array or Set */
|
||||
export function toList(value) {
|
||||
return isList(value) ? value : [value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any value to something that can be iterated over with a for key, value loop.
|
||||
* Arrays and sets will be converted to a Map of value -> undefined
|
||||
*/
|
||||
export function dict(value) {
|
||||
if (value instanceof Map || isObject(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
let list = toList(value);
|
||||
return new Map([...list].map(item => [item, undefined]));
|
||||
}
|
||||
|
||||
export function deepValue(obj, key) {
|
||||
key = Array.isArray(key) ? key : key.split('.');
|
||||
return key.reduce((subObj, property) => subObj?.[property], obj);
|
||||
}
|
||||
|
||||
export function isNumeric(value) {
|
||||
return typeof value === 'number' || (typeof value === 'string' && !isNaN(value));
|
||||
}
|
||||
|
||||
export function isString(value) {
|
||||
return typeof value === 'string';
|
||||
}
|
||||
|
||||
export function isEmpty(value) {
|
||||
return value === null || value === undefined || value === '';
|
||||
}
|
||||
|
||||
function compare(a, b) {
|
||||
let isEmptyA = isEmpty(a);
|
||||
let isEmptyB = isEmpty(b);
|
||||
|
||||
if (isEmptyA) {
|
||||
if (isEmptyB) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if (isEmptyB) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Both strings, and at least one non-numeric
|
||||
if (isNumeric(a) || isNumeric(b)) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
return (a + '').localeCompare(b);
|
||||
}
|
||||
|
||||
/** Sort an array of objects by one or more of their properties */
|
||||
export function sort(arr, by = { 'data.order': 1, 'data.title': '' }) {
|
||||
let keys = Array.isArray(by) ? by : Object.keys(by);
|
||||
|
||||
return arr.sort((a, b) => {
|
||||
let aValues = keys.map(key => deepValue(a, key) ?? by[key]);
|
||||
let bValues = keys.map(key => deepValue(b, key) ?? by[key]);
|
||||
|
||||
for (let i = 0; i < aValues.length; i++) {
|
||||
let aVal = aValues[i];
|
||||
let bVal = bValues[i];
|
||||
let result = compare(aVal, bVal);
|
||||
|
||||
// They are not equal in terms of comparison OR we're at the last key
|
||||
if (result !== 0 || i === aValues.length - 1) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Group an 11ty collection (or any array of objects with a `data.tags` property) by certain tags.
|
||||
* @param {object[]} collection
|
||||
* @param { Object<string, string> | (string | Object<string, string>)[]} [tags] The tags to group by. If not provided/empty, defaults to grouping by all tags.
|
||||
* @returns { Object.<string, object[]> } An object with keys for each tag, and an array of items for each tag.
|
||||
*/
|
||||
export function groupByTags(collection, tags) {
|
||||
if (!tags) {
|
||||
// Default to grouping by union of all tags
|
||||
tags = Array.from(new Set(collection.flatMap(item => item.data.tags)));
|
||||
} else if (Array.isArray(tags)) {
|
||||
// May contain objects of one-off tag -> label mappings
|
||||
tags = tags.map(tag => (typeof tag === 'object' ? Object.keys(tag)[0] : tag));
|
||||
} else if (typeof tags === 'object') {
|
||||
// tags is an object of tags to labels, so we just want the keys
|
||||
tags = Object.keys(tags);
|
||||
}
|
||||
|
||||
let ret = Object.fromEntries(tags.map(tag => [tag, []]));
|
||||
ret.other = [];
|
||||
|
||||
for (let item of collection) {
|
||||
let categorized = false;
|
||||
|
||||
for (let tag of tags) {
|
||||
if (item.data.tags.includes(tag)) {
|
||||
ret[tag].push(item);
|
||||
categorized = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!categorized) {
|
||||
ret.other.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove empty categories
|
||||
for (let category in ret) {
|
||||
if (ret[category].length === 0) {
|
||||
delete ret[category];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function getCategoryTitle(category, categories) {
|
||||
let title;
|
||||
if (Array.isArray(categories)) {
|
||||
// Find relevant entry
|
||||
// [{id: "Title"}, id2, ...]
|
||||
title = categories.find(entry => typeof entry === 'object' && entry?.[category])?.[category];
|
||||
} else if (typeof categories === 'object') {
|
||||
// {id: "Title", id2: "Title 2", ...}
|
||||
title = categories[category];
|
||||
}
|
||||
|
||||
if (title) {
|
||||
return title;
|
||||
}
|
||||
|
||||
// Capitalized
|
||||
return category.charAt(0).toUpperCase() + category.slice(1);
|
||||
}
|
||||
|
||||
const IDENTITY = x => x;
|
||||
|
||||
/**
|
||||
* Helper to print out one or more HTML attributes, especially conditional ones.
|
||||
* Usage in 11ty:
|
||||
* - Single attribute: `<foo{{ value | attr(name) }}>`
|
||||
* - Multiple attributes: `<foo{{ { name1: value1, name2: value2 } | attr }}>`
|
||||
*
|
||||
* @overload
|
||||
* @param {any} value - The attribute value If falsey, the attribute is not printed. If `true` the attribute is printed without a value.
|
||||
* @param {string} name - The name of the attribute
|
||||
*
|
||||
* @overload
|
||||
* @param {Object<string, any>} obj - Map of attribute names to values
|
||||
*
|
||||
* @returns {string} The attribute string. No `| safe` is needed.
|
||||
*/
|
||||
export function attr(value, name) {
|
||||
const safe = this?.env.filters.safe ?? IDENTITY;
|
||||
|
||||
if (arguments.length === 1 && value && typeof value === 'object') {
|
||||
// Called with a single object argument of names to values
|
||||
let ret = Object.entries(obj)
|
||||
.map(([name, value]) => attr(value, name))
|
||||
.join('');
|
||||
return safe(ret);
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
// false, "", null, undefined
|
||||
return '';
|
||||
}
|
||||
|
||||
let ret = ' ' + name + (value === true ? '' : `="${value}"`);
|
||||
|
||||
return safe(ret);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import defaultOptions from '../../prettier.config.js';
|
||||
export async function formatCode(string, options) {
|
||||
return await format(string, {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
...options
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export async function formatCode(string, options) {
|
||||
export function formatCodePlugin(options = {}) {
|
||||
options = {
|
||||
parser: 'html',
|
||||
...options,
|
||||
...options
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* eslint sort-imports-es6-autofix/sort-imports-es6: 0 */
|
||||
import { parse } from 'node-html-parser';
|
||||
import Prism from 'prismjs';
|
||||
import PrismLoader from 'prismjs/components/index.js';
|
||||
import 'prismjs/plugins/custom-class/prism-custom-class.js';
|
||||
import PrismLoader from 'prismjs/components/index.js';
|
||||
|
||||
PrismLoader('diff');
|
||||
PrismLoader.silent = true;
|
||||
@@ -40,7 +40,7 @@ export function highlightCode(code, language = 'plain') {
|
||||
export function highlightCodePlugin(options = {}) {
|
||||
options = {
|
||||
container: 'body',
|
||||
...options,
|
||||
...options
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
|
||||
@@ -14,7 +14,7 @@ export const markdown = MarkdownIt({
|
||||
breaks: false,
|
||||
langPrefix: 'language-',
|
||||
linkify: false,
|
||||
typographer: false,
|
||||
typographer: false
|
||||
});
|
||||
|
||||
markdown.use(markdownItIns);
|
||||
@@ -34,7 +34,7 @@ markdown.use(markdownItMark);
|
||||
`;
|
||||
}
|
||||
return '</div></div>\n';
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@ markdown.use(markdownItContainer, 'aside', {
|
||||
return `<aside>`;
|
||||
}
|
||||
return '</aside>\n';
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
markdown.use(markdownItContainer, 'details', {
|
||||
@@ -55,9 +55,9 @@ markdown.use(markdownItContainer, 'details', {
|
||||
return `<details>\n<summary><span>${markdown.utils.escapeHtml(m[1])}</span></summary>\n`;
|
||||
}
|
||||
return '</details>\n';
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
markdown.use(markdownItAttrs, {
|
||||
allowedAttributes: [],
|
||||
allowedAttributes: []
|
||||
});
|
||||
|
||||
@@ -15,7 +15,7 @@ export function outlinePlugin(options = {}) {
|
||||
target: '.outline',
|
||||
selector: 'h2,h3',
|
||||
ifEmpty: () => null,
|
||||
...options,
|
||||
...options
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { parse } from 'node-html-parser';
|
||||
export function removeDataAlphaElements(options = {}) {
|
||||
options = {
|
||||
isAlpha: false,
|
||||
...options,
|
||||
...options
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* eslint-disable no-invalid-this */
|
||||
import { mkdir, writeFile } from 'fs/promises';
|
||||
import lunr from 'lunr';
|
||||
import { parse } from 'node-html-parser';
|
||||
import { dirname, join } from 'path';
|
||||
import { mkdir, writeFile } from 'fs/promises';
|
||||
import { parse } from 'node-html-parser';
|
||||
import lunr from 'lunr';
|
||||
|
||||
function collapseWhitespace(string) {
|
||||
return string.replace(/\s+/g, ' ');
|
||||
@@ -19,7 +19,7 @@ export function searchPlugin(options = {}) {
|
||||
getDescription: doc => doc.querySelector('meta[name="description"]')?.getAttribute('content') ?? '',
|
||||
getHeadings: doc => [...doc.querySelectorAll('h1, h2, h3, h4, h5, h6')].map(heading => heading.textContent ?? ''),
|
||||
getContent: doc => doc.querySelector('body')?.textContent ?? '',
|
||||
...options,
|
||||
...options
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
@@ -32,8 +32,8 @@ export function searchPlugin(options = {}) {
|
||||
noscript: false,
|
||||
style: false,
|
||||
pre: false,
|
||||
code: false,
|
||||
},
|
||||
code: false
|
||||
}
|
||||
});
|
||||
|
||||
// Remove content that shouldn't be searchable to reduce the index size
|
||||
@@ -46,7 +46,7 @@ export function searchPlugin(options = {}) {
|
||||
description: collapseWhitespace(options.getDescription(doc)),
|
||||
headings: options.getHeadings(doc).map(collapseWhitespace),
|
||||
content: collapseWhitespace(options.getContent(doc)),
|
||||
url: this.page.url === '/' ? '/' : this.page.url.replace(/\/$/, ''),
|
||||
url: this.page.url === '/' ? '/' : this.page.url.replace(/\/$/, '')
|
||||
});
|
||||
|
||||
return content;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
await customElements.whenDefined('wa-checkbox');
|
||||
let container = document.getElementById('page_slots_demo');
|
||||
|
||||
let fieldset = container.querySelector('fieldset');
|
||||
let iframe = container.querySelector('iframe');
|
||||
let stylesheets = Array.from(document.querySelectorAll("link[rel=stylesheet][href^='/dist/']"))
|
||||
@@ -9,17 +9,8 @@ let includes = `${stylesheets}
|
||||
<script src="/dist/webawesome.loader.js" type="module"></script>
|
||||
<link rel="stylesheet" href="/assets/examples/page-demo/page.css">`;
|
||||
|
||||
async function render() {
|
||||
await customElements.whenDefined('wa-checkbox');
|
||||
|
||||
// Let checkboxes update their "state"
|
||||
await Promise.allSettled(
|
||||
Array.from(fieldset.querySelectorAll('wa-checkbox[name=slot]')).map(checkbox => {
|
||||
return checkbox.updateComplete;
|
||||
}),
|
||||
);
|
||||
|
||||
let slots = Array.from(fieldset.querySelectorAll('wa-checkbox[name=slot]:state(checked)'));
|
||||
function render() {
|
||||
let slots = Array.from(fieldset.querySelectorAll('wa-checkbox[name=slot]:is([data-wa-checked])'));
|
||||
let slotsHTML = slots
|
||||
.map(slot => {
|
||||
let name = slot.getAttribute('value');
|
||||
@@ -47,5 +38,13 @@ async function render() {
|
||||
iframe.srcdoc = `${includes}<wa-page>${slotsHTML}</wa-page>`;
|
||||
}
|
||||
}
|
||||
await render();
|
||||
fieldset?.addEventListener('input', render);
|
||||
render();
|
||||
|
||||
//
|
||||
// TODO - fix Turbo caching. When this is removed, visiting the <wa-page> docs via Turbo will cause the <iframe srcdoc>
|
||||
// to not render. Even with this, there are console errors when leaving the page.
|
||||
//
|
||||
// NOTE - the iframe already has `data-turbo="false"` and `data-turbo-temporary` on it.
|
||||
//
|
||||
document.body.setAttribute('data-turbo', 'false');
|
||||
|
||||
@@ -26,7 +26,7 @@ wa-page {
|
||||
|
||||
.slot-content {
|
||||
padding: var(--wa-space-m);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
BIN
docs/assets/images/patterns/flower-crop-1.jpg
Normal file
|
After Width: | Height: | Size: 146 KiB |
BIN
docs/assets/images/patterns/flower-crop-2.jpg
Normal file
|
After Width: | Height: | Size: 326 KiB |
BIN
docs/assets/images/patterns/flower-crop-3.jpg
Normal file
|
After Width: | Height: | Size: 331 KiB |
|
Before Width: | Height: | Size: 698 KiB After Width: | Height: | Size: 698 KiB |
|
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 241 KiB |
|
Before Width: | Height: | Size: 786 KiB After Width: | Height: | Size: 786 KiB |
|
Before Width: | Height: | Size: 716 KiB After Width: | Height: | Size: 716 KiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 438 KiB After Width: | Height: | Size: 438 KiB |
@@ -13,7 +13,7 @@ const matchers = {
|
||||
regexp(textContent, query) {
|
||||
query.lastIndex = 0;
|
||||
return query.test(textContent);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
matchers.iregexp = matchers.regexp; // i is baked into the query
|
||||
|
||||
@@ -18,11 +18,12 @@ document.addEventListener('click', event => {
|
||||
const cdnUrl = document.documentElement.dataset.cdnUrl;
|
||||
const html =
|
||||
`<script type="module" src="${cdnUrl}webawesome.loader.js"></script>\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}styles/themes/default.css">\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}styles/webawesome.css">\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}styles/utilities.css">\n\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}themes/default.css">\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}themes/applied.css">\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}themes/layout.css">\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}themes/utilities.css">\n\n` +
|
||||
`${code.textContent}`;
|
||||
const css = 'html > body {\n padding: 2rem !important;\n}';
|
||||
const css = 'html > body {\n font: 16px sans-serif;\n padding: 2rem;\n}';
|
||||
const js = '';
|
||||
|
||||
const form = document.createElement('form');
|
||||
@@ -43,7 +44,7 @@ document.addEventListener('click', event => {
|
||||
js_pre_processor: 'none',
|
||||
html,
|
||||
css,
|
||||
js,
|
||||
js
|
||||
};
|
||||
|
||||
const input = document.createElement('input');
|
||||
|
||||
@@ -5,24 +5,22 @@
|
||||
function setColorScheme(newColorScheme) {
|
||||
colorScheme = newColorScheme;
|
||||
localStorage.setItem('colorScheme', colorScheme);
|
||||
const presetTheme = window.getPresetTheme();
|
||||
|
||||
// Update the UI
|
||||
updateSelection();
|
||||
|
||||
// Toggle the dark mode class
|
||||
document.documentElement.classList.toggle(`wa-dark`, window.isDark());
|
||||
document.documentElement.classList.toggle(`wa-theme-${presetTheme}-dark`, window.isDark());
|
||||
}
|
||||
|
||||
function updateSelection() {
|
||||
const menus = document.querySelectorAll('.color-scheme-selector wa-menu');
|
||||
|
||||
menus.forEach(menu => {
|
||||
if (!menu) return;
|
||||
[...menu.querySelectorAll('wa-menu-item')].forEach(async item => {
|
||||
await customElements.whenDefined(item.localName);
|
||||
await item.updateComplete;
|
||||
item.checked = item.getAttribute('value') === colorScheme;
|
||||
});
|
||||
const menu = document.querySelector('#color-scheme-selector wa-menu');
|
||||
if (!menu) return;
|
||||
[...menu.querySelectorAll('wa-menu-item')].forEach(async item => {
|
||||
await customElements.whenDefined(item.localName);
|
||||
await item.updateComplete;
|
||||
item.checked = item.getAttribute('value') === colorScheme;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,16 +28,14 @@
|
||||
|
||||
// Selection is not preserved when changing page, so update when opening dropdown
|
||||
document.addEventListener('wa-show', event => {
|
||||
const colorSchemeSelector = event.target.closest('.color-scheme-selector');
|
||||
const colorSchemeSelector = event.target.closest('#color-scheme-selector');
|
||||
if (!colorSchemeSelector) return;
|
||||
updateSelection();
|
||||
});
|
||||
|
||||
// Listen for selections
|
||||
document.addEventListener('wa-select', event => {
|
||||
const selector = event.target.closest('.color-scheme-selector');
|
||||
const menu = selector?.querySelector('wa-menu');
|
||||
console.log(menu);
|
||||
const menu = event.target.closest('#color-scheme-selector wa-menu');
|
||||
if (!menu) return;
|
||||
setColorScheme(event.detail.item.value);
|
||||
});
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
function updateResults(input) {
|
||||
const filter = input.value.toLowerCase().trim();
|
||||
let filtered = Boolean(filter);
|
||||
|
||||
for (let grid of document.querySelectorAll('.index-grid')) {
|
||||
grid.classList.toggle('filtered', filtered);
|
||||
|
||||
for (let item of grid.querySelectorAll('a:has(> wa-card)')) {
|
||||
let isMatch = true;
|
||||
|
||||
if (filter) {
|
||||
const content = item.textContent.toLowerCase() + ' ' + (item.getAttribute('data-keywords') + ' ');
|
||||
isMatch = content.includes(filter);
|
||||
}
|
||||
|
||||
item.hidden = !isMatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.documentElement.addEventListener('wa-input', e => {
|
||||
if (e.target?.matches('#block-filter wa-input')) {
|
||||
updateResults(e.target);
|
||||
}
|
||||
});
|
||||
@@ -79,8 +79,8 @@
|
||||
diffViewer.appendChild(
|
||||
createDiff({
|
||||
serverHTML,
|
||||
clientHTML,
|
||||
}),
|
||||
clientHTML
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -88,7 +88,7 @@
|
||||
function createDiff({ serverHTML, clientHTML }) {
|
||||
const diff = diffLines(serverHTML, clientHTML, {
|
||||
ignoreWhitespace: false,
|
||||
newLineIsToken: true,
|
||||
newLineIsToken: true
|
||||
});
|
||||
const fragment = document.createDocumentFragment();
|
||||
for (var i = 0; i < diff.length; i++) {
|
||||
|
||||
@@ -1,98 +1,70 @@
|
||||
//
|
||||
// Preset theme selector
|
||||
//
|
||||
(() => {
|
||||
function applyThemeChange(stylesheet, newStylesheet) {
|
||||
newStylesheet.rel = 'stylesheet';
|
||||
newStylesheet.id = stylesheet.id;
|
||||
requestAnimationFrame(() => {
|
||||
stylesheet.remove();
|
||||
});
|
||||
}
|
||||
|
||||
function setPresetTheme(newPresetTheme) {
|
||||
presetTheme = newPresetTheme;
|
||||
localStorage.setItem('presetTheme', presetTheme);
|
||||
|
||||
const stylesheet = document.getElementById('theme-stylesheet');
|
||||
|
||||
const newStylesheet = Object.assign(document.createElement('link'), {
|
||||
href: `/dist/styles/themes/${presetTheme}.css`,
|
||||
href: `/dist/themes/${presetTheme}.css`,
|
||||
rel: 'preload',
|
||||
as: 'style',
|
||||
as: 'style'
|
||||
});
|
||||
|
||||
newStylesheet.addEventListener(
|
||||
'load',
|
||||
() => {
|
||||
const canUseViewTransitions =
|
||||
document.startViewTransition && !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
|
||||
if (canUseViewTransitions) {
|
||||
document.startViewTransition(() => applyThemeChange(stylesheet, newStylesheet));
|
||||
} else {
|
||||
applyThemeChange(stylesheet, newStylesheet);
|
||||
}
|
||||
newStylesheet.rel = 'stylesheet';
|
||||
newStylesheet.id = stylesheet.id;
|
||||
requestAnimationFrame(() => {
|
||||
stylesheet.remove();
|
||||
});
|
||||
},
|
||||
{ once: true },
|
||||
{ once: true }
|
||||
);
|
||||
|
||||
document.head.append(newStylesheet);
|
||||
|
||||
// Update the UI
|
||||
updateSelection();
|
||||
document.documentElement.classList.toggle(`wa-dark`, window.isDark());
|
||||
|
||||
// Toggle the dark mode class
|
||||
document.documentElement.classList.toggle(`wa-theme-${presetTheme}-dark`, window.isDark());
|
||||
}
|
||||
|
||||
function updateSelection(container = document) {
|
||||
const menus = container.querySelectorAll('.preset-theme-selector wa-menu');
|
||||
if (!menus) return;
|
||||
|
||||
[...menus].forEach(menu => {
|
||||
// Clear all checked states
|
||||
[...menu.querySelectorAll('wa-menu-item')].forEach(async item => {
|
||||
await customElements.whenDefined(item.localName);
|
||||
await item.updateComplete;
|
||||
item.checked = false; // Reset all items to unchecked first
|
||||
});
|
||||
|
||||
// Then set only the selected item as checked
|
||||
const selectedItem = menu.querySelector(`wa-menu-item[value="${presetTheme}"]`);
|
||||
if (selectedItem) {
|
||||
customElements.whenDefined(selectedItem.localName).then(async () => {
|
||||
await selectedItem.updateComplete;
|
||||
selectedItem.checked = true;
|
||||
container.querySelectorAll('.preset-theme-selector__text').forEach(themeSelector => {
|
||||
themeSelector.textContent = selectedItem.innerText;
|
||||
});
|
||||
});
|
||||
const menu = container.querySelector('#preset-theme-selector wa-menu');
|
||||
if (!menu) return;
|
||||
[...menu.querySelectorAll('wa-menu-item')].forEach(async item => {
|
||||
const isChecked = item.getAttribute('value') === presetTheme;
|
||||
if (isChecked) {
|
||||
container.querySelector('#preset-theme-selector__text').textContent = item.innerText;
|
||||
}
|
||||
await customElements.whenDefined(item.localName);
|
||||
await item.updateComplete;
|
||||
item.checked = isChecked;
|
||||
});
|
||||
}
|
||||
|
||||
// Updates any element on the page with [data-theme-name] and [data-theme-description] with the current themes info
|
||||
function updateThemeNameAndDescription(name, description) {
|
||||
document.querySelectorAll('[data-theme-name]').forEach(el => (el.textContent = name));
|
||||
document.querySelectorAll('[data-theme-description]').forEach(el => (el.textContent = description));
|
||||
}
|
||||
|
||||
let presetTheme = window.getPresetTheme();
|
||||
|
||||
// Selection is not preserved when changing page, so update when opening dropdown
|
||||
document.addEventListener('wa-show', event => {
|
||||
const presetThemeSelector = event.target.closest('.preset-theme-selector');
|
||||
const presetThemeSelector = event.target.closest('#preset-theme-selector');
|
||||
if (!presetThemeSelector) return;
|
||||
updateSelection();
|
||||
});
|
||||
|
||||
// Listen for selections
|
||||
document.addEventListener('wa-select', event => {
|
||||
const menu = event.target.closest('.preset-theme-selector wa-menu');
|
||||
const menu = event.target.closest('#preset-theme-selector wa-menu');
|
||||
if (!menu) return;
|
||||
setPresetTheme(event.detail.item.value);
|
||||
updateThemeNameAndDescription(event.detail.item.textContent, event.detail.item.getAttribute('data-description'));
|
||||
});
|
||||
|
||||
// Set the initial preset name/description in the UI by grabbing it from the dropdown (ugly, but quick)
|
||||
const currentTheme = document.querySelector(`.preset-theme-selector wa-menu-item[value="${presetTheme}"]`);
|
||||
if (currentTheme) {
|
||||
updateThemeNameAndDescription(currentTheme.textContent, currentTheme.getAttribute('data-description'));
|
||||
}
|
||||
|
||||
// Update the color scheme when the preference changes
|
||||
window.matchMedia('(prefers-preset-theme: dark)').addEventListener('change', () => setPresetTheme(presetTheme));
|
||||
updateSelection();
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
// Smooth links
|
||||
document.addEventListener('click', event => {
|
||||
const link = event.target.closest('a');
|
||||
const id = (link?.hash ?? '').substr(1);
|
||||
|
||||
if (!link || link.getAttribute('data-smooth-link') === 'off') {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = (link.hash ?? '').substr(1);
|
||||
|
||||
// Only handle smooth scroll if there's a hash and the link points to the current page
|
||||
if (id && link.pathname === window.location.pathname) {
|
||||
if (id) {
|
||||
const target = document.getElementById(id);
|
||||
const headerHeight = document.querySelector('wa-page > header').clientHeight;
|
||||
|
||||
@@ -16,7 +15,7 @@ document.addEventListener('click', event => {
|
||||
event.preventDefault();
|
||||
window.scroll({
|
||||
top: target.offsetTop - headerHeight,
|
||||
behavior: 'smooth',
|
||||
behavior: 'smooth'
|
||||
});
|
||||
history.pushState(undefined, undefined, `#${id}`);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ const icons = {
|
||||
component: 'puzzle-piece',
|
||||
document: 'file',
|
||||
home: 'house',
|
||||
theme: 'palette',
|
||||
theme: 'palette'
|
||||
};
|
||||
let searchTimeout;
|
||||
|
||||
@@ -18,7 +18,7 @@ function getElements() {
|
||||
return {
|
||||
dialog: document.getElementById('site-search'),
|
||||
input: document.getElementById('site-search-input'),
|
||||
results: document.getElementById('site-search-listbox'),
|
||||
results: document.getElementById('site-search-listbox')
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ function saveScrollPosition() {
|
||||
if (element.id) {
|
||||
positions[element.id] = {
|
||||
top: element.scrollTop,
|
||||
left: element.scrollLeft,
|
||||
left: element.scrollLeft
|
||||
};
|
||||
} else {
|
||||
console.warn(`Can't save scroll position for elements without an id.`, el);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.code-example {
|
||||
border: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
color: var(--wa-color-text-normal);
|
||||
margin-block-end: var(--wa-flow-spacing);
|
||||
}
|
||||
@@ -41,8 +41,8 @@
|
||||
border-bottom: none;
|
||||
|
||||
pre {
|
||||
border-bottom-right-radius: var(--wa-border-radius-l);
|
||||
border-bottom-left-radius: var(--wa-border-radius-l);
|
||||
border-bottom-right-radius: var(--wa-border-radius-m);
|
||||
border-bottom-left-radius: var(--wa-border-radius-m);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,11 +62,11 @@
|
||||
|
||||
&:first-of-type {
|
||||
border-left: none;
|
||||
border-bottom-left-radius: var(--wa-border-radius-l);
|
||||
border-bottom-left-radius: var(--wa-border-radius-m);
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom-right-radius: var(--wa-border-radius-l);
|
||||
border-bottom-right-radius: var(--wa-border-radius-m);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
|
||||
@@ -6,7 +6,7 @@ wa-copy-button.copy-button {
|
||||
right: 0.25rem;
|
||||
font-family: var(--wa-font-family-body);
|
||||
color: var(--wa-color-gray-80);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
padding: 0.25rem;
|
||||
|
||||
&:hover {
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
--wa-brand-grey: #30323b;
|
||||
}
|
||||
|
||||
.wa-dark .only-light,
|
||||
.only-dark:not(.wa-dark, .wa-dark *) {
|
||||
html.wa-theme-default-dark .only-light,
|
||||
html:not(.wa-theme-default-dark) .only-dark {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -22,18 +22,22 @@ wa-page {
|
||||
/* Header */
|
||||
wa-page::part(header) {
|
||||
background-color: var(--wa-color-surface-default);
|
||||
border-bottom: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-surface-border);
|
||||
border-bottom: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
|
||||
}
|
||||
|
||||
wa-page::part(body) {
|
||||
wa-page::part(drawer__body) {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
wa-page::part(header-actions) {
|
||||
wa-page::part(drawer__header-actions) {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
wa-page > header {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-inline: var(--wa-space-xl);
|
||||
|
||||
a[href='/'] {
|
||||
@@ -42,7 +46,7 @@ wa-page > header {
|
||||
}
|
||||
|
||||
wa-button[data-toggle-nav] {
|
||||
--text-color: currentColor;
|
||||
--label-color: currentColor;
|
||||
font-size: 1rem;
|
||||
margin-inline-start: -0.875rem;
|
||||
margin-inline-end: 0;
|
||||
@@ -72,12 +76,14 @@ wa-page > header {
|
||||
margin-block-start: var(--wa-space-2xs);
|
||||
}
|
||||
#version-number + wa-badge {
|
||||
--background-color: var(--wa-color-warning-fill-quiet);
|
||||
--content-color: var(--wa-color-warning-on-quiet);
|
||||
font-size: var(--wa-font-size-2xs);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
wa-button#search-trigger {
|
||||
--background-color: var(--wa-form-control-background-color);
|
||||
--border-color: var(--wa-form-control-border-color);
|
||||
--border-color: var(--wa-form-control-resting-color);
|
||||
}
|
||||
#search-trigger kbd {
|
||||
font-size: var(--wa-font-size-2xs);
|
||||
@@ -91,18 +97,9 @@ wa-page > header {
|
||||
font-size: var(--wa-font-size-m);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h2:not(:first-child),
|
||||
wa-details:not(:first-child) {
|
||||
h2:not(:first-child) {
|
||||
margin-block-start: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
wa-details {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
border-inline-start: var(--wa-border-width-s) solid var(--wa-color-surface-border);
|
||||
font-size: var(--wa-font-size-s);
|
||||
@@ -110,30 +107,21 @@ wa-page > header {
|
||||
margin: 0;
|
||||
padding-inline-start: var(--wa-space-m);
|
||||
}
|
||||
|
||||
ul ul {
|
||||
margin-block-start: var(--wa-space-m);
|
||||
}
|
||||
|
||||
ul:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
|
||||
+ li {
|
||||
margin-block-start: var(--wa-space-m);
|
||||
}
|
||||
}
|
||||
|
||||
li + li {
|
||||
margin-block-start: var(--wa-space-m);
|
||||
}
|
||||
li a {
|
||||
color: var(--wa-color-text-normal);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
li wa-badge::part(base) {
|
||||
@@ -211,20 +199,6 @@ wa-page::part(menu) {
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
wa-page[view='mobile'] :is([slot='navigation-header'], [slot='navigation']) {
|
||||
padding: 0;
|
||||
|
||||
& wa-details::part(icon) {
|
||||
padding-inline: var(--wa-space-xs); /* aligns details icons with drawer close icon */
|
||||
}
|
||||
}
|
||||
|
||||
[slot='navigation-header'] wa-menu {
|
||||
font-family: var(--wa-font-family-body);
|
||||
font-size: var(--wa-font-size-m);
|
||||
font-weight: var(--wa-font-weight-normal);
|
||||
}
|
||||
|
||||
/* Main content */
|
||||
wa-page > main {
|
||||
max-width: 80ch;
|
||||
@@ -240,7 +214,7 @@ h1.title wa-badge {
|
||||
}
|
||||
}
|
||||
|
||||
.block-info {
|
||||
.component-info {
|
||||
margin-block-end: var(--wa-flow-spacing);
|
||||
}
|
||||
|
||||
@@ -271,7 +245,7 @@ h1.title wa-badge {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
border: var(--wa-border-style) var(--wa-border-width-s);
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
padding: 1rem;
|
||||
margin-block-end: var(--wa-flow-spacing);
|
||||
|
||||
@@ -331,47 +305,8 @@ wa-page > main:has(> .index-grid) {
|
||||
|
||||
.index-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(22ch, 100%), 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(20ch, 100%), 1fr));
|
||||
gap: var(--wa-space-2xl);
|
||||
|
||||
a {
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
wa-card {
|
||||
box-shadow: none;
|
||||
--spacing: var(--wa-space-m);
|
||||
inline-size: 100%;
|
||||
|
||||
&:hover {
|
||||
--border-color: var(--wa-color-brand-border-loud);
|
||||
border-color: var(--border-color);
|
||||
box-shadow: 0 0 0 var(--wa-border-width-s) var(--border-color);
|
||||
|
||||
.page-name {
|
||||
color: var(--wa-color-brand-on-quiet);
|
||||
}
|
||||
}
|
||||
|
||||
[slot='header'] {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&::part(header) {
|
||||
background-color: var(--wa-color-neutral-fill-quiet);
|
||||
border-bottom: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-block-size: calc(6rem + var(--spacing));
|
||||
}
|
||||
}
|
||||
|
||||
.page-name {
|
||||
font-size: var(--wa-font-size-s);
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
}
|
||||
}
|
||||
|
||||
.index-category {
|
||||
@@ -380,13 +315,107 @@ wa-page > main:has(> .index-grid) {
|
||||
margin-block-start: var(--wa-space-2xl);
|
||||
}
|
||||
|
||||
.index-grid a {
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
}
|
||||
|
||||
.index-grid wa-card {
|
||||
--box-shadow: none;
|
||||
--spacing: var(--wa-space-m);
|
||||
inline-size: 100%;
|
||||
}
|
||||
|
||||
.index-grid wa-card:hover {
|
||||
--border-color: var(--wa-color-brand-border-loud);
|
||||
--box-shadow: 0 0 0 var(--wa-border-width-s) var(--border-color);
|
||||
& .page-name {
|
||||
color: var(--wa-color-brand-on-quiet);
|
||||
}
|
||||
}
|
||||
|
||||
.index-grid wa-card [slot='header'] {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.index-grid wa-card::part(header) {
|
||||
background-color: var(--wa-color-neutral-fill-quiet);
|
||||
border-bottom: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-block-size: calc(6rem + var(--spacing));
|
||||
}
|
||||
|
||||
.index-grid .page-name {
|
||||
font-size: var(--wa-font-size-s);
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
}
|
||||
|
||||
/* Index Pages */
|
||||
wa-page > main:has(> .index-grid) {
|
||||
max-width: 120ch;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.index-summary {
|
||||
max-inline-size: 80ch;
|
||||
}
|
||||
|
||||
.index-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(20ch, 100%), 1fr));
|
||||
gap: var(--wa-space-2xl);
|
||||
}
|
||||
|
||||
.index-category {
|
||||
grid-column: 1 / -1;
|
||||
margin-block-end: 0;
|
||||
margin-block-start: var(--wa-space-2xl);
|
||||
}
|
||||
|
||||
.index-grid a {
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
}
|
||||
|
||||
.index-grid wa-card {
|
||||
--box-shadow: none;
|
||||
--spacing: var(--wa-space-m);
|
||||
inline-size: 100%;
|
||||
}
|
||||
|
||||
.index-grid wa-card:hover {
|
||||
--border-color: var(--wa-color-brand-border-loud);
|
||||
--box-shadow: 0 0 0 var(--wa-border-width-s) var(--border-color);
|
||||
& .page-name {
|
||||
color: var(--wa-color-brand-on-quiet);
|
||||
}
|
||||
}
|
||||
|
||||
.index-grid wa-card [slot='header'] {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.index-grid wa-card::part(header) {
|
||||
background-color: var(--wa-color-neutral-fill-quiet);
|
||||
border-bottom: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-block-size: calc(6rem + var(--spacing));
|
||||
}
|
||||
|
||||
.index-grid .page-name {
|
||||
font-size: var(--wa-font-size-s);
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
}
|
||||
|
||||
/* Swatches */
|
||||
.swatch {
|
||||
background-color: transparent;
|
||||
border-color: var(--wa-color-neutral-border-normal);
|
||||
border-style: var(--wa-border-style);
|
||||
border-width: var(--wa-border-width-s);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
box-sizing: border-box;
|
||||
line-height: 2.5;
|
||||
height: 2.5em;
|
||||
@@ -396,13 +425,13 @@ wa-page > main:has(> .index-grid) {
|
||||
/* Layout Examples */
|
||||
.layout-example-boundary {
|
||||
border: var(--wa-border-width-s) dashed var(--wa-color-neutral-border-normal);
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
padding: var(--wa-space-s);
|
||||
}
|
||||
|
||||
.layout-example-block {
|
||||
background-color: var(--wa-color-indigo-60);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
min-block-size: 4rem;
|
||||
min-inline-size: 4rem;
|
||||
}
|
||||
@@ -426,7 +455,6 @@ wa-page > main:has(> .index-grid) {
|
||||
|
||||
.table-scroll {
|
||||
overflow-x: auto;
|
||||
margin-block-end: var(--wa-flow-spacing);
|
||||
}
|
||||
|
||||
/** mobile */
|
||||
@@ -438,9 +466,14 @@ wa-page > main:has(> .index-grid) {
|
||||
|
||||
/** desktop */
|
||||
@media screen and not (max-width: 768px) {
|
||||
wa-page [data-toggle-nav],
|
||||
wa-page .only-mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Navigation sidebar */
|
||||
wa-page::part(navigation) {
|
||||
border-right: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-surface-border);
|
||||
border-right: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
|
||||
}
|
||||
|
||||
wa-page > #sidebar {
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
wa-card#drawer-card::part(header) {
|
||||
--spacing: 0;
|
||||
justify-content: flex-end;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#block-filter {
|
||||
margin-block-end: var(--wa-space-xl);
|
||||
}
|
||||
|
||||
.index-grid.filtered {
|
||||
h2 {
|
||||
/* Hide headings while filtering */
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:not(:has(> a:not([hidden]))) {
|
||||
/* We’re filtering and there are no results */
|
||||
|
||||
&::before {
|
||||
content: var(--empty-message);
|
||||
grid-column: 1 / -1;
|
||||
color: var(--wa-color-on-quiet);
|
||||
font-style: italic;
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
}
|
||||
|
||||
/* Show empty state when there's a search filter and no results */
|
||||
&[data-empty] {
|
||||
--empty-message: attr(data-empty);
|
||||
}
|
||||
|
||||
&:not([data-empty]) {
|
||||
--empty-message: 'No results';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
.diff-grid > * {
|
||||
height: 100%;
|
||||
}
|
||||
.diff-dialog {
|
||||
.diff-dialog::part(dialog) {
|
||||
max-width: 90vw;
|
||||
width: 90vw;
|
||||
}
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1199px) {
|
||||
wa-page [slot='aside'] {
|
||||
display: none;
|
||||
}
|
||||
#outline {
|
||||
padding-block: 0.25rem;
|
||||
margin-block-end: -1rem;
|
||||
@@ -45,6 +42,5 @@
|
||||
|
||||
#outline-expandable {
|
||||
display: block;
|
||||
margin-block-end: var(--wa-space-xl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
#site-search {
|
||||
width: 38rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
--width: 38rem;
|
||||
|
||||
&::part(base) {
|
||||
margin-block: 10rem;
|
||||
&::part(dialog) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
padding: 0;
|
||||
margin: 10rem auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&::part(body) {
|
||||
@@ -19,22 +18,21 @@
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
max-width: calc(100% - 2rem);
|
||||
|
||||
&::part(base) {
|
||||
margin-block: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#site-search-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: calc(100vh - 20rem);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
@media screen and (max-width: 900px) {
|
||||
#site-search::part(dialog) {
|
||||
max-width: calc(100% - 2rem);
|
||||
margin-block: 1rem;
|
||||
}
|
||||
|
||||
#site-search-container {
|
||||
max-height: calc(100dvh - 2rem);
|
||||
}
|
||||
}
|
||||
@@ -231,8 +229,8 @@ header {
|
||||
gap: 2rem;
|
||||
color: var(--wa-color-text-quiet);
|
||||
border-top: var(--wa-panel-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
|
||||
border-bottom-left-radius: var(--wa-border-radius-l);
|
||||
border-bottom-right-radius: var(--wa-border-radius-l);
|
||||
border-bottom-left-radius: var(--wa-border-radius-m);
|
||||
border-bottom-right-radius: var(--wa-border-radius-m);
|
||||
padding: 1rem;
|
||||
|
||||
kbd {
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
/* Theme Builder Headers
|
||||
* These styles control the appearance of the header of the theme builder,
|
||||
* allowing each theme to have a unique hero section.
|
||||
*/
|
||||
|
||||
/* #region Default */
|
||||
html.wa-theme-default .preview-container {
|
||||
container-name: default-theme;
|
||||
}
|
||||
|
||||
@container default-theme (min-width: 0) {
|
||||
/* #region Custom Styles */
|
||||
@container preview (min-width: 0) {
|
||||
.hero-background {
|
||||
height: 47rem;
|
||||
background-color: var(--wa-color-brand-fill-loud);
|
||||
@@ -31,8 +22,8 @@ html.wa-theme-default .preview-container {
|
||||
}
|
||||
|
||||
.hero wa-button[variant='brand'] {
|
||||
--background-color: var(--wa-color-neutral-fill-quiet);
|
||||
--text-color: var(--wa-color-neutral-on-normal);
|
||||
--background: var(--wa-color-neutral-fill-quiet);
|
||||
--label-color: var(--wa-color-neutral-on-normal);
|
||||
}
|
||||
|
||||
.project-header {
|
||||
@@ -50,733 +41,10 @@ html.wa-theme-default .preview-container {
|
||||
}
|
||||
|
||||
/* responsive */
|
||||
@container default-theme (min-width: 1040px) {
|
||||
@container preview (min-width: 1040px) {
|
||||
.hero-background::after {
|
||||
background-position: right bottom;
|
||||
background-size: 90%;
|
||||
}
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
/* #region Tailspin */
|
||||
html.wa-theme-tailspin .preview-container {
|
||||
container-name: tailspin-theme;
|
||||
}
|
||||
|
||||
@container tailspin-theme (min-width: 0) {
|
||||
.project-header {
|
||||
background: var(--wa-color-surface-default);
|
||||
}
|
||||
|
||||
.hero {
|
||||
--hero-background-color: var(--wa-color-surface-default);
|
||||
--hero-lines-color: color-mix(in oklab, var(--wa-color-neutral-fill-normal), transparent 30%);
|
||||
background: linear-gradient(to top, var(--wa-color-surface-lowered), transparent 40%),
|
||||
radial-gradient(circle at 10% 70%, color-mix(in oklab, var(--wa-color-red-50) 16%, transparent), transparent 30%),
|
||||
radial-gradient(
|
||||
circle at 40% 50%,
|
||||
color-mix(in oklab, var(--wa-color-indigo-40) 16%, transparent),
|
||||
transparent 40%
|
||||
),
|
||||
radial-gradient(circle at 80% 25%, color-mix(in oklab, var(--wa-color-red-50) 8%, transparent), transparent 20%),
|
||||
radial-gradient(
|
||||
circle at 80% 80%,
|
||||
color-mix(in oklab, var(--wa-color-indigo-40) 16%, transparent),
|
||||
transparent 40%
|
||||
),
|
||||
radial-gradient(circle at 90% 30%, color-mix(in oklab, var(--wa-color-red-60) 8%, transparent), transparent 10%),
|
||||
linear-gradient(176deg, var(--hero-background-color), transparent 6rem),
|
||||
linear-gradient(90deg, var(--hero-background-color), transparent),
|
||||
repeating-linear-gradient(
|
||||
var(--hero-lines-color),
|
||||
var(--hero-lines-color) 1px,
|
||||
transparent 1px,
|
||||
transparent 10rem,
|
||||
var(--hero-lines-color) 10rem
|
||||
),
|
||||
repeating-linear-gradient(
|
||||
90deg,
|
||||
var(--hero-lines-color),
|
||||
var(--hero-lines-color) 1px,
|
||||
transparent 1px,
|
||||
transparent 10rem,
|
||||
var(--hero-lines-color) 10rem
|
||||
),
|
||||
var(--hero-background-color);
|
||||
|
||||
& .title {
|
||||
padding-block: calc(var(--wa-space-3xl) * 2) calc(var(--wa-space-3xl) * 10);
|
||||
|
||||
& .hero-title {
|
||||
font-size: calc((var(--wa-font-size-4xl) * 1.125) * 1.125);
|
||||
margin-block: 0 var(--wa-space-3xl);
|
||||
}
|
||||
}
|
||||
}
|
||||
.badge-stock {
|
||||
position: absolute;
|
||||
top: var(--wa-space-l);
|
||||
left: var(--wa-space-l);
|
||||
}
|
||||
|
||||
.message-composer wa-card {
|
||||
&::part(footer) {
|
||||
border: none;
|
||||
}
|
||||
& wa-icon-button {
|
||||
color: var(--wa-color-base-50);
|
||||
}
|
||||
}
|
||||
|
||||
.products {
|
||||
margin-top: calc(var(--wa-space-3xl) * -8);
|
||||
}
|
||||
|
||||
pre.codeblock {
|
||||
background-color: var(--wa-color-neutral-fill-normal);
|
||||
}
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
/* #region Brutalist */
|
||||
html.wa-theme-brutalist .preview-container {
|
||||
container-name: brutalist-theme;
|
||||
}
|
||||
|
||||
@container brutalist-theme (min-width: 0) {
|
||||
.overlap {
|
||||
background: var(--wa-color-surface-lowered) url('/assets/images/themer/brutalist/hero.png') 50% 3% no-repeat;
|
||||
}
|
||||
|
||||
.strata.hero {
|
||||
height: 42rem;
|
||||
padding-top: 8rem;
|
||||
padding-right: 50%;
|
||||
--wa-font-weight-heading: var(--wa-font-weight-normal);
|
||||
}
|
||||
|
||||
.hero wa-button {
|
||||
--background: var(--wa-color-neutral-fill-loud);
|
||||
margin-block-start: var(--wa-space-xl);
|
||||
font-size: var(--wa-font-size-l);
|
||||
}
|
||||
|
||||
/* imitating the large button styles */
|
||||
.hero wa-button::part(label) {
|
||||
padding: 0 var(--wa-space-l);
|
||||
}
|
||||
|
||||
.strata.products {
|
||||
margin-top: -20rem;
|
||||
padding-top: 10rem;
|
||||
}
|
||||
|
||||
.product-card .badge-stock {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.product-card::part(footer) {
|
||||
--wa-shadow-offset-x-s: 0;
|
||||
--wa-shadow-offset-y-s: 0;
|
||||
border-width: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.product-card wa-button::part(prefix) {
|
||||
padding-inline-start: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.product-card wa-button::part(suffix) {
|
||||
padding-inline-end: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.product-card wa-button:not(:last-child) {
|
||||
margin-inline-end: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
/* imitating the rounded avatar */
|
||||
.blog wa-avatar {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.blog wa-avatar::part(image) {
|
||||
border: var(--wa-border-width-s) solid var(--wa-color-brand-fill-loud);
|
||||
border-radius: var(--wa-border-radius-circle);
|
||||
}
|
||||
|
||||
.blog .landscape-frame {
|
||||
box-shadow: var(--wa-shadow-s);
|
||||
border: var(--wa-panel-border-width) var(--wa-panel-border-style) var(--wa-color-surface-border);
|
||||
margin-block-end: var(--wa-shadow-offset-y-s);
|
||||
}
|
||||
|
||||
.post-meta .categories {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.message-composer wa-card::part(header) {
|
||||
background-color: var(--wa-color-neutral-fill-loud);
|
||||
}
|
||||
|
||||
.message-composer .grouped-buttons {
|
||||
--wa-color-neutral-border-quiet: color-mix(in oklab, var(--wa-color-gray-30), white 40%);
|
||||
}
|
||||
|
||||
.message-composer [slot='header'] wa-icon-button::part(base) {
|
||||
color: var(--wa-color-neutral-on-loud);
|
||||
}
|
||||
|
||||
.message-composer .grouped-buttons wa-icon-button::part(base):hover {
|
||||
background-color: var(--wa-color-neutral-fill-normal);
|
||||
color: var(--wa-color-text-normal);
|
||||
}
|
||||
|
||||
.message-composer wa-tooltip::part(body) {
|
||||
background-color: var(--wa-color-brand-fill-loud);
|
||||
color: var(--wa-color-brand-on-loud);
|
||||
}
|
||||
|
||||
.message-composer wa-tooltip::part(base__arrow) {
|
||||
--arrow-color: var(--wa-color-brand-fill-loud);
|
||||
}
|
||||
|
||||
.message-composer wa-card::part(footer) {
|
||||
border-width: 0;
|
||||
--padding: 0 var(--wa-space-s) var(--wa-space-s) var(--wa-space-s);
|
||||
}
|
||||
|
||||
.support-table th {
|
||||
background-color: var(--wa-color-neutral-fill-loud);
|
||||
color: var(--wa-color-neutral-on-loud);
|
||||
}
|
||||
|
||||
.support-table th wa-checkbox {
|
||||
--background: transparent;
|
||||
--border-color: var(--wa-color-neutral-on-loud);
|
||||
--border-color-checked: var(--wa-color-neutral-on-loud);
|
||||
}
|
||||
|
||||
.checkout-form {
|
||||
font-size: var(--wa-font-size-s);
|
||||
}
|
||||
|
||||
.checkout-form .square-frame {
|
||||
box-shadow: var(--wa-shadow-s);
|
||||
border: var(--wa-panel-border-width) var(--wa-panel-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
|
||||
.wa-theme-brutalist.wa-dark {
|
||||
& p a::before {
|
||||
background: var(--wa-color-yellow-40);
|
||||
}
|
||||
|
||||
& wa-rating {
|
||||
--symbol-color: color-mix(in oklab, var(--wa-color-base-80), transparent 50%);
|
||||
--symbol-color-active: var(--wa-color-gray-80);
|
||||
}
|
||||
|
||||
& wa-alert {
|
||||
&[variant='brand'] {
|
||||
--icon-color: var(--wa-color-brand-on-quiet);
|
||||
}
|
||||
&[variant='success'] {
|
||||
--icon-color: var(--wa-color-success-on-quiet);
|
||||
}
|
||||
&[variant='warning'] {
|
||||
--icon-color: var(--wa-color-warning-on-quiet);
|
||||
}
|
||||
&[variant='danger'] {
|
||||
--icon-color: var(--wa-color-danger-on-quiet);
|
||||
}
|
||||
&[variant='neutral'] {
|
||||
--icon-color: var(--wa-color-neutral-on-quiet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.preview-container pre {
|
||||
border-inline-start: var(--wa-panel-border-width) var(--wa-panel-border-style) var(--wa-color-neutral-border-quiet);
|
||||
}
|
||||
|
||||
p a,
|
||||
a.highlite-link {
|
||||
position: relative;
|
||||
--wa-link-decoration-default: none;
|
||||
--wa-link-decoration-hover: none;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
content: '';
|
||||
background: var(--wa-color-yellow-80);
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
height: 50%;
|
||||
opacity: 0.7;
|
||||
transition: all var(--wa-transition-fast) ease-in-out;
|
||||
}
|
||||
|
||||
&:hover:before {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@container brutalist-theme (min-width: 1040px) and (max-width: 1140px) {
|
||||
.product-card wa-button {
|
||||
font-size: 80%;
|
||||
}
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
/* #region Playful */
|
||||
html.wa-theme-playful .preview-container {
|
||||
container-name: playful-theme;
|
||||
}
|
||||
|
||||
@container playful-theme (min-width: 0) {
|
||||
.project-header {
|
||||
color: var(--wa-color-success-on-normal);
|
||||
}
|
||||
|
||||
.hero-background {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: -60rem;
|
||||
left: 50%;
|
||||
width: 250rem;
|
||||
height: 250rem;
|
||||
transform: translate(-50%, -50%);
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(180deg, var(--wa-color-green-90) 69.42%, var(--wa-color-green-80) 100%);
|
||||
}
|
||||
|
||||
.hero-background::after {
|
||||
background: url(/assets/images/themer/playful/hero.png) 0 50% no-repeat;
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 520px;
|
||||
height: 600px;
|
||||
transform: translateX(-50%);
|
||||
left: 50%;
|
||||
bottom: 33rem;
|
||||
}
|
||||
|
||||
.strata.hero {
|
||||
padding-top: 19rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero .hero-title {
|
||||
color: var(--wa-color-success-on-normal);
|
||||
font-size: var(--wa-font-size-4xl);
|
||||
}
|
||||
|
||||
.hero .hero-cta {
|
||||
font-size: var(--wa-font-size-l);
|
||||
}
|
||||
|
||||
.product-card .badge-stock {
|
||||
position: absolute;
|
||||
top: var(--wa-space-xl);
|
||||
right: var(--wa-space-xl);
|
||||
}
|
||||
|
||||
.product-card {
|
||||
--wa-panel-border-radius: var(--wa-border-radius-l);
|
||||
}
|
||||
|
||||
.product-card::part(footer) {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.product-card wa-button {
|
||||
margin-inline-end: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.blog wa-avatar {
|
||||
--size: 2rem;
|
||||
}
|
||||
|
||||
.blog .landscape-frame {
|
||||
border-radius: var(--wa-border-radius-l);
|
||||
box-shadow: var(--wa-shadow-s);
|
||||
}
|
||||
|
||||
.message-composer wa-card {
|
||||
--background: var(--wa-color-surface-raised);
|
||||
}
|
||||
|
||||
.message-composer wa-card::part(header) {
|
||||
--wa-color-neutral-border-quiet: var(--wa-color-gray-70);
|
||||
border-width: 0;
|
||||
background-color: var(--wa-color-neutral-fill-quiet);
|
||||
}
|
||||
|
||||
&:not(.wa-theme-premium.wa-dark) .message-composer wa-card {
|
||||
--wa-color-neutral-fill-quiet: var(--wa-color-gray-90);
|
||||
}
|
||||
|
||||
.message-composer wa-icon-button {
|
||||
color: var(--wa-text-color-normal);
|
||||
font-size: var(--wa-font-size-l);
|
||||
}
|
||||
|
||||
.message-composer wa-card::part(footer) {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.product-detail .price {
|
||||
font-weight: var(--wa-font-weight-bold);
|
||||
}
|
||||
|
||||
.support-table wa-card {
|
||||
background: var(--wa-color-surface-raised);
|
||||
}
|
||||
|
||||
.support-table th {
|
||||
font-size: var(--wa-font-size-s);
|
||||
font-weight: var(--wa-font-weight-bold);
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
}
|
||||
|
||||
.support-table tr {
|
||||
border-top-color: var(--wa-color-surface-lowered);
|
||||
}
|
||||
|
||||
.support-table .excerpt {
|
||||
color: var(--wa-color-text-quiet);
|
||||
}
|
||||
|
||||
.order-item img {
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
}
|
||||
|
||||
.checkout-form {
|
||||
font-size: var(--wa-font-size-s);
|
||||
}
|
||||
|
||||
.checkout-form h2 {
|
||||
font-size: var(--wa-font-size-3xl);
|
||||
}
|
||||
|
||||
.checkout-form wa-input::part(form-control-label),
|
||||
.checkout-form wa-select::part(form-control-label) {
|
||||
font-size: var(--wa-font-size-s);
|
||||
padding-block-end: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.wa-theme-playful.wa-dark {
|
||||
& .hero-background {
|
||||
background: linear-gradient(180deg, var(--wa-color-green-60) 69.42%, var(--wa-color-green-30) 100%);
|
||||
}
|
||||
|
||||
& .message-composer wa-card {
|
||||
border-color: var(--wa-color-gray-30);
|
||||
}
|
||||
|
||||
& .message-composer wa-card::part(header) {
|
||||
background: var(--wa-color-gray-40);
|
||||
}
|
||||
|
||||
& .message-composer wa-card::part(footer) {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
& .message-composer .tools .grouped-buttons:not(:last-of-type) {
|
||||
--wa-color-neutral-border-quiet: var(--wa-color-gray-40);
|
||||
}
|
||||
|
||||
& .support-table th {
|
||||
background: var(--wa-color-surface-lowered);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* responsive */
|
||||
@container playful-theme (min-width: 1040px) and (max-width: 1140px) {
|
||||
.product-card wa-button {
|
||||
font-size: 80%;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
/* #region Active */
|
||||
html.wa-theme-active .preview-container {
|
||||
container-name: active-theme;
|
||||
}
|
||||
|
||||
@container active-theme (min-width: 0) {
|
||||
.hero-background::after {
|
||||
backdrop-filter: brightness(0.8);
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.hero-background {
|
||||
background: linear-gradient(
|
||||
var(--wa-color-green-80) 20%,
|
||||
var(--wa-color-primary-80) 80.5%,
|
||||
var(--wa-color-base-10) 80.5%,
|
||||
var(--wa-color-primary-80) 100%
|
||||
);
|
||||
background: url(/assets/images/themer/active/hero.png) 50% 0px / cover no-repeat;
|
||||
height: 40rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.strata.hero {
|
||||
height: 24rem;
|
||||
}
|
||||
|
||||
.hero .title {
|
||||
text-align: right;
|
||||
margin-inline-start: 55%;
|
||||
}
|
||||
|
||||
.hero .hero-title {
|
||||
font-style: italic;
|
||||
font-weight: var(--wa-font-weight-black);
|
||||
font-size: var(--wa-font-size-2xl);
|
||||
}
|
||||
|
||||
.hero wa-button[variant='brand'] {
|
||||
--background: var(--wa-color-neutral-fill-quiet);
|
||||
--text-color: var(--wa-color-neutral-on-normal);
|
||||
}
|
||||
|
||||
wa-rating {
|
||||
--symbol-color-active: var(--wa-color-brand-on-quiet);
|
||||
}
|
||||
}
|
||||
|
||||
/* responsive */
|
||||
@container preview (min-width: 1100px) {
|
||||
.hero-background {
|
||||
height: 47rem;
|
||||
}
|
||||
|
||||
.strata.hero {
|
||||
height: 30rem;
|
||||
}
|
||||
|
||||
.hero .title {
|
||||
margin-block-start: 10%;
|
||||
}
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
/* #region Premium */
|
||||
html.wa-theme-premium .preview-container {
|
||||
container-name: premium-theme;
|
||||
}
|
||||
|
||||
@container premium-theme (min-width: 0) {
|
||||
.project-header {
|
||||
background-color: var(--wa-color-warning-fill-normal);
|
||||
}
|
||||
|
||||
.strata.hero {
|
||||
height: 60rem;
|
||||
background: var(--wa-color-warning-fill-normal) url('/assets/images/themer/premium/hero.png') -4rem 12rem no-repeat;
|
||||
background-size: cover;
|
||||
padding-top: var(--wa-space-2xl);
|
||||
padding-left: var(--wa-space-s);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.hero .hero-title {
|
||||
color: var(--wa-color-warning-on-normal);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.blog wa-avatar {
|
||||
border-radius: var(--wa-border-radius-circle);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.strata.products {
|
||||
margin-top: -25rem;
|
||||
padding-top: 10rem;
|
||||
background: linear-gradient(0deg, var(--wa-color-surface-lowered) 80%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
|
||||
.product-card .badge-stock {
|
||||
position: absolute;
|
||||
top: var(--wa-space-xl);
|
||||
right: var(--wa-space-xl);
|
||||
}
|
||||
|
||||
.product-card wa-rating {
|
||||
--symbol-size: var(--wa-font-size-m);
|
||||
}
|
||||
|
||||
.product-card .title {
|
||||
font-size: var(--wa-font-size-2xl);
|
||||
}
|
||||
|
||||
.product-card .description {
|
||||
color: var(--wa-color-text-quiet);
|
||||
}
|
||||
|
||||
.product-card::part(footer) {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.product-card wa-button:not(:last-child) {
|
||||
margin-inline-end: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.blog .authors a {
|
||||
--wa-color-text-link: var(--wa-color-text-quiet);
|
||||
--wa-link-decoration-default: none;
|
||||
}
|
||||
|
||||
.message-composer wa-card {
|
||||
background: var(--wa-color-surface-raised);
|
||||
}
|
||||
|
||||
.message-composer wa-card::part(header) {
|
||||
border-width: 0;
|
||||
background-color: var(--wa-color-neutral-fill-quiet);
|
||||
}
|
||||
|
||||
&:not(.wa-theme-premium.wa-dark) .message-composer wa-card {
|
||||
--wa-color-neutral-fill-quiet: var(--wa-color-base-95);
|
||||
}
|
||||
|
||||
.message-composer wa-card::part(footer) {
|
||||
border-width: 0;
|
||||
--padding: var(--wa-space-s) var(--wa-space-xl);
|
||||
}
|
||||
|
||||
.message-composer .grouped-buttons wa-icon-button::part(base) {
|
||||
block-size: var(--wa-form-control-height-s);
|
||||
inline-size: var(--wa-form-control-height-s);
|
||||
justify-content: center;
|
||||
}
|
||||
.message-composer .grouped-buttons wa-icon-button::part(base):hover {
|
||||
background-color: var(--wa-color-neutral-fill-normal);
|
||||
color: var(--wa-color-text-normal);
|
||||
}
|
||||
|
||||
.support-table th {
|
||||
text-transform: uppercase;
|
||||
font-weight: var(--wa-font-weight-normal);
|
||||
color: var(--wa-color-text-quiet);
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
}
|
||||
|
||||
.support-table th:first-child {
|
||||
border-radius: var(--wa-border-radius-l) 0 0 0;
|
||||
}
|
||||
|
||||
.support-table th:last-child {
|
||||
border-radius: 0 var(--wa-border-radius-l) 0 0;
|
||||
}
|
||||
|
||||
.support-table tr {
|
||||
--wa-color-surface-border: var(--wa-color-surface-lowered);
|
||||
}
|
||||
|
||||
.checkout-form wa-input::part(form-control-label),
|
||||
.checkout-form wa-select::part(form-control-label) {
|
||||
font-size: var(--wa-font-size-s);
|
||||
margin-block-end: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.order-item .finish {
|
||||
color: var(--wa-color-text-quiet);
|
||||
font-size: var(--wa-font-size-s);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.wa-theme-premium.wa-dark {
|
||||
& .message-composer .tools .grouped-buttons:not(:last-of-type) {
|
||||
--wa-color-neutral-border-quiet: var(--wa-color-base-40);
|
||||
}
|
||||
|
||||
& .preview-container pre,
|
||||
& .preview-container code {
|
||||
background-color: var(--wa-color-base-20);
|
||||
}
|
||||
|
||||
/* syntax highlighting */
|
||||
& .token {
|
||||
&.selector {
|
||||
color: var(--wa-color-green-80);
|
||||
}
|
||||
|
||||
&.tag {
|
||||
color: var(--wa-color-primary-80);
|
||||
}
|
||||
|
||||
&.punctuation {
|
||||
color: var(--wa-color-base-95);
|
||||
}
|
||||
|
||||
&.attr-name {
|
||||
color: var(--wa-color-green-80);
|
||||
}
|
||||
|
||||
&.attr-value {
|
||||
color: var(--wa-color-yellow-80);
|
||||
}
|
||||
}
|
||||
}
|
||||
.preview-container pre,
|
||||
.preview-container code {
|
||||
background-color: var(--wa-color-base-90);
|
||||
font-size: var(--font-size-m);
|
||||
}
|
||||
|
||||
/* syntax highlighting */
|
||||
.token {
|
||||
&.selector {
|
||||
color: var(--wa-color-green-30);
|
||||
}
|
||||
|
||||
&.tag {
|
||||
color: var(--wa-color-primary-30);
|
||||
}
|
||||
|
||||
&.punctuation {
|
||||
color: var(--wa-color-base-10);
|
||||
}
|
||||
|
||||
&.attr-name {
|
||||
color: var(--wa-color-green-30);
|
||||
}
|
||||
|
||||
&.attr-value {
|
||||
color: var(--wa-color-yellow-30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* responsive */
|
||||
@container preview (min-width: 1040px) {
|
||||
.strata.hero {
|
||||
background: var(--wa-color-warning-fill-normal) url('/assets/images/themer/premium/hero.png') -4rem 35% no-repeat;
|
||||
padding-top: 15rem;
|
||||
padding-left: 50%;
|
||||
}
|
||||
|
||||
.strata.products {
|
||||
margin-top: -25rem;
|
||||
padding-top: 10rem;
|
||||
background: linear-gradient(0deg, var(--wa-color-surface-lowered) 60%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Animated Image
|
||||
description: A component for displaying animated GIFs and WEBPs that play and pause on interaction.
|
||||
tags: [imagery, niche]
|
||||
icon: animated-image
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Animation
|
||||
description: Animate elements declaratively with nearly 100 baked-in presets, or roll your own with custom keyframes.
|
||||
tags: [helpers, primitives]
|
||||
icon: animation
|
||||
layout: component
|
||||
---
|
||||
|
||||
To animate an element, wrap it in `<wa-animation>` 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.
|
||||
@@ -197,3 +196,4 @@ Animations won't play until you apply the `play` attribute. You can omit it init
|
||||
animation.play = true;
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Avatar
|
||||
description: Avatars are used to represent a person or object.
|
||||
tags: [imagery, apps, content]
|
||||
icon: avatar
|
||||
layout: component
|
||||
---
|
||||
|
||||
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.
|
||||
@@ -98,7 +97,7 @@ You can group avatars with a few lines of CSS.
|
||||
margin-left: calc(-1 * var(--wa-space-m));
|
||||
}
|
||||
|
||||
.avatar-group wa-avatar {
|
||||
.avatar-group wa-avatar::part(base) {
|
||||
border: solid 2px var(--wa-color-surface-default);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Badge
|
||||
description: Badges are used to draw attention and display statuses or counts.
|
||||
tags: [feedback, content]
|
||||
icon: badge
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -23,48 +22,6 @@ Set the `variant` attribute to change the badge's variant.
|
||||
<wa-badge variant="danger">Danger</wa-badge>
|
||||
```
|
||||
|
||||
### Appearance
|
||||
|
||||
Use the `appearance` attribute to change the badge's visual appearance.
|
||||
|
||||
```html {.example}
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-badge appearance="accent outlined" variant="neutral">A+O</wa-badge>
|
||||
<wa-badge appearance="accent" variant="neutral">Accent</wa-badge>
|
||||
<wa-badge appearance="filled outlined" variant="neutral">F+O</wa-badge>
|
||||
<wa-badge appearance="filled" variant="neutral">Filled</wa-badge>
|
||||
<wa-badge appearance="outlined" variant="neutral">Outlined</wa-badge>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-badge appearance="accent outlined" variant="brand">A+O</wa-badge>
|
||||
<wa-badge appearance="accent" variant="brand">Accent</wa-badge>
|
||||
<wa-badge appearance="filled outlined" variant="brand">F+O</wa-badge>
|
||||
<wa-badge appearance="filled" variant="brand">Filled</wa-badge>
|
||||
<wa-badge appearance="outlined" variant="brand">Outlined</wa-badge>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-badge appearance="accent outlined" variant="success">A+O</wa-badge>
|
||||
<wa-badge appearance="accent" variant="success">Accent</wa-badge>
|
||||
<wa-badge appearance="filled outlined" variant="success">F+O</wa-badge>
|
||||
<wa-badge appearance="filled" variant="success">Filled</wa-badge>
|
||||
<wa-badge appearance="outlined" variant="success">Outlined</wa-badge>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-badge appearance="accent outlined" variant="warning">A+O</wa-badge>
|
||||
<wa-badge appearance="accent" variant="warning">Accent</wa-badge>
|
||||
<wa-badge appearance="filled outlined" variant="warning">F+O</wa-badge>
|
||||
<wa-badge appearance="filled" variant="warning">Filled</wa-badge>
|
||||
<wa-badge appearance="outlined" variant="warning">Outlined</wa-badge>
|
||||
</div>
|
||||
<div>
|
||||
<wa-badge appearance="accent outlined" variant="danger">A+O</wa-badge>
|
||||
<wa-badge appearance="accent" variant="danger">Accent</wa-badge>
|
||||
<wa-badge appearance="filled outlined" variant="danger">F+O</wa-badge>
|
||||
<wa-badge appearance="filled" variant="danger">Filled</wa-badge>
|
||||
<wa-badge appearance="outlined" variant="danger">Outlined</wa-badge>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Pill Badges
|
||||
|
||||
Use the `pill` attribute to give badges rounded edges.
|
||||
@@ -128,3 +85,4 @@ When including badges in menu items, use the `suffix` slot to make sure they're
|
||||
<wa-menu-item>Comments <wa-badge slot="suffix" variant="neutral" pill>4</wa-badge></wa-menu-item>
|
||||
<wa-menu-item>Replies <wa-badge slot="suffix" variant="neutral" pill>12</wa-badge></wa-menu-item>
|
||||
</wa-menu>
|
||||
```
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Breadcrumb Item
|
||||
description: Breadcrumb Items are used inside breadcrumbs to represent different links.
|
||||
tags: component
|
||||
parent: breadcrumb
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Breadcrumb
|
||||
description: Breadcrumbs provide a group of links so users can easily navigate a website's hierarchy.
|
||||
tags: [navigation]
|
||||
icon: breadcrumb
|
||||
layout: component
|
||||
---
|
||||
|
||||
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.
|
||||
@@ -136,7 +135,7 @@ Dropdown menus can be placed in the default slot to provide additional options.
|
||||
<wa-breadcrumb-item>Homepage</wa-breadcrumb-item>
|
||||
<wa-breadcrumb-item>
|
||||
<wa-dropdown>
|
||||
<wa-button slot="trigger" size="small" appearance="filled" pill>
|
||||
<wa-button slot="trigger" size="small" appearance="tinted" pill>
|
||||
<wa-icon label="More options" name="ellipsis" variant="solid"></wa-icon>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
@@ -161,7 +160,7 @@ Alternatively, you can place dropdown menus in a prefix or suffix slot.
|
||||
<wa-breadcrumb-item>
|
||||
Web Design
|
||||
<wa-dropdown slot="suffix">
|
||||
<wa-button slot="trigger" size="small" appearance="filled" pill>
|
||||
<wa-button slot="trigger" size="small" appearance="tinted" pill>
|
||||
<wa-icon label="More options" name="ellipsis" variant="solid"></wa-icon>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
@@ -172,3 +171,4 @@ Alternatively, you can place dropdown menus in a prefix or suffix slot.
|
||||
</wa-dropdown>
|
||||
</wa-breadcrumb-item>
|
||||
</wa-breadcrumb>
|
||||
```
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Button Group
|
||||
description: Button groups can be used to group related buttons into sections.
|
||||
tags: [actions, forms, apps]
|
||||
icon: button-group
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -140,17 +139,15 @@ Pill buttons are supported through the button's `pill` attribute.
|
||||
</wa-button-group>
|
||||
```
|
||||
|
||||
### Dropdowns and Native Buttons in Button Groups
|
||||
### Dropdowns in Button Groups
|
||||
|
||||
Other elements can also be placed inside button groups:
|
||||
- Native buttons as long as their [native styles](/docs/native/button) are included
|
||||
- Dropdowns as long as the trigger is either a `<wa-button>`, or a `<button>` with [native styles](/docs/native/button) included.
|
||||
Dropdowns can be placed inside button groups as long as the trigger is an `<wa-button>` element.
|
||||
|
||||
```html {.example}
|
||||
<wa-button-group label="Example Button Group">
|
||||
<wa-button>Button</wa-button>
|
||||
<button>Native Button</button>
|
||||
<wa-dropdown hoist>
|
||||
<wa-button>Button</wa-button>
|
||||
<wa-dropdown>
|
||||
<wa-button slot="trigger" caret>Dropdown</wa-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Item 1</wa-menu-item>
|
||||
@@ -168,9 +165,9 @@ Create a split button using a button and a dropdown. Use a [visually hidden](/do
|
||||
```html {.example}
|
||||
<wa-button-group label="Example Button Group">
|
||||
<wa-button variant="brand">Save</wa-button>
|
||||
<wa-dropdown placement="bottom-end" hoist>
|
||||
<wa-dropdown placement="bottom-end">
|
||||
<wa-button slot="trigger" variant="brand" caret>
|
||||
<span class="wa-visually-hidden">More options</span>
|
||||
<wa-visually-hidden>More options</wa-visually-hidden>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item>Save</wa-menu-item>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
---
|
||||
title: Button
|
||||
description: Buttons represent actions that are available to the user.
|
||||
tags: [actions, forms]
|
||||
native: button
|
||||
icon: button
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -29,37 +27,35 @@ Use the `variant` attribute to set the button's semantic variant.
|
||||
Use the `appearance` attribute to change the button's visual appearance.
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-stack">
|
||||
<div class="wa-gap-m">
|
||||
<wa-button appearance="accent" variant="neutral">Accent</wa-button>
|
||||
<wa-button appearance="outlined" variant="neutral">Outlined</wa-button>
|
||||
<wa-button appearance="filled" variant="neutral">Filled</wa-button>
|
||||
<wa-button appearance="plain" variant="neutral">Plain</wa-button>
|
||||
</div>
|
||||
<div class="wa-gap-m">
|
||||
<wa-button appearance="accent" variant="brand">Accent</wa-button>
|
||||
<wa-button appearance="outlined" variant="brand">Outlined</wa-button>
|
||||
<wa-button appearance="filled" variant="brand">Filled</wa-button>
|
||||
<wa-button appearance="plain" variant="brand">Plain</wa-button>
|
||||
</div>
|
||||
<div class="wa-gap-m">
|
||||
<wa-button appearance="accent" variant="success">Accent</wa-button>
|
||||
<wa-button appearance="outlined" variant="success">Outlined</wa-button>
|
||||
<wa-button appearance="filled" variant="success">Filled</wa-button>
|
||||
<wa-button appearance="plain" variant="success">Plain</wa-button>
|
||||
</div>
|
||||
<div class="wa-gap-m">
|
||||
<wa-button appearance="accent" variant="warning">Accent</wa-button>
|
||||
<wa-button appearance="outlined" variant="warning">Outlined</wa-button>
|
||||
<wa-button appearance="filled" variant="warning">Filled</wa-button>
|
||||
<wa-button appearance="plain" variant="warning">Plain</wa-button>
|
||||
</div>
|
||||
<div class="wa-gap-m">
|
||||
<wa-button appearance="accent" variant="danger">Accent</wa-button>
|
||||
<wa-button appearance="outlined" variant="danger">Outlined</wa-button>
|
||||
<wa-button appearance="filled" variant="danger">Filled</wa-button>
|
||||
<wa-button appearance="plain" variant="danger">Plain</wa-button>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-button appearance="filled" variant="neutral">Filled</wa-button>
|
||||
<wa-button appearance="tinted" variant="neutral">Tinted</wa-button>
|
||||
<wa-button appearance="outlined" variant="neutral">Outlined</wa-button>
|
||||
<wa-button appearance="text" variant="neutral">Text</wa-button>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-button appearance="filled" variant="brand">Filled</wa-button>
|
||||
<wa-button appearance="tinted" variant="brand">Tinted</wa-button>
|
||||
<wa-button appearance="outlined" variant="brand">Outlined</wa-button>
|
||||
<wa-button appearance="text" variant="brand">Text</wa-button>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-button appearance="filled" variant="success">Filled</wa-button>
|
||||
<wa-button appearance="tinted" variant="success">Tinted</wa-button>
|
||||
<wa-button appearance="outlined" variant="success">Outlined</wa-button>
|
||||
<wa-button appearance="text" variant="success">Text</wa-button>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-button appearance="filled" variant="warning">Filled</wa-button>
|
||||
<wa-button appearance="tinted" variant="warning">Tinted</wa-button>
|
||||
<wa-button appearance="outlined" variant="warning">Outlined</wa-button>
|
||||
<wa-button appearance="text" variant="warning">Text</wa-button>
|
||||
</div>
|
||||
<div>
|
||||
<wa-button appearance="filled" variant="danger">Filled</wa-button>
|
||||
<wa-button appearance="tinted" variant="danger">Tinted</wa-button>
|
||||
<wa-button appearance="outlined" variant="danger">Outlined</wa-button>
|
||||
<wa-button appearance="text" variant="danger">Text</wa-button>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -95,7 +91,7 @@ It's often helpful to have a button that works like a link. This is possible by
|
||||
|
||||
### Setting a Custom Width
|
||||
|
||||
As expected, buttons can be given a custom width by setting the `width` CSS property. This is useful for making buttons span the full width of their container on smaller screens.
|
||||
As expected, buttons can be given a custom width by setting the `width` attribute. This is useful for making buttons span the full width of their container on smaller screens.
|
||||
|
||||
```html {.example}
|
||||
<wa-button size="small" style="width: 100%; margin-bottom: 1rem;">Small</wa-button>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Callout
|
||||
description: Callouts are used to display important messages inline.
|
||||
tags: [feedback, content]
|
||||
icon: callout
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -58,71 +57,6 @@ Set the `variant` attribute to change the callout's variant.
|
||||
</wa-callout>
|
||||
```
|
||||
|
||||
### Appearance
|
||||
|
||||
Use the `appearance` attribute to change the callout's visual appearance (the default is `outlined filled`).
|
||||
|
||||
```html {.example}
|
||||
<wa-callout variant="brand" appearance="outlined accent">
|
||||
<wa-icon slot="icon" name="check-to-slot"></wa-icon>
|
||||
This <strong>accent</strong> callout is also <strong>outlined</strong>
|
||||
</wa-callout>
|
||||
|
||||
<br />
|
||||
|
||||
<wa-callout variant="brand" appearance="accent">
|
||||
<wa-icon slot="icon" name="square-check"></wa-icon>
|
||||
This <strong>accent</strong> callout draws attention without an outline
|
||||
</wa-callout>
|
||||
|
||||
<br />
|
||||
|
||||
<wa-callout variant="brand" appearance="outlined filled">
|
||||
<wa-icon slot="icon" name="fill-drip" variant="regular"></wa-icon>
|
||||
This callout is both <strong>filled</strong> and <strong>outlined</strong>
|
||||
</wa-callout>
|
||||
|
||||
<br />
|
||||
|
||||
<wa-callout variant="brand" appearance="filled">
|
||||
<wa-icon slot="icon" name="fill" variant="regular"></wa-icon>
|
||||
This callout is only <strong>filled</strong>
|
||||
</wa-callout>
|
||||
|
||||
<br />
|
||||
|
||||
<wa-callout variant="brand" appearance="outlined">
|
||||
<wa-icon slot="icon" name="lines-leaning" variant="regular"></wa-icon>
|
||||
Here's an <strong>outlined</strong> callout
|
||||
</wa-callout>
|
||||
|
||||
<br />
|
||||
|
||||
<wa-callout variant="brand" appearance="plain">
|
||||
<wa-icon slot="icon" name="font" variant="regular"></wa-icon>
|
||||
No bells and whistles on this <strong>plain</strong> callout
|
||||
</wa-callout>
|
||||
```
|
||||
|
||||
### Sizes
|
||||
|
||||
Use the `size` attribute to change a callout's size.
|
||||
|
||||
```html {.example}
|
||||
<wa-callout variant="brand" appearance="outlined accent" size="large">
|
||||
<wa-icon slot="icon" name="circle-info" variant="solid"></wa-icon>
|
||||
This is meant to be very emphasized.
|
||||
</wa-callout>
|
||||
<wa-callout>
|
||||
<wa-icon slot="icon" name="circle-info" variant="regular"></wa-icon>
|
||||
Normal-sized callout.
|
||||
</wa-callout>
|
||||
<wa-callout variant="plain" appearance="plain" size="small">
|
||||
<wa-icon slot="icon" name="circle-info" variant="regular"></wa-icon>
|
||||
Just a small tip!
|
||||
</wa-callout>
|
||||
```
|
||||
|
||||
### Without Icons
|
||||
|
||||
Icons are optional. Simply omit the `icon` slot if you don't want them.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Card
|
||||
description: Cards can be used to group related subjects in a container.
|
||||
tags: [organization, layout]
|
||||
icon: card
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -60,8 +59,7 @@ Basic cards aren't very exciting, but they can display any content you want them
|
||||
|
||||
### Card with Header
|
||||
|
||||
Headers can be used to display titles and more.
|
||||
If using SSR, you need to also use the `with-header` attribute to add a header to the card (if not, it is added automatically).
|
||||
Headers can be used to display titles and more. Use the `with-header` attribute to add a header to the card.
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-header class="card-header">
|
||||
@@ -96,8 +94,7 @@ If using SSR, you need to also use the `with-header` attribute to add a header t
|
||||
|
||||
### Card with Footer
|
||||
|
||||
Footers can be used to display actions, summaries, or other relevant content.
|
||||
If using SSR, you need to also use the `with-footer` attribute to add a footer to the card (if not, it is added automatically).
|
||||
Footers can be used to display actions, summaries, or other relevant content. Use the `with-footer` attribute to add a footer to the card.
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-footer class="card-footer">
|
||||
@@ -124,8 +121,7 @@ If using SSR, you need to also use the `with-footer` attribute to add a footer t
|
||||
|
||||
### Images
|
||||
|
||||
Card images are displayed atop the card and will stretch to fit.
|
||||
If using SSR, you need to also use the `with-image` attribute to add an image to the card (if not, it is added automatically).
|
||||
Card images are displayed atop the card and will stretch to fit. Use the `with-image` attribute to add an image to the card.
|
||||
|
||||
```html {.example}
|
||||
<wa-card with-image class="card-image">
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
---
|
||||
title: Carousel Item
|
||||
description: A carousel item represent a slide within a carousel.
|
||||
tags: component
|
||||
parent: carousel
|
||||
icon: carousel-item
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Carousel
|
||||
description: Carousels display an arbitrary number of content slides along a horizontal or vertical axis.
|
||||
tags: [imagery, disclosure]
|
||||
icon: carousel
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -535,12 +534,12 @@ The carousel has a robust API that makes it possible to extend and customize. Th
|
||||
</wa-carousel>
|
||||
|
||||
<div class="thumbnails">
|
||||
<div class="scroller">
|
||||
<img alt="Thumbnail by 1" class="image active" src="https://images.unsplash.com/photo-1426604966848-d7adac402bff?q=10" />
|
||||
<img alt="Thumbnail by 2" class="image" src="https://images.unsplash.com/photo-1473448912268-2022ce9509d8?q=10" />
|
||||
<img alt="Thumbnail by 3" class="image" src="https://images.unsplash.com/photo-1499002238440-d264edd596ec?q=10" />
|
||||
<img alt="Thumbnail by 4" class="image" src="https://images.unsplash.com/photo-1475113548554-5a36f1f523d6?q=10" />
|
||||
<img alt="Thumbnail by 5" class="image" src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?q=10" />
|
||||
<div class="thumbnails__scroller">
|
||||
<img alt="Thumbnail by 1" class="thumbnails__image active" src="https://images.unsplash.com/photo-1426604966848-d7adac402bff?q=10" />
|
||||
<img alt="Thumbnail by 2" class="thumbnails__image" src="https://images.unsplash.com/photo-1473448912268-2022ce9509d8?q=10" />
|
||||
<img alt="Thumbnail by 3" class="thumbnails__image" src="https://images.unsplash.com/photo-1499002238440-d264edd596ec?q=10" />
|
||||
<img alt="Thumbnail by 4" class="thumbnails__image" src="https://images.unsplash.com/photo-1475113548554-5a36f1f523d6?q=10" />
|
||||
<img alt="Thumbnail by 5" class="thumbnails__image" src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?q=10" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -554,7 +553,7 @@ The carousel has a robust API that makes it possible to extend and customize. Th
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.scroller {
|
||||
.thumbnails__scroller {
|
||||
display: flex;
|
||||
gap: var(--wa-space-s);
|
||||
overflow-x: auto;
|
||||
@@ -563,11 +562,11 @@ The carousel has a robust API that makes it possible to extend and customize. Th
|
||||
scroll-padding: var(--wa-space-s);
|
||||
}
|
||||
|
||||
.scroller::-webkit-scrollbar {
|
||||
.thumbnails__scroller::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.image {
|
||||
.thumbnails__image {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
object-fit: cover;
|
||||
@@ -579,7 +578,7 @@ The carousel has a robust API that makes it possible to extend and customize. Th
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.image.active {
|
||||
.thumbnails__image.active {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
@@ -587,13 +586,13 @@ The carousel has a robust API that makes it possible to extend and customize. Th
|
||||
<script>
|
||||
{
|
||||
const carousel = document.querySelector('.carousel-thumbnails');
|
||||
const scroller = document.querySelector('.scroller');
|
||||
const thumbnails = document.querySelectorAll('.image');
|
||||
const scroller = document.querySelector('.thumbnails__scroller');
|
||||
const thumbnails = document.querySelectorAll('.thumbnails__image');
|
||||
|
||||
scroller.addEventListener('click', e => {
|
||||
const target = e.target;
|
||||
|
||||
if (target.matches('.image')) {
|
||||
if (target.matches('.thumbnails__image')) {
|
||||
const index = [...thumbnails].indexOf(target);
|
||||
carousel.goToSlide(index);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Component Cheatsheet
|
||||
layout: docs
|
||||
unlisted: true
|
||||
---
|
||||
|
||||
<style>
|
||||
@@ -65,21 +64,15 @@ table code {
|
||||
<tr>
|
||||
<th><code>{{ name }}{{ "()" if type == "method" }}</code></th>
|
||||
<td>
|
||||
{% set componentLinks = [] %}
|
||||
{% for component in thingComponents %}
|
||||
{%- set link -%}
|
||||
<a href="../{{ component.slug }}"><code><{{ component.tagName }}></code></a>
|
||||
{%- endset -%}
|
||||
{# https://giuliachiola.dev/posts/add-items-to-an-array-in-nunjucks/ #}
|
||||
{% set componentLinks = (componentLinks.push(link), componentLinks) %}
|
||||
{%- endfor -%}
|
||||
{% if thingComponents.length > 1 %}
|
||||
<details open>
|
||||
<summary><strong>{{ thingComponents.length }}</strong> components</summary>
|
||||
{{ componentLinks | safe }}
|
||||
{% endif %}
|
||||
{% for component in thingComponents %}
|
||||
<a href="../{{ component.slug }}"><code><{{ component.tagName }}></code></a>
|
||||
{%- endfor -%}
|
||||
{% if thingComponents.length > 1 %}
|
||||
</details>
|
||||
{% else %}
|
||||
{{ componentLinks | safe }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
---
|
||||
title: Checkbox
|
||||
description: Checkboxes allow the user to toggle an option on or off.
|
||||
tags: [inputs, forms]
|
||||
native: checkbox
|
||||
icon: checkbox
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -52,12 +50,12 @@ Use the `size` attribute to change a checkbox's size.
|
||||
<wa-checkbox size="large">Large</wa-checkbox>
|
||||
```
|
||||
|
||||
### Hint
|
||||
### Help Text
|
||||
|
||||
Add descriptive hint to a switch with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
|
||||
Add descriptive help text to a switch with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
|
||||
```html {.example}
|
||||
<wa-checkbox hint="What should the user know about the checkbox?">Label</wa-checkbox>
|
||||
<wa-checkbox help-text="What should the user know about the checkbox?">Label</wa-checkbox>
|
||||
```
|
||||
|
||||
### Custom Validity
|
||||
@@ -94,4 +92,4 @@ Use the `setCustomValidity()` method to set a custom validation message. This wi
|
||||
});
|
||||
});
|
||||
</script>
|
||||
```
|
||||
```
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Code Demo
|
||||
description: Code demos can be used to render code examples as inline live demos.
|
||||
tags: component
|
||||
noAlpha: true
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -82,7 +81,7 @@ There are certain types of elements that are handled specially:
|
||||
This is useful for including resources in your demo that you don't want rendered outside the demo.
|
||||
|
||||
The following example shows both methods.
|
||||
It includes all stylesheets on this page whose URLs start with `/dist/styles/themes/`,
|
||||
It includes all stylesheets on this page whose URLs start with `/dist/themes/`,
|
||||
plus any other elements with the class `.demo-import`, plus a CSS file with the class `wa-code-demo-include`:
|
||||
|
||||
```html {.example}
|
||||
@@ -174,7 +173,7 @@ i.e. the previews of demos using the `viewport` attribute, but also opening demo
|
||||
Just setting `border-radius` or `border` should work as expected:
|
||||
|
||||
```html{.example}
|
||||
<wa-code-demo style="border: 2px dotted var(--wa-color-blue-50); border-radius: var(--wa-border-radius-m)">
|
||||
<wa-code-demo style="border: 2px dotted var(--wa-color-blue-50); border-radius: var(--wa-border-radius-s)">
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
<wa-button>Click me!</wa-button>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
---
|
||||
title: Color Picker
|
||||
description: Color pickers allow the user to select a color.
|
||||
tags: [inputs, forms]
|
||||
native: input
|
||||
icon: color-picker
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -39,12 +37,10 @@ Set the color picker's format with the `format` attribute. Valid options include
|
||||
To prevent users from toggling the format themselves, add the `no-format-toggle` attribute.
|
||||
|
||||
```html {.example}
|
||||
<div class="wa-grid" style="--min-column-size: 12ch;">
|
||||
<wa-color-picker format="hex" value="#4a90e2" label="Pick a hex color"></wa-color-picker>
|
||||
<wa-color-picker format="rgb" value="rgb(80, 227, 194)" label="Pick an RGB color"></wa-color-picker>
|
||||
<wa-color-picker format="hsl" value="hsl(290, 87%, 47%)" label="Pick an HSL color"></wa-color-picker>
|
||||
<wa-color-picker format="hsv" value="hsv(55, 89%, 97%)" label="Pick an HSV color"></wa-color-picker>
|
||||
</div>
|
||||
<wa-color-picker format="hex" value="#4a90e2" label="Select a color"></wa-color-picker>
|
||||
<wa-color-picker format="rgb" value="rgb(80, 227, 194)" label="Select a color"></wa-color-picker>
|
||||
<wa-color-picker format="hsl" value="hsl(290, 87%, 47%)" label="Select a color"></wa-color-picker>
|
||||
<wa-color-picker format="hsv" value="hsv(55, 89%, 97%)" label="Select a color"></wa-color-picker>
|
||||
```
|
||||
|
||||
### Swatches
|
||||
@@ -79,10 +75,10 @@ The color picker can be rendered as disabled.
|
||||
<wa-color-picker disabled label="Select a color"></wa-color-picker>
|
||||
```
|
||||
|
||||
### Hint
|
||||
### Help Text
|
||||
|
||||
Add descriptive hint to a color picker with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
|
||||
Add descriptive help text to a color picker with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
|
||||
```html {.example}
|
||||
<wa-color-picker label="Select a color" hint="Choose a color with appropate contrast!"></wa-color-picker>
|
||||
```
|
||||
<wa-color-picker label="Select a color" help-text="Choose a color with appropate contrast!"></wa-color-picker>
|
||||
```
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"layout": "component.njk",
|
||||
"tags": ["components"],
|
||||
"eleventyComputed": {
|
||||
"component": "{{ components[page.fileSlug] }}",
|
||||
"description": "{{ components[page.fileSlug].summary }}",
|
||||
"status": "{{ components[page.fileSlug].status }}",
|
||||
"since": "{{ components[page.fileSlug].since }}",
|
||||
"element": "<{{ components[page.fileSlug].tagName }}>"
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Copy Button
|
||||
description: Copies data to the clipboard when the user clicks the button.
|
||||
tags: [actions, apps]
|
||||
icon: copy-button
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
---
|
||||
title: Details
|
||||
description: Details show a brief summary and expand to show additional content.
|
||||
tags: [organization, apps, content, disclosure]
|
||||
icon: details
|
||||
native: details
|
||||
layout: component
|
||||
---
|
||||
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
@@ -19,7 +17,7 @@ native: details
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to prevent the details from expanding.
|
||||
Use the `disable` attribute to prevent the details from expanding.
|
||||
|
||||
```html {.example}
|
||||
<wa-details summary="Disabled" disabled>
|
||||
@@ -30,7 +28,7 @@ Use the `disabled` attribute to prevent the details from expanding.
|
||||
|
||||
### Customizing the Summary Icon
|
||||
|
||||
Use the `expand-icon` and `collapse-icon` slots to change the expand and collapse icons, respectively. To disable the animation, override the `rotate` property on the `icon` part as shown below.
|
||||
Use the `expand-icon` and `collapse-icon` slots to change the expand and collapse icons, respectively. To disable the animation, override the `rotate` property on the `summary-icon` part as shown below.
|
||||
|
||||
```html {.example}
|
||||
<wa-details summary="Toggle Me" class="custom-icons">
|
||||
@@ -42,41 +40,13 @@ Use the `expand-icon` and `collapse-icon` slots to change the expand and collaps
|
||||
</wa-details>
|
||||
|
||||
<style>
|
||||
/* Disable the expand/collapse animation */
|
||||
wa-details.custom-icons::part(icon) {
|
||||
wa-details.custom-icons::part(summary-icon) {
|
||||
/* Disable the expand/collapse animation */
|
||||
rotate: none;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### HTML in summary
|
||||
|
||||
To use HTML in the summary, use the `summary` slot.
|
||||
Links and other interactive elements will still retain their behavior:
|
||||
|
||||
```html {.example}
|
||||
<wa-details>
|
||||
<span slot="summary">
|
||||
Some text
|
||||
<a href="https://webawesome.com" target="_blank">a link</a>
|
||||
more text
|
||||
</span>
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
||||
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</wa-details>
|
||||
```
|
||||
|
||||
### Right-to-Left languages
|
||||
|
||||
The details component automatically adapts to right-to-left languages:
|
||||
|
||||
```html {.example}
|
||||
<wa-details summary="تبديلني" lang="ar" dir="rtl">
|
||||
استخدام طريقة لوريم إيبسوم لأنها تعطي توزيعاَ طبيعياَ -إلى حد ما- للأحرف عوضاً عن
|
||||
</wa-details>
|
||||
```
|
||||
|
||||
### Grouping Details
|
||||
|
||||
Details are designed to function independently, but you can simulate a group or "accordion" where only one is shown at a time by listening for the `wa-show` event.
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
---
|
||||
title: Dialog
|
||||
description: 'Dialogs, sometimes called "modals", appear above the page and require the user''s immediate attention.'
|
||||
tags: [organization, apps, disclosure]
|
||||
icon: dialog
|
||||
native: dialog
|
||||
keywords: modal
|
||||
layout: component
|
||||
---
|
||||
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer id="dialog-overview">
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -18,7 +15,7 @@ keywords: modal
|
||||
<wa-button>Open Dialog</wa-button>
|
||||
|
||||
<script>
|
||||
const dialog = document.querySelector('#dialog-overview');
|
||||
const dialog = document.querySelector('.dialog-overview');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
|
||||
openButton.addEventListener('click', () => dialog.open = true);
|
||||
@@ -88,10 +85,10 @@ You can add the special `data-dialog="close"` attribute to a button inside the d
|
||||
|
||||
### Custom Width
|
||||
|
||||
Just use the CSS `width` property to set the dialog's width.
|
||||
Use the `--width` custom property to set the dialog's width.
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-width" style="width: 50vw;">
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-width" style="--width: 50vw;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -222,4 +219,4 @@ To give focus to a specific element when the dialog opens, use the `autofocus` a
|
||||
|
||||
openButton.addEventListener('click', () => dialog.open = true);
|
||||
</script>
|
||||
```
|
||||
```
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Divider
|
||||
description: Dividers are used to visually separate or group elements.
|
||||
tags: [organization, content, forms]
|
||||
icon: divider
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Drawer
|
||||
description: Drawers slide in from a container to expose additional options and information.
|
||||
tags: [organization, disclosure]
|
||||
icon: drawer
|
||||
layout: component
|
||||
---
|
||||
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Dropdown
|
||||
description: 'Dropdowns expose additional content that "drops down" in a panel.'
|
||||
tags: [actions, apps]
|
||||
icon: dropdown
|
||||
layout: component
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Format Bytes
|
||||
description: Formats a number as a human readable bytes value.
|
||||
tags: [helpers, content, inline]
|
||||
icon: format-bytes
|
||||
layout: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Format Date
|
||||
description: Formats a date/time using the specified locale and options.
|
||||
tags: [helpers, content, inline]
|
||||
icon: format-date
|
||||
layout: component
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Format Number
|
||||
description: Formats a number using the specified locale and options.
|
||||
tags: [helpers, content, inline]
|
||||
icon: format-number
|
||||
layout: component
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Icon Button
|
||||
description: Icons buttons are simple, icon-only buttons that can be used for actions and in toolbars.
|
||||
tags: [actions, apps]
|
||||
icon: icon-button
|
||||
layout: component
|
||||
---
|
||||
|
||||
For a full list of icons that come bundled with Web Awesome, refer to the [icon component](/docs/components/icon).
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Icon
|
||||
description: Icons are symbols that can be used to represent various options within an application.
|
||||
tags: [imagery, apps, popular]
|
||||
icon: icon
|
||||
layout: component
|
||||
---
|
||||
|
||||
Web Awesome comes bundled with over 2,000 free icons courtesy of [Font Awesome](https://fontawesome.com/). These icons are part of the `default` icon library. Font Awesome Pro users can unlock additional icon families. Or, if you prefer, you can register your own [custom icon library](#icon-library).
|
||||
@@ -147,7 +146,7 @@ Icons in this library are licensed under the [MIT License](https://github.com/tw
|
||||
resolver: (name, family) => {
|
||||
const suffix = family === 'filled' ? '-fill' : '';
|
||||
return `https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/icons/${name}${suffix}.svg`
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -518,7 +517,7 @@ For example, this will change the default icon library to use [Bootstrap Icons](
|
||||
resolver: (name, family) => {
|
||||
const suffix = family === 'filled' ? '-fill' : '';
|
||||
return `https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/icons/${name}${suffix}.svg`
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Image Comparer
|
||||
description: Compare visual differences between similar photos with a sliding panel.
|
||||
tags: [imagery, niche]
|
||||
icon: image-comparer
|
||||
layout: component
|
||||
---
|
||||
|
||||
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.)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Include
|
||||
description: Includes give you the power to embed external HTML files into the page.
|
||||
tags: [helpers, primitives]
|
||||
icon: include
|
||||
layout: component
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||