mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-14 21:19:13 +00:00
Compare commits
342 Commits
components
...
kj/renamin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed10f36b28 | ||
|
|
a13be817db | ||
|
|
142403fe78 | ||
|
|
a41787d23a | ||
|
|
252adbd830 | ||
|
|
c8db30fa0f | ||
|
|
fa415005eb | ||
|
|
ba8046bff5 | ||
|
|
948254dd29 | ||
|
|
82b799c1a4 | ||
|
|
358444bc1d | ||
|
|
dbab4ae645 | ||
|
|
f5ed55513b | ||
|
|
d6fb269381 | ||
|
|
3734f9cea5 | ||
|
|
5a058a8808 | ||
|
|
e2d99e3c86 | ||
|
|
e74edd8f68 | ||
|
|
d961203d17 | ||
|
|
be752371a6 | ||
|
|
af3b83318b | ||
|
|
b0cd38e2c5 | ||
|
|
0d8d718b7a | ||
|
|
54687046ab | ||
|
|
22529870f4 | ||
|
|
8aafea456d | ||
|
|
cfb70f2135 | ||
|
|
1d02644996 | ||
|
|
312809a766 | ||
|
|
5e221f6c3a | ||
|
|
232734563f | ||
|
|
5cbc64ad4f | ||
|
|
35858e0549 | ||
|
|
752b8d462e | ||
|
|
1da80bee80 | ||
|
|
315dd40734 | ||
|
|
5a82b7ad99 | ||
|
|
1a29875940 | ||
|
|
be0631bd3e | ||
|
|
e882102aff | ||
|
|
97c0470f13 | ||
|
|
47badda35c | ||
|
|
b2353ca9bd | ||
|
|
65310be0b0 | ||
|
|
ac9960c1f0 | ||
|
|
b9393068a7 | ||
|
|
9c216f60ff | ||
|
|
ce65a49dbe | ||
|
|
e973b599aa | ||
|
|
9979028d7e | ||
|
|
d09ea4a73a | ||
|
|
1bf83499b0 | ||
|
|
9c4e4a2280 | ||
|
|
f8e61f72c4 | ||
|
|
d08b95378a | ||
|
|
c1153708f6 | ||
|
|
d676c1b569 | ||
|
|
77f50a4890 | ||
|
|
24e2b47ff1 | ||
|
|
651c38afbf | ||
|
|
2dec73b2c5 | ||
|
|
ad36ba5569 | ||
|
|
1855d1b809 | ||
|
|
543fa3c85c | ||
|
|
fe05300bdc | ||
|
|
0eebf44292 | ||
|
|
7c40243da3 | ||
|
|
4a046684c8 | ||
|
|
49eeca1617 | ||
|
|
88e2af266f | ||
|
|
0bcc788752 | ||
|
|
5d687f1aa0 | ||
|
|
8fbd0b54e4 | ||
|
|
37a1680a85 | ||
|
|
2b0acca219 | ||
|
|
5293f0fa63 | ||
|
|
7d52f00d8d | ||
|
|
f8e367a5e7 | ||
|
|
b9541ba2e0 | ||
|
|
25ee6ef1ad | ||
|
|
45cb5598fc | ||
|
|
a6bf9ea58c | ||
|
|
1e1877c954 | ||
|
|
47c9f43954 | ||
|
|
2136fed4cb | ||
|
|
4b6baa93a6 | ||
|
|
ef4cbd915d | ||
|
|
d9b8fc6806 | ||
|
|
6bb6bcc538 | ||
|
|
e60a5032da | ||
|
|
a6b71e119c | ||
|
|
8e01281c12 | ||
|
|
a31de87882 | ||
|
|
dbfaa4299f | ||
|
|
78432c41d8 | ||
|
|
0d003c0309 | ||
|
|
0a796d618f | ||
|
|
84909930fb | ||
|
|
cbab3b09e5 | ||
|
|
8a321951d3 | ||
|
|
4852f5614f | ||
|
|
87621ef109 | ||
|
|
6a9c7dd2bc | ||
|
|
1fb8088fc8 | ||
|
|
27c58637eb | ||
|
|
426a242d26 | ||
|
|
7a7a7abe78 | ||
|
|
aade89b66e | ||
|
|
771a1559ef | ||
|
|
74ae758819 | ||
|
|
5e2081451d | ||
|
|
1ffdc19305 | ||
|
|
6996d17531 | ||
|
|
1e3b93d579 | ||
|
|
70fab26e6b | ||
|
|
725fb1f013 | ||
|
|
6d4c8e5942 | ||
|
|
b6e0ca5d45 | ||
|
|
35571c1d4e | ||
|
|
82a5aff8db | ||
|
|
e74a30f62a | ||
|
|
11d3a73f05 | ||
|
|
9fefb6d65a | ||
|
|
4b18c74b83 | ||
|
|
f739c6c143 | ||
|
|
9739aceb9f | ||
|
|
afde497a1a | ||
|
|
666f1e5d52 | ||
|
|
1013e83032 | ||
|
|
b15d938c7e | ||
|
|
c066c5f30b | ||
|
|
abbfd9b43d | ||
|
|
ee0167a059 | ||
|
|
f86c07bdab | ||
|
|
699595496e | ||
|
|
fa42764a4b | ||
|
|
15bbafd631 | ||
|
|
9423178df5 | ||
|
|
9260d35b4c | ||
|
|
10156a8218 | ||
|
|
d0574677c1 | ||
|
|
7b0274a657 | ||
|
|
325eaeb225 | ||
|
|
f840d623d5 | ||
|
|
f9590195a5 | ||
|
|
53eb0d8f30 | ||
|
|
b0c4c7263b | ||
|
|
b5d1a71f46 | ||
|
|
dd7b673328 | ||
|
|
9f0276f55e | ||
|
|
15d250b103 | ||
|
|
0c40579be4 | ||
|
|
f0f080a428 | ||
|
|
54b511b709 | ||
|
|
c50da3429b | ||
|
|
ad3cd289dd | ||
|
|
b1fffc7df9 | ||
|
|
587db10022 | ||
|
|
47294ad0ed | ||
|
|
28ebab868b | ||
|
|
07d15fd863 | ||
|
|
2c9eb385fd | ||
|
|
6d9f513f68 | ||
|
|
4b56a03144 | ||
|
|
9c17d27af4 | ||
|
|
cc37a5c44b | ||
|
|
9e6ee89585 | ||
|
|
ea25de8040 | ||
|
|
7bee00d706 | ||
|
|
6b9f064aeb | ||
|
|
e9377cf746 | ||
|
|
35d2b7f12a | ||
|
|
922d7d9894 | ||
|
|
24f5f3c4ca | ||
|
|
8358127992 | ||
|
|
67563b2bba | ||
|
|
73e9e9ab3a | ||
|
|
7ce393feb8 | ||
|
|
b25e58b24b | ||
|
|
cb0240c91d | ||
|
|
16302c0130 | ||
|
|
88f2f99290 | ||
|
|
36a397ddaa | ||
|
|
8fd897e348 | ||
|
|
adc76b4eb1 | ||
|
|
cbb4aa8be1 | ||
|
|
968930c543 | ||
|
|
4be8a46cdd | ||
|
|
c02496ff02 | ||
|
|
4b8afb4bc3 | ||
|
|
01aa2afc15 | ||
|
|
4f3539cb43 | ||
|
|
260bd47030 | ||
|
|
f27c982962 | ||
|
|
19340adcfb | ||
|
|
f22e598ad6 | ||
|
|
68f693cbc0 | ||
|
|
2f6fe33e2c | ||
|
|
c307cfde1c | ||
|
|
883ef50186 | ||
|
|
c359556605 | ||
|
|
3e18309367 | ||
|
|
2fb0cc7d6d | ||
|
|
26449e12e5 | ||
|
|
7058de0568 | ||
|
|
0c3438e1a5 | ||
|
|
bae9b57c2a | ||
|
|
739c45d34c | ||
|
|
32df4598fc | ||
|
|
f52daeecdc | ||
|
|
930216e3f7 | ||
|
|
8e40a082f5 | ||
|
|
e3fdf61e4a | ||
|
|
414b29b046 | ||
|
|
ba4cdc9b28 | ||
|
|
99704faeb4 | ||
|
|
78c446f525 | ||
|
|
b50b4ca632 | ||
|
|
21d84332e4 | ||
|
|
c88a2c788d | ||
|
|
b1c459c226 | ||
|
|
a8ddefe31e | ||
|
|
80d23a4efe | ||
|
|
5393a86e2b | ||
|
|
1d822db30d | ||
|
|
654cd0b0bd | ||
|
|
6da942083c | ||
|
|
f15814c784 | ||
|
|
60c7c91e8a | ||
|
|
62cf254365 | ||
|
|
747f185dc5 | ||
|
|
1a61bd9583 | ||
|
|
7cff8fadde | ||
|
|
67abde6d97 | ||
|
|
6e0b3d820c | ||
|
|
998180b05d | ||
|
|
ee9cc49956 | ||
|
|
3f79b35878 | ||
|
|
fd3ec885f9 | ||
|
|
22ca715ddb | ||
|
|
5e6b8628d4 | ||
|
|
0a980addc3 | ||
|
|
9bbfa1aeb2 | ||
|
|
48fc9d9779 | ||
|
|
8ec8e2a9b4 | ||
|
|
5ec5979136 | ||
|
|
4926ad6ce5 | ||
|
|
f013756b7b | ||
|
|
feb092a7fa | ||
|
|
406e899b34 | ||
|
|
4d89c344d1 | ||
|
|
b9f484ceb6 | ||
|
|
1920ae8c1e | ||
|
|
08422c29e7 | ||
|
|
59a70dd5b7 | ||
|
|
86a80d3e78 | ||
|
|
1cebae7868 | ||
|
|
7b0ab1f7b7 | ||
|
|
1aebdf4a06 | ||
|
|
e94a424596 | ||
|
|
14db763613 | ||
|
|
65ced601e9 | ||
|
|
2f0b259d96 | ||
|
|
8267dd91d9 | ||
|
|
2149a1efde | ||
|
|
7990717a95 | ||
|
|
4526effbfa | ||
|
|
a8774b5c88 | ||
|
|
fbc5946e71 | ||
|
|
0fbdf110b1 | ||
|
|
d37d873b4c | ||
|
|
d5419ab0d0 | ||
|
|
4805cdb64c | ||
|
|
5d74d8163b | ||
|
|
76c74fc8a9 | ||
|
|
321f53f953 | ||
|
|
849def9ef2 | ||
|
|
911668617b | ||
|
|
d55e750ecd | ||
|
|
08d6af502c | ||
|
|
9a68409ccd | ||
|
|
b8f4a38c80 | ||
|
|
a86acc9717 | ||
|
|
a1fc75689e | ||
|
|
0a5e4ab99c | ||
|
|
fd8876b3c4 | ||
|
|
994cba2fcf | ||
|
|
fb565d202e | ||
|
|
adb655a53b | ||
|
|
2d19c5d915 | ||
|
|
ff0e00e4e4 | ||
|
|
1ea76cc08a | ||
|
|
786b3c3da2 | ||
|
|
c74049a140 | ||
|
|
e7a0444c67 | ||
|
|
32ed169ca8 | ||
|
|
9e2f1d15d8 | ||
|
|
8d93a44566 | ||
|
|
471cb0287d | ||
|
|
1428ec0708 | ||
|
|
4ed0a93ec6 | ||
|
|
ba125dc06a | ||
|
|
fe8b0624fe | ||
|
|
56dc07e30d | ||
|
|
6dd31748e9 | ||
|
|
2f4379716a | ||
|
|
58ac1c920d | ||
|
|
abedd14cac | ||
|
|
73ca47b608 | ||
|
|
5ddc832e9d | ||
|
|
c097b21443 | ||
|
|
17fb0ef94e | ||
|
|
2089065499 | ||
|
|
b168214952 | ||
|
|
678e3bd108 | ||
|
|
6cc030fa06 | ||
|
|
b84bd8e3cf | ||
|
|
8c1921da15 | ||
|
|
9a86311bc4 | ||
|
|
5950100615 | ||
|
|
4e3e0aad14 | ||
|
|
6cc3b05fb7 | ||
|
|
0e75ec6758 | ||
|
|
f157d4dfa4 | ||
|
|
3c81f9c5e9 | ||
|
|
d97bf9a9e9 | ||
|
|
bda66ab4b9 | ||
|
|
2719880636 | ||
|
|
ca20f4de22 | ||
|
|
9080810c20 | ||
|
|
0a6b36d3c8 | ||
|
|
0cf6765d56 | ||
|
|
7b3e572d25 | ||
|
|
be387992e6 | ||
|
|
1f8a282971 | ||
|
|
8c804957fa | ||
|
|
8b1fc9a18f | ||
|
|
bd35c23784 | ||
|
|
aef3ed8bcb | ||
|
|
01b23a3e88 | ||
|
|
4185f3816b | ||
|
|
4522b40879 |
@@ -1,10 +0,0 @@
|
||||
.cache
|
||||
docs/dist
|
||||
docs/search.json
|
||||
docs/**/*.min.js
|
||||
dist
|
||||
examples
|
||||
node_modules
|
||||
src/react
|
||||
scripts
|
||||
|
||||
213
.eslintrc.cjs
213
.eslintrc.cjs
@@ -1,213 +0,0 @@
|
||||
/* 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': 'error',
|
||||
'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'
|
||||
}
|
||||
};
|
||||
39
.github/workflows/client_tests.js.yml
vendored
Normal file
39
.github/workflows/client_tests.js.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
# # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: Client Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [next]
|
||||
pull_request:
|
||||
branches: [next]
|
||||
|
||||
jobs:
|
||||
client_test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
run: npm run prettier
|
||||
- name: Build
|
||||
run: npm run build
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
- name: Run CSR tests
|
||||
# FAIL_FAST to fail on first failing test.
|
||||
run: FAIL_FAST="true" CSR_ONLY="true" npm run test
|
||||
@@ -1,42 +1,13 @@
|
||||
# # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: Node.js CI
|
||||
name: SSR Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [next]
|
||||
pull_request:
|
||||
branches: [next]
|
||||
|
||||
jobs:
|
||||
client_test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
run: npm run prettier && npm run lint
|
||||
- name: Build
|
||||
run: npm run build
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
- name: Run CSR tests
|
||||
# FAIL_FAST to fail on first failing test.
|
||||
run: FAIL_FAST="true" CSR_ONLY="true" npm run test
|
||||
ssr_test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -56,7 +27,7 @@ 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 && npm run lint
|
||||
run: npm run prettier
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
@@ -3,7 +3,6 @@
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"bierner.lit-html",
|
||||
"bashmish.es6-string-css",
|
||||
"streetsidesoftware.code-spell-checker"
|
||||
]
|
||||
}
|
||||
|
||||
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"prettier.enable": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
|
||||
14
cspell.json
14
cspell.json
@@ -39,12 +39,15 @@
|
||||
"crutchcorn",
|
||||
"csspart",
|
||||
"cssproperty",
|
||||
"cssstate",
|
||||
"datetime",
|
||||
"describedby",
|
||||
"Docsify",
|
||||
"dogfood",
|
||||
"dropdowns",
|
||||
"easings",
|
||||
"ecommerce",
|
||||
"endfor",
|
||||
"endraw",
|
||||
"endregion",
|
||||
"enterkeyhint",
|
||||
@@ -83,6 +86,8 @@
|
||||
"jsfiddle",
|
||||
"keydown",
|
||||
"keyframes",
|
||||
"keymaker",
|
||||
"Konnor",
|
||||
"Kool",
|
||||
"labelledby",
|
||||
"Laravel",
|
||||
@@ -100,6 +105,7 @@
|
||||
"metaframeworks",
|
||||
"middlewares",
|
||||
"minlength",
|
||||
"minmax",
|
||||
"monospace",
|
||||
"mousedown",
|
||||
"mousemove",
|
||||
@@ -108,6 +114,7 @@
|
||||
"multiselectable",
|
||||
"nextjs",
|
||||
"nocheck",
|
||||
"noindex",
|
||||
"noopener",
|
||||
"noreferrer",
|
||||
"novalidate",
|
||||
@@ -120,6 +127,7 @@
|
||||
"peta",
|
||||
"petabit",
|
||||
"Preact",
|
||||
"preconnect",
|
||||
"prismjs",
|
||||
"progressbar",
|
||||
"radiogroup",
|
||||
@@ -150,16 +158,19 @@
|
||||
"smartquotes",
|
||||
"spacebar",
|
||||
"stylesheet",
|
||||
"svgs",
|
||||
"Tabbable",
|
||||
"tabindex",
|
||||
"tabler",
|
||||
"tablist",
|
||||
"tabpanel",
|
||||
"tbody",
|
||||
"templating",
|
||||
"tera",
|
||||
"testid",
|
||||
"textareas",
|
||||
"textfield",
|
||||
"thead",
|
||||
"Themer",
|
||||
"tinycolor",
|
||||
"transitionend",
|
||||
@@ -183,7 +194,8 @@
|
||||
"webawesomer",
|
||||
"WEBP",
|
||||
"Webpacker",
|
||||
"xmark"
|
||||
"xmark",
|
||||
"zoomable"
|
||||
],
|
||||
"ignorePaths": [
|
||||
"package.json",
|
||||
|
||||
@@ -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 { pascalCase } from 'pascal-case';
|
||||
import fs from 'fs';
|
||||
import { pascalCase } from 'pascal-case';
|
||||
|
||||
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,43 +1,55 @@
|
||||
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 { currentLink } from './_utils/current-link.js';
|
||||
import { highlightCodePlugin } from './_utils/highlight-code.js';
|
||||
import { formatCodePlugin } from './_utils/format-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 { getComponents } from './_utils/manifest.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 isDeveloping = process.argv.includes('--develop');
|
||||
const isDev = process.argv.includes('--develop');
|
||||
|
||||
export default function (eleventyConfig) {
|
||||
// NOTE - alpha setting removes certain pages
|
||||
if (isAlpha) {
|
||||
eleventyConfig.ignores.add('**/components/page.md');
|
||||
eleventyConfig.ignores.add('**/experimental/**');
|
||||
eleventyConfig.ignores.add('**/layout/**');
|
||||
eleventyConfig.ignores.add('**/patterns/**');
|
||||
eleventyConfig.ignores.add('**/style-utilities/**');
|
||||
eleventyConfig.ignores.add('**/components/code-demo.md');
|
||||
eleventyConfig.ignores.add('**/components/viewport-demo.md');
|
||||
}
|
||||
|
||||
// Add template data
|
||||
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 || ''));
|
||||
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;
|
||||
|
||||
for (let name in filters) {
|
||||
eleventyConfig.addFilter(name, filters[name]);
|
||||
}
|
||||
|
||||
eleventyConfig.addFilter('sort', (arr, key = 'data.title') => {
|
||||
key = key.split('.');
|
||||
return arr.sort((a, b) => {
|
||||
let aVal = key.reduce((obj, i) => obj?.[i], a);
|
||||
let bVal = key.reduce((obj, i) => obj?.[i], b);
|
||||
return aVal.localeCompare(bVal);
|
||||
});
|
||||
});
|
||||
|
||||
// Shortcodes - {% shortCode arg1, arg2 %}
|
||||
@@ -46,16 +58,9 @@ export default function (eleventyConfig) {
|
||||
});
|
||||
|
||||
// Helpers
|
||||
eleventyConfig.addNunjucksGlobal('getComponent', tagName => {
|
||||
const component = getComponents().find(c => c.tagName === tagName);
|
||||
|
||||
if (!component) {
|
||||
throw new Error(
|
||||
`Unable to find "<${tagName}>". Make sure the file name is the same as the tag name (without prefix).`
|
||||
);
|
||||
}
|
||||
return component;
|
||||
});
|
||||
// Remove elements that have [data-alpha="remove"]
|
||||
eleventyConfig.addPlugin(removeDataAlphaElements({ isAlpha }));
|
||||
|
||||
// Use our own markdown instance
|
||||
eleventyConfig.setLibrary('md', markdown);
|
||||
@@ -71,15 +76,15 @@ export default function (eleventyConfig) {
|
||||
selector: 'h2, h3',
|
||||
ifEmpty: doc => {
|
||||
doc.querySelector('#outline')?.remove();
|
||||
}
|
||||
})
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// Add current link classes
|
||||
eleventyConfig.addPlugin(currentLink());
|
||||
|
||||
// Add code examples for `<code class="example">` blocks
|
||||
eleventyConfig.addPlugin(codeExamplesPlugin());
|
||||
eleventyConfig.addPlugin(codeExamplesPlugin);
|
||||
|
||||
// Highlight code blocks with Prism
|
||||
eleventyConfig.addPlugin(highlightCodePlugin());
|
||||
@@ -93,61 +98,68 @@ 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>',
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const omittedModules = [];
|
||||
// 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`;
|
||||
});
|
||||
|
||||
// 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 = getComponents()
|
||||
// .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,
|
||||
});
|
||||
|
||||
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
|
||||
if (!isDeveloping) {
|
||||
// Run Prettier on each file (prod only because it can be slow)
|
||||
eleventyConfig.addPlugin(formatCodePlugin());
|
||||
}
|
||||
//
|
||||
// TODO - disabled because it takes about a minute to run now
|
||||
//
|
||||
// if (!isDev) {
|
||||
// // Run Prettier on each file (prod only because it can be slow)
|
||||
// eleventyConfig.addPlugin(formatCodePlugin());
|
||||
// }
|
||||
|
||||
return {
|
||||
markdownTemplateEngine: 'njk',
|
||||
dir: {
|
||||
includes: '_includes',
|
||||
layouts: '_layouts'
|
||||
layouts: '_layouts',
|
||||
},
|
||||
templateFormats: ['njk', 'md']
|
||||
templateFormats: ['njk', 'md'],
|
||||
};
|
||||
}
|
||||
|
||||
75
docs/_data/componentList.js
Normal file
75
docs/_data/componentList.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @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';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const manifest = JSON.parse(readFileSync(resolve(__dirname, '../../dist/custom-elements.json'), 'utf-8'));
|
||||
|
||||
const components = manifest.modules.flatMap(module => {
|
||||
return module.declarations
|
||||
.filter(c => c?.customElement)
|
||||
.map(declaration => {
|
||||
// Generate the dist path based on the src path and attach it to the component
|
||||
declaration.path = module.path.replace(/^src\//, 'dist/').replace(/\.ts$/, '.js');
|
||||
|
||||
// Remove private members and those that lack a description
|
||||
const members = declaration.members?.filter(member => member.description && member.privacy !== 'private');
|
||||
|
||||
const methods = members?.filter(prop => prop.kind === 'method' && prop.privacy !== 'private');
|
||||
const attributes = declaration.attributes ?? [];
|
||||
const properties = members?.filter(prop => {
|
||||
// Look for a corresponding attribute
|
||||
const attribute = attributes?.find(attr => attr.fieldName === prop.name);
|
||||
if (attribute) {
|
||||
prop.attribute = attribute.name || attribute.fieldName;
|
||||
}
|
||||
|
||||
return prop.kind === 'field' && prop.privacy !== 'private';
|
||||
});
|
||||
|
||||
return {
|
||||
...declaration,
|
||||
slug: declaration.tagName.replace(/^wa-/, ''),
|
||||
methods,
|
||||
attributes,
|
||||
properties,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
// Build dependency graphs
|
||||
components.forEach(component => {
|
||||
const dependencies = [];
|
||||
|
||||
// Recursively fetch sub-dependencies
|
||||
function getDependencies(tag) {
|
||||
const cmp = components.find(c => c.tagName === tag);
|
||||
if (!cmp || !Array.isArray(component.dependencies)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmp.dependencies?.forEach(dependentTag => {
|
||||
if (!dependencies.includes(dependentTag)) {
|
||||
dependencies.push(dependentTag);
|
||||
}
|
||||
getDependencies(dependentTag);
|
||||
});
|
||||
}
|
||||
|
||||
getDependencies(component.tagName);
|
||||
|
||||
component.dependencies = dependencies.sort();
|
||||
});
|
||||
|
||||
// Sort by name
|
||||
components.sort((a, b) => {
|
||||
if (a.name < b.name) return -1;
|
||||
if (a.name > b.name) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
export default components;
|
||||
3
docs/_data/components.js
Normal file
3
docs/_data/components.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import componentList from './componentList.js';
|
||||
|
||||
export default Object.fromEntries(componentList.map(component => [component.slug, component]));
|
||||
43
docs/_data/componentsBy.js
Normal file
43
docs/_data/componentsBy.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import components from './components.js';
|
||||
|
||||
const by = {
|
||||
attribute: {},
|
||||
slot: {},
|
||||
event: {},
|
||||
method: {},
|
||||
cssPart: {},
|
||||
cssProperty: {},
|
||||
};
|
||||
|
||||
function getAll(component, type) {
|
||||
let prop = type + 's';
|
||||
if (type === 'cssProperty') {
|
||||
prop = 'cssProperties';
|
||||
}
|
||||
|
||||
return component[prop] ?? [];
|
||||
}
|
||||
|
||||
for (const componentName in components) {
|
||||
const component = components[componentName];
|
||||
|
||||
for (const type of ['attribute', 'slot', 'event', 'method', 'cssPart', 'cssProperty']) {
|
||||
for (const item of getAll(component, type)) {
|
||||
by[type][item.name] ??= [];
|
||||
by[type][item.name].push(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by descending number of components
|
||||
const sortByLengthDesc = (a, b) => b[1].length - a[1].length;
|
||||
|
||||
for (const key in by) {
|
||||
by[key] = sortObject(by[key], sortByLengthDesc);
|
||||
}
|
||||
|
||||
export default by;
|
||||
|
||||
function sortObject(obj, sorter) {
|
||||
return Object.fromEntries(Object.entries(obj).sort(sorter));
|
||||
}
|
||||
@@ -22,10 +22,10 @@
|
||||
|
||||
{# Web Awesome #}
|
||||
<script type="module" src="/dist/webawesome.loader.js"></script>
|
||||
<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" />
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/default.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/applied.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/color/standard.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/forms.css" />
|
||||
|
||||
{# Docs styles #}
|
||||
<link rel="stylesheet" href="/assets/styles/docs.css" />
|
||||
@@ -43,7 +43,7 @@
|
||||
<wa-page>
|
||||
<header slot="header">
|
||||
{# Nav toggle #}
|
||||
<wa-button variant="text" data-toggle-nav>
|
||||
<wa-button appearance="plain" data-toggle-nav>
|
||||
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
|
||||
</wa-button>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<script src="/assets/scripts/hydration-errors.js"></script>
|
||||
<link rel="stylesheet" href="/assets/styles/hydration-errors.css">
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.4/+esm"></script>
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.10/+esm"></script>
|
||||
|
||||
<script type="module" src="/assets/scripts/code-examples.js"></script>
|
||||
<script type="module" src="/assets/scripts/color-scheme.js"></script>
|
||||
@@ -31,11 +31,10 @@
|
||||
|
||||
{# Web Awesome #}
|
||||
<script type="module" src="/dist/webawesome.ssr-loader.js"></script>
|
||||
<link rel="stylesheet" id="theme-stylesheet" />
|
||||
<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" />
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/default.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/applied.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/utilities.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/forms.css" />
|
||||
|
||||
{# Docs styles #}
|
||||
<link rel="stylesheet" href="/assets/styles/docs.css" />
|
||||
@@ -58,10 +57,24 @@
|
||||
return colorScheme === 'dark';
|
||||
}
|
||||
|
||||
const stylesheet = document.getElementById("theme-stylesheet")
|
||||
let preset = getPresetTheme()
|
||||
const oldStylesheet = document.querySelector("#theme-stylesheet")
|
||||
|
||||
stylesheet.href = `/dist/themes/${preset}.css`
|
||||
const newStylesheet = document.createElement("link")
|
||||
|
||||
let preset = getPresetTheme()
|
||||
newStylesheet.href = `/dist/styles/themes/${preset}.css`
|
||||
newStylesheet.rel = "preload"
|
||||
newStylesheet.as = "style"
|
||||
|
||||
document.head.append(newStylesheet)
|
||||
|
||||
function updateStylesheet () {
|
||||
newStylesheet.rel = "stylesheet"
|
||||
newStylesheet.id = "theme-stylesheet"
|
||||
requestAnimationFrame(() => oldStylesheet.remove())
|
||||
}
|
||||
|
||||
newStylesheet.addEventListener("load", updateStylesheet)
|
||||
|
||||
document.documentElement.classList.toggle(
|
||||
`wa-theme-${preset}-dark`,
|
||||
@@ -71,57 +84,29 @@
|
||||
</head>
|
||||
<body class="layout-{{ layout | stripExtension }}">
|
||||
<!-- use view="desktop" as default to reduce layout jank on desktop site. -->
|
||||
<wa-page view="desktop">
|
||||
<wa-page view="desktop" disable-navigation-toggle="">
|
||||
<header slot="header">
|
||||
{# Logo #}
|
||||
<div id="docs-branding">
|
||||
{# Nav toggle #}
|
||||
<wa-button appearance="text" data-toggle-nav>
|
||||
<wa-button appearance="plain" size="small" data-toggle-nav>
|
||||
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
|
||||
</wa-button>
|
||||
|
||||
<a href="/" aria-label="Web Awesome">
|
||||
<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" class="only-desktop">Alpha</wa-badge>
|
||||
<wa-badge variant="warning" appearance="filled" class="only-desktop">Alpha</wa-badge>
|
||||
</div>
|
||||
|
||||
<div id="docs-toolbar">
|
||||
{# Preset theme selector #}
|
||||
<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 id="preset-theme-selector__text" class="only-desktop">Default</span>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item type="checkbox" value="default">Default</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="classic">Classic</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="fa">Font Awesome</wa-menu-item>
|
||||
|
||||
<wa-menu-item type="checkbox" value="active">Active</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="brutalist">Brutalism</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="glassy">Glassy</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="migration">Migration</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="playful">Playful</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="premium">Premium</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
{# Color scheme selector #}
|
||||
<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 only-desktop">Light</span>
|
||||
<span class="only-dark only-desktop">Dark</span>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item type="checkbox" value="light">Light</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="dark">Dark</wa-menu-item>
|
||||
<wa-divider></wa-divider>
|
||||
<wa-menu-item type="checkbox" value="auto">System</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
{# Desktop selectors #}
|
||||
<div class="only-desktop">
|
||||
{% include "preset-theme-selector.njk" %}
|
||||
{% include "color-scheme-selector.njk" %}
|
||||
</div>
|
||||
|
||||
{# Search #}
|
||||
<wa-button id="search-trigger" appearance="outlined" size="small" data-search>
|
||||
@@ -134,12 +119,16 @@
|
||||
|
||||
{# Sidebar #}
|
||||
{% if hasSidebar %}
|
||||
<aside slot="navigation" id="sidebar" class="docs-aside" data-remember-scroll>
|
||||
<wa-icon-button id="sidebar-close-button" name="xmark" label="Close" data-drawer="close"></wa-icon-button>
|
||||
<nav>
|
||||
{% include "sidebar.njk" %}
|
||||
</nav>
|
||||
</aside>
|
||||
{# Mobile selectors #}
|
||||
<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>
|
||||
</div>
|
||||
<div slot="navigation" id="sidebar" class="docs-aside" data-remember-scroll>
|
||||
{% include "sidebar.njk" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Outline #}
|
||||
@@ -160,6 +149,17 @@
|
||||
</details>
|
||||
</nav>
|
||||
|
||||
{% set breadcrumbs = page.url | breadcrumbs %}
|
||||
{% if breadcrumbs.length > 0 %}
|
||||
<wa-breadcrumb id="docs-breadcrumbs">
|
||||
{% for crumb in breadcrumbs %}
|
||||
<wa-breadcrumb-item href="{{ crumb.url }}">{{ crumb.title }}</wa-breadcrumb-item>
|
||||
{% endfor %}
|
||||
<wa-breadcrumb-item>{# Current page #}</wa-breadcrumb-item>
|
||||
</wa-breadcrumb>
|
||||
{% else %}
|
||||
{% endif %}
|
||||
|
||||
{% block beforeContent %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
15
docs/_includes/color-scheme-selector.njk
Normal file
15
docs/_includes/color-scheme-selector.njk
Normal file
@@ -0,0 +1,15 @@
|
||||
{# Color scheme selector #}
|
||||
<wa-dropdown id="color-scheme-selector">
|
||||
<wa-button slot="trigger" appearance="filled" size="small" pill caret title="Press \ to toggle">
|
||||
<wa-icon class="only-light" slot="prefix" name="sun" variant="regular"></wa-icon>
|
||||
<wa-icon class="only-dark" slot="prefix" name="moon" variant="regular"></wa-icon>
|
||||
<span class="only-light">Light</span>
|
||||
<span class="only-dark">Dark</span>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item type="checkbox" value="light">Light</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="dark">Dark</wa-menu-item>
|
||||
<wa-divider></wa-divider>
|
||||
<wa-menu-item type="checkbox" value="auto">System</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
26
docs/_includes/page-demo.njk
Normal file
26
docs/_includes/page-demo.njk
Normal file
@@ -0,0 +1,26 @@
|
||||
<div id="page_slots_demo">
|
||||
<link rel="stylesheet" href="/assets/examples/page-demo/demo.css">
|
||||
{% set slots = components.page.slots %}
|
||||
|
||||
<fieldset id="page_slots_fieldset">
|
||||
<legend>Slots</legend>
|
||||
<div class="options">
|
||||
{% for slot in slots %}
|
||||
{% if (slot.name != "skip-to-content") and (slot.name != "navigation-toggle-icon") %}
|
||||
<wa-checkbox name="slot" value="{{ slot.name }}" {{ 'checked' if slot.name != "menu" and slot.name != 'navigation-toggle' | safe}} class="{{ 'default' if not slot.name }}"
|
||||
data-description="{{ slot.description | inlineMarkdown }}" title="{{ slot.description | inlineMarkdown | striptags | safe }}">
|
||||
{{ slot.name or "(default)" }}
|
||||
</wa-checkbox>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</fieldset>
|
||||
<wa-viewport-demo viewport="1000">
|
||||
<iframe srcdoc="" id="page_slots_iframe"></iframe>
|
||||
</wa-viewport-demo>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
const cacheBust = new Date().toString()
|
||||
import(`/assets/examples/page-demo/demo.js?${cacheBust}`)
|
||||
</script>
|
||||
18
docs/_includes/preset-theme-selector.njk
Normal file
18
docs/_includes/preset-theme-selector.njk
Normal file
@@ -0,0 +1,18 @@
|
||||
{# Preset theme selector #}
|
||||
<wa-dropdown id="preset-theme-selector">
|
||||
<wa-button slot="trigger" appearance="filled" size="small" pill caret>
|
||||
<wa-icon slot="prefix" name="paintbrush" variant="regular"></wa-icon>
|
||||
<span id="preset-theme-selector__text">Default</span>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item type="checkbox" value="default">Default</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="classic">Classic</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="fa">Font Awesome</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="active">Active</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="brutalist">Brutalism</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="glassy">Glassy</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="migration">Migration</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="playful">Playful</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="premium">Premium</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
@@ -6,7 +6,7 @@
|
||||
<wa-input
|
||||
id="site-search-input"
|
||||
type="search"
|
||||
filled
|
||||
appearance="filled"
|
||||
size="large"
|
||||
clearable
|
||||
placeholder="Search"
|
||||
|
||||
@@ -20,205 +20,59 @@
|
||||
</ul>
|
||||
|
||||
{# Components #}
|
||||
<h2>Components</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/components/">Components Overview</a>
|
||||
</li>
|
||||
<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>
|
||||
<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/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>
|
||||
<li>
|
||||
<a href="/docs/components/visually-hidden">Visually Hidden</a>
|
||||
</li>
|
||||
</ul>
|
||||
<wa-details{{ ' open' if '/components/' in page.url }}>
|
||||
<h2 slot=summary>
|
||||
<a href="/docs/components/" title="Overview">Components
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
{% for component in collections.component | sort %}
|
||||
{% if not component.data.parent and not (isAlpha and component.data.isAlpha) %}
|
||||
<li>
|
||||
<a href="/docs/components/{{ component.fileSlug }}">{{ component.data.title }}</a>
|
||||
|
||||
{% if components[component.fileSlug].status == 'experimental' %}<wa-icon name="flask"></wa-icon>{% endif %}
|
||||
{% if component.data.isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
|
||||
<ul>
|
||||
{% for child in collections.component | sort %}
|
||||
{% if child.data.parent == component.fileSlug and not (isAlpha and child.data.isAlpha) %}
|
||||
<li>
|
||||
<a href="/docs/components/{{ child.fileSlug }}">{{ child.data.title }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</wa-details>
|
||||
|
||||
<wa-details{{ ' open' if '/natives/' in page.url }}>
|
||||
<h2 slot=summary>
|
||||
<a href="/docs/natives/" title="Overview">Natives
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
<ul>
|
||||
{% for page in collections.natives | sort %}
|
||||
<li>
|
||||
<a href="/docs/natives/{{ page.fileSlug }}">{{ page.data.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</wa-details>
|
||||
|
||||
{# Layout #}
|
||||
<h2>Layout</h2>
|
||||
{% 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/layout">Layout Overview</a></li>
|
||||
<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>
|
||||
@@ -227,13 +81,12 @@
|
||||
<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/">Pattern Overview</a>
|
||||
</li>
|
||||
<li><a href="/docs/patterns/app">Web App</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce">E-commerce</a>
|
||||
<ul>
|
||||
@@ -243,20 +96,22 @@
|
||||
<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-summmary">Order Summaries</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>Theming</h2>
|
||||
<h2>
|
||||
<a href="/docs/theming" title="Overview">Theming
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/theming/">Theming Overview</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/color">Color</a>
|
||||
</li>
|
||||
@@ -284,10 +139,12 @@
|
||||
</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>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
9
docs/_includes/svgs/page.njk
Normal file
9
docs/_includes/svgs/page.njk
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg width="96" height="80" viewBox="0 0 96 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="1" y="1" width="94" height="6" rx="3" fill="var(--wa-color-surface-default)" stroke="var(--wa-color-surface-border)" stroke-width="2"/>
|
||||
<rect x="1" y="13" width="94" height="6" rx="3" fill="var(--wa-color-surface-default)" stroke="var(--wa-color-surface-border)" stroke-width="2"/>
|
||||
<rect x="1" y="73" width="94" height="6" rx="3" fill="var(--wa-color-surface-default)" stroke="var(--wa-color-surface-border)" stroke-width="2"/>
|
||||
<rect x="25" y="61" width="46" height="6" rx="3" fill="var(--wa-color-surface-default)" stroke="var(--wa-color-surface-border)" stroke-width="2"/>
|
||||
<rect x="25" y="25" width="46" height="30" rx="5" fill="var(--wa-color-surface-default)" stroke="var(--wa-color-surface-border)" stroke-width="2"/>
|
||||
<rect x="1" y="25" width="18" height="42" rx="5" fill="var(--wa-color-surface-default)" stroke="var(--wa-color-surface-border)" stroke-width="2"/>
|
||||
<rect x="77" y="25" width="18" height="42" rx="5" fill="var(--wa-color-surface-default)" stroke="var(--wa-color-surface-border)" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
68
docs/_layouts/blank.njk
Normal file
68
docs/_layouts/blank.njk
Normal file
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-fa-kit-code="b10bfbde90" data-cdn-url="{% cdnUrl %}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="{{ description }}">
|
||||
{% if noindex %}<meta name="robots" content="noindex">{% endif %}
|
||||
|
||||
<title>{{ title }}</title>
|
||||
|
||||
<link rel="icon" href="/assets/images/webawesome-logo.svg" />
|
||||
<link rel="apple-touch-icon" href="/assets/images/app-icon.png">
|
||||
|
||||
{# Scripts #}
|
||||
{# Hydration stuff #}
|
||||
<script src="/assets/scripts/hydration-errors.js"></script>
|
||||
<link rel="stylesheet" href="/assets/styles/hydration-errors.css">
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.10/+esm"></script>
|
||||
|
||||
{# Web Awesome #}
|
||||
<script type="module" src="/dist/webawesome.ssr-loader.js"></script>
|
||||
<link rel="stylesheet" id="theme-stylesheet" />
|
||||
<link rel="stylesheet" href="/dist/styles/applied.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/utilities.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/forms.css" />
|
||||
|
||||
{# Set the theme to prevent flashing #}
|
||||
<script>
|
||||
function getColorScheme() {
|
||||
return localStorage.getItem('colorScheme') || 'auto';
|
||||
}
|
||||
|
||||
function getPresetTheme () {
|
||||
return localStorage.getItem('presetTheme') || 'default';
|
||||
}
|
||||
|
||||
function isDark() {
|
||||
const colorScheme = getColorScheme()
|
||||
if (colorScheme === 'auto') {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
}
|
||||
return colorScheme === 'dark';
|
||||
}
|
||||
|
||||
const stylesheet = document.getElementById("theme-stylesheet")
|
||||
let preset = getPresetTheme()
|
||||
|
||||
stylesheet.href = `/dist/styles/themes/${preset}.css`
|
||||
|
||||
document.documentElement.classList.toggle(
|
||||
`wa-theme-${preset}-dark`,
|
||||
isDark()
|
||||
);
|
||||
</script>
|
||||
</head>
|
||||
<body class="layout-{{ layout | stripExtension }}">
|
||||
|
||||
{% block beforeContent %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
|
||||
{% block afterContent %}{% endblock %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +1,6 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
{% set component = getComponent('wa-' + page.fileSlug) %}
|
||||
{% set component = components[page.fileSlug] %}
|
||||
{% set description = component.summary %}
|
||||
|
||||
{% extends '../_includes/base.njk' %}
|
||||
@@ -9,7 +9,7 @@
|
||||
{% block beforeContent %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
<div class="component-info">
|
||||
<code class="component-tag"><{{ component.tagName }}></code>
|
||||
<code class="tag"><{{ component.tagName }}></code>
|
||||
<wa-badge variant="neutral">Since {{ component.since }}</wa-badge>
|
||||
<wa-badge
|
||||
{% if component.status == 'stable' %}variant="brand"{% endif %}
|
||||
@@ -17,10 +17,19 @@
|
||||
>
|
||||
{{ component.status }}
|
||||
</wa-badge>
|
||||
|
||||
{% if isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
|
||||
</div>
|
||||
<p class="component-summary">
|
||||
<p class="summary">
|
||||
{{ component.summary | inlineMarkdown | safe }}
|
||||
</p>
|
||||
{% if natives %}
|
||||
<wa-callout variant="success">
|
||||
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
|
||||
Just want the styles?
|
||||
Check out <a href="/docs/natives/{{ natives }}/">{{ ('/docs/natives/' + natives + '/') | getTitleFromUrl }} natives</a>!
|
||||
</wa-callout>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{# Content #}
|
||||
@@ -33,6 +42,7 @@
|
||||
{# 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">
|
||||
@@ -62,7 +72,8 @@
|
||||
|
||||
{# Properties #}
|
||||
{% if component.properties.length %}
|
||||
<h2>Properties</h2>
|
||||
<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">
|
||||
@@ -77,9 +88,9 @@
|
||||
{% for prop in component.properties %}
|
||||
<tr>
|
||||
<td class="table-name">
|
||||
<code>{{ prop.name }}</code><br>
|
||||
<code title="JS property">{{ prop.name }}</code><br>
|
||||
{% if prop.attribute %}
|
||||
<div><small><code>{{ prop.attribute }}</code></small></div>
|
||||
<div><small><code title="HTML attribute">{{ prop.attribute }}</code></small></div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="table-description">
|
||||
@@ -109,6 +120,8 @@
|
||||
{# 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>
|
||||
@@ -139,34 +152,10 @@
|
||||
</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">
|
||||
@@ -193,6 +182,7 @@
|
||||
{# 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">
|
||||
@@ -221,9 +211,37 @@
|
||||
</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">
|
||||
@@ -249,7 +267,7 @@
|
||||
{% if component.dependencies.length %}
|
||||
<h2>Dependencies</h2>
|
||||
<p>
|
||||
This component automatically imports the following elements. Subdependencies, if any exist, will also be included in this list.
|
||||
This component automatically imports the following elements. Sub-dependencies, if any exist, will also be included in this list.
|
||||
</p>
|
||||
|
||||
<ul class="dependency-list">
|
||||
@@ -266,9 +284,9 @@
|
||||
</p>
|
||||
|
||||
<wa-tab-group label="How would you like to import this component?">
|
||||
<wa-tab slot="nav" panel="cdn">CDN</wa-tab>
|
||||
<wa-tab slot="nav" panel="npm">npm</wa-tab>
|
||||
<wa-tab slot="nav" panel="react">React</wa-tab>
|
||||
<wa-tab panel="cdn">CDN</wa-tab>
|
||||
<wa-tab panel="npm">npm</wa-tab>
|
||||
<wa-tab panel="react">React</wa-tab>
|
||||
<wa-tab-panel name="cdn">
|
||||
<p>
|
||||
To manually import this component from the CDN, use the following code.
|
||||
|
||||
55
docs/_layouts/element.njk
Normal file
55
docs/_layouts/element.njk
Normal file
@@ -0,0 +1,55 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
|
||||
{% extends '../_includes/base.njk' %}
|
||||
|
||||
{# Component header #}
|
||||
{% block beforeContent %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
<div class="component-info">
|
||||
{% for tag, url in elements %}
|
||||
<code class="tag"><a href="{{ url }}">{{ tag }}</a></code>
|
||||
{% endfor %}
|
||||
{% if since %}<wa-badge variant="neutral">Since {{ since }}</wa-badge>{% endif %}
|
||||
{% if status %}
|
||||
<wa-badge
|
||||
{% if status == 'stable' %}variant="brand"{% endif %}
|
||||
{% if status == 'experimental' %}variant="warning"{% endif %}
|
||||
>
|
||||
{{ status }}
|
||||
</wa-badge>
|
||||
{% endif %}
|
||||
|
||||
{% if isPro %}
|
||||
<wa-badge class="pro">PRO</wa-badge>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if description -%}
|
||||
<p class="summary">{{ description | inlineMarkdown | safe }}</p>
|
||||
{%- endif %}
|
||||
{% if component %}
|
||||
<wa-callout variant="success">
|
||||
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
|
||||
Want to do more?
|
||||
Check out the {% for name in (component | toArray) -%}
|
||||
{{ ' 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 | isArray) }}</a>!
|
||||
</wa-callout>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{# Content #}
|
||||
{% block content %}
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
|
||||
{# Component API #}
|
||||
{% 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 Natives, you can include the following CSS files:</p>
|
||||
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
{% set hasOutline = false %}
|
||||
|
||||
{% extends "../_includes/base.njk" %}
|
||||
|
||||
4
docs/_layouts/pattern.njk
Normal file
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 { v4 as uuid } from 'uuid';
|
||||
import slugify from 'slugify';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
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) {
|
||||
@@ -39,22 +39,26 @@ export function anchorHeadingsPlugin(options = {}) {
|
||||
// Look for headings
|
||||
container.querySelectorAll(options.headingSelector).forEach(heading => {
|
||||
const hasAnchor = heading.querySelector('a');
|
||||
const existingId = heading.getAttribute('id');
|
||||
const clone = parse(heading.outerHTML);
|
||||
|
||||
// Create a clone of the heading so we can remove [data-no-anchor] elements from the text content
|
||||
clone.querySelectorAll('[data-no-anchor]').forEach(el => el.remove());
|
||||
|
||||
const slug = createId(clone.textContent ?? '') ?? uuid().slice(-12);
|
||||
let id = slug;
|
||||
let suffix = 0;
|
||||
|
||||
// Make sure the slug is unique in the document
|
||||
while (doc.getElementById(id) !== null) {
|
||||
id = `${slug}-${++suffix}`;
|
||||
if (hasAnchor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasAnchor || !id) {
|
||||
return;
|
||||
let id = existingId;
|
||||
if (!id) {
|
||||
const slug = createId(clone.textContent ?? '') ?? uuid().slice(-12);
|
||||
id = slug;
|
||||
let suffix = 1;
|
||||
|
||||
// Make sure the slug is unique in the document
|
||||
while (doc.getElementById(id) !== null) {
|
||||
id = `${slug}-${++suffix}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the anchor
|
||||
@@ -67,7 +71,9 @@ export function anchorHeadingsPlugin(options = {}) {
|
||||
anchor.querySelector('.wa-visually-hidden').textContent = options.anchorLabel;
|
||||
|
||||
// Update the heading
|
||||
heading.setAttribute('id', id);
|
||||
if (!existingId) {
|
||||
heading.setAttribute('id', id);
|
||||
}
|
||||
heading.classList.add('anchor-heading');
|
||||
heading.appendChild(anchor);
|
||||
});
|
||||
|
||||
@@ -1,82 +1,190 @@
|
||||
import { parse } from 'node-html-parser';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const templates = {
|
||||
old(pre, code, { open, buttons, edit }) {
|
||||
const id = `code-example-${uuid().slice(-12)}`;
|
||||
let preview = code.textContent;
|
||||
|
||||
// Run preview scripts as modules to prevent collisions
|
||||
const root = parse(preview, { blockTextElements: { script: true } });
|
||||
root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module'));
|
||||
preview = root.toString();
|
||||
|
||||
return `
|
||||
<div class="code-example ${open ? 'open' : ''}">
|
||||
<div class="code-example-preview">
|
||||
${preview}
|
||||
</div>
|
||||
<div class="code-example-source" id="${id}">
|
||||
${pre.outerHTML}
|
||||
</div>
|
||||
${
|
||||
buttons
|
||||
? `
|
||||
<div class="code-example-buttons">
|
||||
<button
|
||||
class="code-example-toggle"
|
||||
type="button"
|
||||
aria-expanded="${open ? 'true' : 'false'}"
|
||||
aria-controls="${id}"
|
||||
>
|
||||
Code
|
||||
<wa-icon name="chevron-down"></wa-icon>
|
||||
</button>
|
||||
${
|
||||
edit
|
||||
? `
|
||||
<button class="code-example-pen" type="button">
|
||||
<wa-icon name="pen-to-square"></wa-icon>
|
||||
Edit
|
||||
</button>
|
||||
`
|
||||
: ''
|
||||
}
|
||||
`
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
new(pre, code, { open, first, attributes }) {
|
||||
attributes = {
|
||||
open,
|
||||
include: `link[rel=stylesheet][href^='/dist/']`,
|
||||
...attributes,
|
||||
};
|
||||
|
||||
const attributesString = Object.entries(attributes)
|
||||
.map(([key, value]) => {
|
||||
if (value === true) {
|
||||
return key;
|
||||
}
|
||||
if (value === false || value === null) {
|
||||
return '';
|
||||
}
|
||||
return `${key}="${value}"`;
|
||||
})
|
||||
.join(' ');
|
||||
|
||||
let includes = '';
|
||||
if (first) {
|
||||
includes = `
|
||||
<template class="wa-code-demo-include-isolated">
|
||||
<script src="/dist/webawesome.loader.js" type="module"></script>
|
||||
</template>`;
|
||||
}
|
||||
|
||||
let preview = '';
|
||||
if (attributes.viewport === undefined) {
|
||||
// Slot in pre-rendered preview
|
||||
preview = `<div style="display:contents" slot="preview">${code.textContent}</div>`;
|
||||
|
||||
// Run preview scripts as modules to prevent collisions
|
||||
const root = parse(preview, { blockTextElements: { script: true } });
|
||||
root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module'));
|
||||
preview = root.toString();
|
||||
}
|
||||
|
||||
return `${includes}
|
||||
<wa-code-demo ${attributesString}>
|
||||
${preview}
|
||||
${pre.outerHTML}
|
||||
</wa-code-demo>
|
||||
`;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Eleventy plugin to turn `<code class="example">` blocks into live examples.
|
||||
*/
|
||||
export function codeExamplesPlugin(options = {}) {
|
||||
options = {
|
||||
export function codeExamplesPlugin(eleventyConfig, options = {}) {
|
||||
const defaultOptions = {
|
||||
container: 'body',
|
||||
...options
|
||||
defaultOpen: (code, { outputPathIndex }) => {
|
||||
return (
|
||||
outputPathIndex === 1 && // is first
|
||||
code.textContent.length < 500
|
||||
); // is short
|
||||
},
|
||||
};
|
||||
options = { ...defaultOptions, ...options };
|
||||
|
||||
const stats = {
|
||||
inputPaths: {},
|
||||
outputPaths: {},
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
eleventyConfig.addTransform('code-examples', content => {
|
||||
const doc = parse(content, { blockTextElements: { code: true } });
|
||||
const container = doc.querySelector(options.container);
|
||||
eleventyConfig.addTransform('code-examples', function (content) {
|
||||
const { inputPath, outputPath } = this.page;
|
||||
|
||||
if (!container) {
|
||||
return content;
|
||||
const doc = parse(content, { blockTextElements: { code: true } });
|
||||
const container = doc.querySelector(options.container);
|
||||
|
||||
if (!container) {
|
||||
return content;
|
||||
}
|
||||
|
||||
// Look for external links
|
||||
container.querySelectorAll('code.example').forEach(code => {
|
||||
stats.inputPaths[inputPath] ??= 0;
|
||||
stats.outputPaths[outputPath] ??= 0;
|
||||
stats.inputPaths[inputPath]++;
|
||||
stats.outputPaths[outputPath]++;
|
||||
|
||||
const pre = code.closest('pre');
|
||||
const first = stats.inputPaths[inputPath] === 1;
|
||||
|
||||
const localOptions = {
|
||||
...options,
|
||||
first,
|
||||
|
||||
// Modifier defaults
|
||||
edit: true,
|
||||
buttons: true,
|
||||
new: true, // comment this line to default back to the old demos
|
||||
attributes: {},
|
||||
};
|
||||
|
||||
for (const prop of ['new', 'open', 'buttons', 'edit']) {
|
||||
if (code.classList.contains(prop)) {
|
||||
localOptions[prop] = true;
|
||||
} else if (code.classList.contains(`no-${prop}`)) {
|
||||
localOptions[prop] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for external links
|
||||
container.querySelectorAll('code.example').forEach(code => {
|
||||
const pre = code.closest('pre');
|
||||
const hasButtons = !code.classList.contains('no-buttons');
|
||||
const isOpen = code.classList.contains('open') || !hasButtons;
|
||||
const noEdit = code.classList.contains('no-edit');
|
||||
const id = `code-example-${uuid().slice(-12)}`;
|
||||
let preview = pre.textContent;
|
||||
for (const attribute of ['viewport', 'include']) {
|
||||
if (code.hasAttribute(attribute)) {
|
||||
localOptions.attributes[attribute] = code.getAttribute(attribute);
|
||||
code.removeAttribute(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
// Run preview scripts as modules to prevent collisions
|
||||
const root = parse(preview, { blockTextElements: { script: true } });
|
||||
root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module'));
|
||||
preview = root.toString();
|
||||
if (Object.keys(localOptions.attributes).length > 0) {
|
||||
// attributes only work on the new syntax
|
||||
localOptions.new = true;
|
||||
}
|
||||
|
||||
const codeExample = parse(`
|
||||
<div class="code-example ${isOpen ? 'open' : ''}">
|
||||
<div class="code-example-preview">
|
||||
${preview}
|
||||
</div>
|
||||
<div class="code-example-source" id="${id}">
|
||||
${pre.outerHTML}
|
||||
</div>
|
||||
${
|
||||
hasButtons
|
||||
? `
|
||||
<div class="code-example-buttons">
|
||||
<button
|
||||
class="code-example-toggle"
|
||||
type="button"
|
||||
aria-expanded="${isOpen ? 'true' : 'false'}"
|
||||
aria-controls="${id}"
|
||||
>
|
||||
Code
|
||||
<wa-icon name="chevron-down"></wa-icon>
|
||||
</button>
|
||||
if (localOptions.open === undefined) {
|
||||
if (localOptions.defaultOpen === true) {
|
||||
localOptions.open = localOptions.defaultOpen;
|
||||
} else if (typeof localOptions.defaultOpen === 'function') {
|
||||
localOptions.open = localOptions.defaultOpen(code, {
|
||||
pre,
|
||||
inputPathIndex: stats.inputPaths[inputPath],
|
||||
outputPathIndex: stats.outputPaths[outputPath],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
${
|
||||
noEdit
|
||||
? ''
|
||||
: `
|
||||
<button class="code-example-pen" type="button">
|
||||
<wa-icon name="pen-to-square"></wa-icon>
|
||||
Edit
|
||||
</button>
|
||||
`
|
||||
}
|
||||
const template = localOptions.new ? 'new' : 'old';
|
||||
const codeExample = parse(templates[template](pre, code, localOptions));
|
||||
|
||||
`
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
pre.replaceWith(codeExample);
|
||||
});
|
||||
|
||||
return doc.toString();
|
||||
pre.replaceWith(codeExample);
|
||||
});
|
||||
};
|
||||
|
||||
return doc.toString();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
79
docs/_utils/filters.js
Normal file
79
docs/_utils/filters.js
Normal file
@@ -0,0 +1,79 @@
|
||||
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 breadcrumbs(url, { withCurrent = false } = {}) {
|
||||
const parts = url.split('/').filter(Boolean);
|
||||
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 isArray(value) {
|
||||
return Array.isArray(value);
|
||||
}
|
||||
|
||||
export function toArray(value) {
|
||||
return isArray(value) ? value : [value];
|
||||
}
|
||||
@@ -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 'prismjs/plugins/custom-class/prism-custom-class.js';
|
||||
import PrismLoader from 'prismjs/components/index.js';
|
||||
import 'prismjs/plugins/custom-class/prism-custom-class.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) {
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname, resolve } from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const manifest = JSON.parse(readFileSync(resolve(__dirname, '../../dist/custom-elements.json'), 'utf-8'));
|
||||
/**
|
||||
* @returns Fetches components from custom-elements.json and returns them in more sane format.
|
||||
*/
|
||||
export function getComponents() {
|
||||
const components = [];
|
||||
|
||||
manifest.modules?.forEach(module => {
|
||||
module.declarations?.forEach(declaration => {
|
||||
if (declaration.customElement) {
|
||||
// Generate the dist path based on the src path and attach it to the component
|
||||
declaration.path = module.path.replace(/^src\//, 'dist/').replace(/\.ts$/, '.js');
|
||||
|
||||
// Remove private members and those that lack a description
|
||||
const members = declaration.members?.filter(member => member.description && member.privacy !== 'private');
|
||||
const methods = members?.filter(prop => prop.kind === 'method' && prop.privacy !== 'private');
|
||||
const properties = members?.filter(prop => {
|
||||
// Look for a corresponding attribute
|
||||
const attribute = declaration.attributes?.find(attr => attr.fieldName === prop.name);
|
||||
if (attribute) {
|
||||
prop.attribute = attribute.name || attribute.fieldName;
|
||||
}
|
||||
|
||||
return prop.kind === 'field' && prop.privacy !== 'private';
|
||||
});
|
||||
components.push({
|
||||
...declaration,
|
||||
methods,
|
||||
properties
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Build dependency graphs
|
||||
components.forEach(component => {
|
||||
const dependencies = [];
|
||||
|
||||
// Recursively fetch sub-dependencies
|
||||
function getDependencies(tag) {
|
||||
const cmp = components.find(c => c.tagName === tag);
|
||||
if (!cmp || !Array.isArray(component.dependencies)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmp.dependencies?.forEach(dependentTag => {
|
||||
if (!dependencies.includes(dependentTag)) {
|
||||
dependencies.push(dependentTag);
|
||||
}
|
||||
getDependencies(dependentTag);
|
||||
});
|
||||
}
|
||||
|
||||
getDependencies(component.tagName);
|
||||
|
||||
component.dependencies = dependencies.sort();
|
||||
});
|
||||
|
||||
// Sort by name
|
||||
return components.sort((a, b) => {
|
||||
if (a.name < b.name) return -1;
|
||||
if (a.name > b.name) return 1;
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
@@ -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: ['id', 'class', 'data']
|
||||
allowedAttributes: [],
|
||||
});
|
||||
|
||||
@@ -15,7 +15,7 @@ export function outlinePlugin(options = {}) {
|
||||
target: '.outline',
|
||||
selector: 'h2,h3',
|
||||
ifEmpty: () => null,
|
||||
...options
|
||||
...options,
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
|
||||
23
docs/_utils/remove-data-alpha-elements.js
Normal file
23
docs/_utils/remove-data-alpha-elements.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { parse } from 'node-html-parser';
|
||||
|
||||
/**
|
||||
* Eleventy plugin to add remove elements with <div data-alpha="remove"> from the alpha build.
|
||||
*/
|
||||
export function removeDataAlphaElements(options = {}) {
|
||||
options = {
|
||||
isAlpha: false,
|
||||
...options,
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
eleventyConfig.addTransform('remove-data-alpha-elements', content => {
|
||||
const doc = parse(content, { blockTextElements: { code: true } });
|
||||
|
||||
if (options.isAlpha) {
|
||||
doc.querySelectorAll('[data-alpha="remove"]').forEach(el => el.remove());
|
||||
}
|
||||
|
||||
return doc.toString();
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
/* eslint-disable no-invalid-this */
|
||||
import { dirname, join } from 'path';
|
||||
import { mkdir, writeFile } from 'fs/promises';
|
||||
import { parse } from 'node-html-parser';
|
||||
import lunr from 'lunr';
|
||||
import { parse } from 'node-html-parser';
|
||||
import { dirname, join } from 'path';
|
||||
|
||||
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;
|
||||
|
||||
23
docs/assets/examples/page-demo/demo.css
Normal file
23
docs/assets/examples/page-demo/demo.css
Normal file
@@ -0,0 +1,23 @@
|
||||
#page_slots_demo {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: 1em;
|
||||
margin-bottom: var(--wa-space-xl);
|
||||
|
||||
fieldset .options {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(9em, 1fr));
|
||||
gap: 0.2em 1em;
|
||||
|
||||
wa-checkbox {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
p {
|
||||
display: contents;
|
||||
}
|
||||
}
|
||||
|
||||
wa-viewport-demo {
|
||||
}
|
||||
}
|
||||
43
docs/assets/examples/page-demo/demo.js
Normal file
43
docs/assets/examples/page-demo/demo.js
Normal file
@@ -0,0 +1,43 @@
|
||||
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/']"))
|
||||
.map(i => i.outerHTML)
|
||||
.join('\n');
|
||||
let includes = `${stylesheets}
|
||||
<script src="/dist/webawesome.loader.js" type="module"></script>
|
||||
<link rel="stylesheet" href="/assets/examples/page-demo/page.css">`;
|
||||
|
||||
function render() {
|
||||
let slots = Array.from(fieldset.querySelectorAll('wa-checkbox[name=slot]:state(checked)'));
|
||||
let slotsHTML = slots
|
||||
.map(slot => {
|
||||
let name = slot.getAttribute('value');
|
||||
let description = slot.getAttribute('data-description');
|
||||
|
||||
let tag = 'div';
|
||||
if (name.endsWith('header')) {
|
||||
tag = 'header';
|
||||
}
|
||||
if (name.endsWith('footer')) {
|
||||
tag = 'footer';
|
||||
}
|
||||
|
||||
return `<${tag} class="slot-content" slot="${name}">
|
||||
<strong>${name || 'main <em>(default)</em>'}</strong>
|
||||
<p>${description}</p>
|
||||
</${tag}>`;
|
||||
})
|
||||
.join('\n');
|
||||
let page = iframe.contentDocument?.querySelector('wa-page');
|
||||
|
||||
if (page) {
|
||||
page.innerHTML = slotsHTML;
|
||||
} else {
|
||||
iframe.srcdoc = `${includes}<wa-page>${slotsHTML}</wa-page>`;
|
||||
}
|
||||
}
|
||||
fieldset?.addEventListener('input', render);
|
||||
render();
|
||||
66
docs/assets/examples/page-demo/page.css
Normal file
66
docs/assets/examples/page-demo/page.css
Normal file
@@ -0,0 +1,66 @@
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
wa-page {
|
||||
margin: var(--wa-space-xs);
|
||||
margin-inline-start: 0;
|
||||
&::part(base),
|
||||
&::part(main),
|
||||
&::part(navigation),
|
||||
&::part(body) {
|
||||
gap: var(--wa-space-xs);
|
||||
}
|
||||
}
|
||||
|
||||
:is([slot='banner'], [slot='header'], [slot='subheader'], [slot='footer'], [slot*='navigation']) {
|
||||
margin-inline-start: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.slot-content[slot='banner'],
|
||||
.slot-content[slot='header'],
|
||||
.slot-content[slot='subheader'] {
|
||||
outline: 2px solid var(--wa-color-surface-default);
|
||||
}
|
||||
|
||||
.slot-content {
|
||||
padding: var(--wa-space-m);
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background: var(--wa-color-blue-80);
|
||||
color: var(--wa-color-blue-20);
|
||||
|
||||
&[slot='banner'] {
|
||||
background: var(--wa-color-blue-50);
|
||||
color: white;
|
||||
}
|
||||
|
||||
&[slot='header'] {
|
||||
background: var(--wa-color-blue-60);
|
||||
color: var(--wa-color-blue-10);
|
||||
}
|
||||
|
||||
&[slot^='main'],
|
||||
&[slot=''] {
|
||||
background: var(--wa-color-gray-80);
|
||||
color: var(--wa-color-gray-20);
|
||||
}
|
||||
|
||||
&[slot^='navigation'] {
|
||||
background: var(--wa-color-violet-80);
|
||||
color: var(--wa-color-violet-20);
|
||||
}
|
||||
|
||||
strong {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:not([slot='']) p {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 66 KiB |
@@ -1,3 +1,3 @@
|
||||
<svg viewBox="0 0 20 16" xmlns="http://www.w3.org/2000/svg" fill="#f68a4c">
|
||||
<path d="M11.63 1.625C11.63 2.27911 11.2435 2.84296 10.6865 3.10064L14 6L17.2622 5.34755C17.0968 5.10642 17 4.81452 17 4.5C17 3.67157 17.6716 3 18.5 3C19.3284 3 20 3.67157 20 4.5C20 5.31157 19.3555 5.9726 18.5504 5.99917L15.0307 13.8207C14.7077 14.5384 13.9939 15 13.2068 15H6.79317C6.00615 15 5.29229 14.5384 4.96933 13.8207L1.44963 5.99917C0.64452 5.9726 0 5.31157 0 4.5C0 3.67157 0.671573 3 1.5 3C2.32843 3 3 3.67157 3 4.5C3 4.81452 2.9032 5.10642 2.73777 5.34755L6 6L9.31702 3.09761C8.76346 2.83855 8.38 2.27656 8.38 1.625C8.38 0.727537 9.10754 0 10.005 0C10.9025 0 11.63 0.727537 11.63 1.625Z"/>
|
||||
</svg>
|
||||
<svg width="20" height="15" viewBox="0 0 20 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.63 1.625C11.63 2.27911 11.2435 2.84296 10.6865 3.10064L14 6L17.2622 5.34755C17.0968 5.10642 17 4.81452 17 4.5C17 3.67157 17.6716 3 18.5 3C19.3284 3 20 3.67157 20 4.5C20 5.31157 19.3555 5.9726 18.5504 5.99917L15.0307 13.8207C14.7077 14.5384 13.9939 15 13.2068 15H6.79317C6.00615 15 5.29229 14.5384 4.96933 13.8207L1.44963 5.99917C0.64452 5.9726 0 5.31157 0 4.5C0 3.67157 0.671573 3 1.5 3C2.32843 3 3 3.67157 3 4.5C3 4.81452 2.9032 5.10642 2.73777 5.34755L6 6L9.31702 3.09761C8.76346 2.83855 8.38 2.27656 8.38 1.625C8.38 0.727537 9.10754 0 10.005 0C10.9025 0 11.63 0.727537 11.63 1.625Z" fill="var(--wa-brand-orange, #f36944)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 684 B After Width: | Height: | Size: 742 B |
76
docs/assets/scripts/cheatsheet.js
Normal file
76
docs/assets/scripts/cheatsheet.js
Normal file
@@ -0,0 +1,76 @@
|
||||
let url = new URL(location);
|
||||
const pushedURL = false;
|
||||
|
||||
const matchers = {
|
||||
default(textContent, query) {
|
||||
return textContent.includes(query);
|
||||
},
|
||||
|
||||
i(textContent, query) {
|
||||
return textContent.toLowerCase().includes(query.toLowerCase());
|
||||
},
|
||||
|
||||
regexp(textContent, query) {
|
||||
query.lastIndex = 0;
|
||||
return query.test(textContent);
|
||||
},
|
||||
};
|
||||
|
||||
matchers.iregexp = matchers.regexp; // i is baked into the query
|
||||
|
||||
function filterByName(value) {
|
||||
const previousFilter = url.searchParams.get('name') || '';
|
||||
url = new URL(location);
|
||||
|
||||
if (value) {
|
||||
const isRegexp = name_search_regexp.checked;
|
||||
const i = !name_search_i.checked;
|
||||
const query = isRegexp ? new RegExp(value, 'gmsv' + (i ? 'i' : '')) : value;
|
||||
const matcherId = (i ? 'i' : '') + (isRegexp ? 'regexp' : '');
|
||||
const matcher = matchers[matcherId] ?? matchers.default;
|
||||
|
||||
for (const th of document.querySelectorAll('table tbody th:first-child')) {
|
||||
const tr = th.parentNode;
|
||||
const matches = matcher(th.textContent, query);
|
||||
tr.toggleAttribute('hidden', !matches);
|
||||
}
|
||||
url.searchParams.set('name', value);
|
||||
|
||||
if (matcherId) {
|
||||
url.searchParams.set('match', matcherId);
|
||||
} else {
|
||||
url.searchParams.delete('match');
|
||||
}
|
||||
} else {
|
||||
for (const tr of document.querySelectorAll('table tbody tr[hidden]')) {
|
||||
tr.removeAttribute('hidden');
|
||||
}
|
||||
url.searchParams.delete('name');
|
||||
url.searchParams.delete('match');
|
||||
}
|
||||
|
||||
if (value !== previousFilter) {
|
||||
history[pushedURL ? 'replaceState' : 'pushState'](null, '', url);
|
||||
}
|
||||
|
||||
// Update heading counts
|
||||
for (const h2 of document.querySelectorAll('h2:has(+ table)')) {
|
||||
const count = h2.querySelector('.count');
|
||||
if (!count) continue;
|
||||
const table = h2.nextElementSibling;
|
||||
const visibleRows = table.querySelectorAll('tbody tr:not([hidden])').length;
|
||||
count.textContent = visibleRows;
|
||||
const outlineLink = document.querySelector(`#outline-standard a[href="#${h2.id}"]`);
|
||||
if (outlineLink) {
|
||||
// Why not just = h2.textContent? To skip the "Jump to heading" link
|
||||
outlineLink.textContent = '';
|
||||
outlineLink.append(...[...h2.childNodes].slice(0, 3).map(n => n.cloneNode(true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (name_search.value) {
|
||||
filterByName(name_search.value);
|
||||
}
|
||||
|
||||
name_search_group.addEventListener('wa-input', e => filterByName(name_search.value));
|
||||
@@ -18,10 +18,11 @@ 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}themes/default.css">\n\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}themes/applied.css">\n\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}styles/themes/default.css">\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}styles/applied.css">\n` +
|
||||
`<link rel="stylesheet" href="${cdnUrl}styles/utilities.css">\n\n` +
|
||||
`${code.textContent}`;
|
||||
const css = 'body {\n font: 16px sans-serif;\n padding: 2rem;\n}';
|
||||
const css = 'html > body {\n font: 16px sans-serif;\n padding: 2rem;\n}';
|
||||
const js = '';
|
||||
|
||||
const form = document.createElement('form');
|
||||
@@ -42,7 +43,7 @@ document.addEventListener('click', event => {
|
||||
js_pre_processor: 'none',
|
||||
html,
|
||||
css,
|
||||
js
|
||||
js,
|
||||
};
|
||||
|
||||
const input = document.createElement('input');
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
const stylesheet = document.getElementById('theme-stylesheet');
|
||||
|
||||
const newStylesheet = Object.assign(document.createElement('link'), {
|
||||
href: `/dist/themes/${presetTheme}.css`,
|
||||
href: `/dist/styles/themes/${presetTheme}.css`,
|
||||
rel: 'preload',
|
||||
as: 'style'
|
||||
as: 'style',
|
||||
});
|
||||
|
||||
newStylesheet.addEventListener(
|
||||
@@ -23,7 +23,7 @@
|
||||
stylesheet.remove();
|
||||
});
|
||||
},
|
||||
{ once: true }
|
||||
{ once: true },
|
||||
);
|
||||
|
||||
document.head.append(newStylesheet);
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (id) {
|
||||
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) {
|
||||
const target = document.getElementById(id);
|
||||
const headerHeight = document.querySelector('wa-page > header').clientHeight;
|
||||
|
||||
@@ -15,7 +16,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);
|
||||
|
||||
@@ -25,12 +25,19 @@ wa-page::part(header) {
|
||||
border-bottom: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-border-quiet);
|
||||
}
|
||||
|
||||
wa-page::part(body) {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
wa-page::part(header-actions) {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
wa-page > header {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 4rem;
|
||||
padding-inline: var(--wa-space-xl);
|
||||
|
||||
a[href='/'] {
|
||||
@@ -39,7 +46,8 @@ wa-page > header {
|
||||
}
|
||||
|
||||
wa-button[data-toggle-nav] {
|
||||
--label-color: currentColor;
|
||||
--text-color: currentColor;
|
||||
font-size: 1rem;
|
||||
margin-inline-start: -0.875rem;
|
||||
margin-inline-end: 0;
|
||||
|
||||
@@ -68,8 +76,6 @@ 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;
|
||||
}
|
||||
@@ -87,11 +93,28 @@ wa-page > header {
|
||||
#outline {
|
||||
h2 {
|
||||
font-size: var(--wa-font-size-m);
|
||||
margin-block-end: var(--wa-space-m);
|
||||
margin: 0;
|
||||
}
|
||||
h2:not(:first-of-type) {
|
||||
margin-block-start: var(--wa-space-xl);
|
||||
|
||||
h2:not(:first-child),
|
||||
wa-details:not(:first-child) {
|
||||
margin-block-start: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
wa-details {
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
wa-details::part(header) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
wa-details::part(content) {
|
||||
padding-inline: 0;
|
||||
padding-block-end: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
border-inline-start: var(--wa-border-width-s) solid var(--wa-color-surface-border);
|
||||
font-size: var(--wa-font-size-s);
|
||||
@@ -99,19 +122,83 @@ 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;
|
||||
margin-block-end: var(--wa-space-m);
|
||||
|
||||
+ 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) {
|
||||
font-size: var(--wa-font-size-2xs);
|
||||
font-weight: var(--wa-font-weight-bold);
|
||||
}
|
||||
|
||||
li wa-icon {
|
||||
color: var(--wa-color-text-quiet);
|
||||
vertical-align: middle;
|
||||
|
||||
&[name='flask'] {
|
||||
margin-inline: 0.125em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#outline-standard h2 {
|
||||
margin-block-end: var(--wa-space-m);
|
||||
}
|
||||
|
||||
/* Pro badges */
|
||||
wa-badge.pro::part(base) {
|
||||
background-color: var(--wa-brand-orange);
|
||||
border-color: var(--wa-brand-orange);
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
h2 {
|
||||
color: var(--wa-color-text-quiet);
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4em;
|
||||
color: var(--wa-color-text-normal);
|
||||
text-decoration: none;
|
||||
|
||||
wa-icon {
|
||||
margin-block-end: -0.15em;
|
||||
font-size: var(--wa-font-size-s);
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
color: var(--wa-color-gray-70);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--wa-color-brand-on-normal);
|
||||
|
||||
wa-icon {
|
||||
color: var(--wa-color-brand-on-quiet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +230,14 @@ wa-page > main {
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
h1.title wa-badge {
|
||||
vertical-align: middle;
|
||||
|
||||
&::part(base) {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.component-info {
|
||||
margin-block-end: var(--wa-flow-spacing);
|
||||
}
|
||||
@@ -384,6 +479,7 @@ wa-page > main:has(> .index-grid) {
|
||||
|
||||
.table-scroll {
|
||||
overflow-x: auto;
|
||||
margin-block-end: var(--wa-flow-spacing);
|
||||
}
|
||||
|
||||
/** mobile */
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
.hero wa-button[variant='brand'] {
|
||||
--background: var(--wa-color-neutral-fill-quiet);
|
||||
--label-color: var(--wa-color-neutral-on-normal);
|
||||
--text-color: var(--wa-color-neutral-on-normal);
|
||||
}
|
||||
|
||||
.project-header {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Animated Image
|
||||
description: A component for displaying animated GIFs and WEBPs that play and pause on interaction.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Animation
|
||||
description: Animate elements declaratively with nearly 100 baked-in presets, or roll your own with custom keyframes.
|
||||
layout: component
|
||||
tags: 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.
|
||||
@@ -196,4 +196,4 @@ Animations won't play until you apply the `play` attribute. You can omit it init
|
||||
animation.play = true;
|
||||
});
|
||||
</script>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Avatar
|
||||
description: Avatars are used to represent a person or object.
|
||||
layout: component
|
||||
tags: 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.
|
||||
@@ -97,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::part(base) {
|
||||
.avatar-group wa-avatar {
|
||||
border: solid 2px var(--wa-color-surface-default);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Badge
|
||||
description: Badges are used to draw attention and display statuses or counts.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -22,6 +22,48 @@ 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.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Breadcrumb Item
|
||||
description: Breadcrumb Items are used inside breadcrumbs to represent different links.
|
||||
layout: component
|
||||
tags: component
|
||||
parent: breadcrumb
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Breadcrumb
|
||||
description: Breadcrumbs provide a group of links so users can easily navigate a website's hierarchy.
|
||||
layout: component
|
||||
tags: 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.
|
||||
@@ -135,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="tinted" pill>
|
||||
<wa-button slot="trigger" size="small" appearance="filled" pill>
|
||||
<wa-icon label="More options" name="ellipsis" variant="solid"></wa-icon>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
@@ -160,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="tinted" pill>
|
||||
<wa-button slot="trigger" size="small" appearance="filled" pill>
|
||||
<wa-icon label="More options" name="ellipsis" variant="solid"></wa-icon>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Button Group
|
||||
description: Button groups can be used to group related buttons into sections.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Button
|
||||
description: Buttons represent actions that are available to the user.
|
||||
layout: component
|
||||
tags: component
|
||||
natives: button
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -28,34 +29,34 @@ Use the `appearance` attribute to change the button's visual appearance.
|
||||
|
||||
```html {.example}
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-button appearance="accent" variant="neutral">Accent</wa-button>
|
||||
<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>
|
||||
<wa-button appearance="plain" variant="neutral">Text</wa-button>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-button appearance="accent" variant="brand">Accent</wa-button>
|
||||
<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>
|
||||
<wa-button appearance="plain" variant="brand">Text</wa-button>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-button appearance="accent" variant="success">Accent</wa-button>
|
||||
<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>
|
||||
<wa-button appearance="plain" variant="success">Text</wa-button>
|
||||
</div>
|
||||
<div style="margin-block-end: 1rem;">
|
||||
<wa-button appearance="accent" variant="warning">Accent</wa-button>
|
||||
<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>
|
||||
<wa-button appearance="plain" variant="warning">Text</wa-button>
|
||||
</div>
|
||||
<div>
|
||||
<wa-button appearance="accent" variant="danger">Accent</wa-button>
|
||||
<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>
|
||||
<wa-button appearance="plain" variant="danger">Text</wa-button>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -91,7 +92,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` attribute. 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` CSS property. 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,7 +1,7 @@
|
||||
---
|
||||
title: Callout
|
||||
description: Callouts are used to display important messages inline.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -64,3 +64,9 @@ Icons are optional. Simply omit the `icon` slot if you don't want them.
|
||||
```html {.example}
|
||||
<wa-callout variant="brand"> Nothing fancy here, just a simple callout. </wa-callout>
|
||||
```
|
||||
|
||||
### Styling
|
||||
|
||||
You can customize the callout's appearance mostly by setting regular CSS properties:
|
||||
- `background`, `border`, `border-radius`, `color`, `padding`, `margin`, etc. work as expected
|
||||
- `gap` sets the space between the icon and the content
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Card
|
||||
description: Cards can be used to group related subjects in a container.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Carousel Item
|
||||
description: A carousel item represent a slide within a carousel.
|
||||
layout: component
|
||||
tags: component
|
||||
parent: carousel
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Carousel
|
||||
description: Carousels display an arbitrary number of content slides along a horizontal or vertical axis.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -534,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="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 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>
|
||||
</div>
|
||||
|
||||
@@ -553,7 +553,7 @@ The carousel has a robust API that makes it possible to extend and customize. Th
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.thumbnails__scroller {
|
||||
.scroller {
|
||||
display: flex;
|
||||
gap: var(--wa-space-s);
|
||||
overflow-x: auto;
|
||||
@@ -562,11 +562,11 @@ The carousel has a robust API that makes it possible to extend and customize. Th
|
||||
scroll-padding: var(--wa-space-s);
|
||||
}
|
||||
|
||||
.thumbnails__scroller::-webkit-scrollbar {
|
||||
.scroller::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.thumbnails__image {
|
||||
.image {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
object-fit: cover;
|
||||
@@ -578,7 +578,7 @@ The carousel has a robust API that makes it possible to extend and customize. Th
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.thumbnails__image.active {
|
||||
.image.active {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
@@ -586,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('.thumbnails__scroller');
|
||||
const thumbnails = document.querySelectorAll('.thumbnails__image');
|
||||
const scroller = document.querySelector('.scroller');
|
||||
const thumbnails = document.querySelectorAll('.image');
|
||||
|
||||
scroller.addEventListener('click', e => {
|
||||
const target = e.target;
|
||||
|
||||
if (target.matches('.thumbnails__image')) {
|
||||
if (target.matches('.image')) {
|
||||
const index = [...thumbnails].indexOf(target);
|
||||
carousel.goToSlide(index);
|
||||
}
|
||||
|
||||
82
docs/docs/components/cheatsheet.njk
Normal file
82
docs/docs/components/cheatsheet.njk
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
title: Component Cheatsheet
|
||||
layout: docs
|
||||
---
|
||||
|
||||
<style>
|
||||
table code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>
|
||||
This page lists every bit of syntax used by every Web Awesome component and which components share it.
|
||||
For these times when your memory is failing, or to simply explore the possibilities!
|
||||
</p>
|
||||
|
||||
<fieldset id="name_search_group">
|
||||
<legend>Filter by name</legend>
|
||||
<wa-input type=search clearable id="name_search"></wa-input>
|
||||
<wa-checkbox id="name_search_i" checked>Case sensitive</wa-checkbox>
|
||||
<wa-checkbox id="name_search_regexp">Regular expression</wa-checkbox>
|
||||
</fieldset>
|
||||
|
||||
<script>
|
||||
{
|
||||
let url = new URL(location);
|
||||
if (url.searchParams.get("name")) {
|
||||
name_search.value = url.searchParams.get("name");
|
||||
}
|
||||
|
||||
if (url.searchParams.get("match")) {
|
||||
let matcherId = url.searchParams.get("match");
|
||||
let caseSensitive = !matcherId.startsWith("i");
|
||||
let isRegexp = matcherId.endsWith("regexp");
|
||||
|
||||
customElements.whenDefined("wa-checkbox").then(async () => {
|
||||
await Promise.all([
|
||||
name_search_i.updateComplete,
|
||||
name_search_regexp.updateComplete,
|
||||
]);
|
||||
name_search_i.checked = caseSensitive;
|
||||
name_search_regexp.checked = isRegexp;
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="/assets/scripts/cheatsheet.js"></script>
|
||||
|
||||
{% for type, all in componentsBy -%}
|
||||
{% set typeTitle = "CSS custom properties" if type == "cssProperty" else ("CSS parts" if type == "cssPart" else (type | title) + "s") %}
|
||||
<h2 id="{{ typeTitle | slugify }}">
|
||||
All <span class="count">{{ (all | keys).length }}</span>
|
||||
{{ typeTitle }}
|
||||
</h2>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Components</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for name, thingComponents in all -%}
|
||||
<tr>
|
||||
<th><code>{{ name }}{{ "()" if type == "method" }}</code></th>
|
||||
<td>
|
||||
{% if thingComponents.length > 1 %}
|
||||
<details open>
|
||||
<summary><strong>{{ thingComponents.length }}</strong> components</summary>
|
||||
{% endif %}
|
||||
{% for component in thingComponents %}
|
||||
<a href="../{{ component.slug }}"><code><{{ component.tagName }}></code></a>
|
||||
{%- endfor -%}
|
||||
{% if thingComponents.length > 1 %}
|
||||
</details>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{%- endfor %}
|
||||
</table>
|
||||
|
||||
{%- endfor %}
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Checkbox
|
||||
description: Checkboxes allow the user to toggle an option on or off.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -50,12 +50,12 @@ Use the `size` attribute to change a checkbox's size.
|
||||
<wa-checkbox size="large">Large</wa-checkbox>
|
||||
```
|
||||
|
||||
### Help Text
|
||||
### Hint
|
||||
|
||||
Add descriptive help text to a switch with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
Add descriptive hint to a switch with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
|
||||
|
||||
```html {.example}
|
||||
<wa-checkbox help-text="What should the user know about the checkbox?">Label</wa-checkbox>
|
||||
<wa-checkbox hint="What should the user know about the checkbox?">Label</wa-checkbox>
|
||||
```
|
||||
|
||||
### Custom Validity
|
||||
@@ -92,4 +92,4 @@ Use the `setCustomValidity()` method to set a custom validation message. This wi
|
||||
});
|
||||
});
|
||||
</script>
|
||||
```
|
||||
```
|
||||
|
||||
212
docs/docs/components/code-demo.md
Normal file
212
docs/docs/components/code-demo.md
Normal file
@@ -0,0 +1,212 @@
|
||||
---
|
||||
title: Code Demo
|
||||
description: Code demos can be used to render code examples as inline live demos.
|
||||
tags: component
|
||||
noAlpha: true
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
<wa-code-demo>
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
<wa-button>Click me!</wa-button>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
This component is used right here in the docs to render code examples.
|
||||
|
||||
:::warning
|
||||
Do not render untrusted content in a `<wa-code-demo>` element. This component renders the content as HTML, which introduces XSS vulnerabilities if used with untrusted content.
|
||||
:::
|
||||
|
||||
## Examples
|
||||
|
||||
### Open by default
|
||||
|
||||
```html {.example}
|
||||
<wa-code-demo open>
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
<wa-button>Click me!</wa-button>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
### Custom previews
|
||||
|
||||
In some cases you may want to preprocess the code displayed, for example to sanitize HTML, remove irrelevant elements or attributes, fix whitespace, or do server-side rendering (SSR).
|
||||
For these cases, you can slot in a custom preview:
|
||||
|
||||
```html {.example}
|
||||
<wa-code-demo>
|
||||
<wa-button slot="preview">Click me!</wa-button>
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
Note that this means the preview will be in the light DOM, and can conflict with other things on the page.
|
||||
To only render the custom preview within the component’s shadow DOM, or to display raw text, you can wrap it in a `<template>` element:
|
||||
|
||||
```html {.example}
|
||||
<wa-code-demo>
|
||||
<template slot="preview">
|
||||
<wa-button>Click me!</wa-button>
|
||||
</template>
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
### Including resources (CSS, scripts, etc.)
|
||||
|
||||
Demos are rendered in the shadow DOM of the component, so any resources (stylesheets, scripts, etc.) must be included anew.
|
||||
The same applies to isolated demos (see below), opening demos in a new tab, or editing them on CodePen.
|
||||
|
||||
While you _could_ manually include all of these on every single demo, it would get tedious to write,
|
||||
and it would add noise for the reader.
|
||||
|
||||
Instead, `<wa-code-demo>` provides several better ways to include resources.
|
||||
The core idea is that rather than specifying these resources over and over on each demo,
|
||||
you would **point to elements** which would then be cloned into the demo, at the beginning.
|
||||
|
||||
There are two ways to point to elements:
|
||||
- Add a `wa-code-demo-include` class to them
|
||||
- Specify a CSS selector for which resources to look for in the demo’s `include` attribute.
|
||||
|
||||
There are certain types of elements that are handled specially:
|
||||
- `<template>`: contents are cloned instead of the element itself.
|
||||
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/`,
|
||||
plus any other elements with the class `.demo-import`, plus a CSS file with the class `wa-code-demo-include`:
|
||||
|
||||
```html {.example}
|
||||
<template class="wa-code-demo-include-isolated">
|
||||
<script type="module" src="/dist/webawesome.loader.js"></script>
|
||||
<style>wa-callout { font-size: var(--wa-font-size-2xl) }</style>
|
||||
<script>console.log('Hello!')</script>
|
||||
</template>
|
||||
<wa-code-demo include="link[rel=stylesheet]">
|
||||
<pre><code class="language-html">
|
||||
<wa-callout>Helloooo!</wa-callout>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
|
||||
### Isolated viewports
|
||||
|
||||
Often you may want to render your demo in a separate viewport, e.g. when it’s about a whole page.
|
||||
Or, you may want to sandbox it.
|
||||
For these cases, you can use the `viewport` attribute, which renders the demo in an iframe:
|
||||
|
||||
```html {.example}
|
||||
<wa-code-demo viewport>
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
### Viewport Emulation
|
||||
|
||||
When you use the `viewport` attribute, `<wa-code-demo>` uses [`<wa-viewport-demo>`](../viewport-demo/) internally, and passes the value of `viewport` to it.
|
||||
This allows you to also also provide a width value to emulate and it will be scaled accordingly:
|
||||
|
||||
```html {.example}
|
||||
<wa-code-demo viewport="300">
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
Or both a width and a height value:
|
||||
|
||||
```html {.example}
|
||||
<wa-code-demo viewport="1600 x 1000">
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed maximus et tortor vel ullamcorper. Fusce tristique et justo quis auctor. In tristique dignissim dignissim. Fusce lacus urna, efficitur vel fringilla sed, hendrerit at ipsum. Donec suscipit ante ac ligula imperdiet varius. Aliquam ullamcorper augue sit amet lectus euismod finibus. Proin semper, diam at rhoncus posuere, diam dui semper turpis, ut faucibus mi ipsum nec ante. Morbi varius nibh ut facilisis varius. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Fusce in blandit velit. Aliquam massa eros, commodo eu vestibulum a, faucibus non risus.
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed maximus et tortor vel ullamcorper. Fusce tristique et justo quis auctor. In tristique dignissim dignissim. Fusce lacus urna, efficitur vel fringilla sed, hendrerit at ipsum. Donec suscipit ante ac ligula imperdiet varius. Aliquam ullamcorper augue sit amet lectus euismod finibus. Proin semper, diam at rhoncus posuere, diam dui semper turpis, ut faucibus mi ipsum nec ante. Morbi varius nibh ut facilisis varius. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Fusce in blandit velit. Aliquam massa eros, commodo eu vestibulum a, faucibus non risus.
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed maximus et tortor vel ullamcorper. Fusce tristique et justo quis auctor. In tristique dignissim dignissim. Fusce lacus urna, efficitur vel fringilla sed, hendrerit at ipsum. Donec suscipit ante ac ligula imperdiet varius. Aliquam ullamcorper augue sit amet lectus euismod finibus. Proin semper, diam at rhoncus posuere, diam dui semper turpis, ut faucibus mi ipsum nec ante. Morbi varius nibh ut facilisis varius. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Fusce in blandit velit. Aliquam massa eros, commodo eu vestibulum a, faucibus non risus.
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
If you only provide a width value, the viewport will be rendered to an initial 16:9 aspect ratio,
|
||||
which can be changed via resizing.
|
||||
You can customize this via the `--viewport-initial-aspect-ratio` property.
|
||||
|
||||
### Isolated demos with resources
|
||||
|
||||
Including resources in isolated demos works the same way.
|
||||
Any relative URLs are still resolved relative to the host document.
|
||||
In addition to the `wa-code-demo-include` class, which specifies resources to be included in *every* demo,
|
||||
you can also use the `wa-code-demo-include-isolated` class which specifies resources to be included in every *isolated* demo,
|
||||
i.e. the previews of demos using the `viewport` attribute, but also opening demos in a new tab or editing them on CodePen.
|
||||
|
||||
```html {.example}
|
||||
<template class="wa-code-demo-include-isolated">
|
||||
<script type="module" src="{% cdnUrl 'webawesome.loader.js' %}"></script>
|
||||
<style>
|
||||
body {
|
||||
padding: var(--wa-space-l);
|
||||
}
|
||||
wa-callout { font-size: var(--wa-font-size-2xl) }
|
||||
</style>
|
||||
<script>console.log('Hello from iframe!')</script>
|
||||
</template>
|
||||
<wa-code-demo viewport include="link[rel=stylesheet]">
|
||||
<pre><code class="language-html">
|
||||
<wa-callout>Helloooo!</wa-callout>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
## Styling
|
||||
|
||||
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-s)">
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
<wa-button>Click me!</wa-button>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
The divider width is controlled separately via `--divider-width`:
|
||||
|
||||
```html{.example}
|
||||
<wa-code-demo open style="border-width: var(--wa-border-width-l); --divider-width: var(--wa-border-width-m);">
|
||||
<pre><code class="language-html">
|
||||
<button>Click me!</button>
|
||||
<wa-button>Click me!</wa-button>
|
||||
</code></pre>
|
||||
</wa-code-demo>
|
||||
```
|
||||
|
||||
## Roadmap
|
||||
|
||||
This component is a work in progress.
|
||||
Some of the things that are not yet implemented are listed below.
|
||||
It goes without saying that this list is a rough plan and subject to change.
|
||||
|
||||
### High priority
|
||||
|
||||
- Make the component dynamic so that when the code changes, the demo is updated
|
||||
|
||||
### Low priority
|
||||
|
||||
- Horizontal layout
|
||||
- Tabbed layout
|
||||
- Provide a way to display CSS and JS separately
|
||||
- Provide a way to customize the playground used (currently it is hardcoded to CodePen)
|
||||
- Provide a way to customize the buttons shown
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Color Picker
|
||||
description: Color pickers allow the user to select a color.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -75,10 +75,10 @@ The color picker can be rendered as disabled.
|
||||
<wa-color-picker disabled label="Select a color"></wa-color-picker>
|
||||
```
|
||||
|
||||
### Help Text
|
||||
### Hint
|
||||
|
||||
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.
|
||||
Add descriptive hint to a color picker with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
|
||||
|
||||
```html {.example}
|
||||
<wa-color-picker label="Select a color" help-text="Choose a color with appropate contrast!"></wa-color-picker>
|
||||
```
|
||||
<wa-color-picker label="Select a color" hint="Choose a color with appropate contrast!"></wa-color-picker>
|
||||
```
|
||||
|
||||
3
docs/docs/components/components.json
Normal file
3
docs/docs/components/components.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"layout": "component.njk"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Copy Button
|
||||
description: Copies data to the clipboard when the user clicks the button.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Details
|
||||
description: Details show a brief summary and expand to show additional content.
|
||||
layout: component
|
||||
tags: component
|
||||
natives: details
|
||||
---
|
||||
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
@@ -17,7 +18,7 @@ layout: component
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disable` attribute to prevent the details from expanding.
|
||||
Use the `disabled` attribute to prevent the details from expanding.
|
||||
|
||||
```html {.example}
|
||||
<wa-details summary="Disabled" disabled>
|
||||
@@ -28,7 +29,7 @@ Use the `disable` 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 `summary-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 `icon` part as shown below.
|
||||
|
||||
```html {.example}
|
||||
<wa-details summary="Toggle Me" class="custom-icons">
|
||||
@@ -40,13 +41,41 @@ Use the `expand-icon` and `collapse-icon` slots to change the expand and collaps
|
||||
</wa-details>
|
||||
|
||||
<style>
|
||||
wa-details.custom-icons::part(summary-icon) {
|
||||
/* Disable the expand/collapse animation */
|
||||
/* Disable the expand/collapse animation */
|
||||
wa-details.custom-icons::part(icon) {
|
||||
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,13 +1,14 @@
|
||||
---
|
||||
title: Dialog
|
||||
description: 'Dialogs, sometimes called "modals", appear above the page and require the user''s immediate attention.'
|
||||
layout: component
|
||||
tags: component
|
||||
natives: dialog
|
||||
---
|
||||
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
|
||||
```html {.example}
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-overview">
|
||||
<wa-dialog label="Dialog" with-header with-footer id="dialog-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -15,7 +16,7 @@ layout: component
|
||||
<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);
|
||||
@@ -85,10 +86,10 @@ You can add the special `data-dialog="close"` attribute to a button inside the d
|
||||
|
||||
### Custom Width
|
||||
|
||||
Use the `--width` custom property to set the dialog's width.
|
||||
Just use the CSS `width` 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>
|
||||
@@ -219,4 +220,4 @@ To give focus to a specific element when the dialog opens, use the `autofocus` a
|
||||
|
||||
openButton.addEventListener('click', () => dialog.open = true);
|
||||
</script>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Divider
|
||||
description: Dividers are used to visually separate or group elements.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Drawer
|
||||
description: Drawers slide in from a container to expose additional options and information.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Dropdown
|
||||
description: 'Dropdowns expose additional content that "drops down" in a panel.'
|
||||
layout: component
|
||||
tags: 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,7 +1,7 @@
|
||||
---
|
||||
title: Format Bytes
|
||||
description: Formats a number as a human readable bytes value.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Format Date
|
||||
description: Formats a date/time using the specified locale and options.
|
||||
layout: component
|
||||
tags: 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,7 +1,7 @@
|
||||
---
|
||||
title: Format Number
|
||||
description: Formats a number using the specified locale and options.
|
||||
layout: component
|
||||
tags: 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,7 +1,7 @@
|
||||
---
|
||||
title: Icon Button
|
||||
description: Icons buttons are simple, icon-only buttons that can be used for actions and in toolbars.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
For a full list of icons that come bundled with Web Awesome, refer to the [icon component](/docs/components/icon).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Icon
|
||||
description: Icons are symbols that can be used to represent various options within an application.
|
||||
layout: component
|
||||
tags: 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).
|
||||
@@ -146,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>
|
||||
```
|
||||
@@ -517,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,7 +1,7 @@
|
||||
---
|
||||
title: Image Comparer
|
||||
description: Compare visual differences between similar photos with a sliding panel.
|
||||
layout: component
|
||||
tags: 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,7 +1,7 @@
|
||||
---
|
||||
title: Include
|
||||
description: Includes give you the power to embed external HTML files into the page.
|
||||
layout: component
|
||||
tags: 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.
|
||||
|
||||
@@ -4,17 +4,13 @@ description: Browse the library of customizable, framework-friendly web componen
|
||||
layout: page-outline
|
||||
---
|
||||
|
||||
<style>
|
||||
wa-card#drawer-card::part(header) {
|
||||
--spacing: 0;
|
||||
justify-content: flex-end;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p class="index-summary">Components are the essential building blocks to create intuitive, cohesive experiences. Browse the library of customizable, framework-friendly web components included in Web Awesome.</p>
|
||||
|
||||
<div class="index-grid">
|
||||
<div id="component-filter">
|
||||
<wa-input type="search" placeholder="Search components" clearable autofocus></wa-input>
|
||||
</div>
|
||||
|
||||
<div id="component-grid" class="index-grid">
|
||||
<h2 class="index-category">Actions</h2>
|
||||
<a href="/docs/components/button">
|
||||
<wa-card with-header>
|
||||
@@ -114,7 +110,7 @@ layout: page-outline
|
||||
<span class="page-name">Skeleton</span>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="/docs/components/spinner">
|
||||
<a href="/docs/components/spinner" data-keywords="loader">
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/spinner.njk" %}
|
||||
@@ -198,7 +194,7 @@ layout: page-outline
|
||||
<span class="page-name">Color Picker</span>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="/docs/components/input">
|
||||
<a href="/docs/components/input" data-keywords="textfield text field">
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/input.njk" %}
|
||||
@@ -238,7 +234,7 @@ layout: page-outline
|
||||
<span class="page-name">Select</span>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="/docs/components/switch">
|
||||
<a href="/docs/components/switch" data-keywords="toggle">
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/switch.njk" %}
|
||||
@@ -298,7 +294,7 @@ layout: page-outline
|
||||
<span class="page-name">Details</span>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="/docs/components/dialog">
|
||||
<a href="/docs/components/dialog" data-keywords="modal">
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/dialog.njk" %}
|
||||
@@ -315,13 +311,21 @@ layout: page-outline
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="/docs/components/drawer">
|
||||
<wa-card id="drawer-card">
|
||||
<wa-card with-header id="drawer-card">
|
||||
<div slot="header">
|
||||
{% include "svgs/drawer.njk" %}
|
||||
</div>
|
||||
<span class="page-name">Drawer</span>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="/docs/components/page">
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
{% include "svgs/page.njk" %}
|
||||
</div>
|
||||
<span class="page-name">Page</span>
|
||||
</wa-card>
|
||||
</a>
|
||||
<a href="/docs/components/split-panel">
|
||||
<wa-card with-header>
|
||||
<div slot="header">
|
||||
@@ -412,4 +416,77 @@ layout: page-outline
|
||||
<span class="page-name">Visually Hidden</span>
|
||||
</wa-card>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="component-filter-empty" hidden>
|
||||
No results
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
const container = document.getElementById('component-filter');
|
||||
const empty = document.getElementById('component-filter-empty');
|
||||
const grid = document.getElementById('component-grid');
|
||||
const input = container.querySelector('wa-input');
|
||||
|
||||
function updateResults() {
|
||||
const filter = input.value.toLowerCase().trim();
|
||||
|
||||
// Hide headings while filtering
|
||||
grid.querySelectorAll('h2').forEach(heading => {
|
||||
heading.hidden = filter === '' ? false : true;
|
||||
});
|
||||
|
||||
// Show matching components
|
||||
grid.querySelectorAll('a').forEach(link => {
|
||||
const content = link.textContent.toLowerCase();
|
||||
const keywords = link.getAttribute('data-keywords') || '';
|
||||
const isMatch = filter === '' || (content + keywords).includes(filter);
|
||||
link.classList.toggle('hidden', !isMatch);
|
||||
});
|
||||
|
||||
// Show empty state when there's a search filter and no results
|
||||
if (filter !== '' && grid.querySelector('a:not(.hidden)') === null) {
|
||||
empty.hidden = false;
|
||||
} else {
|
||||
empty.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
input.addEventListener('wa-input', updateResults);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
wa-card#drawer-card::part(header) {
|
||||
--spacing: 0;
|
||||
justify-content: flex-end;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#component-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
gap: var(--wa-space-m);
|
||||
margin-block-start: var(--wa-space-2xl);
|
||||
|
||||
> a {
|
||||
position: static;
|
||||
visibility: visible;
|
||||
|
||||
&.hidden {
|
||||
display: block;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#component-filter-empty {
|
||||
border: dashed var(--wa-border-width-m) var(--wa-color-neutral-border-quiet);
|
||||
border-radius: var(--wa-border-radius-m);
|
||||
font-size: var(--wa-font-size-l);
|
||||
color: var(--wa-color-text-quiet);
|
||||
text-align: center;
|
||||
padding-block: var(--wa-space-2xl);
|
||||
margin-block-start: 0
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Input
|
||||
description: Inputs collect data from the user.
|
||||
layout: component
|
||||
tags: component
|
||||
natives: input
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -22,12 +23,12 @@ Use the `label` attribute to give the input an accessible label. For labels that
|
||||
<wa-input label="What is your name?"></wa-input>
|
||||
```
|
||||
|
||||
### Help Text
|
||||
### Hint
|
||||
|
||||
Add descriptive help text to an input with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
Add descriptive hint to an input with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
|
||||
|
||||
```html {.example}
|
||||
<wa-input label="Nickname" help-text="What would you like people to call you?"></wa-input>
|
||||
<wa-input label="Nickname" hint="What would you like people to call you?"></wa-input>
|
||||
```
|
||||
|
||||
### Placeholders
|
||||
@@ -54,12 +55,12 @@ Add the `password-toggle` attribute to add a toggle button that will show the pa
|
||||
<wa-input type="password" placeholder="Password Toggle" password-toggle></wa-input>
|
||||
```
|
||||
|
||||
### Filled Inputs
|
||||
### Appearance
|
||||
|
||||
Add the `filled` attribute to draw a filled input.
|
||||
Use the `appearance` attribute to change the input's visual appearance.
|
||||
|
||||
```html {.example}
|
||||
<wa-input placeholder="Type something" filled></wa-input>
|
||||
<wa-input placeholder="Type something" appearance="filled"></wa-input>
|
||||
```
|
||||
|
||||
### Disabled
|
||||
@@ -132,9 +133,9 @@ Use the `prefix` and `suffix` slots to add icons.
|
||||
Use [CSS parts](#css-parts) to customize the way form controls are drawn. This example uses CSS grid to position the label to the left of the control, but the possible orientations are nearly endless. The same technique works for inputs, textareas, radio groups, and similar form controls.
|
||||
|
||||
```html {.example}
|
||||
<wa-input class="label-on-left" label="Name" help-text="Enter your name"></wa-input>
|
||||
<wa-input class="label-on-left" label="Email" type="email" help-text="Enter your email"></wa-input>
|
||||
<wa-textarea class="label-on-left" label="Bio" help-text="Tell us something about yourself"></wa-textarea>
|
||||
<wa-input class="label-on-left" label="Name" hint="Enter your name"></wa-input>
|
||||
<wa-input class="label-on-left" label="Email" type="email" hint="Enter your email"></wa-input>
|
||||
<wa-textarea class="label-on-left" label="Bio" hint="Tell us something about yourself"></wa-textarea>
|
||||
|
||||
<style>
|
||||
.label-on-left {
|
||||
@@ -157,8 +158,8 @@ Use [CSS parts](#css-parts) to customize the way form controls are drawn. This e
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.label-on-left::part(form-control-help-text) {
|
||||
.label-on-left::part(hint) {
|
||||
grid-column-start: 2;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Menu Item
|
||||
description: Menu items provide options for the user to pick from in a menu.
|
||||
layout: component
|
||||
tags: component
|
||||
parent: menu
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Menu Label
|
||||
description: Menu labels are used to describe a group of menu items.
|
||||
layout: component
|
||||
tags: component
|
||||
parent: menu
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Menu
|
||||
description: Menus provide a list of options for the user to choose from.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
You can use [menu items](/docs/components/menu-item), [menu labels](/docs/components/menu-label), and [dividers](/docs/components/divider) to compose a menu. Menus support keyboard interactions, including type-to-select an option.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Mutation Observer
|
||||
description: The Mutation Observer component offers a thin, declarative interface to the MutationObserver API.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
The mutation observer will report changes to the content it wraps through the `wa-mutation` event. When emitted, a collection of [MutationRecord](https://developer.mozilla.org/en-US/docs/Web/API/MutationRecord) objects will be attached to `event.detail` that contains information about how it changed.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Option
|
||||
description: Options define the selectable items within various form controls such as select.
|
||||
layout: component
|
||||
tags: component
|
||||
parent: select
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
236
docs/docs/components/page-samples/documentation.md
Normal file
236
docs/docs/components/page-samples/documentation.md
Normal file
@@ -0,0 +1,236 @@
|
||||
---
|
||||
title: Sample Documentation Page
|
||||
description: A sample page for a documentation website using Web Awesome's page component.
|
||||
layout: blank
|
||||
---
|
||||
|
||||
<style>
|
||||
wa-page {
|
||||
--menu-width: 15rem;
|
||||
--aside-width: 15rem;
|
||||
}
|
||||
|
||||
wa-page[view='mobile'] {
|
||||
--menu-width: auto;
|
||||
--aside-width: auto;
|
||||
}
|
||||
wa-page[view='mobile'] [slot='aside'] {
|
||||
display: none;
|
||||
}
|
||||
wa-page[view='mobile'] #brand-name {
|
||||
display: none;
|
||||
}
|
||||
wa-page[view='mobile'] #search {
|
||||
display: none;
|
||||
}
|
||||
[slot='banner'] {
|
||||
--wa-color-text-link: var(--wa-color-neutral-on-loud);
|
||||
background-color: var(--wa-color-neutral-fill-loud);
|
||||
}
|
||||
[slot='header'] {
|
||||
--wa-link-decoration-default: none;
|
||||
border-block-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
[slot*='header'] a {
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
}
|
||||
[slot='subheader'] {
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
border-block-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
[slot='navigation-header'] {
|
||||
border-block-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
wa-page[view='desktop'] [slot*='navigation'] {
|
||||
border-inline-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
[slot*='navigation'] a {
|
||||
--wa-color-text-link: var(--wa-color-text-normal);
|
||||
}
|
||||
[slot='navigation-footer'] {
|
||||
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
[slot='main-header'],
|
||||
main,
|
||||
[slot='main-footer'] {
|
||||
max-inline-size: 60rem;
|
||||
margin-inline: auto;
|
||||
}
|
||||
[slot='main-footer'] {
|
||||
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
[slot='footer'] {
|
||||
--wa-color-text-link: var(--wa-color-text-quiet);
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
font-size: var(--wa-font-size-s);
|
||||
}
|
||||
</style>
|
||||
|
||||
<wa-page mobile-breakpoint="920">
|
||||
<div slot="banner" class="wa-body-s">
|
||||
<a href="#" class="wa-cluster wa-align-items-baseline wa-gap-xs" style="flex-wrap: nowrap;">
|
||||
<wa-icon name="gift"></wa-icon>
|
||||
<span>Give a Hoot for the Holidays: Donate now and double your impact.</span>
|
||||
</a>
|
||||
</div>
|
||||
<header slot="header" class="wa-split">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="feather-pointed" style="color: var(--wa-color-brand-fill-loud); font-size: 1.5em;"></wa-icon>
|
||||
<span id="brand-name" class="wa-heading-s">Audubon Worldwide</span>
|
||||
<a href="#">Our Work</a>
|
||||
<a href="#">About Us</a>
|
||||
<a href="#">Discover</a>
|
||||
<a href="#">Get Involved</a>
|
||||
</div>
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
<wa-button size="small" variant="brand" appearance="outlined">Find Your Local Audubon</wa-button>
|
||||
<wa-button size="small" variant="brand">Donate</wa-button>
|
||||
</div>
|
||||
</header>
|
||||
<nav slot="subheader">
|
||||
<div class="wa-cluster" style="flex-wrap: nowrap;">
|
||||
<wa-icon-button data-toggle-nav name="bars" label="Menu"></wa-icon-button>
|
||||
<wa-breadcrumb style="font-size: var(--wa-font-size-s);">
|
||||
<wa-breadcrumb-item>Field Guides</wa-breadcrumb-item>
|
||||
<wa-breadcrumb-item>Owls</wa-breadcrumb-item>
|
||||
<wa-breadcrumb-item>Great Horned Owl</wa-breadcrumb-item>
|
||||
</wa-breadcrumb>
|
||||
</div>
|
||||
<wa-input id="search" placeholder="Search" size="small" style="max-inline-size: 12rem;">
|
||||
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
|
||||
</wa-input>
|
||||
</nav>
|
||||
<nav slot="navigation-header">
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1544648720-132573cb590d?q=20" label=""></wa-avatar>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span class="wa-heading-s">Great Horned Owl</span>
|
||||
<span class="wa-caption-s" lang="la"><em>Bubo virginianus</em></span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<nav slot="navigation">
|
||||
<a href="#identification">Identification</a>
|
||||
<a href="#range">Range and Habitat</a>
|
||||
<a href="#behavior">Behavior</a>
|
||||
<a href="#conservation">Conservation</a>
|
||||
</nav>
|
||||
<nav slot="navigation-footer">
|
||||
<a href="#" class="wa-flank" style="--flank-size: 1.25em;">
|
||||
<wa-icon name="camera"></wa-icon>
|
||||
<span>Photo Gallery</span>
|
||||
</a>
|
||||
<a href="#" class="wa-flank" style="--flank-size: 1.25em;">
|
||||
<wa-icon name="map-location-dot"></wa-icon>
|
||||
<span>Interactive Range Map</span>
|
||||
</a>
|
||||
</nav>
|
||||
<header slot="main-header">
|
||||
<div class="wa-flank:end wa-border-radius-m wa-theme-default-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
|
||||
<div class="wa-stack" style="margin: var(--wa-space-2xl);">
|
||||
<h1>Great Horned Owl</h1>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
<wa-tag size="small">Owls</wa-tag>
|
||||
<wa-tag size="small">Birds of Prey</wa-tag>
|
||||
<wa-tag size="small">Pleistocene Birds</wa-tag>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="ruler"></wa-icon>
|
||||
<span class="wa-caption-m">L 21.5" | WS 48.5"</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="earth-americas"></wa-icon>
|
||||
<span class="wa-caption-m">North America (Widespread), Central America (Limited), South America (Limited)</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="shield-heart"></wa-icon>
|
||||
<span class="wa-caption-m">Least Concern</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wa-frame" style="border-radius: var(--wa-border-radius-m); max-inline-size: 40ch;">
|
||||
<img src="https://images.unsplash.com/photo-1544648720-132573cb590d?q=20" />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main class="wa-body-l">
|
||||
<h2 id="identification">Identification</h2>
|
||||
<p>Lorem ipsum odor amet, consectetuer adipiscing elit. Eget habitant scelerisque lectus ultrices nascetur aliquet sapien primis. Cursus sapien fusce semper nulla elit sociosqu lectus per sem. Sem ad porttitor dictum nisl pharetra tortor convallis. Sit molestie hendrerit porta dictum tortor posuere euismod magna. Mauris suspendisse pharetra finibus; eleifend etiam ridiculus.</p>
|
||||
<h2 id="range">Range and Habitat</h2>
|
||||
<p>Diam sed ipsum pretium porttitor class cubilia elementum. Blandit felis ligula habitant ultricies vulputate rutrum lacus commodo pulvinar. Nostra semper placerat lectus in dis eu. Sagittis ipsum placerat rhoncus lacus id eget. Erat pharetra aptent enim, augue accumsan ultricies inceptos habitasse. Senectus id maximus parturient tellus; fermentum posuere vulputate luctus. Ac tempus dapibus vehicula ligula ullamcorper sit duis.</p>
|
||||
<h2 id="behavior">Behavior</h2>
|
||||
<p>Erat vitae luctus arcu taciti malesuada pretium arcu justo primis. Cubilia vitae maecenas congue velit id netus arcu. Dictum vel pellentesque taciti fermentum risus consectetur amet. Faucibus commodo habitasse sem maximus praesent purus, dignissim tristique porta. Platea magna justo ipsum ut metus ac facilisi. Imperdiet laoreet pharetra maximus lacus tortor suscipit. Nam quisque iaculis orci porttitor pellentesque rhoncus. Molestie sagittis tincidunt quisque nisi non urna conubia.</p>
|
||||
<h2 id="conservation">Conservation</h2>
|
||||
<p>Nullam magna quam quisque eu varius integer. Inceptos donec facilisi risus himenaeos semper mollis habitasse. Vehicula lacus vivamus euismod pharetra mollis dictum. Ante ex tortor elementum eleifend habitasse orci aliquam. Fames erat senectus fames etiam dapibus cursus.</p>
|
||||
</main>
|
||||
<footer slot="main-footer">
|
||||
<section>
|
||||
<h2 class="wa-heading-m">Sources</h2>
|
||||
<ul class="wa-body-s">
|
||||
<li><cite><a href="https://www.audubon.org/field-guide/bird/great-horned-owl" target="_blank" rel="noopener">Great Horned Owl</a></cite>, National Audubon Society. Retrieved 5 December 2024.</li>
|
||||
<li><cite><a href="https://www.allaboutbirds.org/guide/Great_Horned_Owl/" target="_blank" rel="noopener">Great Horned Owl</a></cite>, All About Birds by CornellLab. Retrieved 5 December 2024.</li>
|
||||
<li>Armistead, G. L. (2015). <cite>Field guide to birds of Pennsylvania</cite>. Scott & Nix, Inc.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</footer>
|
||||
<aside slot="aside">
|
||||
<h2 class="wa-heading-m">Discover More Birds</h2>
|
||||
<wa-card with-image>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1635254859323-65b78408dcca?q=20" alt="" />
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span class="wa-heading-s">Long-eared Owl</span>
|
||||
<span class="wa-caption-s" lang="la"><em>Asio otus</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-image>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1661350356618-f5915c7b6a3c?q=20" alt="" />
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span class="wa-heading-s">Northen Hawk Owl</span>
|
||||
<span class="wa-caption-s" lang="la"><em>Surnia ulula</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-image>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1660307777355-f08bced145d3?q=20" alt="" />
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span class="wa-heading-s">Golden Eagle</span>
|
||||
<span class="wa-caption-s" lang="la"><em>Aquila chrysaetos</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
</aside>
|
||||
<footer slot="footer" class="wa-grid wa-gap-xl">
|
||||
<div class="wa-cluster" style="flex-wrap: nowrap;">
|
||||
<wa-icon name="feather-pointed" style="font-size: 1.5em;"></wa-icon>
|
||||
<span class="wa-heading-s">Audubon Worldwide</span>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<h3 class="wa-heading-xs">Our Work</h3>
|
||||
<a href="#">Habitat Restoration</a>
|
||||
<a href="#">Migration Science</a>
|
||||
<a href="#">Advocacy</a>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<h3 class="wa-heading-xs">About Us</h3>
|
||||
<a href="#">Our History</a>
|
||||
<a href="#">Leadership</a>
|
||||
<a href="#">Fiscal Reports</a>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<h3 class="wa-heading-xs">Discover</h3>
|
||||
<a href="#">Field Guides</a>
|
||||
<a href="#">Photo Search</a>
|
||||
<a href="#">Gear and Resources</a>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<h3 class="wa-heading-xs">Get Involved</h3>
|
||||
<a href="#">Adopt a Bird</a>
|
||||
<a href="#">Your Local Audubon</a>
|
||||
<a href="#">Youth Audubon Camps</a>
|
||||
</div>
|
||||
</footer>
|
||||
</wa-page>
|
||||
399
docs/docs/components/page-samples/media-app.md
Normal file
399
docs/docs/components/page-samples/media-app.md
Normal file
@@ -0,0 +1,399 @@
|
||||
---
|
||||
title: Sample Media App Page
|
||||
description: A sample page for a media app using Web Awesome's page component.
|
||||
layout: blank
|
||||
---
|
||||
|
||||
<wa-page class="wa-theme-default-dark">
|
||||
<header slot="header">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon-button name="bars" label="Menu" data-toggle-nav></wa-icon-button>
|
||||
<wa-icon name="record-vinyl" family="duotone"></wa-icon>
|
||||
<span class="wa-heading-m">radiogaga</span>
|
||||
</div>
|
||||
<wa-input placeholder="Search" style="max-inline-size: 100%;">
|
||||
<wa-icon slot="prefix" name="magnifying-glass" ></wa-icon>
|
||||
</wa-input>
|
||||
<div class="wa-cluster">
|
||||
<wa-button appearance="outlined">Log In</wa-button>
|
||||
<wa-button>Sign Up</wa-button>
|
||||
</div>
|
||||
</header>
|
||||
<div slot="navigation-header" class="wa-split">
|
||||
<h2 class="wa-heading-s">For You</h2>
|
||||
<wa-icon-button id="settings" name="gear" label="Settings"></wa-icon-button>
|
||||
</div>
|
||||
<nav slot="navigation">
|
||||
<h3 class="wa-heading-xs">Discover</h3>
|
||||
<ul class="wa-stack wa-gap-0">
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="house"></wa-icon>
|
||||
<span>Home</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="sparkles"></wa-icon>
|
||||
<span>New</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="tower-broadcast"></wa-icon>
|
||||
<span>Stations</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="wa-heading-xs">Library</h3>
|
||||
<ul class="wa-stack wa-gap-0">
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="heart"></wa-icon>
|
||||
<span>Favorites</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="list-music"></wa-icon>
|
||||
<span>Playlists</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="microphone-stand"></wa-icon>
|
||||
<span>Artists</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
<span>Albums</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="podcast"></wa-icon>
|
||||
<span>Podcasts</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="wa-heading-xs">Recently Played</h3>
|
||||
<ul id="recent" class="wa-stack wa-gap-0">
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="cassette-tape" style="background: var(--wa-color-red-90); color: var(--wa-color-red-60);"></wa-icon>
|
||||
<span>Lo-Fi Station</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="face-awesome" style="background: var(--wa-color-blue-30); color: var(--wa-color-yellow-90);"></wa-icon>
|
||||
<span>Podcast Awesome</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="seedling" style="background: var(--wa-color-green-70); color: var(--wa-color-green-90);"></wa-icon>
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span>Seasons</span>
|
||||
<span class="wa-caption-s">Blister Soul</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div slot="main-header">
|
||||
<wa-icon-button id="back" name="chevron-left" label="Back"></wa-icon-button>
|
||||
<wa-tooltip for="back" placement="bottom" distance="2">Back</wa-tooltip>
|
||||
<div class="wa-cluster">
|
||||
<wa-icon-button id="favorite" name="heart" variant="regular" label="Favorite"></wa-icon-button>
|
||||
<wa-tooltip for="favorite" placement="bottom" distance="2">Favorite</wa-tooltip>
|
||||
<wa-icon-button id="options" name="ellipsis" label="Options"></wa-icon-button>
|
||||
<wa-tooltip for="options" placement="bottom" distance="2">Options</wa-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<main>
|
||||
<div class="wa-stack wa-gap-3xl">
|
||||
<div class="wa-flank wa-gap-3xl" style="--flank-size: 35%; --content-percentage: 55%;">
|
||||
<div class="wa-frame wa-border-radius-l" style="max-inline-size: 40ch;">
|
||||
<img src="https://images.unsplash.com/photo-1732430579016-8d5e5ebd3c99?q=20" alt="Home for the Holidays album artwork" />
|
||||
</div>
|
||||
<div class="wa-split:column wa-align-items-start">
|
||||
<div class="wa-stack" style="margin-block: auto;">
|
||||
<h1 class="wa-heading-3xl">Home for the Holidays</h1>
|
||||
<a href="#" class="wa-heading-m">The Shire Choir</a>
|
||||
<div class="wa-cluster wa-caption-m wa-gap-2xs">
|
||||
<span>Holiday</span>
|
||||
<span>•</span>
|
||||
<span>2024</span>
|
||||
<span>•</span>
|
||||
<span>12 songs, 41 minutes 9 seconds</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="play-controls" class="wa-split wa-gap-xl">
|
||||
<div class="wa-cluster wa-gap-xl">
|
||||
<wa-icon-button name="play" label="Play"></wa-icon-button>
|
||||
<wa-icon-button name="shuffle" label="Shuffle"></wa-icon-button>
|
||||
</div>
|
||||
<wa-icon-button name="plus" label="Add to Library"></wa-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ol class="wa-stack wa-gap-0">
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="1"></wa-icon>
|
||||
<span>Fa-La-La-Fellowship</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:27</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="2"></wa-icon>
|
||||
<span>Sleigh Ride</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:36</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="3"></wa-icon>
|
||||
<span>All I Want For Christmas Is Stew</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:51</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="4"></wa-icon>
|
||||
<span>Rockin' Around the Christmas Ent</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:05</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="5"></wa-icon>
|
||||
<span>Merry, Did You Know?</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">1:56</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="6"></wa-icon>
|
||||
<span>Run Run Shadowfax</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:32</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="7"></wa-icon>
|
||||
<span>You're a Mean One, Mr. Grima</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:46</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="8"></wa-icon>
|
||||
<span>O Come, All Ye Faithful</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:27</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="9"></wa-icon>
|
||||
<span>Do You Hear What I Hear</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:13</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<span class="wa-cluster wa-gap-3xs">
|
||||
<wa-icon name="1"></wa-icon>
|
||||
<wa-icon name="0"></wa-icon>
|
||||
</span>
|
||||
<span>Carol of the Horns</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:55</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<span class="wa-cluster wa-gap-3xs">
|
||||
<wa-icon name="1"></wa-icon>
|
||||
<wa-icon name="1"></wa-icon>
|
||||
</span>
|
||||
<span>Silent Night</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:10</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<span class="wa-cluster wa-gap-3xs">
|
||||
<wa-icon name="1"></wa-icon>
|
||||
<wa-icon name="2"></wa-icon>
|
||||
</span>
|
||||
<span>Wizard Wonderland</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:22</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</main>
|
||||
<div slot="main-footer" class="wa-grid wa-gap-xl">
|
||||
<h2 class="wa-heading-2xl">More You Might Like</h2>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img src="https://images.unsplash.com/photo-1675219119611-40323b738563?q=20" alt="" />
|
||||
</div>
|
||||
<span class="wa-heading-s">Festival of Lights</span>
|
||||
<span class="wa-caption-s">Station</span>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img src="https://images.unsplash.com/photo-1481930916222-5ec4696fc0f2?q=20" alt="" />
|
||||
</div>
|
||||
<span class="wa-heading-s">Holiday Cheer</span>
|
||||
<span class="wa-caption-s">Essential Playlist</span>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img src="https://images.unsplash.com/photo-1667514627762-521b1c815a89?q=20" alt="" />
|
||||
</div>
|
||||
<span class="wa-heading-s">Nursery Rhymes from the Shire</span>
|
||||
<span class="wa-caption-s">The Shire Choir</span>
|
||||
</div>
|
||||
</div>
|
||||
</wa-page>
|
||||
|
||||
<style>
|
||||
wa-page {
|
||||
--menu-width: 18rem;
|
||||
--wa-tooltip-arrow-size: 0;
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
}
|
||||
|
||||
wa-page[view='mobile'] {
|
||||
--menu-width: auto;
|
||||
}
|
||||
wa-page,
|
||||
[slot='header'],
|
||||
wa-page[view='desktop'] [slot*='navigation'] {
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
}
|
||||
wa-page[view='mobile'] [slot*='navigation'] {
|
||||
padding: 0;
|
||||
}
|
||||
wa-page::part(base) {
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
}
|
||||
[slot='header'] {
|
||||
background: linear-gradient(to bottom, var(--wa-color-surface-raised), var(--wa-color-surface-lowered));
|
||||
}
|
||||
[slot='navigation-header'],
|
||||
[slot='main-header'] {
|
||||
padding-block-end: 0;
|
||||
}
|
||||
[slot='navigation'] a {
|
||||
--wa-color-text-link: var(--wa-color-text-normal);
|
||||
--wa-link-decoration-default: none;
|
||||
--wa-link-decoration-hover: none;
|
||||
--flank-size: 2rem;
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
gap: 0.5rem;
|
||||
}
|
||||
[slot='navigation'] ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
[slot='navigation'] ul a {
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
padding: var(--wa-space-xs);
|
||||
}
|
||||
[slot='navigation'] ul a:hover,
|
||||
main ol li:hover {
|
||||
background-color: color-mix(in oklab, var(--wa-color-surface-default), var(--wa-color-brand-fill-quiet));
|
||||
}
|
||||
[slot='navigation'] wa-icon {
|
||||
align-items: center;
|
||||
aspect-ratio: 1;
|
||||
color: var(--wa-color-brand-fill-loud);
|
||||
display: flex;
|
||||
height: var(--flank-size);
|
||||
justify-content: center;
|
||||
}
|
||||
[slot='navigation'] #recent wa-icon {
|
||||
border-radius: var(--wa-border-radius-xs);
|
||||
}
|
||||
[slot='main-header'] {
|
||||
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
border-inline: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
border-radius: var(--wa-border-radius-l) var(--wa-border-radius-l) 0 0
|
||||
}
|
||||
main,
|
||||
[slot*='main'] {
|
||||
margin-inline: var(--wa-space-m);
|
||||
}
|
||||
main ol li {
|
||||
padding: var(--wa-space-m);
|
||||
}
|
||||
main ol li .wa-flank {
|
||||
--flank-size: 2rem;
|
||||
}
|
||||
main ol li:not(:first-child) {
|
||||
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
main,
|
||||
[slot='main-footer'] {
|
||||
border-inline: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
main,
|
||||
[slot='main-header'] {
|
||||
background-color: var(--wa-color-surface-raised);
|
||||
}
|
||||
#play-controls wa-icon-button::part(base) {
|
||||
border: var(--wa-border-width-l) var(--wa-border-style) currentColor;
|
||||
border-radius: var(--wa-border-radius-circle);
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
#play-controls wa-icon-button[name="play"]::part(base) {
|
||||
background-color: var(--wa-color-brand-fill-loud);
|
||||
border: none;
|
||||
color: var(--wa-color-brand-on-loud);
|
||||
font-size: 3rem;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
@@ -1,50 +1,33 @@
|
||||
---
|
||||
title: Page
|
||||
description: Layouts offer an easy way to scaffold pages using minimal markup.
|
||||
layout: component
|
||||
description: Pages offer an easy way to scaffold entire page layouts using minimal markup.
|
||||
tags: component
|
||||
isPro: true
|
||||
---
|
||||
|
||||
The layout component is designed to power full webpages. It is flexible enough to handle most modern designs and includes a simple mechanism for handling desktop and mobile navigation.
|
||||
|
||||
A number of sections are available as part of the layout, most of which are optional. Content is added by [slotting elements](/docs/usage/#slots) into various locations.
|
||||
|
||||
This component _does not_ implement any [content sectioning](https://developer.mozilla.org/en-US/docs/Web/HTML/Element#content_sectioning) or "semantic elements" internally (such as `<main>`, `<header>`, `<footer>`, etc.). Instead, it is recommended that you slot in content sectioning elements wherever you feel they're appropriate.
|
||||
The page component is designed to power full webpages. It is flexible enough to handle most modern designs and includes a simple mechanism for handling desktop and mobile navigation.
|
||||
|
||||
## Layout Anatomy
|
||||
|
||||
This image depicts the layout's anatomy, including the default positions of each section. The labels represent the [named slots](#slots) you can use to populate them.
|
||||
This image depicts a page's anatomy, including the default positions of each section. The labels represent the [named slots](#slots) you can use to populate them.
|
||||
|
||||
Most slots are optional. Slots that have no content will not be shown, allowing you to opt-in to just the sections of the layout you actually need.
|
||||
Most slots are optional. Slots that have no content will not be shown, allowing you to opt-in to just the sections you actually need.
|
||||
|
||||

|
||||
{% include "page-demo.njk" %}
|
||||
|
||||
<!--  -->
|
||||
|
||||
## Using `wa-page`
|
||||
|
||||
:::info
|
||||
If you're not familiar with how slots work in HTML, you might want to [learn more about slots](/docs/usage/#slots) before using this component.
|
||||
:::
|
||||
|
||||
## Sticky Sections
|
||||
A number of sections are available as part of the page component, most of which are optional. Content is populated by [slotting elements](/docs/usage/#slots) into various locations.
|
||||
|
||||
The following sections of the layout are "sticky" by default, meaning they remain in position as the user scrolls.
|
||||
This component _does not_ implement any [content sectioning](https://developer.mozilla.org/en-US/docs/Web/HTML/Element#content_sectioning) or "semantic elements" internally (such as `<main>`, `<header>`, `<footer>`, etc.). Instead, we recommended that you slot in content sectioning elements wherever you feel they're appropriate.
|
||||
|
||||
- `banner`
|
||||
- `header`
|
||||
- `sub-header`
|
||||
- `aside`
|
||||
- `menu`
|
||||
|
||||
This is often desirable, but you can change this behavior using the `disable-sticky` attribute. Use a space-delimited list of names to tell the layout which sections should not be sticky.
|
||||
|
||||
```html
|
||||
<wa-page disable-sticky="header aside"> ... </wa-page>
|
||||
```
|
||||
|
||||
## How to Apply Spacing to Your Layout
|
||||
|
||||
The layout component _does not_ apply spacing for you. You can apply the appropriate paddings or margins directly to the elements you slot in to fine tune your spacing needs.
|
||||
|
||||
TODO - add example here
|
||||
|
||||
When using `<wa-page>`, make sure to zero out all paddings and margins on `<html>` and `<body>`, otherwise you may see unexpected gaps. The following styles are highly recommended when using `<wa-page>`.
|
||||
When using `<wa-page>`, make sure to zero out all paddings and margins on `<html>` and `<body>`, otherwise you may see unexpected gaps. We highly recommend adding the following styles when using `<wa-page>`:
|
||||
|
||||
```css
|
||||
html,
|
||||
@@ -56,7 +39,720 @@ body {
|
||||
}
|
||||
```
|
||||
|
||||
## Skip To Content
|
||||
## Examples
|
||||
|
||||
:::warning
|
||||
Open demos in a new tab to examine their behavior in different window sizes.
|
||||
The previews below use simulated zooming which, depending on your browser, may not be accurate.
|
||||
:::
|
||||
|
||||
### Documentation
|
||||
|
||||
A sample documentation page using [all available slots](#slots).
|
||||
The navigation menu collapses into a drawer at a custom `mobile-breakpoint` of 920px.
|
||||
It can be opened using a button with `[data-toggle-nav]` that appears in the `subheader` slot. The `aside` slot is also hidden below 920px.
|
||||
|
||||
```html {.example viewport="1600"}
|
||||
<wa-page mobile-breakpoint="920">
|
||||
<div slot="banner" class="wa-body-s">
|
||||
<a href="#" class="wa-cluster wa-align-items-baseline wa-gap-xs" style="flex-wrap: nowrap;">
|
||||
<wa-icon name="gift"></wa-icon>
|
||||
<span>Give a Hoot for the Holidays: Donate now and double your impact.</span>
|
||||
</a>
|
||||
</div>
|
||||
<header slot="header" class="wa-split">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon name="feather-pointed" style="color: var(--wa-color-brand-fill-loud); font-size: 1.5em;"></wa-icon>
|
||||
<span id="brand-name" class="wa-heading-s">Audubon Worldwide</span>
|
||||
<a href="#">Our Work</a>
|
||||
<a href="#">About Us</a>
|
||||
<a href="#">Discover</a>
|
||||
<a href="#">Get Involved</a>
|
||||
</div>
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
<wa-button size="small" variant="brand" appearance="outlined">Find Your Local Audubon</wa-button>
|
||||
<wa-button size="small" variant="brand">Donate</wa-button>
|
||||
</div>
|
||||
</header>
|
||||
<nav slot="subheader">
|
||||
<div class="wa-cluster" style="flex-wrap: nowrap;">
|
||||
<wa-icon-button data-toggle-nav name="bars" label="Menu"></wa-icon-button>
|
||||
<wa-breadcrumb style="font-size: var(--wa-font-size-s);">
|
||||
<wa-breadcrumb-item>Field Guides</wa-breadcrumb-item>
|
||||
<wa-breadcrumb-item>Owls</wa-breadcrumb-item>
|
||||
<wa-breadcrumb-item>Great Horned Owl</wa-breadcrumb-item>
|
||||
</wa-breadcrumb>
|
||||
</div>
|
||||
<wa-input id="search" placeholder="Search" size="small" style="max-inline-size: 12rem;">
|
||||
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
|
||||
</wa-input>
|
||||
</nav>
|
||||
<nav slot="navigation-header">
|
||||
<div class="wa-flank">
|
||||
<wa-avatar image="https://images.unsplash.com/photo-1544648720-132573cb590d?q=20" label=""></wa-avatar>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span class="wa-heading-s">Great Horned Owl</span>
|
||||
<span class="wa-caption-s" lang="la"><em>Bubo virginianus</em></span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<nav slot="navigation">
|
||||
<a href="#identification">Identification</a>
|
||||
<a href="#range">Range and Habitat</a>
|
||||
<a href="#behavior">Behavior</a>
|
||||
<a href="#conservation">Conservation</a>
|
||||
</nav>
|
||||
<nav slot="navigation-footer">
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="camera"></wa-icon>
|
||||
<span>Photo Gallery</span>
|
||||
</a>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="map-location-dot"></wa-icon>
|
||||
<span>Interactive Range Map</span>
|
||||
</a>
|
||||
</nav>
|
||||
<header slot="main-header">
|
||||
<div class="wa-flank:end wa-border-radius-m wa-theme-default-dark" style="background-color: var(--wa-color-surface-lowered); --content-percentage: 35%; padding: var(--wa-space-m);">
|
||||
<div class="wa-stack" style="margin: var(--wa-space-2xl);">
|
||||
<h1>Great Horned Owl</h1>
|
||||
<wa-divider></wa-divider>
|
||||
<div class="wa-cluster wa-gap-xs">
|
||||
<wa-tag size="small">Owls</wa-tag>
|
||||
<wa-tag size="small">Birds of Prey</wa-tag>
|
||||
<wa-tag size="small">Pleistocene Birds</wa-tag>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="ruler"></wa-icon>
|
||||
<span class="wa-caption-m">L 21.5" | WS 48.5"</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="earth-americas"></wa-icon>
|
||||
<span class="wa-caption-m">North America (Widespread), Central America (Limited), South America (Limited)</span>
|
||||
</div>
|
||||
<div class="wa-flank">
|
||||
<wa-icon name="shield-heart"></wa-icon>
|
||||
<span class="wa-caption-m">Least Concern</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wa-frame" style="border-radius: var(--wa-border-radius-m); max-inline-size: 40ch;">
|
||||
<img src="https://images.unsplash.com/photo-1544648720-132573cb590d?q=20" />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main class="wa-body-l">
|
||||
<h2 id="identification">Identification</h2>
|
||||
<p>Lorem ipsum odor amet, consectetuer adipiscing elit. Eget habitant scelerisque lectus ultrices nascetur aliquet sapien primis. Cursus sapien fusce semper nulla elit sociosqu lectus per sem. Sem ad porttitor dictum nisl pharetra tortor convallis. Sit molestie hendrerit porta dictum tortor posuere euismod magna. Mauris suspendisse pharetra finibus; eleifend etiam ridiculus.</p>
|
||||
<h2 id="range">Range and Habitat</h2>
|
||||
<p>Diam sed ipsum pretium porttitor class cubilia elementum. Blandit felis ligula habitant ultricies vulputate rutrum lacus commodo pulvinar. Nostra semper placerat lectus in dis eu. Sagittis ipsum placerat rhoncus lacus id eget. Erat pharetra aptent enim, augue accumsan ultricies inceptos habitasse. Senectus id maximus parturient tellus; fermentum posuere vulputate luctus. Ac tempus dapibus vehicula ligula ullamcorper sit duis.</p>
|
||||
<h2 id="behavior">Behavior</h2>
|
||||
<p>Erat vitae luctus arcu taciti malesuada pretium arcu justo primis. Cubilia vitae maecenas congue velit id netus arcu. Dictum vel pellentesque taciti fermentum risus consectetur amet. Faucibus commodo habitasse sem maximus praesent purus, dignissim tristique porta. Platea magna justo ipsum ut metus ac facilisi. Imperdiet laoreet pharetra maximus lacus tortor suscipit. Nam quisque iaculis orci porttitor pellentesque rhoncus. Molestie sagittis tincidunt quisque nisi non urna conubia.</p>
|
||||
<h2 id="conservation">Conservation</h2>
|
||||
<p>Nullam magna quam quisque eu varius integer. Inceptos donec facilisi risus himenaeos semper mollis habitasse. Vehicula lacus vivamus euismod pharetra mollis dictum. Ante ex tortor elementum eleifend habitasse orci aliquam. Fames erat senectus fames etiam dapibus cursus.</p>
|
||||
</main>
|
||||
<footer slot="main-footer">
|
||||
<section>
|
||||
<h2 class="wa-heading-m">Sources</h2>
|
||||
<ul class="wa-body-s">
|
||||
<li><cite><a href="https://www.audubon.org/field-guide/bird/great-horned-owl" target="_blank" rel="noopener">Great Horned Owl</a></cite>, National Audubon Society. Retrieved 5 December 2024.</li>
|
||||
<li><cite><a href="https://www.allaboutbirds.org/guide/Great_Horned_Owl/" target="_blank" rel="noopener">Great Horned Owl</a></cite>, All About Birds by CornellLab. Retrieved 5 December 2024.</li>
|
||||
<li>Armistead, G. L. (2015). <cite>Field guide to birds of Pennsylvania</cite>. Scott & Nix, Inc.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</footer>
|
||||
<aside slot="aside">
|
||||
<h2 class="wa-heading-m">Discover More Birds</h2>
|
||||
<wa-card with-image>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1635254859323-65b78408dcca?q=20" alt="" />
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span class="wa-heading-s">Long-eared Owl</span>
|
||||
<span class="wa-caption-s" lang="la"><em>Asio otus</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-image>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1661350356618-f5915c7b6a3c?q=20" alt="" />
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span class="wa-heading-s">Northen Hawk Owl</span>
|
||||
<span class="wa-caption-s" lang="la"><em>Surnia ulula</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
<wa-card with-image>
|
||||
<div slot="image" class="wa-frame">
|
||||
<img src="https://images.unsplash.com/photo-1660307777355-f08bced145d3?q=20" alt="" />
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-3xs">
|
||||
<span class="wa-heading-s">Golden Eagle</span>
|
||||
<span class="wa-caption-s" lang="la"><em>Aquila chrysaetos</em></span>
|
||||
</div>
|
||||
</wa-card>
|
||||
</aside>
|
||||
<footer slot="footer" class="wa-grid wa-gap-xl">
|
||||
<div class="wa-cluster" style="flex-wrap: nowrap;">
|
||||
<wa-icon name="feather-pointed" style="font-size: 1.5em;"></wa-icon>
|
||||
<span class="wa-heading-s">Audubon Worldwide</span>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<h3 class="wa-heading-xs">Our Work</h3>
|
||||
<a href="#">Habitat Restoration</a>
|
||||
<a href="#">Migration Science</a>
|
||||
<a href="#">Advocacy</a>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<h3 class="wa-heading-xs">About Us</h3>
|
||||
<a href="#">Our History</a>
|
||||
<a href="#">Leadership</a>
|
||||
<a href="#">Fiscal Reports</a>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<h3 class="wa-heading-xs">Discover</h3>
|
||||
<a href="#">Field Guides</a>
|
||||
<a href="#">Photo Search</a>
|
||||
<a href="#">Gear and Resources</a>
|
||||
</div>
|
||||
<div class="wa-stack">
|
||||
<h3 class="wa-heading-xs">Get Involved</h3>
|
||||
<a href="#">Adopt a Bird</a>
|
||||
<a href="#">Your Local Audubon</a>
|
||||
<a href="#">Youth Audubon Camps</a>
|
||||
</div>
|
||||
</footer>
|
||||
</wa-page>
|
||||
|
||||
<style>
|
||||
wa-page {
|
||||
--menu-width: 15rem;
|
||||
--aside-width: 15rem;
|
||||
}
|
||||
wa-page[view='desktop'] {
|
||||
[data-toggle-nav] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[slot*='navigation'] {
|
||||
border-inline-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
}
|
||||
wa-page[view='mobile'] {
|
||||
--menu-width: auto;
|
||||
--aside-width: auto;
|
||||
|
||||
[slot='aside'],
|
||||
#brand-name,
|
||||
#search {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
[slot='banner'] {
|
||||
--wa-color-text-link: var(--wa-color-neutral-on-loud);
|
||||
background-color: var(--wa-color-neutral-fill-loud);
|
||||
}
|
||||
[slot='header'] {
|
||||
--wa-link-decoration-default: none;
|
||||
border-block-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
[slot*='header'] a {
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
}
|
||||
[slot='subheader'] {
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
border-block-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
[slot='navigation-header'] {
|
||||
border-block-end: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
|
||||
[slot*='navigation'] a {
|
||||
--wa-color-text-link: var(--wa-color-text-normal);
|
||||
}
|
||||
[slot='navigation-footer'] {
|
||||
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
[slot='navigation-footer'] .wa-flank {
|
||||
--flank-size: 1.25em;
|
||||
}
|
||||
[slot='main-header'],
|
||||
main,
|
||||
[slot='main-footer'] {
|
||||
max-inline-size: 60rem;
|
||||
margin-inline: auto;
|
||||
}
|
||||
[slot='main-footer'] {
|
||||
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
[slot='footer'] {
|
||||
--wa-color-text-link: var(--wa-color-text-quiet);
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
font-size: var(--wa-font-size-s);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const sectionAnchors = document.querySelectorAll("[slot*='navigation'] a[href*='#']");
|
||||
sectionAnchors.forEach((sectionAnchor) => sectionAnchor.setAttribute("data-drawer", "close"));
|
||||
</script>
|
||||
```
|
||||
|
||||
### Media
|
||||
|
||||
A sample media app page using `header`, `navigation-header`, `main-header`, and `main-footer` along with the default slot. The navigation menu collapses into a drawer at the default `mobile-breakpoint` and can be opened using a button with `[data-toggle-nav]` that appears in the `header` slot.
|
||||
|
||||
```html {.example viewport="1600"}
|
||||
<wa-page class="wa-theme-default-dark">
|
||||
<header slot="header">
|
||||
<div class="wa-cluster">
|
||||
<wa-icon-button name="bars" label="Menu" data-toggle-nav></wa-icon-button>
|
||||
<wa-icon name="record-vinyl"></wa-icon>
|
||||
<span class="wa-heading-m">radiogaga</span>
|
||||
</div>
|
||||
<wa-input id="search-header" placeholder="Search" style="max-inline-size: 100%;">
|
||||
<wa-icon slot="prefix" name="magnifying-glass" ></wa-icon>
|
||||
</wa-input>
|
||||
<div class="wa-cluster">
|
||||
<wa-button appearance="outlined">Log In</wa-button>
|
||||
<wa-button>Sign Up</wa-button>
|
||||
</div>
|
||||
</header>
|
||||
<div slot="navigation-header" class="wa-split">
|
||||
<wa-input id="search-nav-drawer" placeholder="Search" style="max-inline-size: 100%;">
|
||||
<wa-icon slot="prefix" name="magnifying-glass" ></wa-icon>
|
||||
</wa-input>
|
||||
<div class="wa-split">
|
||||
<h2 class="wa-heading-s">For You</h2>
|
||||
<wa-icon-button id="settings" name="gear" label="Settings"></wa-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
<nav slot="navigation">
|
||||
<h3 class="wa-heading-xs">Discover</h3>
|
||||
<ul class="wa-stack wa-gap-0">
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="house"></wa-icon>
|
||||
<span>Home</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="star"></wa-icon>
|
||||
<span>New</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="tower-broadcast"></wa-icon>
|
||||
<span>Stations</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="wa-heading-xs">Library</h3>
|
||||
<ul class="wa-stack wa-gap-0">
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="heart"></wa-icon>
|
||||
<span>Favorites</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="bars-staggered"></wa-icon>
|
||||
<span>Playlists</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="microphone-lines"></wa-icon>
|
||||
<span>Artists</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="layer-group"></wa-icon>
|
||||
<span>Albums</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="podcast"></wa-icon>
|
||||
<span>Podcasts</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="wa-heading-xs">Recently Played</h3>
|
||||
<ul id="recent" class="wa-stack wa-gap-0">
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="radio" style="background: var(--wa-color-red-90); color: var(--wa-color-red-60);"></wa-icon>
|
||||
<span>Lo-Fi Station</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="font-awesome" style="background: var(--wa-color-blue-30); color: var(--wa-color-yellow-90);"></wa-icon>
|
||||
<span>Podcast Awesome</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="wa-flank">
|
||||
<wa-icon name="seedling" style="background: var(--wa-color-green-70); color: var(--wa-color-green-90);"></wa-icon>
|
||||
<div class="wa-stack wa-gap-0">
|
||||
<span>Seasons</span>
|
||||
<span class="wa-caption-s">Blister Soul</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div slot="main-header">
|
||||
<wa-icon-button id="back" name="chevron-left" label="Back"></wa-icon-button>
|
||||
<wa-tooltip for="back" placement="bottom" distance="2">Back</wa-tooltip>
|
||||
<div class="wa-cluster">
|
||||
<wa-icon-button id="favorite" name="heart" variant="regular" label="Favorite"></wa-icon-button>
|
||||
<wa-tooltip for="favorite" placement="bottom" distance="2">Favorite</wa-tooltip>
|
||||
<wa-icon-button id="options" name="ellipsis" label="Options"></wa-icon-button>
|
||||
<wa-tooltip for="options" placement="bottom" distance="2">Options</wa-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<main>
|
||||
<div class="wa-stack wa-gap-3xl">
|
||||
<div class="wa-flank wa-gap-3xl" style="--content-percentage: 40%;">
|
||||
<div class="wa-frame wa-border-radius-l" style="max-inline-size: 40ch;">
|
||||
<img src="https://images.unsplash.com/photo-1732430579016-8d5e5ebd3c99?q=20" alt="Home for the Holidays album artwork" />
|
||||
</div>
|
||||
<div class="wa-split:column wa-align-items-start">
|
||||
<div class="wa-stack" style="margin-block: auto;">
|
||||
<h1 class="wa-heading-3xl">Home for the Holidays</h1>
|
||||
<a href="#" class="wa-heading-m">The Shire Choir</a>
|
||||
<div class="wa-cluster wa-caption-m wa-gap-2xs">
|
||||
<span>Holiday</span>
|
||||
<span>•</span>
|
||||
<span>2024</span>
|
||||
<span>•</span>
|
||||
<span>12 songs, 41 minutes 9 seconds</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="play-controls" class="wa-split wa-gap-xl">
|
||||
<div class="wa-cluster wa-gap-xl">
|
||||
<wa-icon-button name="play" label="Play"></wa-icon-button>
|
||||
<wa-icon-button name="shuffle" label="Shuffle"></wa-icon-button>
|
||||
</div>
|
||||
<wa-icon-button name="plus" label="Add to Library"></wa-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ol class="wa-stack wa-gap-0">
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="1"></wa-icon>
|
||||
<span>Fa-La-La-Fellowship</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:27</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="2"></wa-icon>
|
||||
<span>Sleigh Ride</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:36</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="3"></wa-icon>
|
||||
<span>All I Want For Christmas Is Stew</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:51</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="4"></wa-icon>
|
||||
<span>Rockin' Around the Christmas Ent</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:05</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="5"></wa-icon>
|
||||
<span>Merry, Did You Know?</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">1:56</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="6"></wa-icon>
|
||||
<span>Run Run Shadowfax</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:32</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="7"></wa-icon>
|
||||
<span>You're a Mean One, Mr. Grima</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:46</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="8"></wa-icon>
|
||||
<span>O Come, All Ye Faithful</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:27</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<wa-icon name="9"></wa-icon>
|
||||
<span>Do You Hear What I Hear</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:13</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<span class="wa-cluster wa-gap-3xs">
|
||||
<wa-icon name="1"></wa-icon>
|
||||
<wa-icon name="0"></wa-icon>
|
||||
</span>
|
||||
<span>Carol of the Horns</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">2:55</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<span class="wa-cluster wa-gap-3xs">
|
||||
<wa-icon name="1"></wa-icon>
|
||||
<wa-icon name="1"></wa-icon>
|
||||
</span>
|
||||
<span>Silent Night</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:10</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wa-split">
|
||||
<span class="wa-flank">
|
||||
<span class="wa-cluster wa-gap-3xs">
|
||||
<wa-icon name="1"></wa-icon>
|
||||
<wa-icon name="2"></wa-icon>
|
||||
</span>
|
||||
<span>Wizard Wonderland</span>
|
||||
</span>
|
||||
<span class="wa-cluster">
|
||||
<span class="wa-caption-m">3:22</span>
|
||||
<wa-icon-button name="ellipsis" label="Song Options"></wa-icon-button>
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</main>
|
||||
<div slot="main-footer" class="wa-grid wa-gap-xl wa-align-items-center">
|
||||
<h2 class="wa-heading-2xl">More You Might Like</h2>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img src="https://images.unsplash.com/photo-1675219119611-40323b738563?q=20" alt="" />
|
||||
</div>
|
||||
<span class="wa-heading-s">Festival of Lights</span>
|
||||
<span class="wa-caption-s">Station</span>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img src="https://images.unsplash.com/photo-1481930916222-5ec4696fc0f2?q=20" alt="" />
|
||||
</div>
|
||||
<span class="wa-heading-s">Holiday Cheer</span>
|
||||
<span class="wa-caption-s">Essential Playlist</span>
|
||||
</div>
|
||||
<div class="wa-stack wa-gap-xs">
|
||||
<div class="wa-frame wa-border-radius-m">
|
||||
<img src="https://images.unsplash.com/photo-1667514627762-521b1c815a89?q=20" alt="" />
|
||||
</div>
|
||||
<span class="wa-heading-s">Nursery Rhymes from the Shire</span>
|
||||
<span class="wa-caption-s">The Shire Choir</span>
|
||||
</div>
|
||||
</div>
|
||||
</wa-page>
|
||||
|
||||
<style>
|
||||
wa-page {
|
||||
--menu-width: 30ch;
|
||||
--wa-tooltip-arrow-size: 0;
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
}
|
||||
wa-page[view='desktop'] {
|
||||
:is([data-toggle-nav], #search-nav-drawer) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
wa-page[view='mobile'] {
|
||||
--menu-width: auto;
|
||||
|
||||
#search-header {
|
||||
display: none;
|
||||
}
|
||||
[slot*='main'], main {
|
||||
padding: var(--wa-space-xl);
|
||||
}
|
||||
}
|
||||
|
||||
wa-page,
|
||||
[slot='header'],
|
||||
wa-page[view='desktop'] [slot*='navigation'] {
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
}
|
||||
wa-page[view='mobile'] [slot*='navigation'] {
|
||||
padding: 0;
|
||||
}
|
||||
wa-page::part(base) {
|
||||
background-color: var(--wa-color-surface-lowered);
|
||||
}
|
||||
[slot='header'] {
|
||||
background: linear-gradient(to bottom, var(--wa-color-surface-raised), var(--wa-color-surface-lowered));
|
||||
}
|
||||
[slot='navigation-header'],
|
||||
[slot='main-header'] {
|
||||
padding-block-end: 0 !important;
|
||||
padding-block-start: var(--wa-space-3xl);
|
||||
}
|
||||
[slot='navigation'] {
|
||||
a {
|
||||
--wa-color-text-link: var(--wa-color-text-normal);
|
||||
--wa-link-decoration-default: none;
|
||||
--wa-link-decoration-hover: none;
|
||||
--flank-size: 2rem;
|
||||
font-weight: var(--wa-font-weight-action);
|
||||
gap: 0.5rem;
|
||||
}
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
|
||||
a {
|
||||
border-radius: var(--wa-border-radius-s);
|
||||
padding: var(--wa-space-xs);
|
||||
|
||||
&:hover {
|
||||
background-color: color-mix(in oklab, var(--wa-color-surface-default), var(--wa-color-brand-fill-quiet));
|
||||
}
|
||||
}
|
||||
}
|
||||
wa-icon {
|
||||
align-items: center;
|
||||
aspect-ratio: 1;
|
||||
color: var(--wa-color-brand-fill-loud);
|
||||
display: flex;
|
||||
height: var(--flank-size);
|
||||
justify-content: center;
|
||||
}
|
||||
#recent wa-icon {
|
||||
border-radius: var(--wa-border-radius-xs);
|
||||
}
|
||||
}
|
||||
|
||||
[slot='main-header'] {
|
||||
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
border-inline: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
border-radius: var(--wa-border-radius-l) var(--wa-border-radius-l) 0 0
|
||||
}
|
||||
main,
|
||||
[slot*='main'] {
|
||||
margin-inline: var(--wa-space-m);
|
||||
}
|
||||
main ol li {
|
||||
padding: var(--wa-space-m);
|
||||
|
||||
&:hover {
|
||||
background-color: color-mix(in oklab, var(--wa-color-surface-default), var(--wa-color-brand-fill-quiet));
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
border-block-start: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
|
||||
.wa-flank {
|
||||
--flank-size: 2rem;
|
||||
}
|
||||
}
|
||||
main,
|
||||
[slot='main-footer'] {
|
||||
border-inline: var(--wa-border-width-s) var(--wa-border-style) var(--wa-color-surface-border);
|
||||
}
|
||||
main,
|
||||
[slot='main-header'] {
|
||||
background-color: var(--wa-color-surface-raised);
|
||||
}
|
||||
#play-controls wa-icon-button::part(base) {
|
||||
border: var(--wa-border-width-l) var(--wa-border-style) currentColor;
|
||||
border-radius: var(--wa-border-radius-circle);
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
#play-controls wa-icon-button[name="play"]::part(base) {
|
||||
background-color: var(--wa-color-brand-fill-loud);
|
||||
border: none;
|
||||
color: var(--wa-color-brand-on-loud);
|
||||
font-size: 3rem;
|
||||
padding: 0.5em 0.45em 0.5em 0.55em;
|
||||
}
|
||||
[slot='main-footer'].wa-grid > * {
|
||||
max-inline-size: 30ch;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const sectionAnchors = document.querySelectorAll("[slot*='navigation'] a[href*='#']");
|
||||
sectionAnchors.forEach((sectionAnchor) => sectionAnchor.setAttribute("data-drawer", "close"));
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
## Customization
|
||||
|
||||
### Sticky Sections
|
||||
|
||||
The following sections of a page are "sticky" by default, meaning they remain in position as the user scrolls.
|
||||
|
||||
- `banner`
|
||||
- `header`
|
||||
- `sub-header`
|
||||
- `menu` (`navigation` itself is not sticky, but its parent `menu` is)
|
||||
- `aside`
|
||||
|
||||
This is often desirable, but you can change this behavior using the `disable-sticky` attribute. Use a space-delimited list of names to tell the page which sections should not be sticky.
|
||||
|
||||
```html
|
||||
<wa-page disable-sticky="header aside"> ... </wa-page>
|
||||
```
|
||||
|
||||
### Skip To Content
|
||||
|
||||
The layout provides a "skip to content" link that's visually hidden until the user tabs into it. You don't have to do anything to configure this, unless you want to change the text displayed in the link. In that case, you can slot in your own text using the `skip-to-content` slot.
|
||||
|
||||
@@ -70,15 +766,62 @@ This example localizes the "skip to content" link for German users.
|
||||
</wa-page>
|
||||
```
|
||||
|
||||
## Responsiveness
|
||||
### Responsiveness
|
||||
|
||||
The layout component tries not to have too many opinions in terms of responsive behaviors — you get to decide with your own CSS and media queries how your content responds! However, the navigation menu _does_ respond by collapsing on smaller screens. The breakpoint at which this occurs is 768px by default, but you can change it using the `mobile-breakpoint` attribute.
|
||||
A page isn't very opinionated when it comes to responsive behaviors, but there are tools in place to help make responsiveness easy.
|
||||
|
||||
#### Default Slot Styles
|
||||
|
||||
Each slot is a [flex container](https://developer.mozilla.org/en-US/docs/Glossary/Flex_Container) and specifies some flex properties so that your content is reasonably responsive by default.
|
||||
|
||||
The following slots specify `justify-content: space-between` and `flex-wrap: wrap` to evenly distribute child elements horizontally and allow them to wrap when space is limited:
|
||||
- `header`
|
||||
- `subheader`
|
||||
- `main-header`
|
||||
- `main-footer`
|
||||
- `footer`
|
||||
|
||||
The following slots specify `flex-direction: column` to arrange child elements vertically:
|
||||
- `navigation-header`
|
||||
- `navigation` (or `menu`)
|
||||
- `navigation-footer`
|
||||
- `aside`
|
||||
|
||||
And the `banner` slot specifies `justify-content: center` to horizontally center its child elements.
|
||||
|
||||
You can override the default display and flex properties for each slot with your own CSS.
|
||||
|
||||
#### Responsive Navigation
|
||||
|
||||
When you use the `navigation` slot, your slotted content automatically collapses into a drawer on smaller screens.
|
||||
The breakpoint at which this occurs is `768px` by default, but you can change it using the `mobile-breakpoint` attribute,
|
||||
which takes either a number or a [CSS length](https://developer.mozilla.org/en-US/docs/Web/CSS/length).
|
||||
|
||||
```html
|
||||
<wa-page mobile-breakpoint="600"> ... </wa-page>
|
||||
```
|
||||
```html {.example viewport}
|
||||
<wa-page mobile-breakpoint="50ch">
|
||||
<div slot=navigation>Nav</div>
|
||||
<header slot=header>
|
||||
<div style="width: 50ch; background: gold">I’m 50ch wide</div>
|
||||
</header>
|
||||
</wa-page>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
min-height: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
You can provide a button to toggle the navigation menu anywhere inside the layout by adding the `data-toggle-nav` attribute. (This _does not_ have to be a Web Awesome button.)
|
||||
By default, a "hamburger" button appears in the `header` slot to toggle the navigation menu on smaller screens.
|
||||
You can customize what this looks like by slotting your own button in the `toggle-navigation` slot,
|
||||
or place the `data-toggle-nav` attribute on any button on your page (This _does not_ have to be a Web Awesome element.).
|
||||
The default button not be shown when using either of these methods — if you want to use multiple navigation toggles on your page, simply add the `data-toggle-nav` attribute to multiple elements.
|
||||
|
||||
```html
|
||||
<wa-page mobile-breakpoint="600">
|
||||
@@ -94,25 +837,45 @@ Alternatively, you can apply `nav-state="open"` and `nav-state="closed"` to the
|
||||
<wa-page nav-state="open"> ... </wa-page>
|
||||
```
|
||||
|
||||
## Providing Navigation Items
|
||||
`<wa-page>` is given the attribute `view="mobile"` or `view="desktop"` when the viewport narrower or wider than the `mobile-breakpoint` value, respectively. You can leverage these attributes to change styles depending on the size of the viewport.
|
||||
This is especially useful to hide your `data-toggle-nav` button when the viewport is wider:
|
||||
```css
|
||||
wa-page[view='desktop'] [data-toggle-nav] {
|
||||
display: none;
|
||||
}
|
||||
```
|
||||
|
||||
- TODO - example with navigation items
|
||||
- TODO - example with`<h2>` and `<a>` as navigation items
|
||||
#### Custom Widths
|
||||
|
||||
## Examples
|
||||
You specify widths for some slots on your page with [CSS custom properties](#css-custom-properties) for `--menu-width`, `--main-width`, and `--aside-width`.
|
||||
|
||||
### Hero Layout
|
||||
If you specify `--menu-width` to apply a specific width to your `navigation` slot, space will still be reserved on the page even below the `mobile-breakpoint`. To collapse this space on smaller screens, add the following code to your styles:
|
||||
```css
|
||||
wa-page[view='mobile'] {
|
||||
--menu-width: auto;
|
||||
}
|
||||
```
|
||||
|
||||
- TODO - Sticky header + main + footer
|
||||
You can use a similar approach for `--aside-width` to hide the `aside` slot on smaller screens. Be sure to also specify `display: none` for the slot:
|
||||
```css
|
||||
wa-page[view='mobile'] {
|
||||
--aside-width: auto;
|
||||
|
||||
### Blog Layout
|
||||
[slot='aside'] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- TODO - Sticky header + main + aside + footer (blog)
|
||||
### Spacing
|
||||
|
||||
### App Layout
|
||||
A page specifies default `padding` within each slot and a `gap` between the slot's direct children. You can drop elements into any slot, and reasonable spacing is already applied for you.
|
||||
|
||||
- TODO - Menu + main, plus maybe headers and footers in each (app)
|
||||
You can override the default spacing for each slot with your own CSS. In this example, we're setting custom `gap` and `padding` for the `footer` slot:
|
||||
```css
|
||||
[slot="footer"] {
|
||||
gap: var(--wa-space-xl);
|
||||
padding: var(--wa-space-xl);
|
||||
}
|
||||
```
|
||||
|
||||
### Docs Layout
|
||||
|
||||
- TODO - Menu + main + aside + footer (docs)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Popup
|
||||
description: 'Popup is a utility that lets you declaratively anchor "popup" containers to another element.'
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
This component's name is inspired by [`<popup>`](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md). It uses [Floating UI](https://floating-ui.com/) under the hood to provide a well-tested, lightweight, and fully declarative positioning utility for tooltips, dropdowns, and more.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Progress Bar
|
||||
description: Progress bars are used to show the status of an ongoing operation.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Progress Ring
|
||||
description: Progress rings are used to show the progress of a determinate operation in a circular fashion.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: QR Code
|
||||
description: Generates a QR code and renders it using the Canvas API.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
QR codes are useful for providing small pieces of information to users who can quickly scan them with a smartphone. Most smartphones have built-in QR code scanners, so simply pointing the camera at a QR code will decode it and allow the user to visit a website, dial a phone number, read a message, etc.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Radio Button
|
||||
description: Radios buttons allow the user to select a single option from a group using a button-like control.
|
||||
layout: component
|
||||
tags: component
|
||||
parent: radio-group
|
||||
---
|
||||
|
||||
Radio buttons are designed to be used with [radio groups](/docs/components/radio-group). When a radio button has focus, the arrow keys can be used to change the selected option just like standard radio controls.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Radio Group
|
||||
description: Radio groups are used to group multiple radios or radio buttons so they function as a single form control.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -14,12 +14,12 @@ layout: component
|
||||
|
||||
## Examples
|
||||
|
||||
### Help Text
|
||||
### Hint
|
||||
|
||||
Add descriptive help text to a radio group with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
Add descriptive hint to a radio group with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
|
||||
|
||||
```html {.example}
|
||||
<wa-radio-group label="Select an option" help-text="Choose the most appropriate option." name="a" value="1">
|
||||
<wa-radio-group label="Select an option" hint="Choose the most appropriate option." name="a" value="1">
|
||||
<wa-radio value="1">Option 1</wa-radio>
|
||||
<wa-radio value="2">Option 2</wa-radio>
|
||||
<wa-radio value="3">Option 3</wa-radio>
|
||||
@@ -31,7 +31,7 @@ Add descriptive help text to a radio group with the `help-text` attribute. For h
|
||||
[Radio buttons](/docs/components/radio-button) offer an alternate way to display radio controls. In this case, an internal [button group](/docs/components/button-group) is used to group the buttons into a single, cohesive control.
|
||||
|
||||
```html {.example}
|
||||
<wa-radio-group label="Select an option" help-text="Select an option that makes you proud." name="a" value="1">
|
||||
<wa-radio-group label="Select an option" hint="Select an option that makes you proud." name="a" value="1">
|
||||
<wa-radio-button value="1">Option 1</wa-radio-button>
|
||||
<wa-radio-button value="2">Option 2</wa-radio-button>
|
||||
<wa-radio-button value="3">Option 3</wa-radio-button>
|
||||
@@ -137,4 +137,4 @@ Use the `setCustomValidity()` method to set a custom validation message. This wi
|
||||
alert('All fields are valid!');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Radio
|
||||
description: Radios allow the user to select a single option from a group.
|
||||
layout: component
|
||||
tags: component
|
||||
parent: radio-group
|
||||
---
|
||||
|
||||
Radios are designed to be used with [radio groups](/docs/components/radio-group).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Range
|
||||
description: Ranges allow the user to select a single value within a given range using a slider.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -22,12 +22,12 @@ Use the `label` attribute to give the range an accessible label. For labels that
|
||||
<wa-range label="Volume" min="0" max="100"></wa-range>
|
||||
```
|
||||
|
||||
### Help Text
|
||||
### Hint
|
||||
|
||||
Add descriptive help text to a range with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
Add descriptive hint to a range with the `hint` attribute. For hints that contain HTML, use the `hint` slot instead.
|
||||
|
||||
```html {.example}
|
||||
<wa-range label="Volume" help-text="Controls the volume of the current song." min="0" max="100"></wa-range>
|
||||
<wa-range label="Volume" hint="Controls the volume of the current song." min="0" max="100"></wa-range>
|
||||
```
|
||||
|
||||
### Min, Max, and Step
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Rating
|
||||
description: Ratings give users a way to quickly view and provide feedback.
|
||||
layout: component
|
||||
tags: component
|
||||
---
|
||||
|
||||
```html {.example}
|
||||
@@ -138,4 +138,4 @@ You can also use the `getSymbol` property to render different icons based on val
|
||||
return `<wa-icon name="${icons[value - 1]}"></wa-icon>`;
|
||||
};
|
||||
</script>
|
||||
```
|
||||
```
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user