Compare commits
702 Commits
v2.0.0-bet
...
context-me
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ee519d40a | ||
|
|
6bc17d48c3 | ||
|
|
a1263f1b9d | ||
|
|
d69ebab765 | ||
|
|
0504946dac | ||
|
|
fbd6691711 | ||
|
|
aec17da6b0 | ||
|
|
639533662d | ||
|
|
a340ce4a68 | ||
|
|
6e5fe64e8b | ||
|
|
84bdbb84b8 | ||
|
|
f91ffb6cb4 | ||
|
|
13815199a3 | ||
|
|
98c20ff551 | ||
|
|
479b6b9081 | ||
|
|
c640d2ea77 | ||
|
|
715547d2fd | ||
|
|
8a914a536b | ||
|
|
f56b6c0648 | ||
|
|
25aa8318d9 | ||
|
|
72f2cbe9e8 | ||
|
|
fc7836084a | ||
|
|
60d9d9202b | ||
|
|
a9df468282 | ||
|
|
0bba773c3e | ||
|
|
7be03ae623 | ||
|
|
d4741532f5 | ||
|
|
10f31efefa | ||
|
|
be662ddf32 | ||
|
|
ff84beaade | ||
|
|
8dba8fa5fb | ||
|
|
3a3f5552a7 | ||
|
|
88cba353c0 | ||
|
|
a2851370bb | ||
|
|
7c0ef7dcf0 | ||
|
|
fb6d5d89b8 | ||
|
|
45ceff4c08 | ||
|
|
6169abc700 | ||
|
|
c09e12d13e | ||
|
|
6152e15e10 | ||
|
|
79910b2ae8 | ||
|
|
c347df7c17 | ||
|
|
e9e2b35c59 | ||
|
|
8ae753c396 | ||
|
|
d2c94321f2 | ||
|
|
4c10f8a537 | ||
|
|
9a19cc2173 | ||
|
|
c4cbc894f5 | ||
|
|
449f5e6c7f | ||
|
|
34447a3f2f | ||
|
|
eee97d7dba | ||
|
|
f16392947a | ||
|
|
c3adf92b49 | ||
|
|
a6580b018d | ||
|
|
00c843c7ce | ||
|
|
5fe55a4db9 | ||
|
|
4ca998c346 | ||
|
|
42b3e2cc11 | ||
|
|
59fb8db6be | ||
|
|
664beafefa | ||
|
|
04443a64e2 | ||
|
|
92dedf3386 | ||
|
|
2ba5fb9820 | ||
|
|
222235159b | ||
|
|
1061bd5e0d | ||
|
|
ccec9a8348 | ||
|
|
bf9e06e67d | ||
|
|
1e03d222c5 | ||
|
|
3722f46b8e | ||
|
|
8d7bf97127 | ||
|
|
d26c1a6407 | ||
|
|
f296ff8476 | ||
|
|
a75a71994a | ||
|
|
7d1373a1d1 | ||
|
|
23abc50015 | ||
|
|
5e28d1131a | ||
|
|
a141e64a69 | ||
|
|
e12ee97bd9 | ||
|
|
ebd84642e1 | ||
|
|
888ac2ea0d | ||
|
|
37068c922c | ||
|
|
eec24d2ed1 | ||
|
|
8fa9d629a3 | ||
|
|
ef22dd7dc4 | ||
|
|
3f12624b78 | ||
|
|
d6fa67374c | ||
|
|
d4183cf718 | ||
|
|
4ad0480039 | ||
|
|
7188425ac0 | ||
|
|
c83581cf47 | ||
|
|
f8fa29f157 | ||
|
|
f2a4db6291 | ||
|
|
a4aff0b1e9 | ||
|
|
f5c2e0b425 | ||
|
|
2f88c55ec0 | ||
|
|
db7075a91a | ||
|
|
8ac007ba9a | ||
|
|
111fa8397c | ||
|
|
0ef4e92a96 | ||
|
|
9123afac18 | ||
|
|
1b5dca52e3 | ||
|
|
bc3e9c43da | ||
|
|
ded01cfd8a | ||
|
|
c737b7494f | ||
|
|
47aff56e71 | ||
|
|
15ce341d81 | ||
|
|
7476204258 | ||
|
|
e083b1a02e | ||
|
|
fa74fc54e3 | ||
|
|
fbbeec6d2f | ||
|
|
b4192364f6 | ||
|
|
c7dc82947f | ||
|
|
c38fd3986c | ||
|
|
35d7926e18 | ||
|
|
86e06ce1e6 | ||
|
|
1a08f063a6 | ||
|
|
740208ed76 | ||
|
|
521f6fe3f1 | ||
|
|
f43d490763 | ||
|
|
898179b645 | ||
|
|
8c3888da02 | ||
|
|
e1471ec9a1 | ||
|
|
eac07a51ba | ||
|
|
753000b56a | ||
|
|
8ab2907c3f | ||
|
|
723ee80c8f | ||
|
|
e1c003c8df | ||
|
|
96c82dc69f | ||
|
|
0dd9483797 | ||
|
|
4da110087d | ||
|
|
7f75a64647 | ||
|
|
71d7f6fd98 | ||
|
|
42595f241f | ||
|
|
c67c84dfda | ||
|
|
2ba6a3b097 | ||
|
|
0456ad96fb | ||
|
|
0ab87b03fa | ||
|
|
54fc41e175 | ||
|
|
261e824290 | ||
|
|
802363e1da | ||
|
|
1054d5bb74 | ||
|
|
f5d143710e | ||
|
|
c025208bf5 | ||
|
|
7306e39f3e | ||
|
|
0d30d183df | ||
|
|
cd504a4127 | ||
|
|
bba41402aa | ||
|
|
e1f129abc5 | ||
|
|
7e6c6924f2 | ||
|
|
185fc4c942 | ||
|
|
5f7c6b307f | ||
|
|
a9f80467c3 | ||
|
|
89fb1a8804 | ||
|
|
54bfce0d5d | ||
|
|
dca1d1b413 | ||
|
|
4b07ee40a7 | ||
|
|
d8644c940b | ||
|
|
7df70abb48 | ||
|
|
6e3c5c0388 | ||
|
|
6cbe2e288b | ||
|
|
1f95c6ca6e | ||
|
|
ac6ae43449 | ||
|
|
ba3117f435 | ||
|
|
fd449f68d9 | ||
|
|
574947656c | ||
|
|
5b1b704d1d | ||
|
|
abbdb207e0 | ||
|
|
2d89fc945f | ||
|
|
25b130ce2c | ||
|
|
ca098eb171 | ||
|
|
f6ccd119e8 | ||
|
|
7b1f99b41a | ||
|
|
4193ee1980 | ||
|
|
c718012c3e | ||
|
|
aca5c8af73 | ||
|
|
2d4a699790 | ||
|
|
fc0475b2c5 | ||
|
|
0f6e13b8c9 | ||
|
|
c60cfae677 | ||
|
|
ded05cf079 | ||
|
|
c360d471cd | ||
|
|
382a39e6ed | ||
|
|
bfa1499889 | ||
|
|
053a5e9bd7 | ||
|
|
3677f6cf0f | ||
|
|
03fb75f030 | ||
|
|
8e209d2767 | ||
|
|
0cf77a4115 | ||
|
|
14368c4ce2 | ||
|
|
e74838fdc1 | ||
|
|
3f64b13d70 | ||
|
|
613f4b6440 | ||
|
|
1bfa4c6ba8 | ||
|
|
9089473cf0 | ||
|
|
687eb7d0dc | ||
|
|
52cb8adf65 | ||
|
|
06f241adb1 | ||
|
|
f5ba173156 | ||
|
|
5bd7bfb4ce | ||
|
|
e4413dceee | ||
|
|
f644454080 | ||
|
|
16f4b485b5 | ||
|
|
679dd4578c | ||
|
|
00bf318ee9 | ||
|
|
da3415d029 | ||
|
|
147a8d2f57 | ||
|
|
a1d354ac15 | ||
|
|
1fb0e41603 | ||
|
|
f121c119f0 | ||
|
|
f4c472e7de | ||
|
|
719d62b670 | ||
|
|
165306f56a | ||
|
|
248bb32977 | ||
|
|
dfb9127052 | ||
|
|
5933e948e1 | ||
|
|
624f6ef5a1 | ||
|
|
2865b546fa | ||
|
|
9d7c3b2af9 | ||
|
|
033896dfc2 | ||
|
|
10d95ba8e6 | ||
|
|
43f74583ea | ||
|
|
36d499f253 | ||
|
|
4c6e61e6dd | ||
|
|
0829af77c0 | ||
|
|
f3281d3985 | ||
|
|
5cd5567292 | ||
|
|
c0102a1658 | ||
|
|
c173d0d76e | ||
|
|
d7dd4b82da | ||
|
|
f9010cf3ca | ||
|
|
a0d2dbf685 | ||
|
|
d679d27043 | ||
|
|
9c0641dcad | ||
|
|
af852a088c | ||
|
|
76f04c0b0e | ||
|
|
27376df5f2 | ||
|
|
fd285dbd6f | ||
|
|
76e1d4b403 | ||
|
|
51dbc1a1ee | ||
|
|
7095236116 | ||
|
|
6014c888c2 | ||
|
|
c41714c6f3 | ||
|
|
a3626e121b | ||
|
|
b7caba8b11 | ||
|
|
0a45f446e2 | ||
|
|
917dbb12da | ||
|
|
767c0b3675 | ||
|
|
30477bb0ad | ||
|
|
1ce4d31503 | ||
|
|
066f7cfa08 | ||
|
|
be8f2bf280 | ||
|
|
e339571ce0 | ||
|
|
3ea89b3956 | ||
|
|
1e65d45844 | ||
|
|
99750b8edb | ||
|
|
2af3831366 | ||
|
|
5d9c65041e | ||
|
|
e789f92db2 | ||
|
|
9a1f7dd3eb | ||
|
|
fb48c4cf0e | ||
|
|
8c5dee529b | ||
|
|
c885b76bbc | ||
|
|
6d03f12e54 | ||
|
|
be5bbe95b6 | ||
|
|
e571c884c1 | ||
|
|
96008539d5 | ||
|
|
8c221f33a8 | ||
|
|
9612af06a8 | ||
|
|
17c1be6dd7 | ||
|
|
6607cdb0bd | ||
|
|
5f33bd312e | ||
|
|
185bc30893 | ||
|
|
b35d5e9914 | ||
|
|
a89eab43c4 | ||
|
|
5eac4ebee8 | ||
|
|
65a3c3a33c | ||
|
|
b0cf35d264 | ||
|
|
f8aff7dcd9 | ||
|
|
b754912990 | ||
|
|
83a01cf0e2 | ||
|
|
d81db3fd4b | ||
|
|
1b383888b8 | ||
|
|
cd76672831 | ||
|
|
94f4d652b4 | ||
|
|
5aab7c34e6 | ||
|
|
72eff3754f | ||
|
|
0d3d9c8233 | ||
|
|
3bb8614143 | ||
|
|
2b12a47915 | ||
|
|
9216e72a3e | ||
|
|
9b99a92dc1 | ||
|
|
ab1a68d0f8 | ||
|
|
4fedf9548f | ||
|
|
a396c86e84 | ||
|
|
75f2da3547 | ||
|
|
6c9a25a0c7 | ||
|
|
34db96822b | ||
|
|
37e60c9dfe | ||
|
|
54b2cbc608 | ||
|
|
7f4169e4e3 | ||
|
|
c356ec40d6 | ||
|
|
23a7268e84 | ||
|
|
35d960c09f | ||
|
|
a7d81993d5 | ||
|
|
e5af3257c9 | ||
|
|
da83581f45 | ||
|
|
5900594562 | ||
|
|
a050832da0 | ||
|
|
fe766dc438 | ||
|
|
c1a5ce4b27 | ||
|
|
64b0e63945 | ||
|
|
95f6841a48 | ||
|
|
3189c6fe98 | ||
|
|
9dbee4c686 | ||
|
|
04a2d45334 | ||
|
|
6766af0f9d | ||
|
|
c7058e7613 | ||
|
|
3d1f858301 | ||
|
|
21de0db790 | ||
|
|
c5d4c532b3 | ||
|
|
3877e89277 | ||
|
|
688ac96faa | ||
|
|
e53f36e5ef | ||
|
|
ad35df2a17 | ||
|
|
fd104ad74f | ||
|
|
bffa9a2ed8 | ||
|
|
dfd18776c6 | ||
|
|
f746ef7954 | ||
|
|
a71b83b4c3 | ||
|
|
cebd206bcc | ||
|
|
d07311cf64 | ||
|
|
7d6390d9bf | ||
|
|
68f40ed779 | ||
|
|
4d56124274 | ||
|
|
6aa31e612a | ||
|
|
6d9018627e | ||
|
|
28b0e74e04 | ||
|
|
246f1155e6 | ||
|
|
a59d29e10c | ||
|
|
b13e2c32ff | ||
|
|
807cba18d1 | ||
|
|
e938f94ffc | ||
|
|
d6e6f2cb25 | ||
|
|
43328b94b7 | ||
|
|
dde15b0881 | ||
|
|
d84fd95f3c | ||
|
|
efed99b890 | ||
|
|
1a6c1ed1c3 | ||
|
|
fa82d31000 | ||
|
|
d11e7fe562 | ||
|
|
e36a49b635 | ||
|
|
17df0e3cd3 | ||
|
|
76df2fd204 | ||
|
|
f9491bb944 | ||
|
|
3541540d84 | ||
|
|
1ae5b9cfcd | ||
|
|
e493bda6df | ||
|
|
7de15e94b2 | ||
|
|
002f847165 | ||
|
|
a654f50c33 | ||
|
|
a2594d4a6b | ||
|
|
b98e1f6b20 | ||
|
|
a48eef2575 | ||
|
|
4aeb804441 | ||
|
|
a30adac959 | ||
|
|
d605de4e07 | ||
|
|
fe49ee0aad | ||
|
|
e47fd3b879 | ||
|
|
383e039297 | ||
|
|
46a206de64 | ||
|
|
f39cb976aa | ||
|
|
ad7c02f745 | ||
|
|
1c98a831d8 | ||
|
|
ffcdf4462b | ||
|
|
22cfc82d35 | ||
|
|
83fbe9eccc | ||
|
|
9a89c14e20 | ||
|
|
6b1d762245 | ||
|
|
0b9da0b049 | ||
|
|
5bcce80b50 | ||
|
|
9f3bf24d06 | ||
|
|
647ab0ab78 | ||
|
|
188a7b661e | ||
|
|
fe4393593a | ||
|
|
6fd5a97fde | ||
|
|
10cd4b8999 | ||
|
|
cb3d76889d | ||
|
|
07504dd149 | ||
|
|
2ea5b65cb8 | ||
|
|
f124c8d81b | ||
|
|
1e7567fb8f | ||
|
|
5f6874edbf | ||
|
|
3558bd5d9b | ||
|
|
8e45f7d785 | ||
|
|
ceb234f0d5 | ||
|
|
1c8a3ea7d2 | ||
|
|
522d6a5fc4 | ||
|
|
21a7df9a84 | ||
|
|
d6eeacbdc1 | ||
|
|
d4d581e4fb | ||
|
|
9c31d148fe | ||
|
|
47c932bd46 | ||
|
|
cc7ab8f7c4 | ||
|
|
6883851866 | ||
|
|
94a5c6244e | ||
|
|
42fb6c7100 | ||
|
|
5e7fcdd105 | ||
|
|
12b0365ce0 | ||
|
|
114dfa3904 | ||
|
|
e31a05beb0 | ||
|
|
a28942f264 | ||
|
|
af61f45ecb | ||
|
|
0da9955403 | ||
|
|
e4f699641a | ||
|
|
23b56b4053 | ||
|
|
0971153a74 | ||
|
|
0b3abfae28 | ||
|
|
d0b9488c1c | ||
|
|
698962e0ea | ||
|
|
1c010ffe5a | ||
|
|
95ba1b5849 | ||
|
|
19dba93cca | ||
|
|
94fe4f1f46 | ||
|
|
de9d43f67a | ||
|
|
301c58d6fb | ||
|
|
227ecc0193 | ||
|
|
ee260e671f | ||
|
|
1a954c5b25 | ||
|
|
a14dd95c21 | ||
|
|
19f7918435 | ||
|
|
1e4de5f821 | ||
|
|
45f4b33eb1 | ||
|
|
16e7287c24 | ||
|
|
3b2b5eed5a | ||
|
|
0521740824 | ||
|
|
1d2033953b | ||
|
|
e20edefc61 | ||
|
|
a9287d9d80 | ||
|
|
ba029db24e | ||
|
|
529c187bc4 | ||
|
|
714914ffe5 | ||
|
|
cd23b9ebfe | ||
|
|
35ce68f4f6 | ||
|
|
f7bcd89b97 | ||
|
|
0b44fba68c | ||
|
|
501869c7aa | ||
|
|
15cb1cb746 | ||
|
|
7454cc12a1 | ||
|
|
52d52810b9 | ||
|
|
936039f7a7 | ||
|
|
ba0e8f7973 | ||
|
|
8449a99418 | ||
|
|
28c9dbab1f | ||
|
|
81753cd44b | ||
|
|
9970bc84ff | ||
|
|
499bc4c4cd | ||
|
|
b0921b5be0 | ||
|
|
afc4dfaf50 | ||
|
|
9dda3a9323 | ||
|
|
115e80dce0 | ||
|
|
9f405686ec | ||
|
|
e7d7469c4e | ||
|
|
0dbb72efe9 | ||
|
|
9b21d5a619 | ||
|
|
8ffcdebffc | ||
|
|
e089184a14 | ||
|
|
a2a059962c | ||
|
|
3eb42321d5 | ||
|
|
474484b059 | ||
|
|
998e255636 | ||
|
|
3938644442 | ||
|
|
b13e637593 | ||
|
|
95e3f5e0e8 | ||
|
|
d5ee79fe1e | ||
|
|
51f003d5fd | ||
|
|
dd89657f1e | ||
|
|
1e280608d3 | ||
|
|
c6e5bedd3c | ||
|
|
0ff5b46799 | ||
|
|
e34090a87b | ||
|
|
f690b24c68 | ||
|
|
10f045fe6e | ||
|
|
8d8b77ca07 | ||
|
|
234d2380ef | ||
|
|
4de659d5bb | ||
|
|
2aabe4e11c | ||
|
|
171e55ce6d | ||
|
|
297e6c8872 | ||
|
|
2b39d613b7 | ||
|
|
2432fd1d85 | ||
|
|
3cc3d4997b | ||
|
|
9c0189f8be | ||
|
|
fc5a21f57d | ||
|
|
ee9ce8a87b | ||
|
|
d720121044 | ||
|
|
3fce846a8d | ||
|
|
8776c3f4a8 | ||
|
|
189ad7889d | ||
|
|
79a15e1470 | ||
|
|
dfd0d0ed30 | ||
|
|
d7bf0bd653 | ||
|
|
6044190019 | ||
|
|
89b8d0ef67 | ||
|
|
489d713fa2 | ||
|
|
8d984d8dac | ||
|
|
cadbae85a5 | ||
|
|
01bb476023 | ||
|
|
d5c37f7b29 | ||
|
|
99181cf5c6 | ||
|
|
7836b8229a | ||
|
|
3cff627b22 | ||
|
|
4263899bc0 | ||
|
|
0f4bb2b24b | ||
|
|
7bd7b421b8 | ||
|
|
49eb9bbcf8 | ||
|
|
a87596b3a1 | ||
|
|
1ca890b1e9 | ||
|
|
52aba14ae9 | ||
|
|
916ee07265 | ||
|
|
1e67c7411c | ||
|
|
62ef8e17c7 | ||
|
|
327ef6b06c | ||
|
|
5dff7b2855 | ||
|
|
22b359a612 | ||
|
|
7bf3a8d8f7 | ||
|
|
4bd73ac374 | ||
|
|
cae50866f9 | ||
|
|
ebd1b95ba0 | ||
|
|
703cb4dc7a | ||
|
|
e274904d28 | ||
|
|
b3bcfc9934 | ||
|
|
a3beaafbcc | ||
|
|
5c619b87b6 | ||
|
|
86fc6b85d6 | ||
|
|
4c1e077833 | ||
|
|
c8e94ea098 | ||
|
|
cf38478cd5 | ||
|
|
e3ca914eac | ||
|
|
18a933bf6b | ||
|
|
7554f47258 | ||
|
|
e579330177 | ||
|
|
360cfa43d8 | ||
|
|
f66535f7d4 | ||
|
|
ce0b64045c | ||
|
|
b09bfdd01d | ||
|
|
eeb1a097a3 | ||
|
|
0911299797 | ||
|
|
af601c6e9c | ||
|
|
51d48b6aad | ||
|
|
a3d38c0e4b | ||
|
|
19f01d29aa | ||
|
|
bf2a4ac6cb | ||
|
|
51c252420e | ||
|
|
a02354283b | ||
|
|
121723b440 | ||
|
|
3834f3a61a | ||
|
|
a1c6035542 | ||
|
|
f2005bdcd8 | ||
|
|
9f42a698c4 | ||
|
|
2bbea51830 | ||
|
|
70a94bb38e | ||
|
|
b06f58db5f | ||
|
|
75bd54d16a | ||
|
|
f4ccf86ece | ||
|
|
b4fc01e99a | ||
|
|
8e404bd478 | ||
|
|
4555406143 | ||
|
|
8f8cf9649d | ||
|
|
9b8bee2bc5 | ||
|
|
5bea4269a7 | ||
|
|
0b4dc3f6a8 | ||
|
|
c2314e9871 | ||
|
|
4b4361c514 | ||
|
|
8d2d8cd9f0 | ||
|
|
d59fdbc443 | ||
|
|
16add89462 | ||
|
|
16a3d5f156 | ||
|
|
19b0c7978f | ||
|
|
7a64963fef | ||
|
|
48216a4fdc | ||
|
|
b2599d5a9f | ||
|
|
2e893bbaf2 | ||
|
|
26bfe8ef11 | ||
|
|
784c173728 | ||
|
|
619758cbc3 | ||
|
|
d1ab1e5cc2 | ||
|
|
261f6bb322 | ||
|
|
e4a4281200 | ||
|
|
dac05f8d06 | ||
|
|
3c9a4812ca | ||
|
|
0208cf6229 | ||
|
|
1282deabd0 | ||
|
|
d6e109b895 | ||
|
|
7a512232c4 | ||
|
|
75d1abaa9c | ||
|
|
485a7252b0 | ||
|
|
0935e1574a | ||
|
|
a04fc7c681 | ||
|
|
a71f28c664 | ||
|
|
e00997ce97 | ||
|
|
c50b57d96b | ||
|
|
3bd3bdd086 | ||
|
|
d059017153 | ||
|
|
28c0121a69 | ||
|
|
560441bea3 | ||
|
|
7518e07882 | ||
|
|
25f63df53a | ||
|
|
9e325dffa0 | ||
|
|
389dd0b44e | ||
|
|
59dd5c0c3e | ||
|
|
1b2e92c153 | ||
|
|
f3db9e92ee | ||
|
|
cb156dc84a | ||
|
|
494be4f25b | ||
|
|
35cde2c3c3 | ||
|
|
401eaf0a63 | ||
|
|
a2e3fe70d5 | ||
|
|
5fd4bca95d | ||
|
|
2fbd2af914 | ||
|
|
a9886851d5 | ||
|
|
b935a0a838 | ||
|
|
db2005d239 | ||
|
|
20eff47286 | ||
|
|
2cf65ff2dd | ||
|
|
a4a2ff948f | ||
|
|
c351e56aa7 | ||
|
|
334a7ca832 | ||
|
|
119245e7ac | ||
|
|
cffa6726db | ||
|
|
b05d1967d0 | ||
|
|
42f646eaaa | ||
|
|
e7cea10e17 | ||
|
|
f50d354ceb | ||
|
|
8aa9466d6b | ||
|
|
7ba0f51e9e | ||
|
|
a67db7e13e | ||
|
|
57b561b353 | ||
|
|
f372e36a79 | ||
|
|
85e2142a56 | ||
|
|
83b38987cc | ||
|
|
30132ed9ea | ||
|
|
1193ba6bb0 | ||
|
|
a70e1ae856 | ||
|
|
0213eb2376 | ||
|
|
a14346ea87 | ||
|
|
0234fe81d5 | ||
|
|
0489d8b5c0 | ||
|
|
93a5be1ce8 | ||
|
|
e15bd8bca1 | ||
|
|
3b3aef7c63 | ||
|
|
c5614bfc95 | ||
|
|
7fb1a83788 | ||
|
|
0114261fa1 | ||
|
|
d5af772444 | ||
|
|
7b907bc326 | ||
|
|
fca8c2fdce | ||
|
|
5f310ddab2 | ||
|
|
cdbae1fca3 | ||
|
|
3f8048fe41 | ||
|
|
b4d51e7ea7 | ||
|
|
a9d7258a07 | ||
|
|
6940713e36 | ||
|
|
32e4bfe83c | ||
|
|
28965a422d | ||
|
|
3c4ec12b18 | ||
|
|
cc24f7ade0 | ||
|
|
d1d1a4d03e | ||
|
|
ce88f2c828 | ||
|
|
935796c545 | ||
|
|
e40744c9ff | ||
|
|
169b2867fc | ||
|
|
c0ec00a0fc | ||
|
|
a0ea729bb9 | ||
|
|
c53634544a | ||
|
|
59cdafd722 | ||
|
|
8e8b692128 | ||
|
|
060936d611 | ||
|
|
47a8b3f19a | ||
|
|
dafb10b1ce | ||
|
|
7d66a031a3 | ||
|
|
9bd703014c | ||
|
|
1d174cfdf5 | ||
|
|
e903c82133 | ||
|
|
fbbfeb00db | ||
|
|
6c39dce582 | ||
|
|
405f38573a | ||
|
|
18859be955 | ||
|
|
786ba8a2fb | ||
|
|
96091e42ff | ||
|
|
6062e73022 | ||
|
|
4673e726a9 | ||
|
|
f10051b588 | ||
|
|
4ef21c2852 | ||
|
|
6283d14758 | ||
|
|
3bb38e74e3 | ||
|
|
a4f64b91eb | ||
|
|
2f4d93700a | ||
|
|
099dfc93d8 | ||
|
|
d4f5a170f5 | ||
|
|
0bccc051d2 | ||
|
|
9e3a573b53 | ||
|
|
1f9771a2d6 |
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,38 +1,36 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Create a report to help us improve.
|
||||
about: Create a bug report to help us fix a demonstrable problem with code in the library.
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: claviska
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
### Describe the bug
|
||||
A bug is _a demonstrable problem_ caused by code in the library. Please provide a clear and concise description of what the bug is here.
|
||||
|
||||
**To Reproduce**
|
||||
### To Reproduce
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
### Demo
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
If the bug isn't obvious, please provide a link to a CodePen or Fiddle with a minimal reproduction. Bugs that have repros get attention faster than those that don't.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
Tip: use the CodePen button on any example in the docs!
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
### Screenshots
|
||||
If applicable, add screenshots to help explain the bug.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
### Browser / OS
|
||||
- OS: [e.g. Mac, Windows]
|
||||
- Browser [e.g. Chrome, Firefox, Safari]
|
||||
- Browser version [e.g. 22]
|
||||
|
||||
### Additional information
|
||||
Provide any additional information about the bug here.
|
||||
|
||||
15
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -7,14 +7,11 @@ assignees: claviska
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
### What issue are you having?
|
||||
Provide a clear and concise description of the problem you're facing.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
### Describe the solution you'd like
|
||||
How would you like to see the library solve it?
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
### Describe alternatives you've considered
|
||||
In what ways have you tried to solve this with the current version?
|
||||
|
||||
31
.github/workflows/node.js.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# 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
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ next ]
|
||||
pull_request:
|
||||
branches: [ next ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x, 16.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm run build --if-present
|
||||
- run: npm test
|
||||
17
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# This workflow will create a GitHub release every time a tag is pushed
|
||||
name: Create GitHub Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v2.*"
|
||||
- "v3.*"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: "marvinpinto/action-automatic-releases@v1.2.1"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
prerelease: false
|
||||
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
.DS_Store
|
||||
.cache
|
||||
docs/dist
|
||||
docs/search.json
|
||||
dist
|
||||
examples
|
||||
node_modules
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.hbs
|
||||
*.md
|
||||
.cache
|
||||
.github
|
||||
|
||||
8
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"esbenp.prettier-vscode",
|
||||
"bierner.lit-html",
|
||||
"bashmish.es6-string-css"
|
||||
]
|
||||
}
|
||||
4
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
206
CONTRIBUTING.md
@@ -1,207 +1,5 @@
|
||||
# Contributing to Shoelace
|
||||
|
||||
Shoelace is an open source project, meaning everyone can use it and contribute to its development. When you join our community, you'll find a friendly group of enthusiasts at all experience levels who are willing to chat about anything and everything related to Shoelace.
|
||||
Before contributing, please review the contributions guidelines at:
|
||||
|
||||
The easiest way to get started contributing is to join the [community chat](https://discord.gg/mg8f26C). This is where we hang out, discuss new ideas, ask for feedback, and more!
|
||||
|
||||
A common misconception about contributing to an open source project is that you need to know how to code. This simply isn't true. In fact, there are _many_ ways to contribute, and some of the most important contributions come from those who never write a single line of code. Here's a list of ways you can make a meaningful contribution to the project:
|
||||
|
||||
- Submitting well-written bug reports
|
||||
- Submitting feature requests that are within the scope of the project
|
||||
- Improving the documentation
|
||||
- Responding to users that need help in the community chat
|
||||
- Triaging issues on GitHub
|
||||
- Being a developer advocate for the project
|
||||
- Sponsoring the project financially
|
||||
- Writing tests
|
||||
- And, of course, contributing code!
|
||||
|
||||
Please take a moment to review these guidelines to make the contribution process as easy as possible for both yourself and the project's maintainers.
|
||||
|
||||
## Using the Issue Tracker
|
||||
|
||||
The [issue tracker](https://github.com/shoelace-style/shoelace/issues) is for bug reports, feature requests, and pull requests.
|
||||
|
||||
- Please **do not** use the issue tracker for personal support requests. Use [the discussion forum](https://github.com/shoelace-style/shoelace/discussions/categories/help) instead.
|
||||
- Please **do not** derail, hijack, or troll issues. Keep the discussion on topic and be respectful of others.
|
||||
- Please **do not** post comments with "+1" or "👍". Use [reactions](https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) instead.
|
||||
- Please **do** use the issue tracker for feature requests, bug reports, and pull requests.
|
||||
|
||||
Issues that do not follow these guidelines are subject to closure. There simply aren't enough resources for the author and contributors to troubleshoot personal support requests.
|
||||
|
||||
### Feature Requests
|
||||
|
||||
Feature requests can be added using the issue tracker.
|
||||
|
||||
- Please **do** search for an existing request before suggesting a new feature.
|
||||
- Please **do** use the "👍" reaction to vote for a feature.
|
||||
- Please **do** share substantial use cases and perspective that support new features if they haven't already been mentioned.
|
||||
- Please **do not** bump, spam, or ping contributors to prioritize your own feature.
|
||||
|
||||
If you would like your feature prioritized, please consider [sponsoring the project](https://github.com/sponsors/claviska).
|
||||
|
||||
### Bug Reports
|
||||
|
||||
A bug is _a demonstrable problem_ caused by code in the library. Bug reports are an important contribution to the quality of the project. When submitting a bug report, there are a few steps you can take to make sure your issues gets attention quickly.
|
||||
|
||||
- Please **do not** paste in large blocks of irrelevant code
|
||||
- Please **do** search for an existing issue before creating a new one
|
||||
- Please **do** explain the bug clearly
|
||||
- Please **do** provide a minimal test case that demonstrates the bug (e.g. [jsfiddle.net](https://jsfiddle.net/) or [CodePen](https://codepen.io/))
|
||||
- Please **do** provide additional information, when necessary, to replicate the bug
|
||||
|
||||
**A minimal test case is critical to a successful bug report.** It demonstrates that the bug exists in the library and not in surrounding code. Contributors should be able to understand the bug without studying your code, otherwise they'll probably move on to another bug.
|
||||
|
||||
If you would like your bug prioritized, please consider [sponsoring the project](https://github.com/sponsors/claviska).
|
||||
|
||||
### Pull Requests
|
||||
|
||||
To keep the project on track, please consider the following guidelines before submitting a PR.
|
||||
|
||||
- Please **do not** submit a PR without opening an issue first, especially for non-trivial changes. This may prevent you from doing work that won't be accepted for various reasons (e.g. someone is already working on it, it's not a good fit for the project, it needs additional planning, etc.)
|
||||
- Please **do** make sure your PR clearly defines what you're changing. Even if you feel your changes are obvious, please explain them so other contributors can more easily review your works. PRs without detailed descriptions are subject to closure pending more details.
|
||||
- Please **do not** edit anything in `dist/`. These files are generated automatically, so you need to edit the source files instead.
|
||||
|
||||
The author reserves the right to reject any PR that's outside the scope of the project or doesn't meet code quality standards.
|
||||
|
||||
### Branches
|
||||
|
||||
`current` - This branch reflects the latest release and powers [shoelace.style](https://shoelace.style/).
|
||||
|
||||
`next` - This branch is where pull requests will land. It reflects what's coming in the _next_ release, which can be previewed at [next.shoelace.style](https://next.shoelace.style/).
|
||||
|
||||
## Conventions
|
||||
|
||||
This section aims to describe some of the design decisions and code conventions that support the project. All contributors are expected to follow conventions and best practices, even those not explicitly defined in this document. When in doubt, refer to existing source code and execute your best judgment.
|
||||
|
||||
In order to keep the project in a maintainable state, code that doesn't follow conventions and best practices will need to be refactored before it will be accepted. This isn't a knock on your code or your style — it's something the author considers necessary to operate a successful open source project.
|
||||
|
||||
### Semantic Versioning
|
||||
|
||||
Shoelace follows [Semantic Versioning](https://semver.org/). Breaking changes in components with the "Stable" badge will not be accepted until the next major version. As such, all contributions must consider the project's roadmap and take this into consideration. Features that are deemed no longer necessary will be deprecated but not removed.
|
||||
|
||||
Components with the "Experimental" badge should not be used in production. They are made available as release candidates for development and testing purposes. As such, changes to experimental components will not be subject to semantic versioning.
|
||||
|
||||
### Code Formatting & Linting
|
||||
|
||||
The majority of code formatting is handled automatically by [Prettier](https://prettier.io/) at build time. However, for the best experience, you should [install it in your editor](https://prettier.io/docs/en/editors.html) and enable format on save.
|
||||
|
||||
Linting is run automatically at build time. By design, the project will not build if the linter is unhappy. Contributors are strongly encouraged to install an ESLint plugin for your editor for the best developer experience.
|
||||
|
||||
### BEM Class Names
|
||||
|
||||
All components use a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM), so styles are completely encapsulated from the rest of the document. As a result, class names _inside_ a component won't conflict with class names _outside_ the component, so we're free to name them whatever we want.
|
||||
|
||||
Internally, each component uses the [BEM methodology](http://getbem.com/) for its class names. There is no technical requirement to do this — it's purely the preference of the author. However, all contributions are expected to follow this practice for the sake of consistency.
|
||||
|
||||
## Developer Tips
|
||||
|
||||
### Documentation is the key to success
|
||||
|
||||
Nobody likes writing documentation, but not having good docs is frustrating to users and makes the project less appealing. Fortunately, writing documentation for Shoelace is really easy!
|
||||
|
||||
A lot of the documentation is generated automatically based on JSDoc comments in each component's source code. If you have ESLint enabled, your editor will tell you when a comment is missing. This may feel a bit naggy, but it's a very good thing. Every property, method, event, etc. is documented this way. By adding comments as you code, the docs are more easily kept up to date.
|
||||
|
||||
The documentation pages are served up by [Docsify](https://docsify.now.sh/). Check out `docs/_sidebar.md` and `docs/components/` to get an idea of how pages are created and formatted. If you're creating a new component, it may help to use an existing component's markdown file as a template.
|
||||
|
||||
If you need help with documentation, feel free to reach out!
|
||||
|
||||
### Choose composability when possible
|
||||
|
||||
When designed right, web components are highly composable, meaning you can easily reuse them in other components. This reduces the overall size of the library, expedites feature development, and maintains a consistent user experience throughout.
|
||||
|
||||
The select component, for example, makes use of the dropdown, input, and menu components. Because it's offloading most of its functionality and styles to these lower-level components, the select component remains very lightweight and its appearance and behavior is consistent with other form controls and menus.
|
||||
|
||||
### When to use a standard property vs. a CSS custom property
|
||||
|
||||
When designing a component's API, standard properties ("props") are generally used to change the _behavior_ of a component, whereas CSS custom properties ("CSS variables") are used to change the _appearance_ of a component. Remember that props can't respond to media queries, but CSS variables can.
|
||||
|
||||
There are some exceptions to this (e.g. when it significantly improves developer experience), but a good rule of thumbs is "will this need to change based on screen size?" If so, you probably want to use a CSS variable.
|
||||
|
||||
### Custom event names
|
||||
|
||||
All custom events must start with `sl-` as a namespace. For compatibility with frameworks that utilize DOM templates, custom events must have lowercase, kebab-style names. For example, use `sl-change` instead of `slChange`.
|
||||
|
||||
This convention avoids the problem of browsers lowercasing attributes, causing some frameworks to be unable to listen to them. This problem isn't specific to one framework, but [Vue's documentation](https://vuejs.org/v2/guide/components-custom-events.html#Event-Names) provides a good explanation of the problem.
|
||||
|
||||
> Additionally, `v-on` event listeners inside DOM templates will be automatically transformed to lowercase (due to HTML’s case-insensitivity), so `v-on:myEvent` would become `v-on:myevent` – making `myEvent` impossible to listen to.
|
||||
|
||||
### When to use a CSS custom property vs. a CSS part
|
||||
|
||||
There are two ways to enable customizations for components. One way is with CSS custom properties ("CSS variables"), the other is with CSS parts ("parts").
|
||||
|
||||
CSS variables are scoped to the host element and can be reused throughout the component. A good example of a CSS variable would be `--border-width`, which might get reused throughout a component to ensure borders share the same width for all internal elements.
|
||||
|
||||
Parts let you target a specific element inside the component's shadow DOM but, by design, you can't target a part's children or siblings. You can _only_ customize the part itself. Use a part when you need to allow a single element inside the component to accept styles.
|
||||
|
||||
This convention can be relaxed when the developer experience is greatly improved by not following these suggestions.
|
||||
|
||||
### Boolean Props
|
||||
|
||||
Boolean props should _always_ default to `false`, otherwise there's no way for the user to unset it without JavaScript. To keep the API as friendly and consistent as possible, use a name like `noHeader` with a default value of `false` instead of `header` with a default value of `true`.
|
||||
|
||||
### A Note About Sass
|
||||
|
||||
The Shoelace _source_ is developed using Sass for the convenience of nested selectors, imports, and tedious things such as color palette generation. By design, Sass variables, color functions, and other preprocessor-specific feaures are not used in the source and will not be accepted in a PR.
|
||||
|
||||
Consumers of the library should never need to worry about preprocessing the library.
|
||||
|
||||
### Positioning Popovers
|
||||
|
||||
Shoelace uses an internal popover utility for dropdowns, tooltips, etc. This is a light abstraction of Popper.js designed to make positioning and transitioning things easy and consistent throughout the library. When possible, use this utility instead of relying on Popper directly. See `src/utilities/popover.ts` for details.
|
||||
|
||||
### Host and Base Elements
|
||||
|
||||
All components have a host element, which is a reference to the actual `<sl-*>` elements. Make sure to always set the host element's `display` property to the appropriate value depending on your needs, as the default is `inline` per the HTML spec.
|
||||
|
||||
```css
|
||||
:host {
|
||||
display: inline-block;
|
||||
}
|
||||
```
|
||||
|
||||
Aside from `display`, avoid setting properties on the host element when possible. The reason for this is that styles applied to the host element are not encapsulated. Instead, create a base element that wraps the internals and style that instead. This convention also makes it easier to use BEM in components.
|
||||
|
||||
```css
|
||||
.sl-example {
|
||||
/* This is the base element */
|
||||
}
|
||||
|
||||
.sl-example--primary {
|
||||
/* Primary modifier */
|
||||
}
|
||||
```
|
||||
|
||||
To expose custom properties for a component, define them in the `:host` block and use the following syntax for comments so they appear in the generated docs.
|
||||
|
||||
```css
|
||||
/**
|
||||
* @param --color: The component's text color.
|
||||
* @param --background-color: The component's background color.
|
||||
*/
|
||||
:host {
|
||||
--color: white;
|
||||
--background-color: tomato;
|
||||
|
||||
display: inline-block;
|
||||
}
|
||||
```
|
||||
|
||||
### Conditional Slots
|
||||
|
||||
When a component relies on the presence of slotted content to do something, don't assume its initial state is permanent. Slotted content can be added or removed any time and components must be aware of this. A good practice to manage this is:
|
||||
|
||||
- Create a `handleSlotChange` method that uses `hasSlot` (imported from `src/utilities/slot.ts`) to update state variables for the associated slot(s)
|
||||
- Add `onSlotchange={this.handleSlotChange}` to the slots you want to watch
|
||||
- Never conditionally render `<slot>` elements in a component — always use `hidden` so the slot remains in the DOM and the `slotchange` event can be captured
|
||||
|
||||
See the source of card, dialog, or drawer for examples.
|
||||
|
||||
### Form Controls
|
||||
|
||||
Form controls should support validation through the following conventions:
|
||||
|
||||
- All form controls must an `invalid` prop that reflects its validity
|
||||
- All form controls must have a `setCustomValidity()` method so the user can set a custom validation message
|
||||
- All form controls must have a `reportValidity()` method that reports its validity during form submission
|
||||
- All form controls should mirror their native validation attributes such as `required`, `pattern`, `minlength`, `maxlength`, etc. when possible
|
||||
[shoelace.style/resources/contributing](https://shoelace.style/resources/contributing)
|
||||
|
||||
18
README.md
@@ -23,7 +23,7 @@ Twitter: [@shoelace_style](https://twitter.com/shoelace_style)
|
||||
|
||||
## Shoemakers 🥾
|
||||
|
||||
Shoemakers, or "Shoelace developers," can use this documentation to learn how to build Shoelace from source. You will need Node >= 12.10.0 to build and run the project locally.
|
||||
Shoemakers, or "Shoelace developers," can use this documentation to learn how to build Shoelace from source. You will need Node >= 14 to build and run the project locally. It is preferred, but not required, to use npm 7.
|
||||
|
||||
**You don't need to do any of this to use Shoelace!** This page is for people who want to contribute to the project, tinker with the source, or create a custom build of Shoelace.
|
||||
|
||||
@@ -31,7 +31,7 @@ If that's not what you're trying to do, the [documentation website](https://shoe
|
||||
|
||||
### What are you using to build Shoelace?
|
||||
|
||||
Components are built with [Shoemaker](https://github.com/shoelace-style/shoemaker), a lightweight utility that provides an elegant API and reactive data binding. The build is a custom script with bundling powered by [esbuild](https://esbuild.github.io/).
|
||||
Components are built with [LitElement](https://lit-element.polymer-project.org/), a custom elements base class that provides an intuitive API and reactive data binding. The build is a custom script with bundling powered by [esbuild](https://esbuild.github.io/).
|
||||
|
||||
### Forking the Repo
|
||||
|
||||
@@ -51,9 +51,7 @@ Once you've cloned the repo, run the following command.
|
||||
npm start
|
||||
```
|
||||
|
||||
This will spin up the Shoelace dev server. After the initial build, a browser will open automatically.
|
||||
|
||||
There is currently no hot module reloading (HMR), as browser's don't provide a way to reregister custom elements, but most changes to the source will reload the browser automatically. The exception is component metadata used by the docs, which is generated by TypeDoc. This tool takes a few seconds to run so, to prevent long reload delays, it only runs once at startup.
|
||||
This will spin up the Shoelace dev server. After the initial build, a browser will open automatically. There is currently no hot module reloading (HMR), as browser's don't provide a way to reregister custom elements, but most changes to the source will reload the browser automatically.
|
||||
|
||||
The documentation is powered by Docsify, which uses raw markdown files to generate pages. As such, no static files are built for the docs.
|
||||
|
||||
@@ -65,6 +63,16 @@ To generate a production build, run the following command.
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Creating New Components
|
||||
|
||||
To scaffold a new component, run the following command, replacing `sl-tag-name` with the desired tag name.
|
||||
|
||||
```bash
|
||||
npm run create sl-tag-name
|
||||
```
|
||||
|
||||
This will generate a source file, a stylesheet, and a docs page for you. When you start the dev server, you'll find the new component in the "Components" section of the sidebar.
|
||||
|
||||
### Contributing
|
||||
|
||||
Shoelace is an open source project and contributions are encouraged! If you're interesting in contributing, please review the [contribution guidelines](CONTRIBUTING.md) first.
|
||||
|
||||
86
custom-elements-manifest.config.js
Normal file
@@ -0,0 +1,86 @@
|
||||
import fs from 'fs';
|
||||
import commentParser from 'comment-parser';
|
||||
|
||||
const packageData = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||
const { name, description, version, author, homepage, license } = packageData;
|
||||
const noDash = string => string.replace(/^\s?-/, '').trim();
|
||||
|
||||
export default {
|
||||
globs: ['src/components/**/*.ts'],
|
||||
exclude: ['**/*.test.ts'],
|
||||
plugins: [
|
||||
// Append package data
|
||||
{
|
||||
name: 'shoelace-package-data',
|
||||
packageLinkPhase({ customElementsManifest, context }) {
|
||||
customElementsManifest.package = { name, description, version, author, homepage, license };
|
||||
}
|
||||
},
|
||||
|
||||
// Parse custom jsDoc tags
|
||||
{
|
||||
name: 'shoelace-custom-tags',
|
||||
analyzePhase({ ts, node, moduleDoc, context }) {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.ClassDeclaration:
|
||||
const className = node.name.getText();
|
||||
const classDoc = moduleDoc?.declarations?.find(declaration => declaration.name === className);
|
||||
const customTags = ['animation', 'dependency', 'since', 'status'];
|
||||
let customComments = '/**';
|
||||
|
||||
node.jsDoc?.forEach(jsDoc => {
|
||||
jsDoc?.tags?.forEach(tag => {
|
||||
const tagName = tag.tagName.getText();
|
||||
|
||||
if (customTags.includes(tagName)) {
|
||||
customComments += `\n * @${tagName} ${tag.comment}`;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const parsed = commentParser.parse(customComments + '\n */');
|
||||
parsed[0].tags?.map(t => {
|
||||
switch (t.tag) {
|
||||
// Animations
|
||||
case 'animation':
|
||||
if (!Array.isArray(classDoc['animations'])) {
|
||||
classDoc['animations'] = [];
|
||||
}
|
||||
classDoc['animations'].push({
|
||||
name: t.name,
|
||||
description: noDash(t.description)
|
||||
});
|
||||
break;
|
||||
|
||||
// Dependencies
|
||||
case 'dependency':
|
||||
if (!Array.isArray(classDoc['dependencies'])) {
|
||||
classDoc['dependencies'] = [];
|
||||
}
|
||||
classDoc['dependencies'].push(t.name);
|
||||
break;
|
||||
|
||||
// Value-only metadata tags
|
||||
case 'since':
|
||||
case 'status':
|
||||
classDoc[t.tag] = t.name;
|
||||
break;
|
||||
|
||||
// All other tags
|
||||
default:
|
||||
if (!Array.isArray(classDoc[t.tag])) {
|
||||
classDoc[t.tag] = [];
|
||||
}
|
||||
|
||||
classDoc[t.tag].push({
|
||||
name: t.name,
|
||||
description: t.description,
|
||||
type: t.type || undefined
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -1,3 +1,5 @@
|
||||
# Not Found
|
||||
|
||||
Sorry, I couldn't find that page.
|
||||
<img class="not-found-image" src="/assets/images/undraw-not-found.svg" alt="Cute monsters hiding behind a tree">
|
||||
|
||||
Sorry, I couldn't find that page. Have you tried pressing <kbd>/</kbd> to search?
|
||||
|
||||
132
docs/_sidebar.md
@@ -1,69 +1,81 @@
|
||||
- Getting Started
|
||||
- [Overview](/)
|
||||
- [Installation](/getting-started/installation.md)
|
||||
- [Usage](/getting-started/usage.md)
|
||||
- [Customizing](/getting-started/customizing.md)
|
||||
- [Themes](/getting-started/themes.md)
|
||||
- [Community](/getting-started/community.md)
|
||||
- [Changelog](/getting-started/changelog.md)
|
||||
- [Installation](/getting-started/installation)
|
||||
- [Usage](/getting-started/usage)
|
||||
- [Themes](/getting-started/themes)
|
||||
- [Customizing](/getting-started/customizing)
|
||||
|
||||
- Resources
|
||||
- [Community](/resources/community)
|
||||
- [Contributing](/resources/contributing)
|
||||
- [Changelog](/resources/changelog)
|
||||
|
||||
- Components
|
||||
- [Alert](/components/alert.md)
|
||||
- [Avatar](/components/avatar.md)
|
||||
- [Badge](/components/badge.md)
|
||||
- [Button](/components/button.md)
|
||||
- [Button Group](/components/button-group.md)
|
||||
- [Card](/components/card.md)
|
||||
- [Checkbox](/components/checkbox.md)
|
||||
- [Color Picker](/components/color-picker.md)
|
||||
- [Details](/components/details.md)
|
||||
- [Dialog](/components/dialog.md)
|
||||
- [Drawer](/components/drawer.md)
|
||||
- [Dropdown](/components/dropdown.md)
|
||||
- [Form](/components/form.md)
|
||||
- [Icon](/components/icon.md)
|
||||
- [Icon Button](/components/icon-button.md)
|
||||
- [Image Comparer](/components/image-comparer.md)
|
||||
- [Input](/components/input.md)
|
||||
- [Menu](/components/menu.md)
|
||||
- [Menu Divider](/components/menu-divider.md)
|
||||
- [Menu Item](/components/menu-item.md)
|
||||
- [Menu Label](/components/menu-label.md)
|
||||
- [Progress Bar](/components/progress-bar.md)
|
||||
- [Progress Ring](/components/progress-ring.md)
|
||||
- [Radio](/components/radio.md)
|
||||
- [Range](/components/range.md)
|
||||
- [Rating](/components/rating.md)
|
||||
- [Responsive Embed](/components/responsive-embed.md)
|
||||
- [Select](/components/select.md)
|
||||
- [Skeleton](/components/skeleton.md)
|
||||
- [Spinner](/components/spinner.md)
|
||||
- [Switch](/components/switch.md)
|
||||
- [Tab Group](/components/tab-group.md)
|
||||
- [Tab](/components/tab.md)
|
||||
- [Tab Panel](/components/tab-panel.md)
|
||||
- [Tag](/components/tag.md)
|
||||
- [Textarea](/components/textarea.md)
|
||||
- [Tooltip](/components/tooltip.md)
|
||||
- [Alert](/components/alert)
|
||||
- [Avatar](/components/avatar)
|
||||
- [Badge](/components/badge)
|
||||
- [Breadcrumb](/components/breadcrumb)
|
||||
- [Breadcrumb Item](/components/breadcrumb-item)
|
||||
- [Button](/components/button)
|
||||
- [Button Group](/components/button-group)
|
||||
- [Card](/components/card)
|
||||
- [Checkbox](/components/checkbox)
|
||||
- [Color Picker](/components/color-picker)
|
||||
- [Context Menu](/components/context-menu)
|
||||
- [Details](/components/details)
|
||||
- [Dialog](/components/dialog)
|
||||
- [Divider](/components/divider)
|
||||
- [Drawer](/components/drawer)
|
||||
- [Dropdown](/components/dropdown)
|
||||
- [Form](/components/form)
|
||||
- [Icon](/components/icon)
|
||||
- [Icon Button](/components/icon-button)
|
||||
- [Image Comparer](/components/image-comparer)
|
||||
- [Input](/components/input)
|
||||
- [Menu](/components/menu)
|
||||
- [Menu Item](/components/menu-item)
|
||||
- [Menu Label](/components/menu-label)
|
||||
- [Progress Bar](/components/progress-bar)
|
||||
- [Progress Ring](/components/progress-ring)
|
||||
- [QR Code](/components/qr-code)
|
||||
- [Radio](/components/radio)
|
||||
- [Radio Group](/components/radio-group)
|
||||
- [Range](/components/range)
|
||||
- [Rating](/components/rating)
|
||||
- [Select](/components/select)
|
||||
- [Skeleton](/components/skeleton)
|
||||
- [Spinner](/components/spinner)
|
||||
- [Switch](/components/switch)
|
||||
- [Tab Group](/components/tab-group)
|
||||
- [Tab](/components/tab)
|
||||
- [Tab Panel](/components/tab-panel)
|
||||
- [Tag](/components/tag)
|
||||
- [Textarea](/components/textarea)
|
||||
- [Tooltip](/components/tooltip)
|
||||
<!--plop:component-->
|
||||
|
||||
- Utility Components
|
||||
- [Animation](/components/animation.md)
|
||||
- [Format Bytes](/components/format-bytes.md)
|
||||
- [Format Date](/components/format-date.md)
|
||||
- [Format Number](/components/format-number.md)
|
||||
- [Include](/components/include.md)
|
||||
- [Relative Time](/components/relative-time.md)
|
||||
- [Resize Observer](/components/resize-observer.md)
|
||||
- Utilities
|
||||
- [Animated Image](/components/animated-image)
|
||||
- [Animation](/components/animation)
|
||||
- [Format Bytes](/components/format-bytes)
|
||||
- [Format Date](/components/format-date)
|
||||
- [Format Number](/components/format-number)
|
||||
- [Include](/components/include)
|
||||
- [Mutation Observer](/components/mutation-observer)
|
||||
- [Relative Time](/components/relative-time)
|
||||
- [Resize Observer](/components/resize-observer)
|
||||
- [Responsive Media](/components/responsive-media)
|
||||
|
||||
- Design Tokens
|
||||
- [Typography](/tokens/typography.md)
|
||||
- [Color](/tokens/color.md)
|
||||
- [Spacing](/tokens/spacing.md)
|
||||
- [Elevation](/tokens/elevation.md)
|
||||
- [Border Radius](/tokens/border-radius.md)
|
||||
- [Transition](/tokens/transition.md)
|
||||
- [Z-index](/tokens/z-index.md)
|
||||
- [Typography](/tokens/typography)
|
||||
- [Color](/tokens/color)
|
||||
- [Spacing](/tokens/spacing)
|
||||
- [Elevation](/tokens/elevation)
|
||||
- [Border Radius](/tokens/border-radius)
|
||||
- [Transition](/tokens/transition)
|
||||
- [Z-index](/tokens/z-index)
|
||||
|
||||
- Tutorials
|
||||
- [Integrating with Rails](/tutorials/integrating-with-rails.md)
|
||||
- [Integrating with NextJS](/tutorials/integrating-with-nextjs.md)
|
||||
- [Integrating with Laravel](/tutorials/integrating-with-laravel)
|
||||
- [Integrating with NextJS](/tutorials/integrating-with-nextjs)
|
||||
- [Integrating with Rails](/tutorials/integrating-with-rails)
|
||||
|
Before Width: | Height: | Size: 678 KiB After Width: | Height: | Size: 688 KiB |
@@ -1,6 +1,6 @@
|
||||
<svg viewBox="0 0 127 141" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g fill-rule="nonzero" fill="#409eff">
|
||||
<g fill-rule="nonzero" fill="#0ea5e9">
|
||||
<path d="M102.375,90.85 C102.979,90.557 103.57,90.215 104.15,89.826 L106.425,88.501 C106.848,88.19 107.64,87.573 108.8,86.65 L108.95,86.501 C109.883,85.567 110.916,85.117 112.05,85.15 C112.55,85.15 113.133,85.284 113.8,85.55 L122.3,78 C122.533,77.8 122.767,77.633 123,77.5 L123.05,77.5 C123.95,76.967 124.7,77 125.3,77.6 C126.367,78.166 126.45,79.133 125.55,80.5 L116.65,88.399 C116.717,88.533 116.75,88.666 116.75,88.799 C116.883,89.399 116.833,89.999 116.6,90.599 C116.4,90.999 116.117,91.382 115.75,91.749 C115.379,92.145 114.996,92.528 114.6,92.898 L109.45,96.648 C108.99,96.97 108.523,97.27 108.05,97.548 C107.46,97.906 106.86,98.232 106.25,98.523 C105.985,98.644 105.718,98.76 105.45,98.874 C103.841,99.559 102.174,100.017 100.45,100.249 C99.65,106.982 97.35,113.183 93.55,118.849 C88.75,125.915 82.183,131.299 73.85,134.999 C65.55,138.699 56.567,140.549 46.9,140.549 C33.567,140.415 22.75,137.415 14.45,131.549 C4.817,124.75 0,115.7 0,104.399 L0,102.849 C0.333,95.149 2.6,87.849 6.8,80.95 C10.933,74.116 16.983,69.5 24.95,67.1 C29.05,65.9 33.166,65.3 37.3,65.3 C41.567,65.3 45.967,66.083 50.5,67.65 C55.033,69.216 60.15,71.916 65.85,75.75 L80.7,85.7 C84.833,88.399 88.6,90.233 92,91.2 C91.3,84.3 88.8,78.399 84.5,73.5 C80.2,68.533 74.717,64.9 68.05,62.6 L61.65,60.4 C55.783,58.333 51.417,56.3 48.55,54.3 C40.817,49.067 36.517,41.883 35.65,32.75 L35.5,30.05 C35.5,21.25 39.067,13.883 46.2,7.95 C52.567,2.65 60.133,0 68.9,0 C75.5,0 81.417,1.9 86.65,5.7 C91.917,9.533 94.9,14.967 95.6,22 L95.75,24.75 C95.75,29.85 94.433,34.216 91.8,37.85 C89.1,41.483 86.717,43.3 84.65,43.3 C84.21,43.269 83.802,43.21 83.425,43.125 L74.1,51.9 C72.6,52.733 71.583,52.583 71.05,51.45 C70.517,50.85 70.567,50.1 71.2,49.2 L71.25,49.15 C71.383,48.95 71.567,48.733 71.8,48.5 L80.475,40.275 C80.376,39.872 80.318,39.431 80.3,38.95 C80.3,37.817 80.75,36.867 81.65,36.1 C85.45,32.7 87.35,28.784 87.35,24.35 C87.35,19.95 85.683,16.25 82.35,13.25 C79.017,10.25 74.467,8.716 68.7,8.65 C61.5,8.65 55.583,10.817 50.95,15.15 C46.317,19.483 44,24.683 44,30.75 C44,35.65 45.883,40.066 49.65,44 C53.383,47.9 59.15,50.966 66.95,53.2 C77.883,56.367 86.233,61.7 92,69.2 C97.133,75.833 100,83.283 100.6,91.55 C101.199,91.365 101.791,91.132 102.375,90.85 Z M71.95,49.05 C71.95,49.35 72.117,49.5 72.45,49.5 C72.483,49.5 75.117,47.066 80.35,42.2 C80.35,41.533 78.95,42.45 76.15,44.95 C73.35,47.483 71.95,48.85 71.95,49.05 Z M74.15,50.8 C74.15,50.533 74.017,50.4 73.75,50.4 C73.45,50.4 73.183,50.55 72.95,50.85 C72.416,50.817 72.033,50.884 71.8,51.05 C71.7,51.117 71.65,51.183 71.65,51.25 C71.65,51.45 71.783,51.6 72.05,51.7 L72.95,51.7 C73.75,51.4 74.15,51.1 74.15,50.8 Z M80.35,45.35 C80.35,44.583 79.9,44.583 79,45.35 C78.567,45.75 78.017,46.317 77.35,47.05 C77.117,47.217 76.633,47.667 75.9,48.4 C75.133,49.2 74.75,49.683 74.75,49.85 L74.8,50.2 C75,50.267 75.133,50.3 75.2,50.3 C75.233,50.3 76.1,49.5 77.8,47.9 C79.5,46.3 80.35,45.45 80.35,45.35 Z M124.2,78.3 L115.8,85.7 C116.3,85.967 116.667,86.349 116.9,86.849 L125.2,79.45 C125.266,79.116 125.217,78.849 125.05,78.649 C124.883,78.517 124.6,78.399 124.2,78.3 Z M123.75,78.05 L123.55,77.85 L116.15,83.85 L116.6,84.4 L123.75,78.05 Z M91.85,99.899 C89.65,99.333 87.617,98.649 85.75,97.849 C81.55,96.149 76.333,93.183 70.1,88.95 L59.85,82 C55.517,79.233 51.567,77.166 48,75.8 C44.4,74.467 40.867,73.8 37.4,73.8 L35.9,73.8 C27.067,74.267 20.2,77.583 15.3,83.75 C10.734,89.45 8.45,96.184 8.45,103.95 C8.45,112.683 11.95,119.516 18.95,124.45 C25.916,129.416 35.467,131.899 47.6,131.899 C57.133,131.899 65.166,130.2 71.7,126.799 C78.2,123.399 83.25,118.899 86.85,113.299 C89.55,109.033 91.217,104.566 91.85,99.899 Z"></path>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 29 KiB |
BIN
docs/assets/images/tie.webp
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 55 KiB |
@@ -5,7 +5,7 @@
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="undraw-content-team" transform="translate(-3.000000, 0.000000)">
|
||||
<rect id="Rectangle" fill-opacity="0.25" fill="#FFFFFF" x="180" y="16" width="579" height="343" rx="20"></rect>
|
||||
<rect id="Rectangle" fill-opacity="0.25" fill="#fff" x="180" y="16" width="579" height="343" rx="20"></rect>
|
||||
<path d="M840.86295,552.21468 L98.22937,552.21468 C84.4769827,552.21468 73.32847,541.066167 73.32847,527.31378 L73.32847,527.31378 C342.533003,496.02706 606.678133,496.02706 865.76386,527.31378 L865.76386,527.31378 C865.763854,541.066169 854.615339,552.21468 840.86295,552.21468 Z" id="Path" fill="#CCCCCC" fill-rule="nonzero"></path>
|
||||
<path d="M865.76386,528.77851 L73.32847,527.31375 L165.16896,372.78153 L165.60837,372.04915 L165.60837,31.47769 C165.607672,23.1290737 168.923838,15.1221947 174.827202,9.21883153 C180.730565,3.31546831 188.737444,-0.00069762467 197.08606,2.84217094e-14 L737.61198,2.84217094e-14 C745.960596,-0.00069762467 753.967475,3.31546831 759.870838,9.21883153 C765.774202,15.1221947 769.090368,23.1290737 769.08967,31.47769 L769.08967,374.39269 L865.76386,528.77851 Z M196.36834,21.97141 C190.70822,21.9777587 186.121369,26.5646095 186.11502,32.22473 L186.11502,342.75394 C186.121622,348.413956 190.708324,353.000658 196.36834,353.00726 L742.72398,353.00726 C748.383893,353.000411 752.970451,348.413853 752.9773,342.75394 L752.9773,32.22473 C752.970704,26.5647122 748.383998,21.9780061 742.72398,21.97141 L196.36834,21.97141 Z" id="Combined-Shape" fill="#E6E6E6" fill-rule="nonzero"></path>
|
||||
<path d="M199.95903,394.02055 C198.24391,394.023463 196.686317,395.021305 195.9667,396.57816 L167.66779,458.0981 C167.041726,459.458563 167.151668,461.044211 167.959498,462.305253 C168.767328,463.566295 170.161797,464.32907 171.6594,464.3291 L766.77054,464.3291 C768.293506,464.329083 769.707849,463.540407 770.508355,462.244793 C771.308862,460.949179 771.381351,459.331427 770.69993,457.96941 L739.93993,396.44947 C739.199697,394.957483 737.676056,394.015676 736.01054,394.0206 L199.95903,394.02055 Z" id="Path" fill="#CCCCCC" fill-rule="nonzero"></path>
|
||||
@@ -22,7 +22,7 @@
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" transform="translate(480.586874, 208.953401) rotate(-40.261060) translate(-480.586874, -208.953401) " cx="480.586874" cy="208.953401" rx="10.63605" ry="3.98853"></ellipse>
|
||||
<circle id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="457.85318" cy="143.08115" r="14.35864"></circle>
|
||||
<circle id="Oval" fill="#3F3D56" fill-rule="nonzero" cx="451.95181" cy="137.93436" r="4.78622"></circle>
|
||||
<path d="M493.93625,107.65269 C494.56802,92.0991 481.16312,78.92509 463.99545,78.22776 C446.82778,77.53043 432.39853,89.57376 431.76672,105.12736 C431.13491,120.68096 443.06863,124.21482 460.23627,124.91221 C477.40391,125.6096 493.30447,123.20627 493.93625,107.65269 Z" id="Path" fill="#009DFF" fill-rule="nonzero"></path>
|
||||
<path d="M493.93625,107.65269 C494.56802,92.0991 481.16312,78.92509 463.99545,78.22776 C446.82778,77.53043 432.39853,89.57376 431.76672,105.12736 C431.13491,120.68096 443.06863,124.21482 460.23627,124.91221 C477.40391,125.6096 493.30447,123.20627 493.93625,107.65269 Z" id="Path" fill="#0ea5e9" fill-rule="nonzero"></path>
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" transform="translate(422.001785, 145.703659) rotate(-77.089900) translate(-422.001785, -145.703659) " cx="422.001785" cy="145.703659" rx="6.59448" ry="21.00616"></ellipse>
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" transform="translate(504.470422, 159.418119) rotate(-77.089900) translate(-504.470422, -159.418119) " cx="504.470422" cy="159.418119" rx="6.59448" ry="21.00616"></ellipse>
|
||||
<path d="M472.3331,169.91416 C472.9488,173.280144 471.720947,176.718794 469.112518,178.933525 C466.504089,181.148255 462.911834,181.802199 459.690258,180.648779 C456.468682,179.495358 454.107795,176.710012 453.4978,173.34299 L453.49445,173.3245 C452.5527,168.12235 456.57483,166.2815 461.77701,165.33976 C466.97919,164.39802 471.39139,164.71201 472.3331,169.91416 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
@@ -32,7 +32,7 @@
|
||||
<rect id="Rectangle" fill="#2F2E41" fill-rule="nonzero" x="278.92063" y="359.95537" width="13.08374" height="23.44171"></rect>
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" cx="263.65629" cy="383.66967" rx="10.90314" ry="4.08868"></ellipse>
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" cx="289.82377" cy="383.12453" rx="10.90314" ry="4.08868"></ellipse>
|
||||
<path d="M230.60203,286.10434 C227.12455,270.53055 238.2407,254.79388 255.43064,250.9555 C272.62058,247.11712 289.37486,256.63058 292.85233,272.20438 C296.3298,287.77818 284.93742,293.52203 267.74748,297.36038 C250.55754,301.19873 234.07951,301.67812 230.60203,286.10434 Z" id="Path" fill="#009DFF" fill-rule="nonzero"></path>
|
||||
<path d="M230.60203,286.10434 C227.12455,270.53055 238.2407,254.79388 255.43064,250.9555 C272.62058,247.11712 289.37486,256.63058 292.85233,272.20438 C296.3298,287.77818 284.93742,293.52203 267.74748,297.36038 C250.55754,301.19873 234.07951,301.67812 230.60203,286.10434 Z" id="Path" fill="#0ea5e9" fill-rule="nonzero"></path>
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" transform="translate(223.870603, 306.172293) rotate(-64.625740) translate(-223.870603, -306.172293) " cx="223.870603" cy="306.172293" rx="6.76007" ry="21.53368"></ellipse>
|
||||
<circle id="Oval" fill="#2F2E41" fill-rule="nonzero" cx="85.9008" cy="369.76318" r="43.06733"></circle>
|
||||
<rect id="Rectangle" fill="#2F2E41" fill-rule="nonzero" x="66.27519" y="403.56287" width="13.08374" height="23.44171"></rect>
|
||||
@@ -50,10 +50,10 @@
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" cx="88.62657" cy="302.9816" rx="10.90314" ry="4.08868"></ellipse>
|
||||
<circle id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="72.27189" cy="235.10965" r="14.71922"></circle>
|
||||
<circle id="Oval" fill="#3F3D56" fill-rule="nonzero" cx="72.27189" cy="235.10965" r="4.90642"></circle>
|
||||
<path d="M29.40483,205.96134 C25.92735,190.38755 37.0435,174.65088 54.23344,170.8125 C71.42338,166.97412 88.17766,176.48758 91.65513,192.06138 C95.1326,207.63518 83.74022,213.37903 66.55028,217.21738 C49.36034,221.05573 32.88231,221.53519 29.40483,205.96134 Z" id="Path" fill="#009DFF" fill-rule="nonzero"></path>
|
||||
<path d="M29.40483,205.96134 C25.92735,190.38755 37.0435,174.65088 54.23344,170.8125 C71.42338,166.97412 88.17766,176.48758 91.65513,192.06138 C95.1326,207.63518 83.74022,213.37903 66.55028,217.21738 C49.36034,221.05573 32.88231,221.53519 29.40483,205.96134 Z" id="Path" fill="#0ea5e9" fill-rule="nonzero"></path>
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" transform="translate(22.673401, 226.029366) rotate(-64.625740) translate(-22.673401, -226.029366) " cx="22.6734006" cy="226.029366" rx="6.76007" ry="21.53368"></ellipse>
|
||||
<path d="M50.02702,261.54972 C50.02702,265.76487 60.88029,274.08829 72.92357,274.08829 C84.96685,274.08829 96.25871,262.22129 96.25871,258.0062 C96.25871,253.79111 84.96678,258.82395 72.92357,258.82395 C60.88036,258.82395 50.02702,257.33457 50.02702,261.54972 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
<path d="M113.52376,81.56869 C111.867655,81.5704977 110.525568,82.9125851 110.52376,84.56869 L110.52376,208.56869 C110.525568,210.224795 111.867655,211.566882 113.52376,211.56869 L400.52376,211.56869 C402.179865,211.566882 403.521952,210.224795 403.52376,208.56869 L403.52376,84.56869 C403.521952,82.9125851 402.179865,81.5704977 400.52376,81.56869 L113.52376,81.56869 Z" id="Path" fill="#009DFF" fill-rule="nonzero"></path>
|
||||
<path d="M113.52376,81.56869 C111.867655,81.5704977 110.525568,82.9125851 110.52376,84.56869 L110.52376,208.56869 C110.525568,210.224795 111.867655,211.566882 113.52376,211.56869 L400.52376,211.56869 C402.179865,211.566882 403.521952,210.224795 403.52376,208.56869 L403.52376,84.56869 C403.521952,82.9125851 402.179865,81.5704977 400.52376,81.56869 L113.52376,81.56869 Z" id="Path" fill="#0ea5e9" fill-rule="nonzero"></path>
|
||||
<circle id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="191.01816" cy="146.56869" r="29.1211"></circle>
|
||||
<path d="M256.7436,142.69417 C254.884983,142.724723 253.39428,144.240132 253.39428,146.099 C253.39428,147.957868 254.884983,149.473277 256.7436,149.50383 L348.68926,149.50383 C349.906316,149.524778 351.042001,148.894505 351.668119,147.850647 C352.294237,146.806789 352.31556,145.508108 351.72405,144.444258 C351.132539,143.380407 350.018157,142.713189 348.80107,142.69417 C348.763797,142.693537 348.726527,142.693537 348.68926,142.69417 L256.7436,142.69417 Z" id="b71acdfd-6a55-428e-917a-53f192cb0203" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
<path d="M256.7436,122.96697 C254.884983,122.997523 253.39428,124.512932 253.39428,126.3718 C253.39428,128.230668 254.884983,129.746077 256.7436,129.77663 L302.65917,129.77663 C303.876249,129.797613 305.011971,129.167347 305.638111,128.123473 C306.26425,127.0796 306.285572,125.78089 305.694037,124.717025 C305.102503,123.65316 303.988082,122.985951 302.77097,122.96697 C302.733703,122.966337 302.696437,122.966337 302.65917,122.96697 L256.7436,122.96697 Z" id="ad4fbcfa-41b0-45f9-a593-23b6dc3fe165" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
@@ -67,7 +67,7 @@
|
||||
<circle id="Oval" fill="#3F3D56" fill-rule="nonzero" cx="725.31949" cy="403.22896" r="4.90642"></circle>
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" transform="translate(771.918005, 384.148727) rotate(-53.549900) translate(-771.918005, -384.148727) " cx="771.918005" cy="384.148727" rx="21.53368" ry="6.76007"></ellipse>
|
||||
<path d="M705.39698,436.33866 C705.39698,432.86466 714.34198,426.00466 724.26778,426.00466 C734.19358,426.00466 743.50006,435.78516 743.50006,439.25914 C743.50006,442.73312 734.19351,438.58514 724.26778,438.58514 C714.34205,438.58514 705.39698,439.81268 705.39698,436.33866 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero" transform="translate(724.448520, 433.325266) rotate(-180.000000) translate(-724.448520, -433.325266) "></path>
|
||||
<path d="M847.1767,378.54172 L611.43117,345.86064 C607.604361,345.32541 604.932725,341.793834 605.45868,337.96574 L631.96057,146.79396 C632.495641,142.967058 636.027329,140.295337 639.85547,140.82147 L875.60098,173.50256 C879.427885,174.037626 882.099609,177.569318 881.57347,181.39746 L855.0716,372.56924 C854.536375,376.396051 851.004794,379.067687 847.1767,378.54172 L847.1767,378.54172 Z" id="Path" fill="#009DFF" fill-rule="nonzero"></path>
|
||||
<path d="M847.1767,378.54172 L611.43117,345.86064 C607.604361,345.32541 604.932725,341.793834 605.45868,337.96574 L631.96057,146.79396 C632.495641,142.967058 636.027329,140.295337 639.85547,140.82147 L875.60098,173.50256 C879.427885,174.037626 882.099609,177.569318 881.57347,181.39746 L855.0716,372.56924 C854.536375,376.396051 851.004794,379.067687 847.1767,378.54172 L847.1767,378.54172 Z" id="Path" fill="#0ea5e9" fill-rule="nonzero"></path>
|
||||
<path d="M762.72231,318.87957 L642.36784,302.19498 C642.216871,302.176045 642.067969,302.14324 641.92302,302.09698 L712.51355,211.39072 C713.394132,210.238632 714.82651,209.649483 716.262854,209.8486 C717.699198,210.047717 718.917295,211.004295 719.45127,212.35248 L748.48059,283.8148 L749.87186,287.23459 L762.72231,318.87957 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
<polygon id="Path" fill="#000000" fill-rule="nonzero" opacity="0.2" points="762.722 318.879 721.63 313.183 745.864 286.679 747.609 284.77 748.481 283.815 749.872 287.235"></polygon>
|
||||
<path d="M829.73481,328.16942 L725.63807,313.73863 L749.87186,287.23463 L751.61612,285.32515 L783.19533,250.78503 C784.29885,249.735613 785.796059,249.204111 787.314261,249.322828 C788.832463,249.441546 790.228856,250.199316 791.15584,251.40751 C791.271244,251.575507 791.375823,251.750689 791.46894,251.93199 L829.73481,328.16942 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
@@ -77,4 +77,4 @@
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" transform="translate(735.010556, 473.249892) rotate(-4.181640) translate(-735.010556, -473.249892) " cx="735.010556" cy="473.249892" rx="10.90314" ry="4.08868"></ellipse>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
1
docs/assets/images/undraw-not-found.svg
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
docs/assets/images/walk.gif
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@@ -1,17 +1,17 @@
|
||||
.code-block {
|
||||
position: relative;
|
||||
border-radius: 3px;
|
||||
background: var(--sl-color-gray-50);
|
||||
background-color: rgb(var(--sl-color-neutral-50));
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.code-block__preview {
|
||||
position: relative;
|
||||
border: solid 1px var(--sl-color-gray-200);
|
||||
border: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
border-bottom: none;
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
background-color: white;
|
||||
background-color: rgb(var(--sl-color-neutral-0));
|
||||
min-width: 20rem;
|
||||
max-width: 100%;
|
||||
padding: 1.5rem 3.25rem 1.5rem 1.5rem;
|
||||
@@ -39,22 +39,14 @@
|
||||
bottom: 0;
|
||||
width: 1.75rem;
|
||||
font-size: 20px;
|
||||
color: var(--sl-color-gray-500);
|
||||
background-color: white;
|
||||
border-left: solid 1px var(--sl-color-gray-200);
|
||||
color: rgb(var(--sl-color-neutral-600));
|
||||
background-color: rgb(var(--sl-color-neutral-0));
|
||||
border-left: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
border-top-right-radius: 3px;
|
||||
cursor: ew-resize;
|
||||
transition: 250ms background-color;
|
||||
}
|
||||
|
||||
.code-block__resizer:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 1px var(--sl-color-primary-400), 0 0 0 var(--sl-focus-ring-width) var(--sl-focus-ring-color-primary);
|
||||
background-color: var(--sl-color-primary-50);
|
||||
color: var(--sl-color-primary-500);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.code-block__preview {
|
||||
padding-right: 1.5rem;
|
||||
@@ -66,102 +58,146 @@
|
||||
}
|
||||
|
||||
.code-block__source {
|
||||
border: solid 1px var(--sl-color-gray-200);
|
||||
border: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
border-bottom: none;
|
||||
border-radius: 0 !important;
|
||||
margin: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.code-block__source .docsify-copy-code-button {
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.code-block--expanded .code-block__source {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.code-block__buttons {
|
||||
position: relative;
|
||||
border: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.code-block__button {
|
||||
flex: 0 0 auto;
|
||||
height: 2.5rem;
|
||||
min-width: 2.5rem;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: rgb(var(--sl-color-neutral-0));
|
||||
font: inherit;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
color: rgb(var(--sl-color-neutral-600));
|
||||
padding: 0 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.code-block__button:not(:last-of-type) {
|
||||
border-right: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
}
|
||||
|
||||
.code-block__button--codepen {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
.code-block__button:first-of-type {
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
|
||||
.code-block__button:last-of-type {
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
|
||||
.code-block__button:hover,
|
||||
.code-block__button:active {
|
||||
box-shadow: 0 0 0 1px rgb(var(--sl-color-primary-400));
|
||||
border-right-color: transparent;
|
||||
background-color: rgb(var(--sl-color-primary-50));
|
||||
color: rgb(var(--sl-color-primary-700));
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.code-block__button:focus-visible {
|
||||
outline: none;
|
||||
color: rgb(var(--sl-color-primary-600));
|
||||
border-color: rgb(var(--sl-color-primary-400));
|
||||
border-right-color: transparent;
|
||||
background-color: rgb(var(--sl-color-primary-50));
|
||||
box-shadow: 0 0 0 1px rgb(var(--sl-color-primary-400)), var(--sl-focus-ring);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.code-block__toggle {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 2.5rem;
|
||||
border: solid 1px var(--sl-color-gray-200);
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
background: var(--sl-color-white);
|
||||
font: inherit;
|
||||
font-size: 0.875rem;
|
||||
color: var(--sl-color-gray-600);
|
||||
color: rgb(var(--sl-color-neutral-600));
|
||||
cursor: pointer;
|
||||
transition: 250ms background-color;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.code-block__toggle:hover,
|
||||
.code-block__toggle:active {
|
||||
border-color: var(--sl-color-primary-400);
|
||||
background-color: var(--sl-color-primary-50);
|
||||
color: var(--sl-color-primary-500);
|
||||
}
|
||||
|
||||
.code-block__toggle:focus {
|
||||
outline: none;
|
||||
border-color: var(--sl-color-primary-400);
|
||||
background-color: var(--sl-color-primary-50);
|
||||
color: var(--sl-color-primary-500);
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-focus-ring-color-primary);
|
||||
}
|
||||
|
||||
.code-block__toggle svg {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
margin-left: 0.25rem;
|
||||
transition: 250ms transform;
|
||||
}
|
||||
|
||||
.code-block--expanded .code-block__toggle svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* Dark theme */
|
||||
.sl-theme-dark .code-block {
|
||||
background-color: var(--sl-color-gray-800);
|
||||
/* Copy button styles */
|
||||
.markdown-section .docsify-copy-code-button {
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
background-color: rgb(var(--sl-color-neutral-600));
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
font-family: var(--sl-font-sans);
|
||||
font-size: var(--sl-font-size-x-small);
|
||||
font-weight: var(--sl-font-weight-semibold);
|
||||
text-transform: uppercase;
|
||||
padding: 8px;
|
||||
user-select: none;
|
||||
transition: 0.1s all;
|
||||
}
|
||||
|
||||
.sl-theme-dark .code-block__preview {
|
||||
background-color: var(--sl-color-gray-900);
|
||||
border-color: var(--sl-color-gray-800);
|
||||
.markdown-section .docsify-copy-code-button.copied {
|
||||
animation: pulse 0.75s;
|
||||
--pulse-color: rgb(var(--sl-color-neutral-600));
|
||||
}
|
||||
|
||||
.sl-theme-dark .code-block__source {
|
||||
border-color: var(--sl-color-gray-800);
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 var(--pulse-color);
|
||||
}
|
||||
70% {
|
||||
box-shadow: 0 0 0 0.5rem transparent;
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.sl-theme-dark .code-block__resizer {
|
||||
border-left-color: var(--sl-color-gray-800);
|
||||
background-color: var(--sl-color-gray-900);
|
||||
color: var(--sl-color-gray-400);
|
||||
.markdown-section .docsify-copy-code-button .label {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.sl-theme-dark .code-block__toggle {
|
||||
background-color: var(--sl-color-gray-900);
|
||||
border-color: var(--sl-color-gray-800);
|
||||
color: var(--sl-color-gray-400);
|
||||
.markdown-section .docsify-copy-code-button .success,
|
||||
.markdown-section .docsify-copy-code-button .error {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sl-theme-dark .code-block__toggle:hover,
|
||||
.sl-theme-dark .code-block__toggle:active {
|
||||
background-color: var(--sl-color-gray-900);
|
||||
border-color: var(--sl-color-gray-800);
|
||||
color: var(--sl-color-gray-400);
|
||||
.markdown-section .docsify-copy-code-button:focus-visible {
|
||||
box-shadow: 0 0 0 3px rgb(var(--sl-color-neutral-500) / 50%);
|
||||
}
|
||||
|
||||
.sl-theme-dark .code-block__toggle:focus {
|
||||
border-color: var(--sl-color-primary-500);
|
||||
background-color: var(--sl-color-primary-900);
|
||||
color: var(--sl-color-primary-500);
|
||||
.markdown-section .docsify-copy-code-button:active {
|
||||
background-color: rgb(var(--sl-color-neutral-600));
|
||||
transform: scale(0.92);
|
||||
}
|
||||
|
||||
@@ -28,58 +28,66 @@
|
||||
hook.afterEach(function (html, next) {
|
||||
const domParser = new DOMParser();
|
||||
const doc = domParser.parseFromString(html, 'text/html');
|
||||
const codePenButton = `
|
||||
<button type="button" class="code-block__button code-block__button--codepen" title="Edit on CodePen">
|
||||
<svg
|
||||
width="138"
|
||||
height="26"
|
||||
viewBox="0 0 138 26"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2.3"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M80 6h-9v14h9 M114 6h-9 v14h9 M111 13h-6 M77 13h-6 M122 20V6l11 14V6 M22 16.7L33 24l11-7.3V9.3L33 2L22 9.3V16.7z M44 16.7L33 9.3l-11 7.4 M22 9.3l11 7.3 l11-7.3 M33 2v7.3 M33 16.7V24 M88 14h6c2.2 0 4-1.8 4-4s-1.8-4-4-4h-6v14 M15 8c-1.3-1.3-3-2-5-2c-4 0-7 3-7 7s3 7 7 7 c2 0 3.7-0.8 5-2 M64 13c0 4-3 7-7 7h-5V6h5C61 6 64 9 64 13z" />
|
||||
</svg>
|
||||
</button>
|
||||
`;
|
||||
|
||||
[...doc.querySelectorAll('code[class^="lang-"]')].map(code => {
|
||||
if (code.classList.contains('preview')) {
|
||||
const codeBlock = document.createElement('div');
|
||||
const preview = document.createElement('div');
|
||||
const pre = code.closest('pre');
|
||||
const preId = `code-block-preview-${count}`;
|
||||
const toggle = document.createElement('button');
|
||||
const toggleId = `code-block-toggle-${count}`;
|
||||
|
||||
wrap(pre, codeBlock);
|
||||
|
||||
codeBlock.classList.add('code-block');
|
||||
|
||||
preview.classList.add('code-block__preview');
|
||||
preview.innerHTML = code.textContent;
|
||||
preview.innerHTML += `
|
||||
<div
|
||||
class="code-block__resizer"
|
||||
tabindex="0"
|
||||
>
|
||||
<sl-icon name="grip-vertical"></sl-icon>
|
||||
</div>
|
||||
`;
|
||||
|
||||
pre.id = preId;
|
||||
pre.classList.add('code-block__source');
|
||||
pre.setAttribute('data-lang', pre.getAttribute('data-lang').replace(/ preview$/, ''));
|
||||
pre.setAttribute('aria-labelledby', toggleId);
|
||||
|
||||
toggle.id = toggleId;
|
||||
toggle.type = 'button';
|
||||
toggle.classList.add('code-block__toggle');
|
||||
toggle.setAttribute('aria-expanded', 'false');
|
||||
toggle.setAttribute('aria-controls', preId);
|
||||
toggle.innerHTML = `
|
||||
Source
|
||||
const codeBlock = `
|
||||
<div class="code-block">
|
||||
<div class="code-block__preview">
|
||||
${code.textContent}
|
||||
<div class="code-block__resizer">
|
||||
<sl-icon name="grip-vertical"></sl-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
${pre.outerHTML}
|
||||
|
||||
<div class="code-block__buttons">
|
||||
<button type="button" class="code-block__button code-block__toggle" aria-expanded="false" aria-controls="${preId}">
|
||||
View Source
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
${!code.classList.contains('no-codepen') ? codePenButton : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
codeBlock.prepend(preview);
|
||||
codeBlock.append(toggle);
|
||||
pre.replaceWith(domParser.parseFromString(codeBlock, 'text/html').body);
|
||||
|
||||
count++;
|
||||
}
|
||||
@@ -105,7 +113,6 @@
|
||||
startWidth = parseInt(document.defaultView.getComputedStyle(preview).width, 10);
|
||||
preview.classList.add('code-block__preview--dragging');
|
||||
event.preventDefault();
|
||||
resizer.focus();
|
||||
document.documentElement.addEventListener('mousemove', dragMove, false);
|
||||
document.documentElement.addEventListener('touchmove', dragMove, false);
|
||||
document.documentElement.addEventListener('mouseup', dragStop, false);
|
||||
@@ -124,30 +131,59 @@
|
||||
document.documentElement.removeEventListener('touchend', dragStop, false);
|
||||
};
|
||||
|
||||
const handleKeyDown = event => {
|
||||
if (['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) {
|
||||
const currentWidth = preview.clientWidth;
|
||||
const maxWidth = preview.parentElement.clientWidth;
|
||||
const incr = event.shiftKey ? 100 : 10;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (event.key === 'ArrowLeft') setWidth(currentWidth - incr);
|
||||
if (event.key === 'ArrowRight') setWidth(currentWidth + incr);
|
||||
if (event.key === 'Home') setWidth(0);
|
||||
if (event.key === 'End') setWidth(maxWidth);
|
||||
}
|
||||
};
|
||||
|
||||
const setWidth = width => (preview.style.width = width + 'px');
|
||||
|
||||
resizer.addEventListener('mousedown', dragStart);
|
||||
resizer.addEventListener('touchstart', dragStart);
|
||||
resizer.addEventListener('keydown', handleKeyDown);
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
// Open in CodePen
|
||||
document.addEventListener('click', event => {
|
||||
const button = event.target.closest('button');
|
||||
|
||||
if (button?.classList.contains('code-block__button--codepen')) {
|
||||
const codeBlock = button.closest('.code-block');
|
||||
const html = codeBlock.querySelector('.code-block__source > code').textContent;
|
||||
const version = sessionStorage.getItem('sl-version');
|
||||
|
||||
const form = document.createElement('form');
|
||||
form.action = 'https://codepen.io/pen/define';
|
||||
form.method = 'POST';
|
||||
form.target = '_blank';
|
||||
|
||||
// Docs: https://blog.codepen.io/documentation/prefill/
|
||||
const data = {
|
||||
title: '',
|
||||
description: '',
|
||||
tags: ['shoelace', 'web components'],
|
||||
editors: '100',
|
||||
head: `<meta name="viewport" content="width=device-width">`,
|
||||
css_external: ``,
|
||||
js_external: ``,
|
||||
js_module: true,
|
||||
html:
|
||||
`<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${version}/dist/themes/light.css">\n` +
|
||||
`<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${version}/dist/shoelace.js"></script>\n` +
|
||||
`\n` +
|
||||
html,
|
||||
css: `body {\n font: 16px sans-serif;\n}`,
|
||||
js: ``
|
||||
};
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'data';
|
||||
input.value = JSON.stringify(data);
|
||||
form.append(input);
|
||||
|
||||
document.body.append(form);
|
||||
form.submit();
|
||||
form.remove();
|
||||
}
|
||||
});
|
||||
|
||||
// Expand and collapse code blocks
|
||||
document.addEventListener('click', event => {
|
||||
const toggle = event.target.closest('.code-block__toggle');
|
||||
@@ -157,4 +193,16 @@
|
||||
event.target.setAttribute('aria-expanded', codeBlock.classList.contains('code-block--expanded'));
|
||||
}
|
||||
});
|
||||
|
||||
// Show pulse when copying
|
||||
document.addEventListener('click', event => {
|
||||
const button = event.target.closest('.docsify-copy-code-button');
|
||||
if (button) {
|
||||
button.classList.remove('copied');
|
||||
requestAnimationFrame(() => {
|
||||
button.addEventListener('animationend', () => button.classList.remove('copied'), { once: true });
|
||||
button.classList.add('copied');
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
(() => {
|
||||
let metadataStore;
|
||||
|
||||
function getAttrName(propName) {
|
||||
return propName.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`).replace(/^-/, '');
|
||||
}
|
||||
const isDev = location.hostname === 'localhost';
|
||||
const isNext = location.hostname === 'next.shoelace.style';
|
||||
const customElements = fetch('/dist/custom-elements.json')
|
||||
.then(res => res.json())
|
||||
.catch(err => console.error(err));
|
||||
|
||||
function createPropsTable(props) {
|
||||
const table = document.createElement('table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Property</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Reflects</th>
|
||||
<th>Type</th>
|
||||
<th>Default</th>
|
||||
</tr>
|
||||
@@ -19,28 +20,40 @@
|
||||
<tbody>
|
||||
${props
|
||||
.map(prop => {
|
||||
const attr = getAttrName(prop.name);
|
||||
const hasAttribute = !!prop.attribute;
|
||||
const isAttributeDifferent = prop.attribute !== prop.name;
|
||||
let attributeInfo = '';
|
||||
|
||||
if (!hasAttribute) {
|
||||
attributeInfo = `<br><small>(property only)</small>`;
|
||||
} else if (isAttributeDifferent) {
|
||||
attributeInfo = `
|
||||
<br>
|
||||
<sl-tooltip content="This attribute is different than the property">
|
||||
<small>
|
||||
<code class="nowrap">
|
||||
${escapeHtml(prop.attribute)}
|
||||
</code>
|
||||
</small>
|
||||
</sl-tooltip>`;
|
||||
}
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>
|
||||
<code>${escapeHtml(prop.name)}</code>
|
||||
${
|
||||
prop.name !== attr
|
||||
? `
|
||||
<br>
|
||||
<small>
|
||||
<sl-tooltip content="This is the attribute name">
|
||||
<code class="attribute-tooltip">${escapeHtml(attr)}</code>
|
||||
</sl-tooltip>
|
||||
</small>`
|
||||
: ''
|
||||
}
|
||||
<code class="nowrap">${escapeHtml(prop.name)}</code>
|
||||
${attributeInfo}
|
||||
</td>
|
||||
<td>${escapeHtml(prop.description)}</td>
|
||||
<td><code style="white-space: normal;">${escapeHtml(prop.type)}</code></td>
|
||||
<td><code style="white-space: normal;">${escapeHtml(prop.defaultValue)}</code></td>
|
||||
<td>
|
||||
${escapeHtml(prop.description)}
|
||||
</td>
|
||||
<td style="text-align: center;">${
|
||||
prop.reflects ? '<sl-icon label="yes" name="check"></sl-icon>' : ''
|
||||
}</td>
|
||||
<td>${prop.type?.text ? `<code>${escapeHtml(prop.type?.text || '')}</code>` : '-'}</td>
|
||||
<td>${prop.default ? `<code>${escapeHtml(prop.default)}</code>` : '-'}</td>
|
||||
</tr>
|
||||
`;
|
||||
`;
|
||||
})
|
||||
.join('')}
|
||||
</tbody>
|
||||
@@ -54,19 +67,21 @@
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Event</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Event Detail</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${events
|
||||
.map(
|
||||
event => `
|
||||
<tr>
|
||||
<td><code>${escapeHtml(event.name)}</code></td>
|
||||
<td>${escapeHtml(event.description)}</td>
|
||||
</tr>
|
||||
`
|
||||
<tr>
|
||||
<td><code class="nowrap">${escapeHtml(event.name)}</code></td>
|
||||
<td>${escapeHtml(event.description)}</td>
|
||||
<td>${event.type?.text ? `<code>${escapeHtml(event.type?.text)}` : '-'}</td>
|
||||
</tr>
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
</tbody>
|
||||
@@ -80,7 +95,7 @@
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Arguments</th>
|
||||
</tr>
|
||||
@@ -90,17 +105,17 @@
|
||||
.map(
|
||||
method => `
|
||||
<tr>
|
||||
<td><code>${escapeHtml(method.name)}</code></td>
|
||||
<td class="nowrap"><code>${escapeHtml(method.name)}</code></td>
|
||||
<td>${escapeHtml(method.description)}</td>
|
||||
<td>
|
||||
${
|
||||
method.params.length
|
||||
method.parameters?.length
|
||||
? `
|
||||
<code style="white-space: normal;">${escapeHtml(
|
||||
method.params.map(param => `${param.name}: ${param.type}`).join(', ')
|
||||
<code>${escapeHtml(
|
||||
method.parameters.map(param => `${param.name}: ${param.type.text}`).join(', ')
|
||||
)}</code>
|
||||
`
|
||||
: ''
|
||||
: '-'
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -118,7 +133,7 @@
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Slot</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -126,11 +141,11 @@
|
||||
${slots
|
||||
.map(
|
||||
slot => `
|
||||
<tr>
|
||||
<td><code>${slot.name ? escapeHtml(slot.name) : '(default)'}</code></td>
|
||||
<td>${escapeHtml(slot.description)}</td>
|
||||
</tr>
|
||||
`
|
||||
<tr>
|
||||
<td class="nowrap">${slot.name ? `<code>${escapeHtml(slot.name)}</code>` : '(default)'}</td>
|
||||
<td>${escapeHtml(slot.description)}</td>
|
||||
</tr>
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
</tbody>
|
||||
@@ -152,11 +167,11 @@
|
||||
${styles
|
||||
.map(
|
||||
style => `
|
||||
<tr>
|
||||
<td><code>${escapeHtml(style.name)}</code></td>
|
||||
<td>${escapeHtml(style.description)}</td>
|
||||
</tr>
|
||||
`
|
||||
<tr>
|
||||
<td><code>${escapeHtml(style.name)}</code></td>
|
||||
<td>${escapeHtml(style.description)}</td>
|
||||
</tr>
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
</tbody>
|
||||
@@ -178,11 +193,37 @@
|
||||
${parts
|
||||
.map(
|
||||
part => `
|
||||
<tr>
|
||||
<td class="nowrap"><code>${escapeHtml(part.name)}</code></td>
|
||||
<td>${escapeHtml(part.description)}</td>
|
||||
</tr>
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
</tbody>
|
||||
`;
|
||||
|
||||
return table.outerHTML;
|
||||
}
|
||||
|
||||
function createAnimationsTable(animations) {
|
||||
const table = document.createElement('table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<td><code>${escapeHtml(part.name)}</code></td>
|
||||
<td>${escapeHtml(part.description)}</td>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
`
|
||||
</thead>
|
||||
<tbody>
|
||||
${animations
|
||||
.map(
|
||||
animation => `
|
||||
<tr>
|
||||
<td class="nowrap"><code>${escapeHtml(animation.name)}</code></td>
|
||||
<td>${escapeHtml(animation.description)}</td>
|
||||
</tr>
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
</tbody>
|
||||
@@ -197,12 +238,12 @@
|
||||
|
||||
// Recursively fetch subdependencies
|
||||
function getDependencies(tag) {
|
||||
const component = allComponents.find(c => c.tag === tag);
|
||||
if (!component && !Array.isArray(component.dependencies)) {
|
||||
const component = allComponents.find(c => c.tagName === tag);
|
||||
if (!component || !Array.isArray(component.dependencies)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
component.dependencies.map(tag => {
|
||||
component.dependencies?.map(tag => {
|
||||
if (!dependencies.includes(tag)) {
|
||||
dependencies.push(tag);
|
||||
}
|
||||
@@ -230,21 +271,24 @@
|
||||
.replace(/`(.*?)`/g, '<code>$1</code>');
|
||||
}
|
||||
|
||||
function getMetadata() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Simple caching to prevent multiple XHR requests
|
||||
if (metadataStore) {
|
||||
return resolve(metadataStore);
|
||||
}
|
||||
function getAllComponents(metadata) {
|
||||
const allComponents = [];
|
||||
metadata.modules?.map(module => {
|
||||
module.declarations?.map(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');
|
||||
|
||||
fetch('/dist/components.json')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
metadataStore = data;
|
||||
resolve(metadataStore);
|
||||
})
|
||||
.catch(err => console.error(err));
|
||||
allComponents.push(declaration);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return allComponents;
|
||||
}
|
||||
|
||||
function getComponent(metadata, tagName) {
|
||||
return getAllComponents(metadata).find(component => component.tagName === tagName);
|
||||
}
|
||||
|
||||
if (!window.$docsify) {
|
||||
@@ -252,64 +296,66 @@
|
||||
}
|
||||
|
||||
window.$docsify.plugins.push((hook, vm) => {
|
||||
hook.mounted(function () {
|
||||
getMetadata().then(metadata => {
|
||||
const target = document.querySelector('.app-name');
|
||||
hook.mounted(async function () {
|
||||
const metadata = await customElements;
|
||||
const target = document.querySelector('.app-name');
|
||||
|
||||
// Add version
|
||||
const version = document.createElement('div');
|
||||
version.classList.add('sidebar-version');
|
||||
version.textContent = metadata.version;
|
||||
target.appendChild(version);
|
||||
// Add version
|
||||
const version = document.createElement('div');
|
||||
version.classList.add('sidebar-version');
|
||||
version.textContent = isDev ? 'Development' : isNext ? 'Next' : metadata.package.version;
|
||||
target.appendChild(version);
|
||||
|
||||
// Add repo buttons
|
||||
const buttons = document.createElement('div');
|
||||
buttons.classList.add('sidebar-buttons');
|
||||
buttons.innerHTML = `
|
||||
<a class="repo-button repo-button--small repo-button--sponsor" href="https://github.com/sponsors/claviska" rel="noopener" target="_blank">
|
||||
<sl-icon name="heart"></sl-icon> Sponsor
|
||||
</a>
|
||||
<a class="repo-button repo-button--small repo-button--github" href="https://github.com/shoelace-style/shoelace/stargazers" rel="noopener" target="_blank">
|
||||
<sl-icon name="github"></sl-icon> <span class="github-star-count">Star</span>
|
||||
</a>
|
||||
<a class="repo-button repo-button--small repo-button--twitter" href="https://twitter.com/shoelace_style" rel="noopener" target="_blank">
|
||||
<sl-icon name="twitter"></sl-icon> Follow
|
||||
</a>
|
||||
`;
|
||||
target.appendChild(buttons);
|
||||
});
|
||||
// Store version for reuse
|
||||
sessionStorage.setItem('sl-version', metadata.package.version);
|
||||
|
||||
// Add repo buttons
|
||||
const buttons = document.createElement('div');
|
||||
buttons.classList.add('sidebar-buttons');
|
||||
buttons.innerHTML = `
|
||||
<sl-button size="small" class="repo-button repo-button--sponsor" href="https://github.com/sponsors/claviska" target="_blank">
|
||||
<sl-icon name="heart"></sl-icon> Sponsor
|
||||
</sl-button>
|
||||
<sl-button size="small" class="repo-button repo-button--github" href="https://github.com/shoelace-style/shoelace/stargazers" target="_blank">
|
||||
<sl-icon name="github"></sl-icon> <span class="github-star-count">Star</span>
|
||||
</sl-button>
|
||||
<sl-button size="small" class="repo-button repo-button--twitter" href="https://twitter.com/shoelace_style" target="_blank">
|
||||
<sl-icon name="twitter"></sl-icon> Follow
|
||||
</sl-button>
|
||||
`;
|
||||
target.appendChild(buttons);
|
||||
});
|
||||
|
||||
hook.beforeEach(async function (content, next) {
|
||||
const metadata = await getMetadata();
|
||||
const metadata = await customElements;
|
||||
|
||||
// Replace %VERSION% placeholders
|
||||
content = content.replace(/%VERSION%/g, metadata.version);
|
||||
content = content.replace(/%VERSION%/g, metadata.package.version);
|
||||
|
||||
// Handle [component-header] tags
|
||||
content = content.replace(/\[component-header:([a-z-]+)\]/g, (match, tag) => {
|
||||
const component = metadata.components.filter(data => data.tag === tag)[0];
|
||||
const component = getComponent(metadata, tag);
|
||||
let result = '';
|
||||
|
||||
if (!component) {
|
||||
console.error('Component not found in metadata: ' + tag);
|
||||
next(content);
|
||||
return next(content);
|
||||
}
|
||||
|
||||
let badgeType = 'info';
|
||||
let badgeType = 'neutral';
|
||||
if (component.status === 'stable') badgeType = 'primary';
|
||||
if (component.status === 'experimental') badgeType = 'warning';
|
||||
if (component.status === 'planned') badgeType = 'info';
|
||||
if (component.status === 'planned') badgeType = 'neutral';
|
||||
if (component.status === 'deprecated') badgeType = 'danger';
|
||||
|
||||
result += `
|
||||
<div class="component-header">
|
||||
<div class="component-header__tag">
|
||||
<code>${component.className} | <${component.tag}></code>
|
||||
<code><${component.tagName}> | ${component.name}</code>
|
||||
</div>
|
||||
|
||||
<div class="component-header__info">
|
||||
<sl-badge type="info" pill>
|
||||
<sl-badge type="neutral" pill>
|
||||
Since ${component.since || '?'}
|
||||
</sl-badge>
|
||||
|
||||
@@ -325,64 +371,120 @@
|
||||
|
||||
// Handle [component-metadata] tags
|
||||
content = content.replace(/\[component-metadata:([a-z-]+)\]/g, (match, tag) => {
|
||||
const component = metadata.components.filter(data => data.tag === tag)[0];
|
||||
const component = getComponent(metadata, tag);
|
||||
let result = '';
|
||||
|
||||
if (!component) {
|
||||
console.error('Component not found in metadata: ' + tag);
|
||||
next(content);
|
||||
return next(content);
|
||||
}
|
||||
|
||||
if (component.props.length) {
|
||||
// Remove members that are private or don't have a description
|
||||
const members = component.members?.filter(member => member.description && member.privacy !== 'private');
|
||||
const methods = members?.filter(prop => prop.kind === 'method' && prop.privacy !== 'private');
|
||||
const props = members?.filter(prop => {
|
||||
// Look for a corresponding attribute
|
||||
const attribute = component.attributes?.find(attr => attr.fieldName === prop.name);
|
||||
if (attribute) {
|
||||
prop.attribute = attribute.name || attribute.fieldName;
|
||||
}
|
||||
|
||||
return prop.kind === 'field' && prop.privacy !== 'private';
|
||||
});
|
||||
|
||||
if (props?.length) {
|
||||
result += `
|
||||
## Properties
|
||||
${createPropsTable(component.props)}
|
||||
${createPropsTable(props)}
|
||||
`;
|
||||
}
|
||||
|
||||
if (component.events.length) {
|
||||
if (component.events?.length) {
|
||||
result += `
|
||||
## Events
|
||||
${createEventsTable(component.events)}
|
||||
`;
|
||||
}
|
||||
|
||||
if (component.methods.length) {
|
||||
if (methods?.length) {
|
||||
result += `
|
||||
## Methods
|
||||
${createMethodsTable(component.methods)}
|
||||
## Methods
|
||||
${createMethodsTable(methods)}
|
||||
`;
|
||||
}
|
||||
|
||||
if (component.slots.length) {
|
||||
if (component.slots?.length) {
|
||||
result += `
|
||||
## Slots
|
||||
${createSlotsTable(component.slots)}
|
||||
`;
|
||||
}
|
||||
|
||||
if (component.cssCustomProperties.length) {
|
||||
if (component.cssProperties?.length) {
|
||||
result += `
|
||||
## CSS Custom Properties
|
||||
${createCustomPropertiesTable(component.cssCustomProperties)}
|
||||
${createCustomPropertiesTable(component.cssProperties)}
|
||||
`;
|
||||
}
|
||||
|
||||
if (component.parts.length) {
|
||||
if (component.cssParts?.length) {
|
||||
result += `
|
||||
## CSS Parts
|
||||
${createPartsTable(component.parts)}
|
||||
${createPartsTable(component.cssParts)}
|
||||
`;
|
||||
}
|
||||
|
||||
if (component.dependencies.length) {
|
||||
if (component.animations?.length) {
|
||||
result += `
|
||||
## Animations
|
||||
${createAnimationsTable(component.animations)}
|
||||
|
||||
Learn how to [customize animations](/getting-started/customizing#animations).
|
||||
`;
|
||||
}
|
||||
|
||||
if (component.dependencies?.length) {
|
||||
result += `
|
||||
## Dependencies
|
||||
|
||||
This component has the following dependencies so, if you're [cherry picking](/getting-started/installation#cherry-picking),
|
||||
be sure to import these components in addition to <code><${tag}></code>.
|
||||
This component imports the following dependencies.
|
||||
|
||||
${createDependenciesList(component.tag, metadata.components)}
|
||||
${createDependenciesList(component.tagName, getAllComponents(metadata))}
|
||||
`;
|
||||
}
|
||||
|
||||
if (component.path) {
|
||||
/* prettier-ignore */
|
||||
result += `
|
||||
## Importing
|
||||
|
||||
<sl-tab-group>
|
||||
<sl-tab slot="nav" panel="cdn" active>CDN</sl-tab>
|
||||
<sl-tab slot="nav" panel="bundler">Bundler</sl-tab>
|
||||
<sl-tab slot="nav" panel="react">React</sl-tab>
|
||||
|
||||
<sl-tab-panel name="cdn">\n
|
||||
To import this component from [the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace):
|
||||
|
||||
\`\`\`js
|
||||
import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${metadata.package.version}/${component.path}';
|
||||
\`\`\`
|
||||
</sl-tab-panel>
|
||||
|
||||
<sl-tab-panel name="bundler">\n
|
||||
To import this component using [a bundler](/getting-started/installation#bundling):
|
||||
\`\`\`js
|
||||
import '@shoelace-style/shoelace/${component.path}';
|
||||
\`\`\`
|
||||
</sl-tab-panel>
|
||||
|
||||
<sl-tab-panel name="react">\n
|
||||
To import this component using [\`@shoelace-style/react\`](https://www.npmjs.com/package/@shoelace-style/react):
|
||||
\`\`\`js
|
||||
import '@shoelace-style/react/dist/${component.tagName.replace(/^sl-/, '')}';
|
||||
\`\`\`
|
||||
</sl-tab-panel>
|
||||
</sl-tab-group>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -392,5 +494,19 @@
|
||||
|
||||
next(content);
|
||||
});
|
||||
|
||||
// Wrap tables so we can scroll them horizontally when needed
|
||||
hook.doneEach(function () {
|
||||
const content = document.querySelector('.content');
|
||||
const tables = [...content.querySelectorAll('table')];
|
||||
|
||||
tables.map(table => {
|
||||
table.outerHTML = `
|
||||
<div class="table-wrapper">
|
||||
${table.outerHTML}
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
1310
docs/assets/plugins/search/lunr.min.js
vendored
Normal file
172
docs/assets/plugins/search/search.css
Normal file
@@ -0,0 +1,172 @@
|
||||
body.site-search-visible {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar .search-box {
|
||||
margin: 1.25rem 26px;
|
||||
}
|
||||
|
||||
.sidebar .search-box kbd {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
/* Site search */
|
||||
.site-search {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.site-search[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.site-search__overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgb(var(--sl-overlay-background-color) / var(--sl-overlay-opacity));
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.site-search__panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 460px;
|
||||
max-height: calc(100vh - 20rem);
|
||||
background-color: rgb(var(--sl-surface-base-alt));
|
||||
border-radius: var(--sl-border-radius-large);
|
||||
box-shadow: var(--sl-shadow-x-large);
|
||||
margin: 10rem auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
.site-search__panel {
|
||||
max-width: 100%;
|
||||
max-height: calc(92vh - 120px); /* allow iOS browser chrome */
|
||||
margin: 4vh var(--sl-spacing-medium);
|
||||
}
|
||||
}
|
||||
|
||||
.site-search__input::part(base) {
|
||||
border: none;
|
||||
background: transparent;
|
||||
border-radius: var(--sl-border-radius-large);
|
||||
}
|
||||
|
||||
.site-search__input:focus-within::part(base) {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.site-search__input {
|
||||
--sl-input-height-large: 4rem;
|
||||
}
|
||||
|
||||
.site-search__body {
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.site-search--has-results .site-search__body {
|
||||
border-top: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
}
|
||||
|
||||
.site-search__results {
|
||||
display: none;
|
||||
line-height: var(--sl-line-height-dense);
|
||||
list-style: none;
|
||||
padding: var(--sl-spacing-x-small) 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.site-search--has-results .site-search__results {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.site-search__results a {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
padding: var(--sl-spacing-x-small) var(--sl-spacing-large);
|
||||
}
|
||||
|
||||
.site-search__results li a:hover,
|
||||
.site-search__results li a:hover small {
|
||||
background-color: rgb(var(--sl-color-neutral-100));
|
||||
}
|
||||
|
||||
.site-search__results li[aria-selected='true'] a,
|
||||
.site-search__results li[aria-selected='true'] a small,
|
||||
.site-search__results li[aria-selected='true'] a sl-icon {
|
||||
outline: none;
|
||||
color: rgb(var(--sl-color-neutral-0));
|
||||
background-color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
.site-search__results h3 {
|
||||
font-weight: var(--sl-font-weight-semibold);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.site-search__results small {
|
||||
display: block;
|
||||
color: rgb(var(--sl-color-neutral-600));
|
||||
}
|
||||
|
||||
.site-search__result {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.site-search__result a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--sl-spacing-medium);
|
||||
}
|
||||
|
||||
.site-search__result-icon {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
color: rgb(var(--sl-color-neutral-400));
|
||||
font-size: var(--sl-font-size-x-large);
|
||||
}
|
||||
|
||||
.site-search__result-description {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.site-search__empty {
|
||||
display: none;
|
||||
border-top: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
text-align: center;
|
||||
padding: var(--sl-spacing-x-large);
|
||||
}
|
||||
|
||||
.site-search--no-results .site-search__empty {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.site-search__footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: var(--sl-spacing-large);
|
||||
border-top: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
border-bottom-left-radius: inherit;
|
||||
border-bottom-right-radius: inherit;
|
||||
padding: var(--sl-spacing-medium);
|
||||
}
|
||||
|
||||
.site-search__footer small {
|
||||
color: rgb(var(--sl-color-neutral-700));
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
.site-search__footer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
293
docs/assets/plugins/search/search.js
Normal file
@@ -0,0 +1,293 @@
|
||||
(() => {
|
||||
if (!window.$docsify) {
|
||||
throw new Error('Docsify must be loaded before installing this plugin.');
|
||||
}
|
||||
|
||||
window.$docsify.plugins.push((hook, vm) => {
|
||||
// Append the search box to the sidebar
|
||||
hook.mounted(function () {
|
||||
const appName = document.querySelector('.sidebar .app-name');
|
||||
const searchBox = document.createElement('div');
|
||||
searchBox.classList.add('search-box');
|
||||
searchBox.innerHTML = `
|
||||
<sl-input
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
clearable
|
||||
pill
|
||||
>
|
||||
<sl-icon slot="prefix" name="search"></sl-icon>
|
||||
<kbd slot="suffix" title="Press / to search">/</kbd>
|
||||
</sl-input>
|
||||
`;
|
||||
const searchBoxInput = searchBox.querySelector('sl-input');
|
||||
|
||||
appName.insertAdjacentElement('afterend', searchBox);
|
||||
|
||||
// Show the search panel when the search is clicked
|
||||
searchBoxInput.addEventListener('mousedown', event => {
|
||||
event.preventDefault();
|
||||
show();
|
||||
});
|
||||
|
||||
// Show the search panel when a key is pressed
|
||||
searchBoxInput.addEventListener('keydown', event => {
|
||||
if (event.key === 'Tab') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass the character that was typed through to the search input
|
||||
if (event.key.length === 1) {
|
||||
event.preventDefault();
|
||||
input.value = event.key;
|
||||
show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Append the search panel to the body
|
||||
const siteSearch = document.createElement('div');
|
||||
siteSearch.classList.add('site-search');
|
||||
siteSearch.hidden = true;
|
||||
siteSearch.innerHTML = `
|
||||
<div class="site-search__overlay"></div>
|
||||
<div class="site-search__panel">
|
||||
<header class="site-search__header">
|
||||
<sl-input
|
||||
class="site-search__input"
|
||||
type="search"
|
||||
placeholder="Search this site"
|
||||
size="large"
|
||||
clearable
|
||||
>
|
||||
<sl-icon slot="prefix" name="search"></sl-icon>
|
||||
</sl-input>
|
||||
</header>
|
||||
<div class="site-search__body">
|
||||
<ul class="site-search__results"></ul>
|
||||
<div class="site-search__empty">No results found.</div>
|
||||
</div>
|
||||
<footer class="site-search__footer">
|
||||
<small><kbd>↑</kbd> <kbd>↓</kbd> navigate</small>
|
||||
<small><kbd>↲</kbd> select</small>
|
||||
<small><kbd>esc</kbd> close</small>
|
||||
</footer>
|
||||
</div>
|
||||
`;
|
||||
document.body.append(siteSearch);
|
||||
|
||||
const searchButtons = [...document.querySelectorAll('[data-site-search]')];
|
||||
const overlay = siteSearch.querySelector('.site-search__overlay');
|
||||
const panel = siteSearch.querySelector('.site-search__panel');
|
||||
const input = siteSearch.querySelector('.site-search__input');
|
||||
const results = siteSearch.querySelector('.site-search__results');
|
||||
const animationDuration = 150;
|
||||
const searchDebounce = 200;
|
||||
let isShowing = false;
|
||||
let searchTimeout;
|
||||
let searchIndex;
|
||||
let map;
|
||||
|
||||
// Load search data
|
||||
const searchData = fetch('../../../search.json')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
searchIndex = lunr.Index.load(data.searchIndex);
|
||||
map = data.map;
|
||||
});
|
||||
|
||||
async function show() {
|
||||
isShowing = true;
|
||||
document.body.classList.add('site-search-visible');
|
||||
siteSearch.hidden = false;
|
||||
input.focus();
|
||||
updateResults();
|
||||
|
||||
await Promise.all([
|
||||
panel.animate(
|
||||
[
|
||||
{ opacity: 0, transform: 'scale(.9)' },
|
||||
{ opacity: 1, transform: 'scale(1)' }
|
||||
],
|
||||
{ duration: animationDuration }
|
||||
).finished,
|
||||
overlay.animate([{ opacity: 0 }, { opacity: 1 }], { duration: animationDuration }).finished
|
||||
]);
|
||||
|
||||
document.addEventListener('mousedown', handleDocumentMouseDown);
|
||||
document.addEventListener('keydown', handleDocumentKeyDown);
|
||||
document.addEventListener('focusin', handleDocumentFocusIn);
|
||||
}
|
||||
|
||||
async function hide() {
|
||||
isShowing = false;
|
||||
document.body.classList.remove('site-search-visible');
|
||||
|
||||
await Promise.all([
|
||||
panel.animate(
|
||||
[
|
||||
{ opacity: 1, transform: 'scale(1)' },
|
||||
{ opacity: 0, transform: 'scale(.9)' }
|
||||
],
|
||||
{ duration: animationDuration }
|
||||
).finished,
|
||||
overlay.animate([{ opacity: 1 }, { opacity: 0 }], { duration: animationDuration }).finished
|
||||
]);
|
||||
|
||||
siteSearch.hidden = true;
|
||||
input.value = '';
|
||||
updateResults();
|
||||
|
||||
document.removeEventListener('mousedown', handleDocumentMouseDown);
|
||||
document.removeEventListener('keydown', handleDocumentKeyDown);
|
||||
document.removeEventListener('focusin', handleDocumentFocusIn);
|
||||
}
|
||||
|
||||
function handleInput() {
|
||||
// Debounce search queries
|
||||
clearTimeout(searchTimeout);
|
||||
searchTimeout = setTimeout(() => updateResults(input.value), searchDebounce);
|
||||
}
|
||||
|
||||
function handleDocumentFocusIn(event) {
|
||||
// Close when focus leaves the panel
|
||||
if (event.target.closest('.site-search__panel') !== panel) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
function handleDocumentMouseDown(event) {
|
||||
// Close when clicking outside of the panel
|
||||
if (event.target.closest('.site-search__overlay') === overlay) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
function handleDocumentKeyDown(event) {
|
||||
// Close when pressing escape
|
||||
if (event.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle keyboard selections
|
||||
if (['ArrowDown', 'ArrowUp', 'Home', 'End', 'Enter'].includes(event.key)) {
|
||||
event.preventDefault();
|
||||
|
||||
const currentEl = results.querySelector('[aria-selected="true"]');
|
||||
const items = [...results.querySelectorAll('li')];
|
||||
const index = items.indexOf(currentEl);
|
||||
let nextEl;
|
||||
|
||||
if (items.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case 'ArrowUp':
|
||||
nextEl = items[Math.max(0, index - 1)];
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
nextEl = items[Math.min(items.length - 1, index + 1)];
|
||||
break;
|
||||
case 'Home':
|
||||
nextEl = items[0];
|
||||
break;
|
||||
case 'End':
|
||||
nextEl = items[items.length - 1];
|
||||
break;
|
||||
case 'Enter':
|
||||
currentEl?.querySelector('a')?.click();
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the selected item
|
||||
items.map(item => {
|
||||
if (item === nextEl) {
|
||||
item.setAttribute('aria-selected', 'true');
|
||||
nextEl.scrollIntoView({ block: 'nearest' });
|
||||
} else {
|
||||
item.setAttribute('aria-selected', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
async function updateResults(query = '') {
|
||||
try {
|
||||
await searchIndex;
|
||||
|
||||
const hasQuery = query.length > 0;
|
||||
let matches = hasQuery ? searchIndex.search(`${query}`) : [];
|
||||
|
||||
// Fall back to a fuzzy search if no matches are found
|
||||
if (matches.length === 0 && hasQuery) {
|
||||
matches = searchIndex.search(`${query}~2`);
|
||||
}
|
||||
|
||||
let hasResults = hasQuery && matches.length > 0;
|
||||
siteSearch.classList.toggle('site-search--has-results', hasQuery && hasResults);
|
||||
siteSearch.classList.toggle('site-search--no-results', hasQuery && !hasResults);
|
||||
panel.setAttribute('aria-expanded', hasQuery && hasResults ? 'true' : 'false');
|
||||
|
||||
results.innerHTML = '';
|
||||
|
||||
matches.map((match, index) => {
|
||||
const page = map[match.ref];
|
||||
const li = document.createElement('li');
|
||||
const a = document.createElement('a');
|
||||
let icon = 'file-text';
|
||||
|
||||
if (page.url.includes('getting-started/')) icon = 'lightbulb';
|
||||
if (page.url.includes('resources/')) icon = 'book';
|
||||
if (page.url.includes('components/')) icon = 'puzzle';
|
||||
if (page.url.includes('tokens/')) icon = 'palette2';
|
||||
if (page.url.includes('utilities/')) icon = 'wrench';
|
||||
if (page.url.includes('tutorials/')) icon = 'joystick';
|
||||
|
||||
a.href = $docsify.routerMode === 'hash' ? `/#/${page.url}` : `/${page.url}`;
|
||||
a.innerHTML = `
|
||||
<div class="site-search__result-icon">
|
||||
<sl-icon name="${icon}" aria-hidden="true"></sl-icon>
|
||||
</div>
|
||||
<div class="site-search__result__details">
|
||||
<h3>${page.title}</h3>
|
||||
<small>${page.url}</small>
|
||||
</div>
|
||||
`;
|
||||
|
||||
li.classList.add('site-search__result');
|
||||
li.setAttribute('aria-selected', index === 0 ? 'true' : 'false');
|
||||
li.appendChild(a);
|
||||
results.appendChild(li);
|
||||
});
|
||||
} catch {
|
||||
// Ignore query errors as the user types
|
||||
}
|
||||
}
|
||||
|
||||
// Show the search panel slash is pressed outside of a form element
|
||||
document.addEventListener('keydown', event => {
|
||||
if (
|
||||
!isShowing &&
|
||||
event.key === '/' &&
|
||||
!event.composedPath().some(el => ['input', 'textarea'].includes(el?.tagName?.toLowerCase()))
|
||||
) {
|
||||
event.preventDefault();
|
||||
show();
|
||||
}
|
||||
});
|
||||
|
||||
input.addEventListener('sl-input', handleInput);
|
||||
|
||||
// Close when a result is selected
|
||||
results.addEventListener('click', event => {
|
||||
if (event.target.closest('a')) {
|
||||
hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
@@ -1,14 +0,0 @@
|
||||
(() => {
|
||||
if (!window.$docsify) {
|
||||
throw new Error('Docsify must be loaded before installing this plugin.');
|
||||
}
|
||||
|
||||
window.$docsify.plugins.push((hook, vm) => {
|
||||
hook.mounted(function () {
|
||||
// Move search below the app name
|
||||
const appName = document.querySelector('.sidebar .app-name');
|
||||
const search = document.querySelector('.sidebar .search');
|
||||
appName.insertAdjacentElement('afterend', search);
|
||||
});
|
||||
});
|
||||
})();
|
||||
29
docs/assets/plugins/theme-picker/theme-picker.css
Normal file
@@ -0,0 +1,29 @@
|
||||
.theme-picker {
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
z-index: 30;
|
||||
}
|
||||
|
||||
.theme-picker:not(:defined) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.theme-picker sl-menu-label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.theme-picker sl-menu-label kbd {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.theme-picker {
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
}
|
||||
|
||||
.theme-picker sl-menu-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
84
docs/assets/plugins/theme-picker/theme-picker.js
Normal file
@@ -0,0 +1,84 @@
|
||||
(() => {
|
||||
if (!window.$docsify) {
|
||||
throw new Error('Docsify must be loaded before installing this plugin.');
|
||||
}
|
||||
|
||||
window.$docsify.plugins.push((hook, vm) => {
|
||||
hook.mounted(function () {
|
||||
function getTheme() {
|
||||
return localStorage.getItem('theme') || 'auto';
|
||||
}
|
||||
|
||||
function isDark() {
|
||||
if (theme === 'auto') {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
} else {
|
||||
return theme === 'dark';
|
||||
}
|
||||
}
|
||||
|
||||
function setTheme(newTheme) {
|
||||
const noTransitions = Object.assign(document.createElement('style'), {
|
||||
textContent: '* { transition: none !important; }'
|
||||
});
|
||||
|
||||
theme = newTheme;
|
||||
localStorage.setItem('theme', theme);
|
||||
|
||||
// Update the UI
|
||||
[...menu.querySelectorAll('sl-menu-item')].map(item => (item.checked = item.getAttribute('value') === theme));
|
||||
menuIcon.name = isDark() ? 'moon' : 'sun';
|
||||
|
||||
// Toggle the dark mode class without transitions
|
||||
document.body.appendChild(noTransitions);
|
||||
requestAnimationFrame(() => {
|
||||
document.documentElement.classList.toggle('sl-theme-dark', isDark());
|
||||
requestAnimationFrame(() => document.body.removeChild(noTransitions));
|
||||
});
|
||||
}
|
||||
|
||||
let theme = getTheme();
|
||||
|
||||
// Generate the theme picker dropdown
|
||||
const dropdown = document.createElement('sl-dropdown');
|
||||
dropdown.classList.add('theme-picker');
|
||||
dropdown.innerHTML = `
|
||||
<sl-button size="small" pill slot="trigger" caret>
|
||||
<sl-icon name="sun" label="Select Theme"></sl-icon>
|
||||
</sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-label>Toggle <kbd>\\</kbd></sl-menu-label>
|
||||
<sl-menu-item value="light">Light</sl-menu-item>
|
||||
<sl-menu-item value="dark">Dark</sl-menu-item>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="auto">Auto</sl-menu-item>
|
||||
</sl-menu>
|
||||
`;
|
||||
document.querySelector('.sidebar-toggle').insertAdjacentElement('afterend', dropdown);
|
||||
|
||||
// Listen for selections
|
||||
const menu = dropdown.querySelector('sl-menu');
|
||||
const menuIcon = dropdown.querySelector('sl-icon');
|
||||
menu.addEventListener('sl-select', event => setTheme(event.detail.item.value));
|
||||
|
||||
// Update the theme when the preference changes
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addListener(event => setTheme(theme));
|
||||
|
||||
// Toggle themes when pressing backslash
|
||||
document.addEventListener('keydown', event => {
|
||||
if (
|
||||
event.key === '\\' &&
|
||||
!event.composedPath().some(el => ['input', 'textarea'].includes(el?.tagName?.toLowerCase()))
|
||||
) {
|
||||
event.preventDefault();
|
||||
|
||||
setTheme(isDark() ? 'light' : 'dark');
|
||||
show();
|
||||
}
|
||||
});
|
||||
|
||||
// Set the intial theme and sync the UI
|
||||
setTheme(theme);
|
||||
});
|
||||
});
|
||||
})();
|
||||
@@ -1,13 +0,0 @@
|
||||
.theme-toggle {
|
||||
position: fixed;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.theme-toggle {
|
||||
top: 0.25rem;
|
||||
right: 0.25rem;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
(() => {
|
||||
if (!window.$docsify) {
|
||||
throw new Error('Docsify must be loaded before installing this plugin.');
|
||||
}
|
||||
|
||||
window.$docsify.plugins.push((hook, vm) => {
|
||||
hook.mounted(function () {
|
||||
let isDark = localStorage.getItem('theme') === 'sl-theme-dark';
|
||||
const sidebarToggle = document.querySelector('.sidebar-toggle');
|
||||
const noTransitions = Object.assign(document.createElement('style'), {
|
||||
textContent: '* { transition: none !important; }'
|
||||
});
|
||||
const toggle = Object.assign(document.createElement('sl-icon-button'), {
|
||||
name: isDark ? 'sun' : 'moon',
|
||||
label: 'Toggle dark mode'
|
||||
});
|
||||
toggle.classList.add('theme-toggle');
|
||||
|
||||
// Set initial theme
|
||||
if (isDark) {
|
||||
document.body.classList.add('sl-theme-dark');
|
||||
}
|
||||
|
||||
// Toggle theme
|
||||
toggle.addEventListener('click', () => {
|
||||
isDark = !isDark;
|
||||
isDark ? localStorage.setItem('theme', 'sl-theme-dark') : localStorage.removeItem('theme');
|
||||
toggle.name = isDark ? 'sun' : 'moon';
|
||||
|
||||
// Disable transitions as the theme changes
|
||||
document.body.appendChild(noTransitions);
|
||||
requestAnimationFrame(() => {
|
||||
document.body.classList.toggle('sl-theme-dark', isDark);
|
||||
requestAnimationFrame(() => document.body.removeChild(noTransitions));
|
||||
});
|
||||
});
|
||||
|
||||
sidebarToggle.insertAdjacentElement('afterend', toggle);
|
||||
});
|
||||
});
|
||||
})();
|
||||
@@ -1,60 +0,0 @@
|
||||
/* Color demo */
|
||||
.color-demo {
|
||||
width: 4rem;
|
||||
height: 2rem;
|
||||
border-radius: var(--sl-border-radius-small);
|
||||
box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.33);
|
||||
}
|
||||
|
||||
/* Border radius demo */
|
||||
.border-radius-demo {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
background: var(--sl-color-primary-500);
|
||||
}
|
||||
|
||||
/* Transition demo */
|
||||
.transition-demo {
|
||||
position: relative;
|
||||
background: var(--sl-color-gray-200);
|
||||
width: 8rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.transition-demo:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: var(--sl-color-primary-500);
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
transition-duration: inherit;
|
||||
transition-property: width;
|
||||
}
|
||||
|
||||
.transition-demo:hover:after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sl-theme-dark .transition-demo {
|
||||
background: var(--sl-color-gray-800);
|
||||
}
|
||||
|
||||
/* Spacing demo */
|
||||
.spacing-demo {
|
||||
width: 100px;
|
||||
background: var(--sl-color-primary-500);
|
||||
}
|
||||
|
||||
/* Elevation dmeo */
|
||||
.elevation-demo {
|
||||
background: var(--sl-color-white);
|
||||
border-radius: 3px;
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
.sl-theme-dark .elevation-demo {
|
||||
background-color: var(--sl-color-gray-800);
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
/* Elevation tokens */
|
||||
.sl-theme-dark {
|
||||
--sl-shadow-x-small: 0 1px 0 #6b72800d;
|
||||
--sl-shadow-small: 0 1px 2px #6b72801a;
|
||||
--sl-shadow-medium: 0 2px 4px #6b72801a;
|
||||
--sl-shadow-large: 0 2px 8px #6b72801a;
|
||||
--sl-shadow-x-large: 0 4px 16px #6b72801a;
|
||||
}
|
||||
|
||||
.sl-theme-dark {
|
||||
background: var(--sl-color-gray-900);
|
||||
color: var(--sl-color-gray-200);
|
||||
}
|
||||
|
||||
/* Sidebar **/
|
||||
.sl-theme-dark .sidebar {
|
||||
background: var(--sl-color-gray-900);
|
||||
border-right-color: var(--sl-color-gray-900);
|
||||
}
|
||||
|
||||
.sl-theme-dark .sidebar li > p {
|
||||
color: var(--sl-color-white);
|
||||
border-bottom-color: var(--sl-color-gray-800);
|
||||
}
|
||||
|
||||
.sl-theme-dark .sidebar-toggle {
|
||||
background-color: var(--sl-color-gray-900);
|
||||
}
|
||||
|
||||
.sl-theme-dark .docsify-pagination-container {
|
||||
border-top-color: var(--sl-color-gray-800) !important;
|
||||
}
|
||||
|
||||
/* Search */
|
||||
.sl-theme-dark .sidebar .search input[type='search'] {
|
||||
background: var(--sl-input-background-color);
|
||||
border-color: var(--sl-input-border-color);
|
||||
color: var(--sl-input-color);
|
||||
}
|
||||
|
||||
.sl-theme-dark .sidebar .search input[type='search']:hover {
|
||||
border-color: var(--sl-input-border-color-hover);
|
||||
}
|
||||
|
||||
.sl-theme-dark .sidebar .search input[type='search']:focus {
|
||||
border-color: var(--sl-input-border-color-focus);
|
||||
}
|
||||
|
||||
.sl-theme-dark .sidebar .clear-button {
|
||||
color: var(--sl-color-gray-700);
|
||||
}
|
||||
|
||||
.sl-theme-dark .sidebar .clear-button svg circle {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.sl-theme-dark .component-header {
|
||||
border-bottom-color: var(--sl-color-gray-800);
|
||||
}
|
||||
|
||||
.sl-theme-dark .anchor span {
|
||||
color: var(--sl-color-white);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section h2 {
|
||||
border-bottom-color: var(--sl-color-gray-800);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section blockquote {
|
||||
border-left-color: var(--sl-color-gray-800);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section kbd {
|
||||
border-color: var(--sl-color-gray-800);
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
.sl-theme-dark .markdown-section tr:nth-child(2n) {
|
||||
background: var(--sl-color-gray-950);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section td {
|
||||
border-top-color: var(--sl-color-gray-800);
|
||||
border-bottom-color: var(--sl-color-gray-800);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section table .attribute-tooltip {
|
||||
border-bottom-color: var(--sl-color-gray-700);
|
||||
}
|
||||
|
||||
/* Tips & warnings */
|
||||
.sl-theme-dark .markdown-section p.tip,
|
||||
.sl-theme-dark .markdown-section p.warn {
|
||||
background-color: var(--sl-color-gray-950);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section p.tip:before,
|
||||
.sl-theme-dark .markdown-section p.warn:before {
|
||||
color: var(--sl-color-gray-900);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section p.tip code,
|
||||
.sl-theme-dark .markdown-section p.warn code {
|
||||
background-color: var(--sl-color-gray-800);
|
||||
}
|
||||
|
||||
/* Code */
|
||||
.sl-theme-dark .markdown-section code {
|
||||
background: var(--sl-color-gray-950);
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
.sl-theme-dark .markdown-section pre,
|
||||
.sl-theme-dark .code-block__source {
|
||||
background-color: var(--sl-color-gray-800);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre > code {
|
||||
color: var(--sl-color-gray-200);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre .token.comment {
|
||||
color: var(--sl-color-gray-600);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre .token.prolog,
|
||||
.sl-theme-dark .markdown-section pre .token.doctype,
|
||||
.sl-theme-dark .markdown-section pre .token.cdata,
|
||||
.sl-theme-dark .markdown-section pre .token.operator {
|
||||
color: var(--sl-color-gray-300);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre .token.property,
|
||||
.sl-theme-dark .markdown-section pre .token.keyword,
|
||||
.sl-theme-dark .markdown-section pre .token.tag,
|
||||
.sl-theme-dark .markdown-section pre .token.url {
|
||||
color: var(--sl-color-primary-400);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre .token.symbol,
|
||||
.sl-theme-dark .markdown-section pre .token.deleted {
|
||||
color: #f92672;
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre .token.boolean,
|
||||
.sl-theme-dark .markdown-section pre .token.constant,
|
||||
.sl-theme-dark .markdown-section pre .token.selector,
|
||||
.sl-theme-dark .markdown-section pre .token.attr-name,
|
||||
.sl-theme-dark .markdown-section pre .token.string,
|
||||
.sl-theme-dark .markdown-section pre .token.char,
|
||||
.sl-theme-dark .markdown-section pre .token.builtin,
|
||||
.sl-theme-dark .markdown-section pre .token.inserted {
|
||||
color: var(--sl-color-success-400);
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre .token.atrule,
|
||||
.sl-theme-dark .markdown-section pre .token.attr-value,
|
||||
.sl-theme-dark .markdown-section pre .token.number,
|
||||
.sl-theme-dark .markdown-section pre .token.variable {
|
||||
color: #c380ff;
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre .token.function,
|
||||
.sl-theme-dark .markdown-section pre .token.class-name {
|
||||
color: #ffbb4d;
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre .token.regex {
|
||||
color: #f8bd5b;
|
||||
}
|
||||
|
||||
.sl-theme-dark .markdown-section pre .token.important {
|
||||
color: #fd495f;
|
||||
}
|
||||
|
||||
/* Repo buttons */
|
||||
.sl-theme-dark .repo-button {
|
||||
background-color: var(--sl-color-gray-900);
|
||||
border-color: var(--sl-color-gray-800);
|
||||
color: var(--sl-color-gray-200);
|
||||
}
|
||||
|
||||
.sl-theme-dark .repo-button--github sl-icon {
|
||||
color: var(--sl-color-white);
|
||||
}
|
||||
|
||||
.sl-theme-dark .repo-button:hover {
|
||||
background-color: var(--sl-color-gray-900);
|
||||
border: solid 1px var(--sl-color-gray-700);
|
||||
}
|
||||
|
||||
.sl-theme-dark .repo-button:focus {
|
||||
border-color: var(--sl-color-primary-500);
|
||||
}
|
||||
@@ -13,12 +13,17 @@ body {
|
||||
font-size: var(--sl-font-size-medium);
|
||||
font-weight: var(--sl-font-weight-normal);
|
||||
letter-spacing: var(--sl-letter-spacing-normal);
|
||||
color: var(--sl-color-gray-800);
|
||||
background-color: rgb(var(--sl-surface-base));
|
||||
color: rgb(var(--sl-color-neutral-800));
|
||||
line-height: var(--sl-line-height-normal);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--sl-color-primary-500);
|
||||
color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: rgb(var(--sl-color-primary-700));
|
||||
}
|
||||
|
||||
strong {
|
||||
@@ -27,19 +32,18 @@ strong {
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
background: var(--sl-color-white);
|
||||
border-right: solid 1px var(--sl-color-gray-200);
|
||||
background-color: rgb(var(--sl-surface-base));
|
||||
border-right: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
}
|
||||
|
||||
.sidebar .app-name {
|
||||
padding: 0 1.5rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.sidebar-version {
|
||||
font-size: var(--sl-font-size-x-small);
|
||||
font-weight: var(--sl-font-weight-normal);
|
||||
color: var(--sl-color-gray-400);
|
||||
color: rgb(var(--sl-color-neutral-500));
|
||||
text-align: right;
|
||||
padding: 0 var(--sl-spacing-small);
|
||||
margin: -1.25rem 0 0.6rem 0;
|
||||
@@ -50,76 +54,6 @@ strong {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Search */
|
||||
.sidebar .search {
|
||||
position: relative;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.sidebar .search input[type='search'] {
|
||||
border: solid 1px var(--sl-input-border-color);
|
||||
border-radius: var(--sl-border-radius-pill);
|
||||
padding-left: 1rem;
|
||||
padding-right: 2rem;
|
||||
margin: 0 1.25rem;
|
||||
transition: var(--sl-transition-fast) color, var(--sl-transition-fast) border, var(--sl-transition-fast) box-shadow;
|
||||
}
|
||||
|
||||
.sidebar .search input[type='search']:hover {
|
||||
border-color: var(--sl-input-border-color-hover);
|
||||
}
|
||||
|
||||
.sidebar .search input[type='search']:focus {
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-focus-ring-color-primary);
|
||||
border-color: var(--sl-input-border-color-focus);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.sidebar .input-wrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 0 0.25rem;
|
||||
}
|
||||
|
||||
.sidebar .clear-button {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: 7px;
|
||||
width: 22px !important;
|
||||
height: 22px !important;
|
||||
}
|
||||
|
||||
.sidebar .clear-button svg {
|
||||
transform: scale(0.75) !important;
|
||||
}
|
||||
|
||||
.sidebar .clear-button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.search .results-panel {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.search .matching-post {
|
||||
border-bottom: solid 1px var(--sl-color-gray-500) !important;
|
||||
padding: 0.25rem 1.5rem;
|
||||
}
|
||||
|
||||
.search .matching-post a {
|
||||
display: block;
|
||||
border-radius: inherit;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.search .matching-post h2 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.search .matching-post p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Sidebar toggle */
|
||||
.sidebar-toggle {
|
||||
top: 0.25rem;
|
||||
@@ -127,13 +61,21 @@ strong {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
background-color: var(--sl-color-white);
|
||||
background-color: rgb(var(--sl-surface-base));
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.sidebar-toggle:hover .sidebar-toggle-button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.sidebar-toggle:active .sidebar-toggle-button span {
|
||||
background-color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
.sidebar-toggle:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-focus-ring-color-primary);
|
||||
box-shadow: var(--sl-focus-ring);
|
||||
}
|
||||
|
||||
.sidebar-toggle span:last-child {
|
||||
@@ -168,12 +110,12 @@ strong {
|
||||
|
||||
.sidebar-nav li.collapse > a,
|
||||
.sidebar-nav li.active > a {
|
||||
color: var(--sl-color-primary-500);
|
||||
color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
.sidebar li > p {
|
||||
font-weight: var(--sl-font-weight-bold);
|
||||
border-bottom: solid 1px var(--sl-color-gray-200);
|
||||
border-bottom: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
margin: 0 0.75rem 0.5rem 0;
|
||||
}
|
||||
|
||||
@@ -218,6 +160,11 @@ strong {
|
||||
max-width: 22rem;
|
||||
}
|
||||
|
||||
.markdown-section .splash-start h1:first-of-type {
|
||||
font-size: var(--sl-font-size-large);
|
||||
margin: 0 0 0.5rem 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1040px) {
|
||||
.splash {
|
||||
display: block;
|
||||
@@ -253,9 +200,13 @@ strong {
|
||||
overflow-anchor: none;
|
||||
}
|
||||
|
||||
.anchor span {
|
||||
color: rgb(var(--sl-color-neutral-1000));
|
||||
}
|
||||
|
||||
.markdown-section blockquote {
|
||||
position: relative;
|
||||
border-left: solid 4px var(--sl-color-gray-200);
|
||||
border-left: solid 4px rgb(var(--sl-color-neutral-200));
|
||||
font-style: italic;
|
||||
padding: 1rem 1.5rem;
|
||||
margin: 0 0 1rem 0;
|
||||
@@ -279,7 +230,13 @@ strong {
|
||||
}
|
||||
|
||||
.docsify-pagination-container {
|
||||
border-top-color: var(--sl-color-gray-200) !important;
|
||||
border-top-color: rgb(var(--sl-color-neutral-200)) !important;
|
||||
}
|
||||
|
||||
.pagination-item-label,
|
||||
.pagination-item-subtitle,
|
||||
.pagination-item-title {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.markdown-section h1,
|
||||
@@ -293,12 +250,12 @@ strong {
|
||||
}
|
||||
|
||||
.markdown-section h1 {
|
||||
font-size: var(--sl-font-size-xx-large);
|
||||
font-size: var(--sl-font-size-2x-large);
|
||||
}
|
||||
|
||||
.markdown-section h2 {
|
||||
font-size: var(--sl-font-size-x-large);
|
||||
border-bottom: solid 1px var(--sl-color-gray-200);
|
||||
border-bottom: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
@@ -329,23 +286,30 @@ strong {
|
||||
.markdown-section code {
|
||||
font-family: var(--sl-font-mono);
|
||||
font-size: 87.5%;
|
||||
background: var(--sl-color-gray-50);
|
||||
background-color: rgb(var(--sl-color-neutral-50));
|
||||
border-radius: var(--sl-border-radius-small);
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.markdown-section tr:nth-child(2n) code {
|
||||
background-color: rgb(var(--sl-color-neutral-100));
|
||||
}
|
||||
|
||||
kbd,
|
||||
.markdown-section kbd {
|
||||
font-family: var(--sl-font-mono);
|
||||
font-size: 87.5%;
|
||||
background-color: rgb(var(--sl-color-neutral-50));
|
||||
border-radius: var(--sl-border-radius-small);
|
||||
border: solid 1px var(--sl-color-gray-200);
|
||||
padding: 2px 4px;
|
||||
border: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
box-shadow: inset 0 1px 0 rgb(var(--sl-color-neutral-0));
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
.markdown-section pre {
|
||||
position: relative;
|
||||
background: var(--sl-color-gray-50);
|
||||
background-color: rgb(var(--sl-color-neutral-50));
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
}
|
||||
|
||||
@@ -353,7 +317,7 @@ strong {
|
||||
display: block;
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
color: var(--sl-color-gray-700);
|
||||
color: rgb(var(--sl-color-neutral-800));
|
||||
padding: var(--sl-spacing-medium);
|
||||
overflow: auto;
|
||||
hyphens: none;
|
||||
@@ -361,18 +325,18 @@ strong {
|
||||
}
|
||||
|
||||
.markdown-section pre .token.comment {
|
||||
color: var(--sl-color-gray-400);
|
||||
color: rgb(var(--sl-color-neutral-500));
|
||||
}
|
||||
|
||||
.markdown-section pre .token.prolog,
|
||||
.markdown-section pre .token.doctype,
|
||||
.markdown-section pre .token.cdata,
|
||||
.markdown-section pre .token.operator {
|
||||
color: var(--sl-color-gray-600);
|
||||
color: rgb(var(--sl-color-neutral-600));
|
||||
}
|
||||
|
||||
.markdown-section pre .token.punctuation {
|
||||
color: var(--sl-color-gray-500);
|
||||
color: rgb(var(--sl-color-neutral-600));
|
||||
}
|
||||
|
||||
.namespace {
|
||||
@@ -383,12 +347,12 @@ strong {
|
||||
.markdown-section pre .token.keyword,
|
||||
.markdown-section pre .token.tag,
|
||||
.markdown-section pre .token.url {
|
||||
color: var(--sl-color-primary-500);
|
||||
color: rgb(var(--sl-color-sky-600));
|
||||
}
|
||||
|
||||
.markdown-section pre .token.symbol,
|
||||
.markdown-section pre .token.deleted {
|
||||
color: #f92672;
|
||||
color: rgb(var(--sl-color-pink-600));
|
||||
}
|
||||
|
||||
.markdown-section pre .token.boolean,
|
||||
@@ -399,27 +363,24 @@ strong {
|
||||
.markdown-section pre .token.char,
|
||||
.markdown-section pre .token.builtin,
|
||||
.markdown-section pre .token.inserted {
|
||||
color: var(--sl-color-success-600);
|
||||
color: rgb(var(--sl-color-emerald-600));
|
||||
}
|
||||
|
||||
.markdown-section pre .token.atrule,
|
||||
.markdown-section pre .token.attr-value,
|
||||
.markdown-section pre .token.number,
|
||||
.markdown-section pre .token.variable {
|
||||
color: #9013fe;
|
||||
color: rgb(var(--sl-color-violet-600));
|
||||
}
|
||||
|
||||
.markdown-section pre .token.function,
|
||||
.markdown-section pre .token.class-name {
|
||||
color: #eb9200;
|
||||
}
|
||||
|
||||
.markdown-section pre .token.class-name,
|
||||
.markdown-section pre .token.regex {
|
||||
color: #f5a623;
|
||||
color: rgb(var(--sl-color-orange-600));
|
||||
}
|
||||
|
||||
.markdown-section pre .token.important {
|
||||
color: #d0021b;
|
||||
color: rgb(var(--sl-color-red-600));
|
||||
}
|
||||
|
||||
.markdown-section pre .token.important,
|
||||
@@ -432,7 +393,18 @@ strong {
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
.table-wrapper {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.table-wrapper table {
|
||||
min-width: 800px;
|
||||
}
|
||||
}
|
||||
|
||||
.markdown-section table {
|
||||
display: table;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
@@ -441,29 +413,28 @@ strong {
|
||||
}
|
||||
|
||||
.markdown-section tr:nth-child(2n) {
|
||||
background: var(--sl-color-gray-50);
|
||||
background: rgb(var(--sl-color-neutral-50));
|
||||
}
|
||||
|
||||
.markdown-section th {
|
||||
border: none;
|
||||
font-weight: inherit;
|
||||
font-weight: var(--sl-font-weight-semibold);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.markdown-section td {
|
||||
border-top: solid 1px var(--sl-color-gray-200);
|
||||
border-bottom: solid 1px var(--sl-color-gray-200);
|
||||
border-top: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
border-bottom: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.markdown-section td code {
|
||||
.markdown-section table .nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.markdown-section table .attribute-tooltip {
|
||||
background: none;
|
||||
border-bottom: dashed 1px var(--sl-color-gray-200);
|
||||
.markdown-section table sl-tooltip code {
|
||||
border-bottom: dashed 1px rgb(var(--sl-color-neutral-300));
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
@@ -476,7 +447,7 @@ strong {
|
||||
.markdown-section p.tip,
|
||||
.markdown-section p.warn {
|
||||
position: relative;
|
||||
background: var(--sl-color-gray-50);
|
||||
background-color: rgb(var(--sl-color-neutral-50));
|
||||
border-left: solid 4px transparent;
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
padding-left: 1.5rem;
|
||||
@@ -486,7 +457,7 @@ strong {
|
||||
.markdown-section p.warn:before {
|
||||
content: '!';
|
||||
border-radius: 100%;
|
||||
color: var(--sl-color-white);
|
||||
color: rgb(var(--sl-color-neutral-0));
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
left: -12px;
|
||||
@@ -499,29 +470,29 @@ strong {
|
||||
}
|
||||
|
||||
.markdown-section p.warn {
|
||||
border-left-color: var(--sl-color-primary-500);
|
||||
border-left-color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
.markdown-section p.warn:before {
|
||||
background-color: var(--sl-color-primary-500);
|
||||
background-color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
.markdown-section p.tip {
|
||||
border-left-color: var(--sl-color-danger-500);
|
||||
border-left-color: rgb(var(--sl-color-danger-600));
|
||||
}
|
||||
|
||||
.markdown-section p.tip:before {
|
||||
background-color: var(--sl-color-danger-500);
|
||||
background-color: rgb(var(--sl-color-danger-600));
|
||||
}
|
||||
|
||||
.markdown-section p.tip code,
|
||||
.markdown-section p.warn code {
|
||||
background-color: var(--sl-color-gray-100);
|
||||
background-color: rgb(var(--sl-color-neutral-100));
|
||||
}
|
||||
|
||||
/* Component headers */
|
||||
.component-header {
|
||||
border-bottom: solid 1px var(--sl-color-gray-200);
|
||||
border-bottom: solid 1px rgb(var(--sl-color-neutral-200));
|
||||
padding-bottom: 2rem;
|
||||
margin-top: -1rem;
|
||||
margin-bottom: 2rem;
|
||||
@@ -533,9 +504,9 @@ strong {
|
||||
margin: 0.75rem 0 0.25rem 0;
|
||||
}
|
||||
|
||||
.component-header__tag code {
|
||||
.markdown-section .component-header__tag code {
|
||||
background: none;
|
||||
color: var(--sl-color-gray-500);
|
||||
color: rgb(var(--sl-color-neutral-600));
|
||||
font-size: var(--sl-font-size-large);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
@@ -551,71 +522,122 @@ strong {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Copy button */
|
||||
.docsify-copy-code-button {
|
||||
font-size: var(--sl-font-size-small) !important;
|
||||
border-top-right-radius: var(--sl-border-radius-medium) !important;
|
||||
border-bottom-left-radius: var(--sl-border-radius-medium) !important;
|
||||
}
|
||||
|
||||
/* Repo buttons */
|
||||
html .repo-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
background-color: var(--sl-color-white);
|
||||
border: solid 1px var(--sl-color-gray-200);
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
box-shadow: var(--sl-shadow-x-small);
|
||||
font-size: var(--sl-font-size-small);
|
||||
font-weight: var(--sl-font-weight-semibold);
|
||||
line-height: 2;
|
||||
text-decoration: none;
|
||||
color: var(--sl-color-gray-700);
|
||||
padding: var(--sl-spacing-xx-small) var(--sl-spacing-small);
|
||||
margin-bottom: var(--sl-spacing-xx-small);
|
||||
transition: 0.25s all;
|
||||
.repo-button--sponsor sl-icon {
|
||||
color: rgb(var(--sl-color-pink-600));
|
||||
}
|
||||
|
||||
html .repo-button:hover {
|
||||
text-decoration: none;
|
||||
background-color: var(--sl-color-gray-50);
|
||||
border: solid 1px var(--sl-color-gray-200);
|
||||
.repo-button--github sl-icon {
|
||||
color: rgb(var(--sl-color-neutral-700));
|
||||
}
|
||||
|
||||
html .repo-button:focus {
|
||||
outline: none;
|
||||
border-color: var(--sl-color-primary-500);
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-focus-ring-color-primary);
|
||||
.repo-button--twitter sl-icon {
|
||||
color: rgb(var(--sl-color-sky-500));
|
||||
}
|
||||
|
||||
html .repo-button:not(:last-of-type) {
|
||||
margin-right: 0.125rem;
|
||||
@media screen and (max-width: 400px) {
|
||||
:not(.sidebar-buttons) > .repo-button {
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
html .repo-button sl-icon {
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
margin-right: 0.35rem;
|
||||
}
|
||||
|
||||
html .repo-button--small {
|
||||
font-size: var(--sl-font-size-x-small);
|
||||
padding: var(--sl-spacing-xxx-small) var(--sl-spacing-x-small);
|
||||
}
|
||||
|
||||
html .repo-button--sponsor sl-icon {
|
||||
color: #ea4aaa;
|
||||
}
|
||||
|
||||
html .repo-button--github sl-icon {
|
||||
color: #242a2e;
|
||||
}
|
||||
|
||||
html .repo-button--twitter sl-icon {
|
||||
color: #1ea0f2;
|
||||
}
|
||||
|
||||
body[data-page^='tokens/'] .table-wrapper td:first-child,
|
||||
body[data-page^='tokens/'] .table-wrapper td:first-child code {
|
||||
body[data-page^='/tokens/'] .table-wrapper td:first-child,
|
||||
body[data-page^='/tokens/'] .table-wrapper td:first-child code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Border radius demo */
|
||||
.border-radius-demo {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
background: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
/* Transition demo */
|
||||
.transition-demo {
|
||||
position: relative;
|
||||
background: rgb(var(--sl-color-neutral-200));
|
||||
width: 8rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.transition-demo:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: rgb(var(--sl-color-primary-600));
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
transition-duration: inherit;
|
||||
transition-property: width;
|
||||
}
|
||||
|
||||
.transition-demo:hover:after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Spacing demo */
|
||||
.spacing-demo {
|
||||
width: 100px;
|
||||
background: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
/* Elevation dmeo */
|
||||
.elevation-demo {
|
||||
background: transparent;
|
||||
border-radius: 3px;
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
/* Color palettes */
|
||||
.color-palette {
|
||||
display: grid;
|
||||
grid-template-columns: 200px repeat(11, 1fr);
|
||||
gap: 1rem var(--sl-spacing-2x-small);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.color-palette__name {
|
||||
font-size: var(--sl-font-size-medium);
|
||||
font-weight: var(--sl-font-weight-semibold);
|
||||
grid-template-columns: repeat(11, 1fr);
|
||||
}
|
||||
|
||||
.color-palette__name code {
|
||||
background: none;
|
||||
font-size: var(--sl-font-size-x-small);
|
||||
}
|
||||
|
||||
.color-palette__example {
|
||||
font-size: var(--sl-font-size-x-small);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.color-palette__swatch {
|
||||
height: 3rem;
|
||||
border-radius: var(--sl-border-radius-small);
|
||||
}
|
||||
|
||||
.color-palette__swatch--border {
|
||||
box-shadow: inset 0 0 0 1px rgb(var(--sl-color-neutral-1000) / 10%);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.color-palette {
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
}
|
||||
|
||||
.color-palette__name {
|
||||
grid-column-start: span 6;
|
||||
}
|
||||
}
|
||||
|
||||
.not-found-image {
|
||||
display: block;
|
||||
max-width: 460px;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ Set the `type` attribute to change the alert's type.
|
||||
|
||||
<br>
|
||||
|
||||
<sl-alert type="info" open>
|
||||
<sl-alert type="neutral" open>
|
||||
<sl-icon slot="icon" name="gear"></sl-icon>
|
||||
<strong>Your settings have been updated</strong><br>
|
||||
Settings will take affect on next login.
|
||||
@@ -89,7 +89,7 @@ Icons are optional. Simply omit the `icon` slot if you don't want them.
|
||||
|
||||
### Duration
|
||||
|
||||
Set the `duration` prop to automatically hide an alert after a period of time. This is useful for alerts that don't require acknowledgement.
|
||||
Set the `duration` attribute to automatically hide an alert after a period of time. This is useful for alerts that don't require acknowledgement.
|
||||
|
||||
```html preview
|
||||
<div class="alert-duration">
|
||||
@@ -120,13 +120,13 @@ Set the `duration` prop to automatically hide an alert after a period of time. T
|
||||
|
||||
To display an alert as a toast notification, or "toast", create the alert and call its `toast()` method. This will move the alert out of its position in the DOM and into [the toast stack](#the-toast-stack) where it will be shown. Once dismissed, it will be removed from the DOM completely. To reuse a toast, store a reference to it and call `toast()` again later on.
|
||||
|
||||
You should always use the `closable` prop so users can dismiss the notification. It's also common to set a reasonable `duration` when the notification doesn't require acknowledgement.
|
||||
You should always use the `closable` attribute so users can dismiss the notification. It's also common to set a reasonable `duration` when the notification doesn't require acknowledgement.
|
||||
|
||||
```html preview
|
||||
<div class="alert-toast">
|
||||
<sl-button type="primary">Primary</sl-button>
|
||||
<sl-button type="success">Success</sl-button>
|
||||
<sl-button type="info">Info</sl-button>
|
||||
<sl-button type="neutral">Neutral</sl-button>
|
||||
<sl-button type="warning">Warning</sl-button>
|
||||
<sl-button type="danger">Danger</sl-button>
|
||||
|
||||
@@ -142,7 +142,7 @@ You should always use the `closable` prop so users can dismiss the notification.
|
||||
You can safely exit the app now.
|
||||
</sl-alert>
|
||||
|
||||
<sl-alert type="info" duration="3000" closable>
|
||||
<sl-alert type="neutral" duration="3000" closable>
|
||||
<sl-icon slot="icon" name="gear"></sl-icon>
|
||||
<strong>Your settings have been updated</strong><br>
|
||||
Settings will take affect on next login.
|
||||
@@ -164,7 +164,7 @@ You should always use the `closable` prop so users can dismiss the notification.
|
||||
<script>
|
||||
const container = document.querySelector('.alert-toast');
|
||||
|
||||
['primary', 'success', 'info', 'warning', 'danger'].map(type => {
|
||||
['primary', 'success', 'neutral', 'warning', 'danger'].map(type => {
|
||||
const button = container.querySelector(`sl-button[type="${type}"]`);
|
||||
const alert = container.querySelector(`sl-alert[type="${type}"]`);
|
||||
|
||||
|
||||
63
docs/components/animated-image.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Animated Image
|
||||
|
||||
[component-header:sl-animated-image]
|
||||
|
||||
A component for displaying animated GIFs and WEBPs that play and pause on interaction.
|
||||
|
||||
```html preview
|
||||
<sl-animated-image
|
||||
src="/assets/images/walk.gif"
|
||||
alt="Animation of untied shoes walking on pavement"
|
||||
></sl-animated-image>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### WEBP Images
|
||||
|
||||
Both GIF and WEBP images are supported.
|
||||
|
||||
```html preview
|
||||
<sl-animated-image
|
||||
src="/assets/images/tie.webp"
|
||||
alt="Animation of a shoe being tied"
|
||||
></sl-animated-image>
|
||||
```
|
||||
|
||||
### Setting a Width and Height
|
||||
|
||||
To set a custom size, apply a width and/or height to the host element.
|
||||
|
||||
```html preview
|
||||
<sl-animated-image
|
||||
src="/assets/images/walk.gif"
|
||||
alt="Animation of untied shoes walking on pavement"
|
||||
style="width: 150px; height: 200px;"
|
||||
>
|
||||
</sl-animated-image>
|
||||
```
|
||||
|
||||
### Customizing the Control Box
|
||||
|
||||
You can change the appearance and location of the control box by targeting the `control-box` part in your styles.
|
||||
|
||||
```html preview
|
||||
<sl-animated-image
|
||||
src="/assets/images/walk.gif"
|
||||
alt="Animation of untied shoes walking on pavement"
|
||||
class="animated-image-custom-control-box"
|
||||
></sl-animated-image>
|
||||
|
||||
<style>
|
||||
.animated-image-custom-control-box::part(control-box) {
|
||||
top: auto;
|
||||
right: auto;
|
||||
bottom: 1rem;
|
||||
left: 1rem;
|
||||
background-color: deeppink;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
[component-metadata:sl-animated-image]
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
Animate elements declaratively with nearly 100 baked-in presets, or roll your own with custom keyframes. Powered by the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API).
|
||||
|
||||
To animate an element, wrap it in `<sl-animation>` and set a `name` and `duration`. Refer to the [properties table](#properties) for additional options.
|
||||
To animate an element, wrap it in `<sl-animation>` and set an animation `name`. The animation not start until you add the `play` attribute. Refer to the [properties table](#properties) for a list of all animation options.
|
||||
|
||||
```html preview
|
||||
<div class="animation-overview">
|
||||
<sl-animation name="bounce" duration="2000"><div class="box"></div></sl-animation>
|
||||
<sl-animation name="jello" duration="2000"><div class="box"></div></sl-animation>
|
||||
<sl-animation name="heartBeat" duration="2000"><div class="box"></div></sl-animation>
|
||||
<sl-animation name="flip" duration="2000"><div class="box"></div></sl-animation>
|
||||
<sl-animation name="bounce" duration="2000" play><div class="box"></div></sl-animation>
|
||||
<sl-animation name="jello" duration="2000" play><div class="box"></div></sl-animation>
|
||||
<sl-animation name="heartBeat" duration="2000" play><div class="box"></div></sl-animation>
|
||||
<sl-animation name="flip" duration="2000" play><div class="box"></div></sl-animation>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -19,13 +19,13 @@ To animate an element, wrap it in `<sl-animation>` and set a `name` and `duratio
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: var(--sl-color-primary-500);
|
||||
background-color: rgb(var(--sl-color-primary-600));
|
||||
margin: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
?> The animation will be applied only to the first child element found in `<sl-animation>`.
|
||||
?> The animation will only be applied to the first child element found in `<sl-animation>`.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -35,7 +35,7 @@ This example demonstrates all of the baked-in animations and easings. Animations
|
||||
|
||||
```html preview
|
||||
<div class="animation-sandbox">
|
||||
<sl-animation name="bounce" easing="ease-in-out" duration="2000">
|
||||
<sl-animation name="bounce" easing="ease-in-out" duration="2000" play>
|
||||
<div class="box"></div>
|
||||
</sl-animation>
|
||||
|
||||
@@ -47,7 +47,7 @@ This example demonstrates all of the baked-in animations and easings. Animations
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import { getAnimationNames, getEasingNames } from '/dist/shoelace.js';
|
||||
import { getAnimationNames, getEasingNames } from '/dist/utilities/animation.js';
|
||||
|
||||
const container = document.querySelector('.animation-sandbox');
|
||||
const animation = container.querySelector('sl-animation');
|
||||
@@ -83,7 +83,7 @@ This example demonstrates all of the baked-in animations and easings. Animations
|
||||
.animation-sandbox .box {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: var(--sl-color-primary-500);
|
||||
background-color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
.animation-sandbox .controls {
|
||||
@@ -115,11 +115,10 @@ Use an [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/
|
||||
const observer = new IntersectionObserver(entries => {
|
||||
if (entries[0].isIntersecting) {
|
||||
// Start the animation when the box enters the viewport
|
||||
animation.pause = null;
|
||||
animation.play = true;
|
||||
} else {
|
||||
// Reset the animation when the box leaves the viewport
|
||||
animation.pause = true;
|
||||
animation.setCurrentTime(0);
|
||||
animation.play = false;
|
||||
animation.currentTime = 0;
|
||||
}
|
||||
});
|
||||
observer.observe(box);
|
||||
@@ -130,7 +129,7 @@ Use an [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: var(--sl-color-primary-500);
|
||||
background-color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
</style>
|
||||
```
|
||||
@@ -141,7 +140,7 @@ Supply your own [keyframe formats](https://developer.mozilla.org/en-US/docs/Web/
|
||||
|
||||
```html preview
|
||||
<div class="animation-keyframes">
|
||||
<sl-animation easing="ease-in-out" duration="2000">
|
||||
<sl-animation easing="ease-in-out" duration="2000" play>
|
||||
<div class="box"></div>
|
||||
</sl-animation>
|
||||
</div>
|
||||
@@ -170,9 +169,31 @@ Supply your own [keyframe formats](https://developer.mozilla.org/en-US/docs/Web/
|
||||
.animation-keyframes .box {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: var(--sl-color-primary-500);
|
||||
background-color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### Playing Animations on Demand
|
||||
|
||||
Animations won't play until you apply the `play` attribute. You can omit it initially, then apply it on demand such as after a user interaction. In this example, the button will animate once every time the button is clicked.
|
||||
|
||||
```html preview
|
||||
<div class="animation-form">
|
||||
<sl-animation name="rubberBand" duration="1000" iterations="1">
|
||||
<sl-button type="primary">Click me</sl-button>
|
||||
</sl-animation>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.animation-form');
|
||||
const animation = container.querySelector('sl-animation');
|
||||
const button = container.querySelector('sl-button');
|
||||
|
||||
button.addEventListener('click', () => {
|
||||
animation.play = true;
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
[component-metadata:sl-animation]
|
||||
|
||||
@@ -78,7 +78,7 @@ You can group avatars with a few lines of CSS.
|
||||
}
|
||||
|
||||
.avatar-group sl-avatar::part(base) {
|
||||
border: solid 2px white;
|
||||
border: solid 2px rgb(var(--sl-color-neutral-0));
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@@ -17,7 +17,7 @@ Set the `type` attribute to change the badge's type.
|
||||
```html preview
|
||||
<sl-badge type="primary">Primary</sl-badge>
|
||||
<sl-badge type="success">Success</sl-badge>
|
||||
<sl-badge type="info">Info</sl-badge>
|
||||
<sl-badge type="neutral">Neutral</sl-badge>
|
||||
<sl-badge type="warning">Warning</sl-badge>
|
||||
<sl-badge type="danger">Danger</sl-badge>
|
||||
```
|
||||
@@ -29,7 +29,7 @@ Use the `pill` attribute to give badges rounded edges.
|
||||
```html preview
|
||||
<sl-badge type="primary" pill>Primary</sl-badge>
|
||||
<sl-badge type="success" pill>Success</sl-badge>
|
||||
<sl-badge type="info" pill>Info</sl-badge>
|
||||
<sl-badge type="neutral" pill>Neutral</sl-badge>
|
||||
<sl-badge type="warning" pill>Warning</sl-badge>
|
||||
<sl-badge type="danger" pill>Danger</sl-badge>
|
||||
```
|
||||
@@ -42,7 +42,7 @@ Use the `pulse` attribute to draw attention to the badge with a subtle animation
|
||||
<div class="badge-pulse">
|
||||
<sl-badge type="primary" pill pulse>1</sl-badge>
|
||||
<sl-badge type="success" pill pulse>1</sl-badge>
|
||||
<sl-badge type="info" pill pulse>1</sl-badge>
|
||||
<sl-badge type="neutral" pill pulse>1</sl-badge>
|
||||
<sl-badge type="warning" pill pulse>1</sl-badge>
|
||||
<sl-badge type="danger" pill pulse>1</sl-badge>
|
||||
</div>
|
||||
@@ -80,10 +80,10 @@ One of the most common use cases for badges is attaching them to buttons. To mak
|
||||
When including badges in menu items, use the `suffix` slot to make sure they're aligned correctly.
|
||||
|
||||
```html preview
|
||||
<sl-menu style="max-width: 240px; border: solid 1px var(--sl-panel-border-color); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu style="max-width: 240px; border: solid 1px rgb(var(--sl-panel-border-color)); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu-label>Messages</sl-menu-label>
|
||||
<sl-menu-item>Comments <sl-badge slot="suffix" type="info" pill>4</sl-badge></sl-menu-item>
|
||||
<sl-menu-item>Replies <sl-badge slot="suffix" type="info" pill>12</sl-badge></sl-menu-item>
|
||||
<sl-menu-item>Comments <sl-badge slot="suffix" type="neutral" pill>4</sl-badge></sl-menu-item>
|
||||
<sl-menu-item>Replies <sl-badge slot="suffix" type="neutral" pill>12</sl-badge></sl-menu-item>
|
||||
</sl-menu>
|
||||
```
|
||||
|
||||
|
||||
20
docs/components/breadcrumb-item.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Breadcrumb Item
|
||||
|
||||
[component-header:sl-breadcrumb-item]
|
||||
|
||||
Breadcrumb Items are used inside [breadcrumbs](/components/breadcrumb) to represent different links.
|
||||
|
||||
```html preview
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb-item>
|
||||
<sl-icon slot="prefix" name="house"></sl-icon>
|
||||
Home
|
||||
</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Clothing</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Shirts</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
?> Additional demonstrations can be found in the [breadcrumb examples](/components/breadcrumb).
|
||||
|
||||
[component-metadata:sl-breadcrumb-item]
|
||||
132
docs/components/breadcrumb.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Breadcrumb
|
||||
|
||||
[component-header:sl-breadcrumb]
|
||||
|
||||
Breadcrumbs provide a group of links so users can easily navigate a website's hierarchy.
|
||||
|
||||
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.
|
||||
|
||||
```html preview
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb-item>Catalog</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Clothing</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Women's</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Shirts & Tops</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Breadcrumb Links
|
||||
|
||||
By default, breadcrumb items are rendered as buttons so you can use them to navigate single-page applications. In this case, you'll need to add event listeners to handle clicks.
|
||||
|
||||
For websites, you'll probably want to use links instead. You can make any breadcrumb item a link by applying an `href` attribute to it. Now, when the user activates it, they'll be taken to the corresponding page — no event listeners required.
|
||||
|
||||
```html preview
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb-item href="https://example.com/home">
|
||||
Homepage
|
||||
</sl-breadcrumb-item>
|
||||
|
||||
<sl-breadcrumb-item href="https://example.com/home/services">
|
||||
Our Services
|
||||
</sl-breadcrumb-item>
|
||||
|
||||
<sl-breadcrumb-item href="https://example.com/home/services/digital">
|
||||
Digital Media
|
||||
</sl-breadcrumb-item>
|
||||
|
||||
<sl-breadcrumb-item href="https://example.com/home/services/digital/web-design">
|
||||
Web Design
|
||||
</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
### Custom Separators
|
||||
|
||||
Use the `separator` slot to change the separator that goes between breadcrumb items. Icons work well, but you can also use text or an image.
|
||||
|
||||
```html preview
|
||||
<sl-breadcrumb>
|
||||
<sl-icon name="dot" slot="separator"></sl-icon>
|
||||
<sl-breadcrumb-item>First</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Second</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Third</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
|
||||
<br>
|
||||
|
||||
<sl-breadcrumb>
|
||||
<sl-icon name="arrow-right" slot="separator"></sl-icon>
|
||||
<sl-breadcrumb-item>First</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Second</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Third</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
|
||||
<br>
|
||||
|
||||
<sl-breadcrumb>
|
||||
<span slot="separator">/</span>
|
||||
<sl-breadcrumb-item>First</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Second</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Third</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
### Prefixes
|
||||
|
||||
Use the `prefix` slot to add content before any breadcrumb item.
|
||||
|
||||
```html preview
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb-item>
|
||||
<sl-icon slot="prefix" name="house"></sl-icon>
|
||||
Home
|
||||
</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Articles</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Traveling</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
### Suffixes
|
||||
|
||||
Use the `suffix` slot to add content after any breadcrumb item.
|
||||
|
||||
```html preview
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb-item>Documents</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Policies</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>
|
||||
Security
|
||||
<sl-icon slot="suffix" name="shield-lock"></sl-icon>
|
||||
</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
### With Dropdowns
|
||||
|
||||
Dropdown menus can be placed in a prefix or suffix slot to provide additional options.
|
||||
|
||||
```html preview
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb-item>Homepage</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Our Services</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Digital Media</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>
|
||||
Web Design
|
||||
<sl-dropdown slot="suffix">
|
||||
<sl-button slot="trigger" size="small" circle>
|
||||
<sl-icon label="More options" name="three-dots"></sl-icon>
|
||||
</sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-item checked>Web Design</sl-menu-item>
|
||||
<sl-menu-item>Web Development</sl-menu-item>
|
||||
<sl-menu-item>Marketing</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
[component-metadata:sl-breadcrumb]
|
||||
@@ -64,9 +64,9 @@ Theme buttons are supported through the button's `type` attribute.
|
||||
<br><br>
|
||||
|
||||
<sl-button-group>
|
||||
<sl-button type="info">Left</sl-button>
|
||||
<sl-button type="info">Center</sl-button>
|
||||
<sl-button type="info">Right</sl-button>
|
||||
<sl-button type="neutral">Left</sl-button>
|
||||
<sl-button type="neutral">Center</sl-button>
|
||||
<sl-button type="neutral">Right</sl-button>
|
||||
</sl-button-group>
|
||||
|
||||
<br><br>
|
||||
@@ -116,7 +116,7 @@ Pill buttons are supported through the button's `pill` attribute.
|
||||
|
||||
### Dropdowns in Button Groups
|
||||
|
||||
Dropdowns can be placed inside button groups as long as the trigger is a `<sl-button>` element.
|
||||
Dropdowns can be placed inside button groups as long as the trigger is an `<sl-button>` element.
|
||||
|
||||
```html preview
|
||||
<sl-button-group>
|
||||
@@ -141,7 +141,7 @@ Create a split button using a button and a dropdown.
|
||||
<sl-button-group>
|
||||
<sl-button type="primary">Save</sl-button>
|
||||
<sl-dropdown placement="bottom-end">
|
||||
<sl-button slot="trigger" type="primary"caret></sl-button>
|
||||
<sl-button slot="trigger" type="primary" caret></sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-item>Save</sl-menu-item>
|
||||
<sl-menu-item>Save as…</sl-menu-item>
|
||||
|
||||
@@ -18,14 +18,14 @@ Use the `type` attribute to set the button's type.
|
||||
<sl-button type="default">Default</sl-button>
|
||||
<sl-button type="primary">Primary</sl-button>
|
||||
<sl-button type="success">Success</sl-button>
|
||||
<sl-button type="info">Info</sl-button>
|
||||
<sl-button type="neutral">Neutral</sl-button>
|
||||
<sl-button type="warning">Warning</sl-button>
|
||||
<sl-button type="danger">Danger</sl-button>
|
||||
```
|
||||
|
||||
### Sizes
|
||||
|
||||
Use the `size` prop to change a button's size.
|
||||
Use the `size` attribute to change a button's size.
|
||||
|
||||
```html preview
|
||||
<sl-button size="small">Small</sl-button>
|
||||
@@ -33,9 +33,22 @@ Use the `size` prop to change a button's size.
|
||||
<sl-button size="large">Large</sl-button>
|
||||
```
|
||||
|
||||
### Outline Buttons
|
||||
|
||||
Use the `outline` attribute to draw outlined buttons with transparent backgrounds.
|
||||
|
||||
```html preview
|
||||
<sl-button type="default" outline>Default</sl-button>
|
||||
<sl-button type="primary" outline>Primary</sl-button>
|
||||
<sl-button type="success" outline>Success</sl-button>
|
||||
<sl-button type="neutral" outline>Neutral</sl-button>
|
||||
<sl-button type="warning" outline>Warning</sl-button>
|
||||
<sl-button type="danger" outline>Danger</sl-button>
|
||||
```
|
||||
|
||||
### Pill Buttons
|
||||
|
||||
Use the `pill` prop to give buttons rounded edges.
|
||||
Use the `pill` attribute to give buttons rounded edges.
|
||||
|
||||
```html preview
|
||||
<sl-button size="small" pill>Small</sl-button>
|
||||
@@ -45,7 +58,7 @@ Use the `pill` prop to give buttons rounded edges.
|
||||
|
||||
### Circle Buttons
|
||||
|
||||
Use the `circle` prop to create circular icon buttons.
|
||||
Use the `circle` attribute to create circular icon buttons.
|
||||
|
||||
```html preview
|
||||
<sl-button type="default" size="small" circle><sl-icon name="gear"></sl-icon></sl-button>
|
||||
@@ -146,7 +159,7 @@ Use the `prefix` and `suffix` slots to add icons.
|
||||
|
||||
### Caret
|
||||
|
||||
Use the `caret` prop to add a dropdown indicator when a button will trigger a dropdown, menu, or popover.
|
||||
Use the `caret` attribute to add a dropdown indicator when a button will trigger a dropdown, menu, or popover.
|
||||
|
||||
```html preview
|
||||
<sl-button size="small" caret>Small</sl-button>
|
||||
@@ -156,28 +169,72 @@ Use the `caret` prop to add a dropdown indicator when a button will trigger a dr
|
||||
|
||||
### Loading
|
||||
|
||||
Use the `loading` prop to make a button busy. The width will remain the same as before, preventing adjacent elements from moving around. Clicks will be suppressed until the loading state is removed.
|
||||
Use the `loading` attribute to make a button busy. The width will remain the same as before, preventing adjacent elements from moving around. Clicks will be suppressed until the loading state is removed.
|
||||
|
||||
```html preview
|
||||
<sl-button type="default" loading>Default</sl-button>
|
||||
<sl-button type="primary" loading>Primary</sl-button>
|
||||
<sl-button type="success" loading>Success</sl-button>
|
||||
<sl-button type="info" loading>Info</sl-button>
|
||||
<sl-button type="neutral" loading>Neutral</sl-button>
|
||||
<sl-button type="warning" loading>Warning</sl-button>
|
||||
<sl-button type="danger" loading>Danger</sl-button>
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable a button. Clicks will be suppressed until the disabled state is removed.
|
||||
Use the `disabled` attribute to disable a button. Clicks will be suppressed until the disabled state is removed.
|
||||
|
||||
```html preview
|
||||
<sl-button type="default" disabled>Default</sl-button>
|
||||
<sl-button type="primary" disabled>Primary</sl-button>
|
||||
<sl-button type="success" disabled>Success</sl-button>
|
||||
<sl-button type="info" disabled>Info</sl-button>
|
||||
<sl-button type="neutral" disabled>Neutral</sl-button>
|
||||
<sl-button type="warning" disabled>Warning</sl-button>
|
||||
<sl-button type="danger" disabled>Danger</sl-button>
|
||||
```
|
||||
|
||||
### Styling Buttons
|
||||
|
||||
This example demonstrates how to style buttons using a custom class. This is the recommended approach if you need to add additional variations. To customize an existing variation, modify the selector to target the button's type attribute instead of a class (e.g. `sl-button[type="primary"]`).
|
||||
|
||||
```html preview
|
||||
<sl-button class="pink">Pink Button</sl-button>
|
||||
|
||||
<style>
|
||||
sl-button.pink::part(base) {
|
||||
/* Set design tokens for height and border width */
|
||||
--sl-input-height-medium: 48px;
|
||||
--sl-input-border-width: 4px;
|
||||
|
||||
border-radius: 0;
|
||||
background-color: #ff1493;
|
||||
border-top-color: #ff7ac1;
|
||||
border-left-color: #ff7ac1;
|
||||
border-bottom-color: #ad005c;
|
||||
border-right-color: #ad005c;
|
||||
color: white;
|
||||
font-size: 1.125rem;
|
||||
box-shadow: 0 2px 10px #0002;
|
||||
transition: var(--sl-transition-medium) transform ease, var(--sl-transition-medium) border ease;
|
||||
}
|
||||
|
||||
sl-button.pink::part(base):hover {
|
||||
transform: scale(1.05) rotate(-1deg);
|
||||
}
|
||||
|
||||
sl-button.pink::part(base):active {
|
||||
border-top-color: #ad005c;
|
||||
border-right-color: #ff7ac1;
|
||||
border-bottom-color: #ff7ac1;
|
||||
border-left-color: #ad005c;
|
||||
transform: scale(1.05) rotate(-1deg) translateY(2px);
|
||||
}
|
||||
|
||||
sl-button.pink::part(base):focus-visible {
|
||||
outline: dashed 2px deeppink;
|
||||
outline-offset: 4px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
[component-metadata:sl-button]
|
||||
|
||||
@@ -28,7 +28,7 @@ Cards can be used to group related subjects in a container.
|
||||
}
|
||||
|
||||
.card-overview small {
|
||||
color: var(--sl-color-gray-500);
|
||||
color: rgb(var(--sl-color-neutral-500));
|
||||
}
|
||||
|
||||
.card-overview [slot="footer"] {
|
||||
|
||||
@@ -8,7 +8,7 @@ Checkboxes allow the user to toggle an option on or off.
|
||||
<sl-checkbox>Checkbox</sl-checkbox>
|
||||
```
|
||||
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form.md) instead.
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form) instead.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
140
docs/components/context-menu.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Context Menu
|
||||
|
||||
[component-header:sl-context-menu]
|
||||
|
||||
Context menus offer additional options through a menu that opens at the pointer's location, usually activated by a right-click.
|
||||
|
||||
Context menus are designed to work with [menus](/components/menu) and [menu items](/components/menu-item). The menu must include `slot="menu"`. Other content you provide will be part of the context menu's target area.
|
||||
|
||||
```html preview
|
||||
<sl-context-menu>
|
||||
<div style="height: 200px; background: rgb(var(--sl-color-neutral-100)); display: flex; align-items: center; justify-content: center; padding: 1rem;">
|
||||
Right-click to activate the context menu
|
||||
</div>
|
||||
|
||||
<sl-menu slot="menu">
|
||||
<sl-menu-item value="undo">Undo</sl-menu-item>
|
||||
<sl-menu-item value="redo">Redo</sl-menu-item>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="cut">Cut</sl-menu-item>
|
||||
<sl-menu-item value="copy">Copy</sl-menu-item>
|
||||
<sl-menu-item value="paste">Paste</sl-menu-item>
|
||||
<sl-menu-item value="delete">Delete</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-context-menu>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Handling Selections
|
||||
|
||||
The [menu component](/components/menu) emits an `sl-select` event when a menu item is selected. You can use this to handle selections. The selected item will be available in `event.detail.item`.
|
||||
|
||||
```html preview
|
||||
<div class="context-menu-selections">
|
||||
<sl-context-menu>
|
||||
<div style="height: 200px; background: rgb(var(--sl-color-neutral-100)); display: flex; align-items: center; justify-content: center; padding: 1rem;">
|
||||
Right-click to activate the context menu
|
||||
</div>
|
||||
|
||||
<sl-menu slot="menu">
|
||||
<sl-menu-item value="cut">Cut</sl-menu-item>
|
||||
<sl-menu-item value="copy">Copy</sl-menu-item>
|
||||
<sl-menu-item value="paste">Paste</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-context-menu>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.context-menu-selections');
|
||||
const menu = container.querySelector('sl-menu');
|
||||
const result = container.querySelector('.result');
|
||||
|
||||
menu.addEventListener('sl-select', event => {
|
||||
console.log(`You selected: ${event.detail.item.value}`);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Inline
|
||||
|
||||
The context menu uses `display: contents`, so it will assume the shape of the content you slot in.
|
||||
|
||||
```html preview
|
||||
<sl-context-menu>
|
||||
<span style="background: rgb(var(--sl-color-neutral-100)); padding: .5rem 1rem;">
|
||||
Right-click here
|
||||
</span>
|
||||
|
||||
<sl-menu slot="menu">
|
||||
<sl-menu-item value="cut">Cut</sl-menu-item>
|
||||
<sl-menu-item value="copy">Copy</sl-menu-item>
|
||||
<sl-menu-item value="paste">Paste</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-context-menu>
|
||||
```
|
||||
|
||||
### Placement
|
||||
|
||||
The preferred placement of the context menu can be set with the `placement` attribute. Note that the actual position may vary to ensure the menu remains in the viewport.
|
||||
|
||||
```html preview
|
||||
<sl-context-menu placement="top-end">
|
||||
<div style="height: 200px; background: rgb(var(--sl-color-neutral-100)); display: flex; align-items: center; justify-content: center; padding: 1rem;">
|
||||
Right-click to activate the context menu
|
||||
</div>
|
||||
|
||||
<sl-menu slot="menu">
|
||||
<sl-menu-item value="undo">Undo</sl-menu-item>
|
||||
<sl-menu-item value="redo">Redo</sl-menu-item>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="cut">Cut</sl-menu-item>
|
||||
<sl-menu-item value="copy">Copy</sl-menu-item>
|
||||
<sl-menu-item value="paste">Paste</sl-menu-item>
|
||||
<sl-menu-item value="delete">Delete</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-context-menu>
|
||||
```
|
||||
|
||||
### Detecting the Target Item
|
||||
|
||||
A single context menu can wrap a number of items. To detect the item that activated the context menu...
|
||||
|
||||
TODO
|
||||
|
||||
```html preview
|
||||
<div class="context-menu-detecting">
|
||||
<sl-context-menu>
|
||||
<ul>
|
||||
<li>Item 1</li>
|
||||
<li>Item 2</li>
|
||||
<li>Item 3</li>
|
||||
<li>Item 4</li>
|
||||
<li>Item 5</li>
|
||||
</ul>
|
||||
|
||||
<sl-menu slot="menu">
|
||||
<sl-menu-item value="cut">Cut</sl-menu-item>
|
||||
<sl-menu-item value="copy">Copy</sl-menu-item>
|
||||
<sl-menu-item value="paste">Paste</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-context-menu>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.context-menu-detecting ul {
|
||||
max-width: 300px;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.context-menu-detecting li {
|
||||
background: rgb(var(--sl-color-neutral-100));
|
||||
padding: .5rem 1rem;
|
||||
margin: 0 0 2px 0;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
[component-metadata:sl-context-menu]
|
||||
@@ -57,7 +57,7 @@ Details are designed to function independently, but you can simulate a group or
|
||||
|
||||
<style>
|
||||
.details-group-example sl-details:not(:last-of-type) {
|
||||
margin-bottom: var(--sl-spacing-xx-small);
|
||||
margin-bottom: var(--sl-spacing-2x-small);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@@ -13,14 +13,12 @@ Dialogs, sometimes called "modals", appear above the page and require the user's
|
||||
<sl-button>Open Dialog</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const dialog = document.querySelector('.dialog-overview');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
const dialog = document.querySelector('.dialog-overview');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -45,14 +43,12 @@ Use the `--width` custom property to set the dialog's width.
|
||||
<sl-button>Open Dialog</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const dialog = document.querySelector('.dialog-width');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
const dialog = document.querySelector('.dialog-width');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -62,7 +58,7 @@ By design, a dialog's height will never exceed that of the viewport. As such, di
|
||||
|
||||
```html preview
|
||||
<sl-dialog label="Dialog" class="dialog-scrolling">
|
||||
<div style="height: 150vh; border: dashed 2px var(--sl-color-gray-200); padding: 0 1rem;">
|
||||
<div style="height: 150vh; border: dashed 2px rgb(var(--sl-color-neutral-200)); padding: 0 1rem;">
|
||||
<p>Scroll down and give it a try! 👇</p>
|
||||
</div>
|
||||
<sl-button slot="footer" type="primary">Close</sl-button>
|
||||
@@ -71,46 +67,44 @@ By design, a dialog's height will never exceed that of the viewport. As such, di
|
||||
<sl-button>Open Dialog</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const dialog = document.querySelector('.dialog-scrolling');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
const dialog = document.querySelector('.dialog-scrolling');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
### Ignoring Clicks on the Overlay
|
||||
### Preventing the Dialog from Closing
|
||||
|
||||
By default, dialogs are closed when the user clicks or taps on the overlay. To prevent this behavior, cancel the `sl-overlay-dismiss` event.
|
||||
By default, dialogs will close when the user clicks the close button, clicks the overlay, or presses the <kbd>Escape</kbd> key. In most cases, the default behavior is the best behavior in terms of UX. However, there are situations where this may be undesirable, such as when data loss will occur.
|
||||
|
||||
To keep the dialog open in such cases, you can cancel the `sl-request-close` event. When canceled, the dialog will remain open and pulse briefly to draw the user's attention to it.
|
||||
|
||||
```html preview
|
||||
<sl-dialog label="Dialog" class="dialog-no-overlay-dismiss">
|
||||
This dialog will not be closed when you click outside of it.
|
||||
<sl-button slot="footer" type="primary">Close</sl-button>
|
||||
<sl-dialog label="Dialog" class="dialog-deny-close">
|
||||
This dialog will not close unless you use the button below.
|
||||
<sl-button slot="footer" type="primary">Save & Close</sl-button>
|
||||
</sl-dialog>
|
||||
|
||||
<sl-button>Open Dialog</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const dialog = document.querySelector('.dialog-no-overlay-dismiss');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
const dialog = document.querySelector('.dialog-deny-close');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const saveButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
saveButton.addEventListener('click', () => dialog.hide());
|
||||
|
||||
dialog.addEventListener('sl-overlay-dismiss', event => event.preventDefault());
|
||||
})();
|
||||
dialog.addEventListener('sl-request-close', event => event.preventDefault());
|
||||
</script>
|
||||
```
|
||||
|
||||
### Customizing Initial Focus
|
||||
|
||||
By default, the dialog's panel will gain focus when opened. To set focus on a different element, listen for the `sl-initial-focus` event.
|
||||
By default, the dialog's panel will gain focus when opened. This allows the first tab press to focus on the first tabbable element within the dialog. To set focus on a different element, listen for and cancel the `sl-initial-focus` event.
|
||||
|
||||
```html preview
|
||||
<sl-dialog label="Dialog" class="dialog-focus">
|
||||
@@ -121,20 +115,18 @@ By default, the dialog's panel will gain focus when opened. To set focus on a di
|
||||
<sl-button>Open Dialog</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const dialog = document.querySelector('.dialog-focus');
|
||||
const input = dialog.querySelector('sl-input');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
const dialog = document.querySelector('.dialog-focus');
|
||||
const input = dialog.querySelector('sl-input');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
|
||||
dialog.addEventListener('sl-initial-focus', event => {
|
||||
event.preventDefault();
|
||||
input.setFocus({ preventScroll: true });
|
||||
});
|
||||
})();
|
||||
dialog.addEventListener('sl-initial-focus', event => {
|
||||
event.preventDefault();
|
||||
input.focus({ preventScroll: true });
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
71
docs/components/divider.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Divider
|
||||
|
||||
[component-header:sl-divider]
|
||||
|
||||
Dividers are used to visually separate or group elements.
|
||||
|
||||
```html preview
|
||||
<sl-divider></sl-divider>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Width
|
||||
|
||||
Use the `--width` custom property to change the width of the divider.
|
||||
|
||||
```html preview
|
||||
<sl-divider style="--width: 4px;"></sl-divider>
|
||||
```
|
||||
|
||||
### Color
|
||||
|
||||
Use the `--color` custom property to change the color of the divider.
|
||||
|
||||
```html preview
|
||||
<sl-divider style="--color: tomato;"></sl-divider>
|
||||
```
|
||||
|
||||
### Spacing
|
||||
|
||||
Use the `--spacing` custom property to change the amount of space between the divider and it's neighboring elements.
|
||||
|
||||
```html preview
|
||||
<div style="text-align: center;">
|
||||
Above
|
||||
<sl-divider style="--spacing: 2rem;"></sl-divider>
|
||||
Below
|
||||
</div>
|
||||
```
|
||||
|
||||
### Vertical
|
||||
|
||||
Add the `vertical` attribute to draw the divider in a vertical orientation. The divider will span the full height of its container. Vertical dividers work especially well inside of a flex container.
|
||||
|
||||
```html preview
|
||||
<div style="display: flex; align-items: center; height: 2rem;">
|
||||
First
|
||||
<sl-divider vertical></sl-divider>
|
||||
Middle
|
||||
<sl-divider vertical></sl-divider>
|
||||
Last
|
||||
</div>
|
||||
```
|
||||
|
||||
### Menu Dividers
|
||||
|
||||
Use dividers in [menus](/components/menu) to visually group menu items.
|
||||
|
||||
```html preview
|
||||
<sl-menu style="max-width: 200px; border: solid 1px rgb(var(--sl-panel-border-color)); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu-item value="1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="3">Option 3</sl-menu-item>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="4">Option 4</sl-menu-item>
|
||||
<sl-menu-item value="5">Option 5</sl-menu-item>
|
||||
<sl-menu-item value="6">Option 6</sl-menu-item>
|
||||
</sl-menu>
|
||||
```
|
||||
|
||||
[component-metadata:sl-divider]
|
||||
@@ -13,40 +13,36 @@ Drawers slide in from a container to expose additional options and information.
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const drawer = document.querySelector('.drawer-overview');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
const drawer = document.querySelector('.drawer-overview');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Slide in From Left
|
||||
### Slide in From Start
|
||||
|
||||
To make the drawer slide in from the left, set the `placement` attribute to `left`.
|
||||
By default, drawers slide in from the end. To make the drawer slide in from the start, set the `placement` attribute to `start`.
|
||||
|
||||
```html preview
|
||||
<sl-drawer label="Drawer" placement="left" class="drawer-placement-left">
|
||||
This drawer slides in from the left.
|
||||
<sl-drawer label="Drawer" placement="start" class="drawer-placement-start">
|
||||
This drawer slides in from the start.
|
||||
<sl-button slot="footer" type="primary">Close</sl-button>
|
||||
</sl-drawer>
|
||||
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const drawer = document.querySelector('.drawer-placement-left');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
const drawer = document.querySelector('.drawer-placement-start');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -63,14 +59,12 @@ To make the drawer slide in from the top, set the `placement` attribute to `top`
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const drawer = document.querySelector('.drawer-placement-top');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
const drawer = document.querySelector('.drawer-placement-top');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -87,24 +81,22 @@ To make the drawer slide in from the bottom, set the `placement` attribute to `b
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const drawer = document.querySelector('.drawer-placement-bottom');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
const drawer = document.querySelector('.drawer-placement-bottom');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
### Contained to an Element
|
||||
|
||||
By default, the drawer slides out of its [containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#Identifying_the_containing_block), which is usually the viewport. To make the drawer slide out of its parent element, add the `contained` prop and `position: relative` to the parent.
|
||||
By default, the drawer slides out of its [containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#Identifying_the_containing_block), which is usually the viewport. To make the drawer slide out of its parent element, add the `contained` attribute and `position: relative` to the parent.
|
||||
|
||||
```html preview
|
||||
<div
|
||||
style="position: relative; border: solid 2px var(--sl-panel-border-color); height: 300px; padding: 1rem; margin-bottom: 1rem;"
|
||||
style="position: relative; border: solid 2px rgb(var(--sl-panel-border-color)); height: 300px; padding: 1rem; margin-bottom: 1rem;"
|
||||
>
|
||||
The drawer will be contained to this box. This content won't shift or be affected in any way when the drawer opens.
|
||||
|
||||
@@ -117,14 +109,12 @@ By default, the drawer slides out of its [containing block](https://developer.mo
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const drawer = document.querySelector('.drawer-contained');
|
||||
const openButton = drawer.parentElement.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
const drawer = document.querySelector('.drawer-contained');
|
||||
const openButton = drawer.parentElement.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -141,14 +131,12 @@ Use the `--size` custom property to set the drawer's size. This will be applied
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const drawer = document.querySelector('.drawer-custom-size');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
const drawer = document.querySelector('.drawer-custom-size');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -158,7 +146,7 @@ By design, a drawer's height will never exceed 100% of its container. As such, d
|
||||
|
||||
```html preview
|
||||
<sl-drawer label="Drawer" class="drawer-scrolling">
|
||||
<div style="height: 150vh; border: dashed 2px var(--sl-color-gray-200); padding: 0 1rem;">
|
||||
<div style="height: 150vh; border: dashed 2px rgb(var(--sl-color-neutral-200)); padding: 0 1rem;">
|
||||
<p>Scroll down and give it a try! 👇</p>
|
||||
</div>
|
||||
<sl-button slot="footer" type="primary">Close</sl-button>
|
||||
@@ -167,46 +155,45 @@ By design, a drawer's height will never exceed 100% of its container. As such, d
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const drawer = document.querySelector('.drawer-scrolling');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
const drawer = document.querySelector('.drawer-scrolling');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
})();
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
### Ignoring Clicks on the Overlay
|
||||
### Preventing the Drawer from Closing
|
||||
|
||||
By default, drawers will close when the user clicks the close button, clicks the overlay, or presses the <kbd>Escape</kbd> key. In most cases, the default behavior is the best behavior in terms of UX. However, there are situations where this may be undesirable, such as when data loss will occur.
|
||||
|
||||
To keep the drawer open in such cases, you can cancel the `sl-request-close` event. When canceled, the drawer will remain open and pulse briefly to draw the user's attention to it.
|
||||
|
||||
By default, drawers are closed when the user clicks or taps on the overlay. To prevent this behavior, cancel the `sl-overlay-dismiss` event.
|
||||
|
||||
```html preview
|
||||
<sl-drawer label="Drawer" class="drawer-no-overlay-dismiss">
|
||||
This drawer will not be closed when you click outside of it.
|
||||
<sl-button slot="footer" type="primary">Close</sl-button>
|
||||
<sl-drawer label="Drawer" class="drawer-deny-close">
|
||||
This dialog will not close unless you use the button below.
|
||||
<sl-button slot="footer" type="primary">Save & Close</sl-button>
|
||||
</sl-drawer>
|
||||
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const drawer = document.querySelector('.drawer-no-overlay-dismiss');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
const drawer = document.querySelector('.drawer-deny-close');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
|
||||
drawer.addEventListener('sl-overlay-dismiss', event => event.preventDefault());
|
||||
})();
|
||||
drawer.addEventListener('sl-request-close', event => event.preventDefault());
|
||||
</script>
|
||||
```
|
||||
|
||||
### Customizing Initial Focus
|
||||
|
||||
By default, the drawer's panel will gain focus when opened. To set focus on a different element, listen for the `sl-initial-focus` event.
|
||||
By default, the drawer's panel will gain focus when opened. This allows the first tab press to focus on the first tabbable element within the drawer. To set focus on a different element, listen for and cancel the `sl-initial-focus` event.
|
||||
|
||||
```html preview
|
||||
<sl-drawer label="Drawer" class="drawer-focus">
|
||||
@@ -217,20 +204,18 @@ By default, the drawer's panel will gain focus when opened. To set focus on a di
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
const drawer = document.querySelector('.drawer-focus');
|
||||
const input = drawer.querySelector('sl-input');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
const drawer = document.querySelector('.drawer-focus');
|
||||
const input = drawer.querySelector('sl-input');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
|
||||
drawer.addEventListener('sl-initial-focus', event => {
|
||||
event.preventDefault();
|
||||
input.setFocus({ preventScroll: true });
|
||||
});
|
||||
})();
|
||||
drawer.addEventListener('sl-initial-focus', event => {
|
||||
event.preventDefault();
|
||||
input.focus({ preventScroll: true });
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Dropdowns expose additional content that "drops down" in a panel.
|
||||
|
||||
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.
|
||||
|
||||
Dropdowns are designed to work well with [menus](/components/menu.md) to provide a list of options the user can select from. However, dropdowns can also be used in lower-level applications (e.g. [color picker](/components/color-picker.md) and [select](/components/select.md)). The API gives you complete control over showing, hiding, and positioning the panel.
|
||||
Dropdowns are designed to work well with [menus](/components/menu) to provide a list of options the user can select from. However, dropdowns can also be used in lower-level applications (e.g. [color picker](/components/color-picker) and [select](/components/select)). The API gives you complete control over showing, hiding, and positioning the panel.
|
||||
|
||||
```html preview
|
||||
<sl-dropdown>
|
||||
@@ -15,10 +15,10 @@ Dropdowns are designed to work well with [menus](/components/menu.md) to provide
|
||||
<sl-menu-item>Dropdown Item 1</sl-menu-item>
|
||||
<sl-menu-item>Dropdown Item 2</sl-menu-item>
|
||||
<sl-menu-item>Dropdown Item 3</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item checked>Checked</sl-menu-item>
|
||||
<sl-menu-item disabled>Disabled</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item>
|
||||
Prefix
|
||||
<sl-icon slot="prefix" name="gift"></sl-icon>
|
||||
@@ -33,6 +33,33 @@ Dropdowns are designed to work well with [menus](/components/menu.md) to provide
|
||||
|
||||
## Examples
|
||||
|
||||
### Getting the Selected Item
|
||||
|
||||
When dropdowns are used with [menus](/components/menu), you can listen for the `sl-select` event to determine which menu item was selected. The menu item element will be exposed in `event.detail.item`. You can set `value` props to make it easier to identify commands.
|
||||
|
||||
```html preview
|
||||
<div class="dropdown-selection">
|
||||
<sl-dropdown>
|
||||
<sl-button slot="trigger" caret>Edit</sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-item value="cut">Cut</sl-menu-item>
|
||||
<sl-menu-item value="copy">Copy</sl-menu-item>
|
||||
<sl-menu-item value="paste">Paste</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.dropdown-selection');
|
||||
const dropdown = container.querySelector('sl-dropdown');
|
||||
|
||||
dropdown.addEventListener('sl-select', event => {
|
||||
const selectedItem = event.detail.item;
|
||||
console.log(selectedItem.value);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Placement
|
||||
|
||||
The preferred placement of the dropdown can be set with the `placement` attribute. Note that the actual position may vary to ensure the panel remains in the viewport.
|
||||
@@ -44,7 +71,7 @@ The preferred placement of the dropdown can be set with the `placement` attribut
|
||||
<sl-menu-item>Cut</sl-menu-item>
|
||||
<sl-menu-item>Copy</sl-menu-item>
|
||||
<sl-menu-item>Paste</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item>Find</sl-menu-item>
|
||||
<sl-menu-item>Replace</sl-menu-item>
|
||||
</sl-menu>
|
||||
@@ -62,7 +89,7 @@ The distance from the panel to the trigger can be customized using the `distance
|
||||
<sl-menu-item>Cut</sl-menu-item>
|
||||
<sl-menu-item>Copy</sl-menu-item>
|
||||
<sl-menu-item>Paste</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item>Find</sl-menu-item>
|
||||
<sl-menu-item>Replace</sl-menu-item>
|
||||
</sl-menu>
|
||||
@@ -80,7 +107,7 @@ The offset of the panel along the trigger can be customized using the `skidding`
|
||||
<sl-menu-item>Cut</sl-menu-item>
|
||||
<sl-menu-item>Copy</sl-menu-item>
|
||||
<sl-menu-item>Paste</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item>Find</sl-menu-item>
|
||||
<sl-menu-item>Replace</sl-menu-item>
|
||||
</sl-menu>
|
||||
@@ -114,64 +141,11 @@ Dropdown panels will be clipped if they're inside a container that has `overflow
|
||||
|
||||
<style>
|
||||
.dropdown-hoist {
|
||||
border: solid 2px var(--sl-panel-border-color);
|
||||
border: solid 2px rgb(var(--sl-panel-border-color));
|
||||
padding: var(--sl-spacing-medium);
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### Getting the Selected Item
|
||||
|
||||
When dropdowns are used with [menus](/components/menu.md), you can listen for the `sl-select` event to determine which menu item was selected. The menu item element will be exposed in `event.detail.item`. You can set `value` props to make it easier to identify commands.
|
||||
|
||||
```html preview
|
||||
<div class="dropdown-selection">
|
||||
<sl-dropdown>
|
||||
<sl-button slot="trigger" caret>Edit</sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-item value="cut">Cut</sl-menu-item>
|
||||
<sl-menu-item value="copy">Copy</sl-menu-item>
|
||||
<sl-menu-item value="paste">Paste</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.dropdown-selection');
|
||||
const dropdown = container.querySelector('sl-dropdown');
|
||||
|
||||
dropdown.addEventListener('sl-select', event => {
|
||||
const selectedItem = event.detail.item;
|
||||
console.log(selectedItem.value);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
Alternatively, you can listen for the `click` event on individual menu items. Note that, using this approach, disabled menu items will still emit a `click` event.
|
||||
|
||||
```html preview
|
||||
<div class="dropdown-selection-alt">
|
||||
<sl-dropdown>
|
||||
<sl-button slot="trigger" caret>Edit</sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-item value="cut">Cut</sl-menu-item>
|
||||
<sl-menu-item value="copy">Copy</sl-menu-item>
|
||||
<sl-menu-item value="paste">Paste</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.dropdown-selection-alt');
|
||||
const cut = container.querySelector('sl-menu-item[value="cut"]');
|
||||
const copy = container.querySelector('sl-menu-item[value="copy"]');
|
||||
const paste = container.querySelector('sl-menu-item[value="paste"]');
|
||||
|
||||
cut.addEventListener('click', () => console.log('cut'));
|
||||
copy.addEventListener('click', () => console.log('copy'));
|
||||
paste.addEventListener('click', () => console.log('paste'));
|
||||
</script>
|
||||
```
|
||||
|
||||
[component-metadata:sl-dropdown]
|
||||
|
||||
@@ -8,7 +8,7 @@ All Shoelace components make use of a [shadow DOM](https://developer.mozilla.org
|
||||
|
||||
This component solves that problem by serializing _both_ Shoelace form controls and native form controls when the form is submitted. The resulting form data is exposed in the `sl-submit` event as a [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object in `event.detail.formData`. You can also find an array of form controls in `event.detail.formControls`.
|
||||
|
||||
Shoelace forms don't make use of `action` and `method` attributes and they don't submit the same was as native forms. To handle submission, you need to listen for the `sl-submit` event as shown in the example below and make an XHR request with the resulting form data.
|
||||
Shoelace forms don't make use of `action` and `method` attributes and they don't submit the same way as native forms. To handle submission, you need to listen for the `sl-submit` event as shown in the example below and make an XHR request with the resulting form data.
|
||||
|
||||
```html preview
|
||||
<sl-form class="form-overview">
|
||||
@@ -75,8 +75,6 @@ When a form control is invalid, the containing form will not be submitted. Inste
|
||||
|
||||
All form controls support validation, but not all validation props are available for every component. Refer to a component's documentation to see which validation props it supports.
|
||||
|
||||
Note that validity is not checked until the user interacts with the control or its containing form is submitted. This prevents required controls from being rendered as invalid right away, which can result in a poor user experience. If you need this behavior, set the `invalid` attribute initially.
|
||||
|
||||
!> Client-side validation can be used to improve the UX of forms, but it is not a replacement for server-side validation. **You should always validate and sanitize user input on the server!**
|
||||
|
||||
### Required Fields
|
||||
@@ -181,15 +179,15 @@ The `invalid` attribute reflects the form control's validity, so you can style i
|
||||
<style>
|
||||
.custom-input[invalid]:not([disabled])::part(label),
|
||||
.custom-input[invalid]:not([disabled])::part(help-text) {
|
||||
color: var(--sl-color-danger-600);
|
||||
color: rgb(var(--sl-color-danger-600));
|
||||
}
|
||||
|
||||
.custom-input[invalid]:not([disabled])::part(base) {
|
||||
border-color: var(--sl-color-danger-500);
|
||||
border-color: rgb(var(--sl-color-danger-500));
|
||||
}
|
||||
|
||||
.custom-input[invalid] {
|
||||
--focus-ring: 0 0 0 var(--sl-focus-ring-width) var(--sl-focus-ring-color-danger);
|
||||
.custom-input[invalid]:focus-within::part(base) {
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-danger-500) / var(--sl-focus-ring-alpha));
|
||||
}
|
||||
</style>
|
||||
```
|
||||
@@ -198,7 +196,7 @@ The `invalid` attribute reflects the form control's validity, so you can style i
|
||||
|
||||
To opt out of the browser's built-in validation and use your own, add the `novalidate` attribute to the form. This will ignore all constraints and prevent the browser from showing its own warnings when form controls are invalid.
|
||||
|
||||
Remember that the `invalid` prop on form controls reflects validity as defined by the [Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation). You can set it initially, but the `invalid` prop will update as the user interacts with the form control. As such, you should not rely on it to set invalid styles using a custom validation library.
|
||||
Remember that the `invalid` attribute on form controls reflects validity as defined by the [Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation). You can set it initially, but the `invalid` attribute will update as the user interacts with the form control. As such, you should not rely on it to set invalid styles using a custom validation library.
|
||||
|
||||
Instead, toggle a class and target it in your stylesheet as shown below.
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Localization is handled by the browser's [`Intl.DateTimeFormat` API](https://dev
|
||||
<sl-format-date date="2020-07-15T09:17:00-04:00"></sl-format-date>
|
||||
```
|
||||
|
||||
The `date` prop determines the date/time to use when formatting. It must be a string that [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse) can interpret or a [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object set via JavaScript. If omitted, the current date/time will be assumed.
|
||||
The `date` attribute determines the date/time to use when formatting. It must be a string that [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse) can interpret or a [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object set via JavaScript. If omitted, the current date/time will be assumed.
|
||||
|
||||
?> When using strings, avoid ambiguous dates such as `03/04/2020` which can be interpreted as March 4 or April 3 depending on the user's browser and locale. Instead, always use a valid [ISO 8601 date time string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#Date_Time_String_Format) to ensure the date will be parsed properly by all clients.
|
||||
|
||||
@@ -44,7 +44,7 @@ Formatting options are based on those found in the [`Intl.DateTimeFormat` API](h
|
||||
|
||||
### Hour Formatting
|
||||
|
||||
By default, the browser will determine whether to use 12-hour or 24-hour time. To force one or the other, set the `hourFormat` prop to `12` or `24`.
|
||||
By default, the browser will determine whether to use 12-hour or 24-hour time. To force one or the other, set the `hour-format` attribute to `12` or `24`.
|
||||
|
||||
```html preview
|
||||
<sl-format-date hour="numeric" minute="numeric" hour-format="12"></sl-format-date><br>
|
||||
|
||||
@@ -8,8 +8,6 @@ For a full list of icons that come bundled with Shoelace, refer to the [icon com
|
||||
|
||||
```html preview
|
||||
<sl-icon-button name="gear" label="Settings"></sl-icon-button>
|
||||
<sl-icon-button name="sliders" label="Options"></sl-icon-button>
|
||||
<sl-icon-button name="x" label="Close"></sl-icon-button>
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -39,7 +37,7 @@ Icon buttons are designed to have a uniform appearance, so their color is not in
|
||||
.icon-button-color sl-icon-button::part(base) {
|
||||
color: #b00091;
|
||||
}
|
||||
|
||||
|
||||
.icon-button-color sl-icon-button::part(base):hover,
|
||||
.icon-button-color sl-icon-button::part(base):focus {
|
||||
color: #c913aa;
|
||||
@@ -51,6 +49,14 @@ Icon buttons are designed to have a uniform appearance, so their color is not in
|
||||
</style>
|
||||
```
|
||||
|
||||
### Link Buttons
|
||||
|
||||
Use the `href` attribute to convert the button to a link.
|
||||
|
||||
```html preview
|
||||
<sl-icon-button name="gear" label="Settings" href="https://example.com" target="_blank"></sl-icon-button>
|
||||
```
|
||||
|
||||
### Icon Button with Tooltip
|
||||
|
||||
Wrap a tooltip around an icon button to provide contextual information to the user.
|
||||
@@ -62,6 +68,9 @@ Wrap a tooltip around an icon button to provide contextual information to the us
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to disable the icon button.
|
||||
|
||||
```html preview
|
||||
<sl-icon-button name="gear" label="Settings" disabled></sl-icon-button>
|
||||
```
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Icons are symbols that can be used to represent various options within an application.
|
||||
|
||||
Shoelace comes bundled with over 1,300 icons courtesy of the [Bootstrap Icons](https://icons.getbootstrap.com/) project. If you prefer, you can also register a [custom icon library](#icon-libraries).
|
||||
Shoelace comes bundled with over 1,300 icons courtesy of the [Bootstrap Icons](https://icons.getbootstrap.com/) project. These icons are part of the `default` icon library. If you prefer, you can register [custom icon libraries](#icon-libraries) as well.
|
||||
|
||||
Click or tap on an icon below to copy its name and use it like this.
|
||||
|
||||
@@ -64,9 +64,11 @@ Custom icons can be loaded individually with the `src` attribute. Only SVGs on a
|
||||
|
||||
## Icon Libraries
|
||||
|
||||
Shoelace lets you register additional icons to use with the `<sl-icon>` component through icon libraries. The icon files can exist locally or on a CORS-enabled endpoint (e.g. a CDN). There is no limit to how many icon libraries you can register and there is no cost associated with registering them, as individual icons are only requested when they're used.
|
||||
You can register additional icons to use with the `<sl-icon>` component through icon libraries. Icon files can exist locally or on a CORS-enabled endpoint (e.g. a CDN). There is no limit to how many icon libraries you can register and there is no cost associated with registering them, as individual icons are only requested when they're used.
|
||||
|
||||
To register an icon library, use the `registerIconLibrary()` function that's exported from `utilities/icon-library.js`. At a minimum, you must provide a name and a resolver function. The resolver function translates an icon name to a URL where the corresponding SVG file exists. Refer to the examples below to better understand how it works.
|
||||
Shoelace ships with two built-in icon libraries, `default` and `system`. The [default icon library](#customizing-the-default-library) contains all of the icons in the Bootstrap Icons project. The [system icon library](#customizing-the-system-library) contains only a small subset of icons that are used internally by Shoelace components.
|
||||
|
||||
To register an additional icon library, use the `registerIconLibrary()` function that's exported from `utilities/icon-library.js`. At a minimum, you must provide a name and a resolver function. The resolver function translates an icon name to a URL where the corresponding SVG file exists. Refer to the examples below to better understand how it works.
|
||||
|
||||
If necessary, a mutator function can be used to mutate the SVG element before rendering. This is necessary for some libraries due to the many possible ways SVGs are crafted. For example, icons should ideally inherit the current text color via `currentColor`, so you may need to apply `fill="currentColor` or `stroke="currentColor"` to the SVG element using this function.
|
||||
|
||||
@@ -74,7 +76,7 @@ Here's an example that registers an icon library located in the `/assets/icons`
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/shoelace/dist/utilities/icon-library.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('my-icons', {
|
||||
resolver: name => `/assets/icons/${name}.svg`,
|
||||
@@ -102,7 +104,7 @@ Icons in this library are licensed under the [Creative Commons 4.0 License](http
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/shoelace.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('boxicons', {
|
||||
resolver: name => {
|
||||
@@ -156,7 +158,7 @@ Icons in this library are licensed under the [MIT License](https://github.com/fe
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/shoelace.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('feather', {
|
||||
resolver: name => `https://cdn.jsdelivr.net/npm/feather-icons@4.28.0/dist/icons/${name}.svg`
|
||||
@@ -172,7 +174,7 @@ Icons in this library are licensed under the [Font Awesome Free License](https:/
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/shoelace.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('fa', {
|
||||
resolver: name => {
|
||||
@@ -218,7 +220,7 @@ Icons in this library are licensed under the [MIT License](https://github.com/ta
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/shoelace.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('heroicons', {
|
||||
resolver: name => `https://cdn.jsdelivr.net/npm/heroicons@0.4.2/outline/${name}.svg`
|
||||
@@ -235,6 +237,31 @@ Icons in this library are licensed under the [MIT License](https://github.com/ta
|
||||
</div>
|
||||
```
|
||||
|
||||
### Iconoir
|
||||
|
||||
This will register the [Iconoir](https://iconoir.com/) library using the jsDelivr CDN.
|
||||
|
||||
Icons in this library are licensed under the [MIT License](https://github.com/lucaburgio/iconoir/blob/master/LICENSE).
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('iconoir', {
|
||||
resolver: name => `https://cdn.jsdelivr.net/gh/lucaburgio/iconoir@latest/icons/${name}.svg`
|
||||
});
|
||||
</script>
|
||||
|
||||
<div style="font-size: 24px;">
|
||||
<sl-icon library="iconoir" name="check-circled-outline"></sl-icon>
|
||||
<sl-icon library="iconoir" name="drawer"></sl-icon>
|
||||
<sl-icon library="iconoir" name="keyframes"></sl-icon>
|
||||
<sl-icon library="iconoir" name="headset-help"></sl-icon>
|
||||
<sl-icon library="iconoir" name="color-picker"></sl-icon>
|
||||
<sl-icon library="iconoir" name="wifi"></sl-icon>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Ionicons
|
||||
|
||||
This will register the [Ionicons](https://ionicons.com/) library using the jsDelivr CDN. This library has three variations: outline (default), filled (`*-filled`), and sharp (`*-sharp`). A mutator function is required to polyfill a handful of styles we're not including.
|
||||
@@ -243,11 +270,11 @@ Icons in this library are licensed under the [MIT License](https://github.com/io
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/shoelace.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('ionicons', {
|
||||
resolver: name => `https://cdn.jsdelivr.net/npm/ionicons@5.1.2/dist/ionicons/svg/${name}.svg`,
|
||||
mutator: svg => {
|
||||
mutator: svg => {
|
||||
svg.setAttribute('fill', 'currentColor');
|
||||
svg.setAttribute('stroke', 'currentColor');
|
||||
[...svg.querySelectorAll('.ionicon-fill-none')].map(el => el.setAttribute('fill', 'none'));
|
||||
@@ -288,7 +315,7 @@ Icons in this library are licensed under the [MIT License](https://github.com/mi
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/shoelace.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('jam', {
|
||||
resolver: name => `https://cdn.jsdelivr.net/npm/jam-icons@2.0.0/svg/${name}.svg`,
|
||||
@@ -321,7 +348,7 @@ Icons in this library are licensed under the [Apache 2.0 License](https://github
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/shoelace.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('material', {
|
||||
resolver: name => {
|
||||
@@ -358,31 +385,31 @@ Icons in this library are licensed under the [Apache 2.0 License](https://github
|
||||
|
||||
### Remix Icon
|
||||
|
||||
This will register the [Remix Icon](https://remixicon.com/) library using the jsDelivr CDN. This library has two variations: line (default) and fill (`*-fill`). It also groups icons by categories, so the name must include the category and icon separated by a slash. A mutator function is required to set the SVG's `fill` to `currentColor`.
|
||||
This will register the [Remix Icon](https://remixicon.com/) library using the jsDelivr CDN. This library groups icons by categories, so the name must include the category and icon separated by a slash, as well as the `-line` or `-fill` suffix as needed. A mutator function is required to set the SVG's `fill` to `currentColor`.
|
||||
|
||||
Icons in this library are licensed under the [Apache 2.0 License](https://github.com/Remix-Design/RemixIcon/blob/master/License).
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/shoelace.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('remixicon', {
|
||||
resolver: name => {
|
||||
const match = name.match(/^(.*?)\/(.*?)(-(fill))?$/);
|
||||
const match = name.match(/^(.*?)\/(.*?)?$/);
|
||||
match[1] = match[1].charAt(0).toUpperCase() + match[1].slice(1);
|
||||
return `https://cdn.jsdelivr.net/npm/remixicon@2.5.0/icons/${match[1]}/${match[2]}${match[3] || '-line'}.svg`;
|
||||
return `https://cdn.jsdelivr.net/npm/remixicon@2.5.0/icons/${match[1]}/${match[2]}.svg`;
|
||||
},
|
||||
mutator: svg => svg.setAttribute('fill', 'currentColor')
|
||||
});
|
||||
</script>
|
||||
|
||||
<div style="font-size: 24px;">
|
||||
<sl-icon library="remixicon" name="business/cloud"></sl-icon>
|
||||
<sl-icon library="remixicon" name="design/brush"></sl-icon>
|
||||
<sl-icon library="remixicon" name="business/pie-chart"></sl-icon>
|
||||
<sl-icon library="remixicon" name="development/bug"></sl-icon>
|
||||
<sl-icon library="remixicon" name="media/image"></sl-icon>
|
||||
<sl-icon library="remixicon" name="system/alert"></sl-icon>
|
||||
<sl-icon library="remixicon" name="business/cloud-line"></sl-icon>
|
||||
<sl-icon library="remixicon" name="design/brush-line"></sl-icon>
|
||||
<sl-icon library="remixicon" name="business/pie-chart-line"></sl-icon>
|
||||
<sl-icon library="remixicon" name="development/bug-line"></sl-icon>
|
||||
<sl-icon library="remixicon" name="media/image-line"></sl-icon>
|
||||
<sl-icon library="remixicon" name="system/alert-line"></sl-icon>
|
||||
<br>
|
||||
<sl-icon library="remixicon" name="business/cloud-fill"></sl-icon>
|
||||
<sl-icon library="remixicon" name="design/brush-fill"></sl-icon>
|
||||
@@ -401,7 +428,7 @@ Icons in this library are licensed under the [Apache 2.0 License](https://github
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/shoelace.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('unicons', {
|
||||
resolver: name => {
|
||||
@@ -431,13 +458,13 @@ Icons in this library are licensed under the [Apache 2.0 License](https://github
|
||||
|
||||
### Customizing the Default Library
|
||||
|
||||
Shoelace comes bundled with over 1,300 icons courtesy of the [Bootstrap Icons](https://icons.getbootstrap.com/) project. These are the default icons that display when you use `<sl-icon>` without a `name` attribute. If you prefer to have these icons resolve elsewhere, you can register an icon library with the `default` name and a custom resolver.
|
||||
The default icon library contains over 1,300 icons courtesy of the [Bootstrap Icons](https://icons.getbootstrap.com/) project. These are the icons that display when you use `<sl-icon>` without the `library` attribute. If you prefer to have these icons resolve elsewhere or to a different icon library, register an icon library using the `default` name and a custom resolver.
|
||||
|
||||
This example will load the same set of icons from the jsDelivr CDN instead of your local assets folder.
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/shoelace/dist/utilities/icon-library.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('default', {
|
||||
resolver: name => `https://cdn.jsdelivr.net/npm/bootstrap-icons@1.0.0/icons/${name}.svg`
|
||||
@@ -445,14 +472,18 @@ This example will load the same set of icons from the jsDelivr CDN instead of yo
|
||||
</script>
|
||||
```
|
||||
|
||||
Alternatively, you can replace the default icons with a completely different icon set. Just keep in mind that some of the default icons are used by components so you'll want to make sure those names resolve to an appropriate alternative.
|
||||
### Customizing the System Library
|
||||
|
||||
The system library contains only the icons used internally by Shoelace components. Unlike the default icon library, the system library does not rely on physical assets. Instead, its icons are hard-coded as data URIs into the resolver to ensure their availability.
|
||||
|
||||
If you want to change the icons Shoelace uses internally, you can register an icon library using the `system` name and a custom resolver. If you choose to do this, it's your responsibility to provide all of the icons that are required by components. You can reference `src/components/library.system.ts` for a complete list of system icons used by Shoelace.
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/shoelace/dist/utilities/icon-library.js';
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('default', {
|
||||
name => `/my/custom/icons/${name}.svg`
|
||||
registerIconLibrary('system', {
|
||||
resolver: name => `/path/to/custom/icons/${name}.svg`
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -469,6 +500,7 @@ Alternatively, you can replace the default icons with a completely different ico
|
||||
const loader = container.querySelector('.icon-loader');
|
||||
const list = container.querySelector('.icon-list');
|
||||
const queue = [];
|
||||
let inputTimeout;
|
||||
|
||||
// Generate icons
|
||||
icons.map(i => {
|
||||
@@ -499,15 +531,18 @@ Alternatively, you can replace the default icons with a completely different ico
|
||||
|
||||
// Filter as the user types
|
||||
input.addEventListener('sl-input', () => {
|
||||
[...list.querySelectorAll('.icon-list-item')].map(item => {
|
||||
const filter = input.value.toLowerCase();
|
||||
if (filter === '') {
|
||||
item.hidden = false;
|
||||
} else {
|
||||
const terms = item.getAttribute('data-terms').toLowerCase();
|
||||
item.hidden = terms.indexOf(filter) < 0;
|
||||
}
|
||||
});
|
||||
clearTimeout(inputTimeout);
|
||||
inputTimeout = setTimeout(() => {
|
||||
[...list.querySelectorAll('.icon-list-item')].map(item => {
|
||||
const filter = input.value.toLowerCase();
|
||||
if (filter === '') {
|
||||
item.hidden = false;
|
||||
} else {
|
||||
const terms = item.getAttribute('data-terms').toLowerCase();
|
||||
item.hidden = terms.indexOf(filter) < 0;
|
||||
}
|
||||
});
|
||||
}, 250);
|
||||
});
|
||||
|
||||
// Sort by type and remember preference
|
||||
@@ -523,11 +558,15 @@ Alternatively, you can replace the default icons with a completely different ico
|
||||
|
||||
<style>
|
||||
.icon-search {
|
||||
border: solid 1px var(--sl-panel-border-color);
|
||||
border: solid 1px rgb(var(--sl-panel-border-color));
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
padding: var(--sl-spacing-medium);
|
||||
}
|
||||
|
||||
.icon-search [hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.icon-search-controls {
|
||||
display: flex;
|
||||
}
|
||||
@@ -565,7 +604,7 @@ Alternatively, you can replace the default icons with a completely different ico
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--sl-border-radius-circle);
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
font-size: 24px;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
@@ -575,12 +614,8 @@ Alternatively, you can replace the default icons with a completely different ico
|
||||
}
|
||||
|
||||
.icon-list-item:hover {
|
||||
background-color: var(--sl-color-primary-50);
|
||||
color: var(--sl-color-primary-500);
|
||||
}
|
||||
|
||||
.sl-theme-dark .icon-list-item:hover {
|
||||
background-color: var(--sl-color-primary-900);
|
||||
background-color: rgb(var(--sl-color-primary-50));
|
||||
color: rgb(var(--sl-color-primary-600));
|
||||
}
|
||||
|
||||
.icon-list[data-type="outline"] .icon-list-item[data-name$="-fill"] {
|
||||
|
||||
@@ -20,7 +20,7 @@ For best results, use images that share the same dimensions. The slider can be c
|
||||
Use the `position` attribute to set the initial position of the slider. This is a percentage from `0` to `100`.
|
||||
|
||||
```html preview
|
||||
<sl-image-comparer position="0">
|
||||
<sl-image-comparer position="25">
|
||||
<img slot="before" src="https://images.unsplash.com/photo-1520903074185-8eca362b3dce?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1200&q=80" alt="A person sitting on bricks wearing untied boots.">
|
||||
<img slot="after" src="https://images.unsplash.com/photo-1520640023173-50a135e35804?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2250&q=80" alt="A person sitting on a yellow curb tying shoelaces on a boot.">
|
||||
</sl-image-comparer>
|
||||
|
||||
@@ -8,7 +8,7 @@ Included files are asynchronously requested using `window.fetch()`. Requests are
|
||||
|
||||
The included content will be inserted into the `<sl-include>` element's default slot so it can be easily accessed and styled through the light DOM.
|
||||
|
||||
```html preview
|
||||
```html preview no-codepen
|
||||
<sl-include src="/assets/examples/include.html"></sl-include>
|
||||
```
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Inputs collect data from the user.
|
||||
<sl-input></sl-input>
|
||||
```
|
||||
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form.md) instead.
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form) instead.
|
||||
|
||||
?> Please refer to the section on [form control validation](/components/form?id=form-control-validation) to learn how to do client-side validation.
|
||||
|
||||
@@ -24,7 +24,7 @@ Use the `placeholder` attribute to add a placeholder.
|
||||
|
||||
### Clearable
|
||||
|
||||
Add the `clearable` prop to add a clear button when the input has content.
|
||||
Add the `clearable` attribute to add a clear button when the input has content.
|
||||
|
||||
```html preview
|
||||
<sl-input placeholder="Clearable" clearable></sl-input>
|
||||
@@ -32,7 +32,7 @@ Add the `clearable` prop to add a clear button when the input has content.
|
||||
|
||||
### Toggle Password
|
||||
|
||||
Add the `toggle-password` prop to add a toggle button that will show the password when activated.
|
||||
Add the `toggle-password` attribute to add a toggle button that will show the password when activated.
|
||||
|
||||
```html preview
|
||||
<sl-input type="password" placeholder="Password Toggle" size="small" toggle-password></sl-input>
|
||||
@@ -42,9 +42,17 @@ Add the `toggle-password` prop to add a toggle button that will show the passwor
|
||||
<sl-input type="password" placeholder="Password Toggle" size="large" toggle-password></sl-input>
|
||||
```
|
||||
|
||||
### Filled Inputs
|
||||
|
||||
Add the `filled` attribute to draw a filled input.
|
||||
|
||||
```html preview
|
||||
<sl-input placeholder="Type something" filled></sl-input>
|
||||
```
|
||||
|
||||
### Pill
|
||||
|
||||
Use the `pill` prop to give inputs rounded edges.
|
||||
Use the `pill` attribute to give inputs rounded edges.
|
||||
|
||||
```html preview
|
||||
<sl-input placeholder="Small" size="small" pill></sl-input>
|
||||
@@ -54,6 +62,18 @@ Use the `pill` prop to give inputs rounded edges.
|
||||
<sl-input placeholder="Large" size="large" pill></sl-input>
|
||||
```
|
||||
|
||||
### Input Types
|
||||
|
||||
The `type` attribute controls the type of input the browser renders.
|
||||
|
||||
```html preview
|
||||
<sl-input type="email" Placeholder="Email"></sl-input>
|
||||
<br>
|
||||
<sl-input type="number" Placeholder="Number"></sl-input>
|
||||
<br>
|
||||
<sl-input type="date" Placeholder="Date"></sl-input>
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to disable an input.
|
||||
@@ -84,18 +104,18 @@ Use the `prefix` and `suffix` slots to add icons.
|
||||
|
||||
```html preview
|
||||
<sl-input placeholder="Small" size="small">
|
||||
<sl-icon name="tag" slot="prefix"></sl-icon>
|
||||
<sl-icon name="gear" slot="suffix"></sl-icon>
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-icon name="chat" slot="suffix"></sl-icon>
|
||||
</sl-input>
|
||||
<br>
|
||||
<sl-input placeholder="Medium" size="medium">
|
||||
<sl-icon name="tag" slot="prefix"></sl-icon>
|
||||
<sl-icon name="gear" slot="suffix"></sl-icon>
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-icon name="chat" slot="suffix"></sl-icon>
|
||||
</sl-input>
|
||||
<br>
|
||||
<sl-input placeholder="Large" size="large">
|
||||
<sl-icon name="tag" slot="prefix"></sl-icon>
|
||||
<sl-icon name="gear" slot="suffix"></sl-icon>
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-icon name="chat" slot="suffix"></sl-icon>
|
||||
</sl-input>
|
||||
```
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
# Menu Divider
|
||||
|
||||
[component-header:sl-menu-divider]
|
||||
|
||||
Menu dividers are used to visually group menu items.
|
||||
|
||||
```html preview
|
||||
<sl-menu
|
||||
style="max-width: 200px; border: solid 1px var(--sl-panel-border-color); border-radius: var(--sl-border-radius-medium);"
|
||||
>
|
||||
<sl-menu-item value="1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="2">Option 2</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-menu-item value="3">Option 3</sl-menu-item>
|
||||
<sl-menu-item value="4">Option 4</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-menu-item value="5">Option 5</sl-menu-item>
|
||||
<sl-menu-item value="6">Option 6</sl-menu-item>
|
||||
</sl-menu>
|
||||
```
|
||||
|
||||
[component-metadata:sl-menu-divider]
|
||||
@@ -5,16 +5,14 @@
|
||||
Menu items provide options for the user to pick from in a menu.
|
||||
|
||||
```html preview
|
||||
<sl-menu
|
||||
style="max-width: 200px; border: solid 1px var(--sl-panel-border-color); border-radius: var(--sl-border-radius-medium);"
|
||||
>
|
||||
<sl-menu style="max-width: 200px; border: solid 1px rgb(var(--sl-panel-border-color)); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu-item>Option 1</sl-menu-item>
|
||||
<sl-menu-item>Option 2</sl-menu-item>
|
||||
<sl-menu-item>Option 3</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item checked>Checked</sl-menu-item>
|
||||
<sl-menu-item disabled>Disabled</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item>
|
||||
Prefix Icon
|
||||
<sl-icon slot="prefix" name="gift"></sl-icon>
|
||||
@@ -26,4 +24,82 @@ Menu items provide options for the user to pick from in a menu.
|
||||
</sl-menu>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Checked
|
||||
|
||||
Use the `checked` attribute to draw menu items in a checked state.
|
||||
|
||||
```html preview
|
||||
<sl-menu style="max-width: 200px; border: solid 1px rgb(var(--sl-panel-border-color)); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu-item>Option 1</sl-menu-item>
|
||||
<sl-menu-item checked>Option 2</sl-menu-item>
|
||||
<sl-menu-item>Option 3</sl-menu-item>
|
||||
</sl-menu>
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Add the `disabled` attribute to disable the menu item so it cannot be selected.
|
||||
|
||||
```html preview
|
||||
<sl-menu style="max-width: 200px; border: solid 1px rgb(var(--sl-panel-border-color)); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu-item>Option 1</sl-menu-item>
|
||||
<sl-menu-item disabled>Option 2</sl-menu-item>
|
||||
<sl-menu-item>Option 3</sl-menu-item>
|
||||
</sl-menu>
|
||||
```
|
||||
|
||||
### Prefix & Suffix
|
||||
|
||||
Add content to the start and end of menu items using the `prefix` and `suffix` slots.
|
||||
|
||||
```html preview
|
||||
<sl-menu style="max-width: 200px; border: solid 1px rgb(var(--sl-panel-border-color)); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu-item>
|
||||
<sl-icon slot="prefix" name="house"></sl-icon>
|
||||
Home
|
||||
</sl-menu-item>
|
||||
|
||||
<sl-menu-item>
|
||||
<sl-icon slot="prefix" name="envelope"></sl-icon>
|
||||
Messages
|
||||
<sl-badge slot="suffix" type="primary" pill>12</sl-badge>
|
||||
</sl-menu-item>
|
||||
|
||||
<sl-divider></sl-divider>
|
||||
|
||||
<sl-menu-item>
|
||||
<sl-icon slot="prefix" name="gear"></sl-icon>
|
||||
Settings
|
||||
</sl-menu-item>
|
||||
</sl-menu>
|
||||
```
|
||||
|
||||
### Value & Selection
|
||||
|
||||
The `value` attribute can be used to assign a hidden value, such as a unique identifier, to a menu item. When an item is selected, the `sl-select` event will be emitted and a reference to the item will be available at `event.detail.item`. You can use this reference to access the selected item's value, its checked state, and more.
|
||||
|
||||
```html preview
|
||||
<sl-menu class="menu-value" style="max-width: 200px; border: solid 1px rgb(var(--sl-panel-border-color)); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu-item value="opt-1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="opt-2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="opt-3">Option 3</sl-menu-item>
|
||||
</sl-menu>
|
||||
|
||||
<script>
|
||||
const menu = document.querySelector('.menu-value');
|
||||
|
||||
menu.addEventListener('sl-select', event => {
|
||||
const item = event.detail.item;
|
||||
|
||||
// Toggle checked state
|
||||
item.checked = !item.checked;
|
||||
|
||||
// Log value
|
||||
console.log(`Selected value: ${item.value}`);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
[component-metadata:sl-menu-item]
|
||||
|
||||
@@ -6,13 +6,13 @@ Menu labels are used to describe a group of menu items.
|
||||
|
||||
```html preview
|
||||
<sl-menu
|
||||
style="max-width: 200px; border: solid 1px var(--sl-panel-border-color); border-radius: var(--sl-border-radius-medium);"
|
||||
style="max-width: 200px; border: solid 1px rgb(var(--sl-panel-border-color)); border-radius: var(--sl-border-radius-medium);"
|
||||
>
|
||||
<sl-menu-label>Fruits</sl-menu-label>
|
||||
<sl-menu-item value="apple">Apple</sl-menu-item>
|
||||
<sl-menu-item value="banana">Banana</sl-menu-item>
|
||||
<sl-menu-item value="orange">Orange</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-label>Vegetables</sl-menu-label>
|
||||
<sl-menu-item value="broccoli">Broccoli</sl-menu-item>
|
||||
<sl-menu-item value="carrot">Carrot</sl-menu-item>
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
Menus provide a list of options for the user to choose from.
|
||||
|
||||
Use [menu items](/components/menu-item.md), [menu dividers](/components/menu-divider.md), and [menu labels](/components/menu-label.md) to compose a menu.
|
||||
You can use [menu items](/components/menu-item), [menu labels](/components/menu-label), and [dividers](/components/divider) to compose a menu. Menus support keyboard interactions, including type-to-select an option.
|
||||
|
||||
```html preview
|
||||
<sl-menu style="max-width: 200px; border: solid 1px var(--sl-panel-border-color); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu style="max-width: 200px; border: solid 1px rgb(var(--sl-panel-border-color)); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu-item value="undo">Undo</sl-menu-item>
|
||||
<sl-menu-item value="redo">Redo</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="cut">Cut</sl-menu-item>
|
||||
<sl-menu-item value="copy">Copy</sl-menu-item>
|
||||
<sl-menu-item value="paste">Paste</sl-menu-item>
|
||||
@@ -18,4 +18,6 @@ Use [menu items](/components/menu-item.md), [menu dividers](/components/menu-div
|
||||
</sl-menu>
|
||||
```
|
||||
|
||||
?> Menus are intended for system menus (dropdown menus, select menus, context menus, etc.). They should not be mistaken for navigation menus which serve a different purpose and have a different semantic meaning. If you're building navigation, use `<nav>` and `<a>` elements instead.
|
||||
|
||||
[component-metadata:sl-menu]
|
||||
|
||||
104
docs/components/mutation-observer.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# Mutation Observer
|
||||
|
||||
[component-header:sl-mutation-observer]
|
||||
|
||||
The Mutation Observer component offers a thin, declarative interface to the [`MutationObserver API`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
|
||||
|
||||
The mutation observer will report changes to the content it wraps through the `sl-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.
|
||||
|
||||
```html preview
|
||||
<div class="mutation-overview">
|
||||
<sl-mutation-observer attr>
|
||||
<sl-button type="primary">Click to mutate</sl-button>
|
||||
</sl-mutation-observer>
|
||||
|
||||
<br>
|
||||
👆 Click the button and watch the console
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.mutation-overview');
|
||||
const mutationObserver = container.querySelector('sl-mutation-observer');
|
||||
const button = container.querySelector('sl-button');
|
||||
const types = ['primary', 'success', 'neutral', 'warning', 'danger'];
|
||||
let clicks = 0;
|
||||
|
||||
// Change the button's type attribute
|
||||
button.addEventListener('click', () => {
|
||||
clicks++;
|
||||
button.setAttribute('type', types[clicks % types.length]);
|
||||
});
|
||||
|
||||
// Log mutations
|
||||
mutationObserver.addEventListener('sl-mutation', event => {
|
||||
console.log(event.detail);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.mutation-overview sl-button {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
```
|
||||
|
||||
?> When you create a mutation observer, you must indicate what changes it should respond to by including at least one of `attr`, `child-list`, or `char-data`. If you don't specify at least one of these attributes, no mutation events will be emitted.
|
||||
|
||||
## Examples
|
||||
|
||||
### Child List
|
||||
|
||||
Use the `child-list` attribute to watch for new child elements that are added or removed.
|
||||
|
||||
```html preview
|
||||
<div class="mutation-child-list">
|
||||
<sl-mutation-observer child-list>
|
||||
<div class="buttons">
|
||||
<sl-button type="primary">Add button</sl-button>
|
||||
</div>
|
||||
</sl-mutation-observer>
|
||||
|
||||
👆 Add and remove buttons and watch the console
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.mutation-child-list');
|
||||
const mutationObserver = container.querySelector('sl-mutation-observer');
|
||||
const buttons = container.querySelector('.buttons');
|
||||
const button = container.querySelector('sl-button[type="primary"]');
|
||||
let i = 0;
|
||||
|
||||
// Add a button
|
||||
button.addEventListener('click', () => {
|
||||
const button = document.createElement('sl-button');
|
||||
button.textContent = ++i;
|
||||
buttons.append(button);
|
||||
});
|
||||
|
||||
// Remove a button
|
||||
buttons.addEventListener('click', event => {
|
||||
const target = event.target.closest('sl-button:not([type="primary"])');
|
||||
event.stopPropagation();
|
||||
|
||||
if (target) {
|
||||
target.remove();
|
||||
}
|
||||
});
|
||||
|
||||
// Log mutations
|
||||
mutationObserver.addEventListener('sl-mutation', event => {
|
||||
console.log(event.detail);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.mutation-child-list .buttons {
|
||||
display: flex;
|
||||
gap: .25rem;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
```
|
||||
|
||||
[component-metadata:sl-mutation-observer]
|
||||
@@ -5,7 +5,7 @@
|
||||
Progress bars are used to show the status of an ongoing operation.
|
||||
|
||||
```html preview
|
||||
<sl-progress-bar percentage="50"></sl-progress-bar>
|
||||
<sl-progress-bar value="50"></sl-progress-bar>
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -15,15 +15,23 @@ Progress bars are used to show the status of an ongoing operation.
|
||||
Use the `--height` custom property to set the progress bar's height.
|
||||
|
||||
```html preview
|
||||
<sl-progress-bar percentage="50" style="--height: 6px;"></sl-progress-bar>
|
||||
<sl-progress-bar value="50" style="--height: 6px;"></sl-progress-bar>
|
||||
```
|
||||
|
||||
### Labels
|
||||
|
||||
Use the default slot to show a label.
|
||||
Use the `label` attribute to label the progress bar and tell assistive devices how to announce it.
|
||||
|
||||
```html preview
|
||||
<sl-progress-bar percentage="50" class="progress-bar-labels">50%</sl-progress-bar>
|
||||
<sl-progress-bar value="50" label="Upload progress"></sl-progress-bar>
|
||||
```
|
||||
|
||||
### Showing Values
|
||||
|
||||
Use the default slot to show a value.
|
||||
|
||||
```html preview
|
||||
<sl-progress-bar value="50" class="progress-bar-values">50%</sl-progress-bar>
|
||||
|
||||
<br>
|
||||
|
||||
@@ -31,27 +39,27 @@ Use the default slot to show a label.
|
||||
<sl-button circle><sl-icon name="plus"></sl-icon></sl-button>
|
||||
|
||||
<script>
|
||||
const progressBar = document.querySelector('.progress-bar-labels');
|
||||
const progressBar = document.querySelector('.progress-bar-values');
|
||||
const subtractButton = progressBar.nextElementSibling.nextElementSibling;
|
||||
const addButton = subtractButton.nextElementSibling;
|
||||
|
||||
addButton.addEventListener('click', () => {
|
||||
const percentage = Math.min(100, progressBar.percentage + 10);
|
||||
progressBar.percentage = percentage;
|
||||
progressBar.textContent = `${percentage}%`;
|
||||
const value = Math.min(100, progressBar.value + 10);
|
||||
progressBar.value = value;
|
||||
progressBar.textContent = `${value}%`;
|
||||
});
|
||||
|
||||
subtractButton.addEventListener('click', () => {
|
||||
const percentage = Math.max(0, progressBar.percentage - 10)
|
||||
progressBar.percentage = percentage;
|
||||
progressBar.textContent = `${percentage}%`;
|
||||
const value = Math.max(0, progressBar.value - 10)
|
||||
progressBar.value = value;
|
||||
progressBar.textContent = `${value}%`;
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Indeterminate
|
||||
|
||||
The `indeterminate` attribute can be used to inform the user that the operation is pending, but its status cannot currently be determined. In this state, `percentage` is ignored and the label, if present, will not be shown.
|
||||
The `indeterminate` attribute can be used to inform the user that the operation is pending, but its status cannot currently be determined. In this state, `value` is ignored and the label, if present, will not be shown.
|
||||
|
||||
```html preview
|
||||
<sl-progress-bar indeterminate></sl-progress-bar>
|
||||
|
||||
@@ -5,25 +5,25 @@
|
||||
Progress rings are used to show the progress of a determinate operation in a circular fashion.
|
||||
|
||||
```html preview
|
||||
<sl-progress-ring percentage="50"></sl-progress-ring>
|
||||
<sl-progress-ring value="25"></sl-progress-ring>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Size
|
||||
|
||||
Use the `size` attribute to set the diameter of the progress ring.
|
||||
Use the `--size` custom property to set the diameter of the progress ring.
|
||||
|
||||
```html preview
|
||||
<sl-progress-ring percentage="50" size="200"></sl-progress-ring>
|
||||
<sl-progress-ring value="50" style="--size: 200px;"></sl-progress-ring>
|
||||
```
|
||||
|
||||
### Stroke Width
|
||||
### Track Width
|
||||
|
||||
Use the `stroke-width` attribute to set the width of the progress ring's indicator.
|
||||
Use the `--track-width` custom property to set the width of the progress ring's track.
|
||||
|
||||
```html preview
|
||||
<sl-progress-ring percentage="50" stroke-width="10"></sl-progress-ring>
|
||||
<sl-progress-ring value="50" style="--track-width: 10px;"></sl-progress-ring>
|
||||
```
|
||||
|
||||
### Colors
|
||||
@@ -32,17 +32,28 @@ To change the color, use the `--track-color` and `--indicator-color` custom prop
|
||||
|
||||
```html preview
|
||||
<sl-progress-ring
|
||||
percentage="50"
|
||||
style="--track-color: #ffe2c6; --indicator-color: tomato;"
|
||||
value="50"
|
||||
style="
|
||||
--track-color: pink;
|
||||
--indicator-color: deeppink;
|
||||
"
|
||||
></sl-progress-ring>
|
||||
```
|
||||
|
||||
### Labels
|
||||
|
||||
Use the `label` attribute to label the progress ring and tell assistive devices how to announce it.
|
||||
|
||||
```html preview
|
||||
<sl-progress-ring value="50" label="Upload progress"></sl-progress-ring>
|
||||
```
|
||||
|
||||
### Showing Values
|
||||
|
||||
Use the default slot to show a label.
|
||||
|
||||
```html preview
|
||||
<sl-progress-ring percentage="50" size="200" class="progress-ring-labels" style="margin-bottom: .5rem;">50%</sl-progress-ring>
|
||||
<sl-progress-ring value="50" class="progress-ring-values" style="margin-bottom: .5rem;">50%</sl-progress-ring>
|
||||
|
||||
<br>
|
||||
|
||||
@@ -50,20 +61,20 @@ Use the default slot to show a label.
|
||||
<sl-button circle><sl-icon name="plus"></sl-icon></sl-button>
|
||||
|
||||
<script>
|
||||
const progressRing = document.querySelector('.progress-ring-labels');
|
||||
const progressRing = document.querySelector('.progress-ring-values');
|
||||
const subtractButton = progressRing.nextElementSibling.nextElementSibling;
|
||||
const addButton = subtractButton.nextElementSibling;
|
||||
|
||||
addButton.addEventListener('click', () => {
|
||||
const percentage = Math.min(100, progressRing.percentage + 10);
|
||||
progressRing.percentage = percentage;
|
||||
progressRing.textContent = `${percentage}%`;
|
||||
const value = Math.min(100, progressRing.value + 10);
|
||||
progressRing.value = value;
|
||||
progressRing.textContent = `${value}%`;
|
||||
});
|
||||
|
||||
subtractButton.addEventListener('click', () => {
|
||||
const percentage = Math.max(0, progressRing.percentage - 10)
|
||||
progressRing.percentage = percentage;
|
||||
progressRing.textContent = `${percentage}%`;
|
||||
const value = Math.max(0, progressRing.value - 10)
|
||||
progressRing.value = value;
|
||||
progressRing.textContent = `${value}%`;
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
84
docs/components/qr-code.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# QR Code
|
||||
|
||||
[component-header:sl-qr-code]
|
||||
|
||||
Generates a [QR code](https://www.qrcode.com/) and renders it using the [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API).
|
||||
|
||||
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.
|
||||
|
||||
```html preview
|
||||
<div class="qr-overview">
|
||||
<sl-qr-code value="https://shoelace.style/" label="Scan this code to visit Shoelace on the web!"></sl-qr-code>
|
||||
<br>
|
||||
|
||||
<sl-input maxlength="255" clearable></sl-input>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.qr-overview');
|
||||
const qrCode = container.querySelector('sl-qr-code');
|
||||
const input = container.querySelector('sl-input');
|
||||
|
||||
input.value = qrCode.value;
|
||||
input.addEventListener('sl-input', () => qrCode.value = input.value);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.qr-overview {
|
||||
max-width: 256px;
|
||||
}
|
||||
|
||||
.qr-overview sl-input {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Colors
|
||||
|
||||
Use the `fill` and `background` attributes to modify the QR code's colors. You should always ensure good contrast for optimal compatibility with QR code scanners.
|
||||
|
||||
```html preview
|
||||
<sl-qr-code value="https://shoelace.style/" fill="deeppink" background="white"></sl-qr-code>
|
||||
```
|
||||
|
||||
### Size
|
||||
|
||||
Use the `size` attribute to change the size of the QR code.
|
||||
|
||||
```html preview
|
||||
<sl-qr-code value="https://shoelace.style/" size="64"></sl-qr-code>
|
||||
```
|
||||
|
||||
### Radius
|
||||
|
||||
Create a rounded effect with the `radius` attribute.
|
||||
|
||||
```html preview
|
||||
<sl-qr-code value="https://shoelace.style/" radius="0.5"></sl-qr-code>
|
||||
```
|
||||
|
||||
### Error Correction
|
||||
|
||||
QR codes can be rendered with various levels of [error correction](https://www.qrcode.com/en/about/error_correction.html) that can be set using the `error-correction` attribute. This example generates four codes with the same value using different error correction levels.
|
||||
|
||||
```html preview
|
||||
<div class="qr-error-correction">
|
||||
<sl-qr-code value="https://shoelace.style/" error-correction="L"></sl-qr-code>
|
||||
<sl-qr-code value="https://shoelace.style/" error-correction="M"></sl-qr-code>
|
||||
<sl-qr-code value="https://shoelace.style/" error-correction="Q"></sl-qr-code>
|
||||
<sl-qr-code value="https://shoelace.style/" error-correction="H"></sl-qr-code>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.qr-error-correction {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
[component-metadata:sl-qr-code]
|
||||
29
docs/components/radio-group.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Radio Group
|
||||
|
||||
[component-header:sl-radio-group]
|
||||
|
||||
Radio Groups are used to group multiple radios so they function as a single control.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an item">
|
||||
<sl-radio value="1" checked>Item 1</sl-radio>
|
||||
<sl-radio value="2">Item 2</sl-radio>
|
||||
<sl-radio value="3">Item 3</sl-radio>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Showing the Fieldset
|
||||
|
||||
You can show a fieldset and legend that wraps the radio group using the `fieldset` attribute.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an item" fieldset>
|
||||
<sl-radio value="1" checked>Item 1</sl-radio>
|
||||
<sl-radio value="2">Item 2</sl-radio>
|
||||
<sl-radio value="3">Item 3</sl-radio>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
[component-metadata:sl-radio-group]
|
||||
@@ -4,39 +4,31 @@
|
||||
|
||||
Radios allow the user to select one option from a group of many.
|
||||
|
||||
Radios are designed to be used with [radio groups](/components/radio-group). As such, all of the examples on this page utilize them to demonstrate their correct usage.
|
||||
|
||||
```html preview
|
||||
<sl-radio>Radio</sl-radio>
|
||||
<sl-radio-group label="Select an option" no-fieldset>
|
||||
<sl-radio value="1" checked>Option 1</sl-radio>
|
||||
<sl-radio value="2">Option 2</sl-radio>
|
||||
<sl-radio value="3">Option 3</sl-radio>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form.md) instead.
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form) instead.
|
||||
|
||||
## Examples
|
||||
|
||||
### Checked
|
||||
|
||||
Use the `checked` attribute to activate the radio.
|
||||
|
||||
```html preview
|
||||
<sl-radio checked>Checked</sl-radio>
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to disable the radio.
|
||||
Use the `disabled` attribute to disable a radio.
|
||||
|
||||
```html preview
|
||||
<sl-radio disabled>Disabled</sl-radio>
|
||||
```
|
||||
|
||||
### Grouping Radios
|
||||
|
||||
Radios are grouped based on their `name` attribute and scoped to the nearest form.
|
||||
|
||||
```html preview
|
||||
<sl-radio name="option" checked>Option 1</sl-radio><br>
|
||||
<sl-radio name="option">Option 2</sl-radio><br>
|
||||
<sl-radio name="option">Option 3</sl-radio><br>
|
||||
<sl-radio name="option">Option 4</sl-radio>
|
||||
<sl-radio-group label="Select an option" no-fieldset>
|
||||
<sl-radio value="1" checked>Option 1</sl-radio>
|
||||
<sl-radio value="2">Option 2</sl-radio>
|
||||
<sl-radio value="3">Option 3</sl-radio>
|
||||
<sl-radio value="4" disabled>Disabled</sl-radio>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
[component-metadata:sl-radio]
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
Ranges allow the user to select a single value within a given range using a slider.
|
||||
|
||||
```html preview
|
||||
<sl-range min="0" max="100" step="1"></sl-range>
|
||||
<sl-range></sl-range>
|
||||
```
|
||||
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form.md) instead.
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form) instead.
|
||||
|
||||
## Examples
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable a slider.
|
||||
Use the `disabled` attribute to disable a slider.
|
||||
|
||||
```html preview
|
||||
<sl-range min="0" max="100" step="1" disabled></sl-range>
|
||||
@@ -36,9 +36,20 @@ To disable the tooltip, set `tooltip` to `none`.
|
||||
<sl-range min="0" max="100" step="1" tooltip="none"></sl-range>
|
||||
```
|
||||
|
||||
### Custom Track Colors
|
||||
|
||||
You can customize the active and inactive portions of the track using the `--track-color-active` and `--track-color-inactive` custom properties.
|
||||
|
||||
```html preview
|
||||
<sl-range style="
|
||||
--track-color-active: rgb(var(--sl-color-primary-600));
|
||||
--track-color-inactive: rgb(var(--sl-color-primary-200));
|
||||
"></sl-range>
|
||||
```
|
||||
|
||||
### Custom Tooltip Formatter
|
||||
|
||||
You can change the tooltip's content by setting the `tooltipFormatter` prop to a function that accepts the range's value as an argument.
|
||||
You can change the tooltip's content by setting the `tooltipFormatter` property to a function that accepts the range's value as an argument.
|
||||
|
||||
```html preview
|
||||
<sl-range min="0" max="100" step="1" class="range-with-custom-formatter"></sl-range>
|
||||
|
||||
@@ -53,7 +53,12 @@ Use the `disable` attribute to disable the rating.
|
||||
### Custom Icons
|
||||
|
||||
```html preview
|
||||
<sl-rating symbol="heart-fill" style="--symbol-color-active: #ff4136;"></sl-rating>
|
||||
<sl-rating class="rating-hearts" style="--symbol-color-active: #ff4136;"></sl-rating>
|
||||
|
||||
<script>
|
||||
const rating = document.querySelector('.rating-hearts');
|
||||
rating.getSymbol = () => '<sl-icon name="heart-fill"></sl-icon>';
|
||||
</script>
|
||||
```
|
||||
|
||||
### Value-based Icons
|
||||
@@ -64,9 +69,9 @@ Use the `disable` attribute to disable the rating.
|
||||
<script>
|
||||
const rating = document.querySelector('.rating-emojis');
|
||||
|
||||
rating.symbol = (value) => {
|
||||
rating.getSymbol = (value) => {
|
||||
const icons = ['emoji-angry', 'emoji-frown', 'emoji-expressionless', 'emoji-smile', 'emoji-laughing'];
|
||||
return icons[value - 1];
|
||||
return `<sl-icon name="${icons[value - 1]}"></sl-icon>`;
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -11,7 +11,7 @@ Localization is handled by the browser's [`Intl.RelativeTimeFormat` API](https:/
|
||||
<sl-relative-time date="2020-07-15T09:17:00-04:00"></sl-relative-time>
|
||||
```
|
||||
|
||||
The `date` prop determines when the date/time is calculated from. It must be a string that [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse) can interpret or a [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object set via JavaScript.
|
||||
The `date` attribute determines when the date/time is calculated from. It must be a string that [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse) can interpret or a [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object set via JavaScript.
|
||||
|
||||
?> When using strings, avoid ambiguous dates such as `03/04/2020` which can be interpreted as March 4 or April 3 depending on the user's browser and locale. Instead, always use a valid [ISO 8601 date time string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#Date_Time_String_Format) to ensure the date will be parsed properly by all clients.
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
[component-header:sl-resize-observer]
|
||||
|
||||
Resize observers offer a thin, declarative interface to the [`ResizeObserver API`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
|
||||
The Resize Observer component offers a thin, declarative interface to the [`ResizeObserver API`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
|
||||
|
||||
The resize observer will report changes to the dimensions of the elements it wraps through the `sl-resize` event. When emitted, a collection of [`ResizeObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry) objects will be attached to `event.detail`, containing the target element and information about its dimensions.
|
||||
The resize observer will report changes to the dimensions of the elements it wraps through the `sl-resize` event. When emitted, a collection of [`ResizeObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry) objects will be attached to `event.detail` that contains the target element and information about its dimensions.
|
||||
|
||||
```html preview
|
||||
<div class="resize-observer-overview">
|
||||
@@ -20,14 +20,14 @@ The resize observer will report changes to the dimensions of the elements it wra
|
||||
const resizeObserver = container.querySelector('sl-resize-observer');
|
||||
|
||||
resizeObserver.addEventListener('sl-resize', event => {
|
||||
console.log(event);
|
||||
console.log(event.detail);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.resize-observer-overview div {
|
||||
display: flex;
|
||||
border: solid 2px var(--sl-input-border-color);
|
||||
border: solid 2px rgb(var(--sl-input-border-color));
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# Responsive Embed
|
||||
|
||||
[component-header:sl-responsive-embed]
|
||||
|
||||
Displays embedded media in a responsive manner based on its aspect ratio.
|
||||
|
||||
You can embed any element of the `<iframe>`, `<embed>`, or `<object>` type. The default aspect ratio is `16:9`.
|
||||
|
||||
```html preview
|
||||
<sl-responsive-embed>
|
||||
<iframe src="https://player.vimeo.com/video/1053647?title=0&byline=0&portrait=0" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe>
|
||||
</sl-responsive-embed>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Aspect Ratio
|
||||
|
||||
To set the aspect ratio, use the `aspect-ratio` attribute.
|
||||
|
||||
```html preview
|
||||
<sl-responsive-embed aspect-ratio="4:3">
|
||||
<iframe src="https://www.youtube.com/embed/mM5_T-F1Yn4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</sl-responsive-embed>
|
||||
```
|
||||
|
||||
[component-metadata:sl-responsive-embed]
|
||||
37
docs/components/responsive-media.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Responsive Media
|
||||
|
||||
[component-header:sl-responsive-media]
|
||||
|
||||
Displays media in the desired aspect ratio.
|
||||
|
||||
You can slot in any [replaced element](https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element), including `<iframe>`, `<img>`, and `<video>`. As the element's width changes, its height will resize proportionally. Only one element should be slotted into the container. The default aspect ratio is `16:9`.
|
||||
|
||||
```html preview
|
||||
<sl-responsive-media>
|
||||
<img src="https://images.unsplash.com/photo-1541427468627-a89a96e5ca1d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1800&q=80" alt="A train riding through autumn foliage with mountains in the distance.">
|
||||
</sl-responsive-media>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Responsive Images
|
||||
|
||||
The following image maintains a `4:3` aspect ratio as its container is resized.
|
||||
|
||||
```html preview
|
||||
<sl-responsive-media aspect-ratio="4:3">
|
||||
<img src="https://images.unsplash.com/photo-1473186578172-c141e6798cf4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1800&q=80" alt="Two blue chairs on a sandy beach.">
|
||||
</sl-responsive-media>
|
||||
```
|
||||
|
||||
### Responsive Videos
|
||||
|
||||
The following video is embedded using an `iframe` and maintains a `16:9` aspect ratio as its container is resized.
|
||||
|
||||
```html preview
|
||||
<sl-responsive-media aspect-ratio="16:9">
|
||||
<iframe src="https://player.vimeo.com/video/1053647?title=0&byline=0&portrait=0" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe>
|
||||
</sl-responsive-media>
|
||||
```
|
||||
|
||||
[component-metadata:sl-responsive-media]
|
||||
@@ -9,14 +9,14 @@ Selects allow you to choose one or more items from a dropdown menu.
|
||||
<sl-menu-item value="option-1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="option-2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="option-3">Option 3</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="option-4">Option 4</sl-menu-item>
|
||||
<sl-menu-item value="option-5">Option 5</sl-menu-item>
|
||||
<sl-menu-item value="option-6">Option 6</sl-menu-item>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form.md) instead.
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form) instead.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -44,9 +44,21 @@ Use the `clearable` attribute to make the control clearable.
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
### Filled Selects
|
||||
|
||||
Add the `filled` attribute to draw a filled select.
|
||||
|
||||
```html preview
|
||||
<sl-select filled>
|
||||
<sl-menu-item value="option-1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="option-2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="option-3">Option 3</sl-menu-item>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
### Pill
|
||||
|
||||
Use the `pill` prop to give selects rounded edges.
|
||||
Use the `pill` attribute to give selects rounded edges.
|
||||
|
||||
```html preview
|
||||
<sl-select pill>
|
||||
@@ -58,7 +70,7 @@ Use the `pill` prop to give selects rounded edges.
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable a select.
|
||||
Use the `disabled` attribute to disable a select.
|
||||
|
||||
```html preview
|
||||
<sl-select placeholder="Disabled" disabled>
|
||||
@@ -77,7 +89,7 @@ To allow multiple options to be selected, use the `multiple` attribute. It's a g
|
||||
<sl-menu-item value="option-1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="option-2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="option-3">Option 3</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="option-4">Option 4</sl-menu-item>
|
||||
<sl-menu-item value="option-5">Option 5</sl-menu-item>
|
||||
<sl-menu-item value="option-6">Option 6</sl-menu-item>
|
||||
@@ -86,7 +98,7 @@ To allow multiple options to be selected, use the `multiple` attribute. It's a g
|
||||
|
||||
### Grouping Options
|
||||
|
||||
Options can be grouped visually using menu labels and menu dividers.
|
||||
Options can be grouped visually using menu labels and dividers.
|
||||
|
||||
```html preview
|
||||
<sl-select placeholder="Select one">
|
||||
@@ -94,7 +106,7 @@ Options can be grouped visually using menu labels and menu dividers.
|
||||
<sl-menu-item value="option-1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="option-2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="option-3">Option 3</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-label>Group 2</sl-menu-label>
|
||||
<sl-menu-item value="option-4">Option 4</sl-menu-item>
|
||||
<sl-menu-item value="option-5">Option 5</sl-menu-item>
|
||||
@@ -132,7 +144,7 @@ Use the `size` attribute to change a select's size.
|
||||
|
||||
### Selecting Options Programmatically
|
||||
|
||||
The `value` prop is bound to the current selection. As the selection changes, so will the value. To programmatically manage the selection, update the `value` property.
|
||||
The `value` property is bound to the current selection. As the selection changes, so will the value. To programmatically manage the selection, update the `value` property.
|
||||
|
||||
```html preview
|
||||
<div class="selecting-example">
|
||||
@@ -188,4 +200,34 @@ Add descriptive help text to a select with the `help-text` attribute. For help t
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
### Prefix & Suffix Icons
|
||||
|
||||
Use the `prefix` and `suffix` slots to add icons.
|
||||
|
||||
```html preview
|
||||
<sl-select placeholder="Small" size="small">
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-menu-item value="option-1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="option-2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="option-3">Option 3</sl-menu-item>
|
||||
<sl-icon name="chat" slot="suffix"></sl-icon>
|
||||
</sl-select>
|
||||
<br>
|
||||
<sl-select placeholder="Medium" size="medium">
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-menu-item value="option-1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="option-2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="option-3">Option 3</sl-menu-item>
|
||||
<sl-icon name="chat" slot="suffix"></sl-icon>
|
||||
</sl-select>
|
||||
<br>
|
||||
<sl-select placeholder="Large" size="large">
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-menu-item value="option-1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="option-2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="option-3">Option 3</sl-menu-item>
|
||||
<sl-icon name="chat" slot="suffix"></sl-icon>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
[component-metadata:sl-select]
|
||||
|
||||
@@ -58,18 +58,18 @@ Skeletons try not to be opinionated, as there are endless possibilities for desi
|
||||
|
||||
### Effects
|
||||
|
||||
The default effect is `sheen`, which animates a sheen horizontally across the skeleton. There's also `pulse`, which fades the skeleton in and out. To disable animations, use `none`. Effects are intentionally subtle, as they can be distracting otherwise.
|
||||
There are two built-in effects, `sheen` and `pulse`. Effects are intentionally subtle, as they can be distracting when used extensively. The default is `none`, which displays a static, non-animated skeleton.
|
||||
|
||||
```html preview
|
||||
<div class="skeleton-effects">
|
||||
<sl-skeleton effect="none"></sl-skeleton>
|
||||
None
|
||||
|
||||
<sl-skeleton effect="sheen"></sl-skeleton>
|
||||
Sheen
|
||||
|
||||
<sl-skeleton effect="pulse"></sl-skeleton>
|
||||
Pulse
|
||||
|
||||
<sl-skeleton effect="none"></sl-skeleton>
|
||||
None
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -198,7 +198,7 @@ Use the `--border-radius` custom property to make circles, squares, and rectangl
|
||||
Set the `--color` and `--sheen-color` custom properties to adjust the skeleton's color.
|
||||
|
||||
```html preview
|
||||
<sl-skeleton style="--color: tomato; --sheen-color: #ffb094;"></sl-skeleton>
|
||||
<sl-skeleton effect="sheen" style="--color: tomato; --sheen-color: #ffb094;"></sl-skeleton>
|
||||
```
|
||||
|
||||
[component-metadata:sl-skeleton]
|
||||
|
||||
@@ -12,7 +12,7 @@ Spinners are used to show the progress of an indeterminate operation.
|
||||
|
||||
### Size
|
||||
|
||||
Spinners are sized relative to the current font size. To change their size, set the `font-size` property on the spinner itself or on a parent element as shown below.
|
||||
Spinners are sized based on the current font size. To change their size, set the `font-size` property on the spinner itself or on a parent element as shown below.
|
||||
|
||||
```html preview
|
||||
<sl-spinner></sl-spinner>
|
||||
@@ -20,12 +20,12 @@ Spinners are sized relative to the current font size. To change their size, set
|
||||
<sl-spinner style="font-size: 3rem;"></sl-spinner>
|
||||
```
|
||||
|
||||
### Stroke Width
|
||||
### Track Width
|
||||
|
||||
The width of the spinner can be changed by setting the `--stroke-width` custom property.
|
||||
The width of the spinner's track can be changed by setting the `--track-width` custom property.
|
||||
|
||||
```html preview
|
||||
<sl-spinner style="font-size: 2rem; --stroke-width: 6px;"></sl-spinner>
|
||||
<sl-spinner style="font-size: 3rem; --track-width: 6px;"></sl-spinner>
|
||||
```
|
||||
|
||||
### Color
|
||||
@@ -33,7 +33,7 @@ The width of the spinner can be changed by setting the `--stroke-width` custom p
|
||||
The spinner's colors can be changed by setting the `--indicator-color` and `--track-color` custom properties.
|
||||
|
||||
```html preview
|
||||
<sl-spinner style="font-size: 2rem; --indicator-color: tomato;"></sl-spinner>
|
||||
<sl-spinner style="font-size: 3rem; --indicator-color: deeppink; --track-color: pink;"></sl-spinner>
|
||||
```
|
||||
|
||||
[component-metadata:sl-spinner]
|
||||
|
||||
@@ -8,7 +8,7 @@ Switches allow the user to toggle an option on or off.
|
||||
<sl-switch>Switch</sl-switch>
|
||||
```
|
||||
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form.md) instead.
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form) instead.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Tab groups organize content into a container that shows one section at a time.
|
||||
|
||||
Tab groups make use of [tabs](/components/tab.md) and [tab panels](/components/tab-panel.md). Each tab must be slotted into the `nav` slot and its `panel` must refer to a tab panel of the same name.
|
||||
Tab groups make use of [tabs](/components/tab) and [tab panels](/components/tab-panel). Each tab must be slotted into the `nav` slot and its `panel` must refer to a tab panel of the same name.
|
||||
|
||||
```html preview
|
||||
<sl-tab-group>
|
||||
@@ -40,12 +40,12 @@ Tabs can be shown on the bottom by setting `placement` to `bottom`.
|
||||
</sl-tab-group>
|
||||
```
|
||||
|
||||
### Tabs on Left
|
||||
### Tabs on Start
|
||||
|
||||
Tabs can be shown on the left by setting `placement` to `left`.
|
||||
Tabs can be shown on the starting side by setting `placement` to `start`.
|
||||
|
||||
```html preview
|
||||
<sl-tab-group placement="left">
|
||||
<sl-tab-group placement="start">
|
||||
<sl-tab slot="nav" panel="general">General</sl-tab>
|
||||
<sl-tab slot="nav" panel="custom">Custom</sl-tab>
|
||||
<sl-tab slot="nav" panel="advanced">Advanced</sl-tab>
|
||||
@@ -58,12 +58,12 @@ Tabs can be shown on the left by setting `placement` to `left`.
|
||||
</sl-tab-group>
|
||||
```
|
||||
|
||||
### Tabs on Right
|
||||
### Tabs on End
|
||||
|
||||
Tabs can be shown on the right by setting `placement` to `right`.
|
||||
Tabs can be shown on the ending side by setting `placement` to `end`.
|
||||
|
||||
```html preview
|
||||
<sl-tab-group placement="right">
|
||||
<sl-tab-group placement="end">
|
||||
<sl-tab slot="nav" panel="general">General</sl-tab>
|
||||
<sl-tab slot="nav" panel="custom">Custom</sl-tab>
|
||||
<sl-tab slot="nav" panel="advanced">Advanced</sl-tab>
|
||||
@@ -78,7 +78,7 @@ Tabs can be shown on the right by setting `placement` to `right`.
|
||||
|
||||
### Closable Tabs
|
||||
|
||||
Add the `closable` prop to a tab to show a close button. This example shows how you can dynamically remove tabs from the DOM when the close button is activated.
|
||||
Add the `closable` attribute to a tab to show a close button. This example shows how you can dynamically remove tabs from the DOM when the close button is activated.
|
||||
|
||||
```html preview
|
||||
<sl-tab-group class="tabs-closable">
|
||||
@@ -162,4 +162,22 @@ When there are more tabs than horizontal space allows, the nav will be scrollabl
|
||||
</sl-tab-group>
|
||||
```
|
||||
|
||||
### Manual Activation
|
||||
|
||||
When focused, keyboard users can press <kbd>Left</kbd> or <kbd>Right</kbd> to select the desired tab. By default, the corresponding tab panel will be shown immediately (automatic activation). You can change this behavior by setting `activation="manual"` which will require the user to press <kbd>Space</kbd> or <kbd>Enter</kbd> before showing the tab panel (manual activation).
|
||||
|
||||
```html preview
|
||||
<sl-tab-group activation="manual">
|
||||
<sl-tab slot="nav" panel="general">General</sl-tab>
|
||||
<sl-tab slot="nav" panel="custom">Custom</sl-tab>
|
||||
<sl-tab slot="nav" panel="advanced">Advanced</sl-tab>
|
||||
<sl-tab slot="nav" panel="disabled" disabled>Disabled</sl-tab>
|
||||
|
||||
<sl-tab-panel name="general">This is the general tab panel.</sl-tab-panel>
|
||||
<sl-tab-panel name="custom">This is the custom tab panel.</sl-tab-panel>
|
||||
<sl-tab-panel name="advanced">This is the advanced tab panel.</sl-tab-panel>
|
||||
<sl-tab-panel name="disabled">This is a disabled tab panel.</sl-tab-panel>
|
||||
</sl-tab-group>
|
||||
```
|
||||
|
||||
[component-metadata:sl-tab-group]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[component-header:sl-tab-panel]
|
||||
|
||||
Tab panels are used inside tab groups to display content.
|
||||
Tab panels are used inside [tab groups](/components/tab-group) to display tabbed content.
|
||||
|
||||
```html preview
|
||||
<sl-tab-group>
|
||||
@@ -18,6 +18,6 @@ Tab panels are used inside tab groups to display content.
|
||||
</sl-tab-group>
|
||||
```
|
||||
|
||||
?> Additional demonstrations can be found in the [tab group examples](/components/tab-group.md).
|
||||
?> Additional demonstrations can be found in the [tab group examples](/components/tab-group).
|
||||
|
||||
[component-metadata:sl-tab-panel]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[component-header:sl-tab]
|
||||
|
||||
Tabs are used inside tab groups to represent tab panels.
|
||||
Tabs are used inside [tab groups](/components/tab-group) to represent and activate [tab panels](/components/tab-panel).
|
||||
|
||||
```html preview
|
||||
<sl-tab>Tab</sl-tab>
|
||||
@@ -11,6 +11,6 @@ Tabs are used inside tab groups to represent tab panels.
|
||||
<sl-tab disabled>Disabled</sl-tab>
|
||||
```
|
||||
|
||||
?> Additional demonstrations can be found in the [tab group examples](/components/tab-group.md).
|
||||
?> Additional demonstrations can be found in the [tab group examples](/components/tab-group).
|
||||
|
||||
[component-metadata:sl-tab]
|
||||
|
||||
@@ -7,7 +7,7 @@ Tags are used as labels to organize things or to indicate a selection.
|
||||
```html preview
|
||||
<sl-tag type="primary">Primary</sl-tag>
|
||||
<sl-tag type="success">Success</sl-tag>
|
||||
<sl-tag type="info">Info</sl-tag>
|
||||
<sl-tag type="neutral">Neutral</sl-tag>
|
||||
<sl-tag type="warning">Warning</sl-tag>
|
||||
<sl-tag type="danger">Danger</sl-tag>
|
||||
```
|
||||
@@ -16,7 +16,7 @@ Tags are used as labels to organize things or to indicate a selection.
|
||||
|
||||
### Sizes
|
||||
|
||||
Use the `size` prop to change a tab's size.
|
||||
Use the `size` attribute to change a tab's size.
|
||||
|
||||
```html preview
|
||||
<sl-tag size="small">Small</sl-tag>
|
||||
@@ -26,7 +26,7 @@ Use the `size` prop to change a tab's size.
|
||||
|
||||
### Pill
|
||||
|
||||
Use the `pill` prop to give tabs rounded edges.
|
||||
Use the `pill` attribute to give tabs rounded edges.
|
||||
|
||||
```html preview
|
||||
<sl-tag size="small" pill>Small</sl-tag>
|
||||
@@ -34,21 +34,21 @@ Use the `pill` prop to give tabs rounded edges.
|
||||
<sl-tag size="large" pill>Large</sl-tag>
|
||||
```
|
||||
|
||||
### Clearable
|
||||
### Removable
|
||||
|
||||
Use the `clearable` attribute to add a clear button to the tag.
|
||||
Use the `removable` attribute to add a remove button to the tag.
|
||||
|
||||
```html preview
|
||||
<div class="tags-clearable">
|
||||
<sl-tag size="small" clearable>Small</sl-tag>
|
||||
<sl-tag size="medium" clearable>Medium</sl-tag>
|
||||
<sl-tag size="large" clearable>Large</sl-tag>
|
||||
<div class="tags-removable">
|
||||
<sl-tag size="small" removable>Small</sl-tag>
|
||||
<sl-tag size="medium" removable>Medium</sl-tag>
|
||||
<sl-tag size="large" removable>Large</sl-tag>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const div = document.querySelector('.tags-clearable');
|
||||
const div = document.querySelector('.tags-removable');
|
||||
|
||||
div.addEventListener('sl-clear', event => {
|
||||
div.addEventListener('sl-remove', event => {
|
||||
const tag = event.target;
|
||||
tag.style.opacity = '0';
|
||||
setTimeout(() => tag.style.opacity = '1', 2000);
|
||||
@@ -56,7 +56,7 @@ Use the `clearable` attribute to add a clear button to the tag.
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tags-clearable sl-tag {
|
||||
.tags-removable sl-tag {
|
||||
transition: var(--sl-transition-medium) opacity;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,7 +8,7 @@ Textareas collect data from the user and allow multiple lines of text.
|
||||
<sl-textarea></sl-textarea>
|
||||
```
|
||||
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form.md) instead.
|
||||
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form) instead.
|
||||
|
||||
?> Please refer to the section on [form control validation](/components/form?id=form-control-validation) to learn how to do client-side validation.
|
||||
|
||||
@@ -30,9 +30,17 @@ Use the `placeholder` attribute to add a placeholder.
|
||||
<sl-textarea placeholder="Type something"></sl-textarea>
|
||||
```
|
||||
|
||||
### Filled Textareas
|
||||
|
||||
Add the `filled` attribute to draw a filled textarea.
|
||||
|
||||
```html preview
|
||||
<sl-textarea placeholder="Type something" filled></sl-textarea>
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to disable an input.
|
||||
Use the `disabled` attribute to disable a textarea.
|
||||
|
||||
```html preview
|
||||
<sl-textarea placeholder="Textarea" disabled></sl-textarea>
|
||||
|
||||
@@ -122,7 +122,7 @@ Set the `trigger` attribute to `click` to toggle the tooltip on click instead of
|
||||
|
||||
### Manual Trigger
|
||||
|
||||
Tooltips can be controller programmatically by setting the `trigger` attribute to `manual`. Use the `open` prop to control when the tooltip is shown.
|
||||
Tooltips can be controller programmatically by setting the `trigger` attribute to `manual`. Use the `open` attribute to control when the tooltip is shown.
|
||||
|
||||
```html preview
|
||||
<sl-button style="margin-right: 4rem;">Toggle Manually</sl-button>
|
||||
@@ -155,7 +155,7 @@ You can control the size of tooltip arrows by overriding the `--sl-tooltip-arrow
|
||||
</div>
|
||||
```
|
||||
|
||||
To override it globally, set it in a root block in your stylesheet after `shoelace.css` is loaded.
|
||||
To override it globally, set it in a root block in your stylesheet after the Shoelace stylesheet is loaded.
|
||||
|
||||
```css
|
||||
:root {
|
||||
@@ -165,7 +165,7 @@ To override it globally, set it in a root block in your stylesheet after `shoela
|
||||
|
||||
### HTML in Tooltips
|
||||
|
||||
Use the `content` slot to create tooltips with HTML content.
|
||||
Use the `content` slot to create tooltips with HTML content. Tooltips are designed only for text and presentational elements. Avoid placing interactive content, such as buttons, links, and form controls, in a tooltip.
|
||||
|
||||
```html preview
|
||||
<sl-tooltip>
|
||||
@@ -174,4 +174,29 @@ Use the `content` slot to create tooltips with HTML content.
|
||||
</sl-tooltip>
|
||||
```
|
||||
|
||||
### Hoisting
|
||||
|
||||
Tooltips will be clipped if they're inside a container that has `overflow: auto|hidden|scroll`. The `hoist` attribute forces the tooltip to use a fixed positioning strategy, allowing it to break out of the container. In this case, the tooltip will be positioned relative to its containing block, which is usually the viewport unless an ancestor uses a `transform`, `perspective`, or `filter`. [Refer to this page](https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed) for more details.
|
||||
|
||||
```html preview
|
||||
<div class="tooltip-hoist">
|
||||
<sl-tooltip content="This is a tooltip">
|
||||
<sl-button>No Hoist</sl-button>
|
||||
</sl-tooltip>
|
||||
|
||||
<sl-tooltip content="This is a tooltip" hoist>
|
||||
<sl-button>Hoist</sl-button>
|
||||
</sl-tooltip>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.tooltip-hoist {
|
||||
border: solid 2px rgb(var(--sl-panel-border-color));
|
||||
overflow: hidden;
|
||||
padding: var(--sl-spacing-medium);
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
[component-metadata:sl-tooltip]
|
||||
|
||||
@@ -1,392 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
Shoelace follows [Semantic Versioning](https://semver.org/). Breaking changes in components with the <sl-badge type="primary" pill>Stable</sl-badge> badge will not be accepted until the next major version. As such, all contributions must consider the project's roadmap and take this into consideration. Features that are deemed no longer necessary will be deprecated but not removed.
|
||||
|
||||
Components with the <sl-badge type="warning" pill>Experimental</sl-badge> badge should not be used in production. They are made available as release candidates for development and testing purposes. As such, changes to experimental components will not be subject to semantic versioning.
|
||||
|
||||
_During the beta period, these restrictions may be relaxed in the event of a mission-critical bug._ 🐛
|
||||
|
||||
## 2.0.0-beta.28
|
||||
|
||||
**This release includes a major under the hood overhaul of the library and how it's distributed.** Until now, Shoelace was developed with Stencil. This release moves to a lightweight tool called [Shoemaker](https://github.com/shoelace-style/shoemaker), a homegrown utility that provides declarative templating and data binding while reducing the boilerplate required for said features. The base class is open source and less than [200 lines of code](https://github.com/shoelace-style/shoemaker/blob/master/src/shoemaker.ts).
|
||||
|
||||
This change in tooling addresses a number of longstanding bugs and limitations. It also gives us more control over the library and build process while streamlining development and maintenance. Instead of two different distributions, Shoelace now offers a single, standards-compliant collection of ES modules. This may affect how you install and use the library, so please refer to the [installation page](/getting-started/installation) for details.
|
||||
|
||||
!> Due to the large number of internal changes, I would consider this update to be less stable than previous ones. If you're using Shoelace in a production app, consider holding off until the next beta to allow for more exhaustive testing from the community. Please report any bugs you find on the [issue tracker](https://github.com/shoelace-style/shoelace/issues).
|
||||
|
||||
The component API remains the same except for the changes noted below. Thanks for your patience as I work diligently to make Shoelace more stable and future-proof. 🙌
|
||||
|
||||
- 🚨 BREAKING: removed the custom elements bundle (you can import ES modules directly)
|
||||
- 🚨 BREAKING: removed `getAnimationNames()` and `getEasingNames()` methods from `sl-animation` (you can import them from `utilities/animation.js` instead)
|
||||
- 🚨 BREAKING: removed the `sl-icon-library` component since it required imperative initialization (you can import the `registerIconLibrary()` function from `utilities/icon-library.js` instead)
|
||||
- 🚨 BREAKING: removed the experimental `sl-theme` component due to limitations (you should set the `sl-theme-[name]` class on the `<body>` instead)
|
||||
- 🚨 BREAKING: moved the base stylesheet from `dist/shoelace.css` to `dist/themes/base.css`
|
||||
- 🚨 BREAKING: moved `icons` into `assets/icons` to make future assets easier to colocate
|
||||
- 🚨 BREAKING: changed `getSymbol` prop in `sl-rating` to `symbol` (it now accepts a string or a function that returns an icon name)
|
||||
- 🚨 BREAKING: renamed `setAssetPath()` to `setBasePath()` and added the ability to set the library's base path with a `data-shoelace` attribute (`setBasePath()` is exported from `utilities/base-path.js`)
|
||||
- Fixed `min` and `max` types in `sl-input` to allow numbers and strings [#330](https://github.com/shoelace-style/shoelace/issues/330)
|
||||
- Fixed a bug where `sl-checkbox`, `sl-radio`, and `sl-switch` controls would shrink with long labels [#325](https://github.com/shoelace-style/shoelace/issues/325)
|
||||
- Fixed a bug in `sl-select` where the dropdown menu wouldn't reposition when the box resized [#340](https://github.com/shoelace-style/shoelace/issues/340)
|
||||
- Fixed a bug where ignoring clicks and clicking the overlay would prevent the escape key from closing the dialog/drawer [#344](https://github.com/shoelace-style/shoelace/pull/344)
|
||||
- Removed the lazy loading dist (importing `shoelace.js` will load and register all components now)
|
||||
- Switched from Stencil to Shoemaker
|
||||
- Switched to a custom build powered by [esbuild](https://esbuild.github.io/)
|
||||
- Updated to Bootstrap Icons 1.4.0
|
||||
|
||||
## 2.0.0-beta.27
|
||||
|
||||
- Added `handle-icon` slot to `sl-image-comparer` [#311](https://github.com/shoelace-style/shoelace/issues/311)
|
||||
- Added `label` and `helpText` props and slots to `sl-range` [#318](https://github.com/shoelace-style/shoelace/issues/318)
|
||||
- Added "Integrating with NextJS" tutorial to the docs, courtesy of [crutchcorn](https://github.com/crutchcorn)
|
||||
- Added `content` slot to `sl-tooltip` [#322](https://github.com/shoelace-style/shoelace/pull/322)
|
||||
- Fixed a bug in `sl-select` where removing a tag would toggle the dropdown
|
||||
- Fixed a bug in `sl-input` and `sl-textarea` where the input might not exist when the value watcher is called [#313](https://github.com/shoelace-style/shoelace/issues/313)
|
||||
- Fixed a bug in `sl-details` where hidden elements would receive focus when tabbing [#323](https://github.com/shoelace-style/shoelace/issues/323)
|
||||
- Fixed a bug in `sl-icon` where `sl-error` would only be emitted for network failures [#326](https://github.com/shoelace-style/shoelace/pull/326)
|
||||
- Reduced the default line-height for `sl-tooltip`
|
||||
- Updated `sl-menu-item` focus styles
|
||||
- Updated `sl-select` so tags will wrap when `multiple` is true
|
||||
- Updated to Stencil 2.4.0
|
||||
|
||||
## 2.0.0-beta.26
|
||||
|
||||
- 🚨 BREAKING: Fixed animations bloat
|
||||
- Removed ~400 baked-in Animista animations because they were causing ~200KB of bloat (they can still be used with custom keyframes)
|
||||
- Reworked animations into a separate module ([`@shoelace-style/animations`](https://github.com/shoelace-style/animations)) so it's more maintainable and animations are sync with the latest version of animate.css
|
||||
- Animation and easing names are now camelcase (e.g. `easeInOut` instead of `ease-in-out`)
|
||||
- Added initial E2E tests [#169](https://github.com/shoelace-style/shoelace/pull/169)
|
||||
- Added the `FocusOptions` argument to all components that have a `setFocus()` method
|
||||
- Added `sl-initial-focus` event to `sl-dialog` and `sl-drawer` so focus can be customized to a specific element
|
||||
- Added `close-button` part to `sl-tab` so the close button can be customized
|
||||
- Added `scroll-button` part to `sl-tab-group` so the scroll buttons can be customized
|
||||
- Fixed a bug where `sl-hide` would be emitted twice when closing an alert with `hide()`
|
||||
- Fixed a bug in `sl-color-picker` where the toggle button was smaller than the preview button in Safari
|
||||
- Fixed a bug in `sl-tab-group` where activating a nested tab group didn't work properly [#299](https://github.com/shoelace-style/shoelace/issues/299)
|
||||
- Fixed a bug in `sl-tab-group` where removing tabs would throw an error
|
||||
- Fixed a bug in `sl-alert`, `sl-dialog`, `sl-drawer`, `sl-select`, and `sl-tag` where the close button's base wasn't exported so it couldn't be styled
|
||||
- Removed `text` type from `sl-badge` as it was erroneously copied and never had styles
|
||||
- Updated `sl-tab-group` so the `active` prop is reflected to the attribute
|
||||
- Updated the docs to show dependencies instead of dependents which is much more useful when working with the custom elements bundle
|
||||
- Updated to Bootstrap Icons 1.3.0
|
||||
|
||||
## 2.0.0-beta.25
|
||||
|
||||
- 🚨 BREAKING: Reworked color tokens
|
||||
- Theme colors are now inspired by Tailwind's professionally-designed color palette
|
||||
- Color token variations now range from 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950
|
||||
- Color token variations were inverted, e.g. 50 is lightest and 950 is darkest
|
||||
- All component styles were adapted to use the new color tokens, but visual changes are subtle
|
||||
- The dark theme was adapted use the new color tokens
|
||||
- HSL is no longer used because it is not perceptually uniform (this may be revisited when all browsers support [LCH colors](https://lea.verou.me/2020/04/lch-colors-in-css-what-why-and-how/))
|
||||
- 🚨 BREAKING: Refactored `sl-select` to improve accessibility [#216](https://github.com/shoelace-style/shoelace/issues/216)
|
||||
- Removed the internal `sl-input` because it was causing problems with a11y and virtual keyboards
|
||||
- Removed `input`, `prefix` and `suffix` parts
|
||||
- 🚨 BREAKING: Removed `copy-button` part from `sl-color-picker` since copying is now done by clicking the preview
|
||||
- Added `getFormattedValue()` method to `sl-color-picker` so you can retrieve the current value in any format
|
||||
- Added visual separators between solid buttons in `sl-button-group`
|
||||
- Added `help-text` prop to `sl-input`, `sl-textarea`, and `sl-select`
|
||||
- Fixed a bug where moving the mouse while `sl-dropdown` is closing would remove focus from the trigger
|
||||
- Fixed a bug where `sl-menu-item` didn't set a default color in the dark theme
|
||||
- Fixed a bug where `sl-color-picker` preview wouldn't update in Safari
|
||||
- Fixed a bug where removing an icon's `name` or `src` wouldn't remove the previously rendered SVG [#285](https://github.com/shoelace-style/shoelace/issues/285)
|
||||
- Fixed a bug where disabled link buttons didn't appear disabled
|
||||
- Improved button spacings and added split button example
|
||||
- Improved elevation tokens in dark theme
|
||||
- Improved accessibility in `sl-tooltip` by allowing escape to dismiss it [#219](https://github.com/shoelace-style/shoelace/issues/219)
|
||||
- Improved slot detection in `sl-card`, `sl-dialog`, and `sl-drawer`
|
||||
- Made `@types/resize-observer-browser` a dependency so users don't have to install it manually
|
||||
- Refactored internal label + help text logic into a functional component used by `sl-input`, `sl-textarea`, and `sl-select`
|
||||
- Removed `sl-blur` and `sl-focus` events from `sl-menu` since menus can't have focus as of 2.0.0-beta.22
|
||||
- Updated `sl-spinner` so the indicator is more obvious
|
||||
- Updated to Bootstrap Icons 1.2.2
|
||||
|
||||
## 2.0.0-beta.24
|
||||
|
||||
- Added `sl-format-date` component
|
||||
- Added `indeterminate` state to `sl-progress-bar` [#274](https://github.com/shoelace-style/shoelace/issues/274)
|
||||
- Added `--track-color`, `--indicator-color`, and `--label-color` to `sl-progress-bar` [#276](https://github.com/shoelace-style/shoelace/issues/276)
|
||||
- Added `allow-scripts` prop to `sl-include` [#280](https://github.com/shoelace-style/shoelace/issues/280)
|
||||
- Fixed a bug where `sl-menu-item` color variable was incorrect [#272](https://github.com/shoelace-style/shoelace/issues/272)
|
||||
- Fixed a bug where `sl-dialog` and `sl-drawer` would emit the `sl-hide` event twice [#275](https://github.com/shoelace-style/shoelace/issues/275)
|
||||
- Fixed a bug where calling `event.preventDefault()` on certain form elements wouldn't prevent `sl-form` from submitting [#277](https://github.com/shoelace-style/shoelace/issues/277)
|
||||
- Fixed drag handle orientation in `sl-image-comparer`
|
||||
- Restyled `sl-spinner` so the track is visible and the indicator is smaller.
|
||||
- Removed `resize-observer-polyfill` in favor of `@types/resize-observer-browser` since all target browsers support `ResizeObserver`
|
||||
- Upgraded the status of `sl-form`, `sl-image-comparer`, and `sl-include` from experimental to stable
|
||||
|
||||
## 2.0.0-beta.23
|
||||
|
||||
- Added `sl-format-number` component
|
||||
- Added `sl-relative-time` component
|
||||
- Added `closable` prop to `sl-tab`
|
||||
- Added experimental `sl-resize-observer` utility
|
||||
- Added experimental `sl-theme` utility and updated theming documentation
|
||||
- Fixed a bug where `sl-menu-item` wouldn't render properly in the dark theme
|
||||
- Fixed a bug where `sl-select` would show an autocomplete menu
|
||||
- Improved placeholder contrast in dark theme
|
||||
- Updated to Boostrap Icons 1.1.0
|
||||
- Updated to Stencil 2.3.0
|
||||
|
||||
## 2.0.0-beta.22
|
||||
|
||||
- 🚨 BREAKING: Refactored `sl-menu` and `sl-menu-item` to improve accessibility by using proper focus states [#217](https://github.com/shoelace-style/shoelace/issues/217)
|
||||
- Moved `tabindex` from `sl-menu` to `sl-menu-item`
|
||||
- Removed the `active` prop from `sl-menu-item` because synthetic focus states are bad for accessibility
|
||||
- Removed the `sl-activate` and `sl-deactivate` events from `sl-menu-item` (listen for `focus` and `blur` instead)
|
||||
- Updated `sl-select` so keyboard navigation still works
|
||||
- Added `no-scroll-controls` prop to `sl-tab-group` [#253](https://github.com/shoelace-style/shoelace/issues/253)
|
||||
- Fixed a bug where setting `open` initially wouldn't show `sl-dialog` or `sl-drawer` [#255](https://github.com/shoelace-style/shoelace/issues/255)
|
||||
- Fixed a bug where `disabled` could be set when buttons are rendered as links
|
||||
- Fixed a bug where hoisted dropdowns would render in the wrong position when placed inside `sl-dialog` [#252](https://github.com/shoelace-style/shoelace/issues/252)
|
||||
- Fixed a bug where boolean aria attributes didn't explicitly set `true|false` string values in the DOM
|
||||
- Fixed a bug where `aria-describedby` was never set on tooltip targets in `sl-tooltip`
|
||||
- Fixed a bug where setting `position` on `sl-image-comparer` wouldn't update the divider's position
|
||||
- Fixed a bug where the check icon was announced to screen readers in `sl-menu-item`
|
||||
- Improved `sl-icon-button` accessibility by encouraging proper use of `label` and hiding the internal icon from screen readers [#220](https://github.com/shoelace-style/shoelace/issues/220)
|
||||
- Improved `sl-dropdown` accessibility by attaching `aria-haspopup` and `aria-expanded` to the slotted trigger
|
||||
- Refactored position logic to remove an unnecessary state variable in `sl-image-comparer`
|
||||
- Refactored design tokens to use `rem` instead of `px` for input height and spacing [#221](https://github.com/shoelace-style/shoelace/issues/221)
|
||||
- Removed `console.log` from modal utility
|
||||
- Updated to Stencil 2.2.0
|
||||
|
||||
## 2.0.0-beta.21
|
||||
|
||||
- Added `label` slot to `sl-input`, `sl-select`, and `sl-textarea` [#248](https://github.com/shoelace-style/shoelace/issues/248)
|
||||
- Added `label` slot to `sl-dialog` and `sl-drawer`
|
||||
- Added experimental `sl-include` component
|
||||
- Added status code to the `sl-error` event in `sl-icon`
|
||||
- Fixed a bug where initial transitions didn't show in `sl-dialog` and `sl-drawer` [#247](https://github.com/shoelace-style/shoelace/issues/247)
|
||||
- Fixed a bug where indeterminate checkboxes would maintain the indeterminate state when toggled
|
||||
- Fixed a bug where concurrent active modals (i.e. dialog, drawer) would try to steal focus from each other
|
||||
- Improved `sl-color-picker` grid and slider handles [#246](https://github.com/shoelace-style/shoelace/issues/246)
|
||||
- Refactored `sl-icon` request logic and removed unused cache map
|
||||
- Reworked show/hide logic in `sl-alert`, `sl-dialog`, and `sl-drawer` to not use reflow hacks and the `hidden` attribute
|
||||
- Reworked slot logic in `sl-card`, `sl-dialog`, and `sl-drawer`
|
||||
- Updated to Popper 2.5.3 to address a fixed position bug in Firefox
|
||||
|
||||
## 2.0.0-beta.20
|
||||
|
||||
- 🚨 BREAKING: Transformed all Shoelace events to lowercase ([details](#why-did-event-names-change))
|
||||
- Added support for dropdowns and non-icon elements to `sl-input`
|
||||
- Added `spellcheck` prop to `sl-input`
|
||||
- Added `sl-icon-library` to allow custom icon library registration
|
||||
- Added `library` prop to `sl-icon` and `sl-icon-button`
|
||||
- Added "Integrating with Rails" tutorial to the docs, courtesy of [ParamagicDev](https://github.com/ParamagicDev)
|
||||
- Fixed a bug where `sl-progress-ring` rendered incorrectly when zoomed in Safari [#227](https://github.com/shoelace-style/shoelace/issues/227)
|
||||
- Fixed a bug where tabbing into slotted elements closes `sl-dropdown` when used in a shadow root [#223](https://github.com/shoelace-style/shoelace/issues/223)
|
||||
- Fixed a bug where scroll anchoring caused undesirable scrolling when `sl-details` are grouped
|
||||
|
||||
### Why did event names change?
|
||||
|
||||
Shoelace events were updated to use a lowercase, kebab-style naming convention. Instead of event names such as `slChange` and `slAfterShow`, you'll need to use `sl-change` and `sl-after-show` now.
|
||||
|
||||
This change was necessary to address a critical issue in frameworks that use DOM templates with declarative event bindings such as `<sl-button @slChange="handler">`. Due to HTML's case-insensitivity, browsers translate attribute names to lowercase, turning `@slChange` into `@slchange`, making it impossible to listen to `slChange`.
|
||||
|
||||
While declarative event binding is a non-standard feature, not supporting it would make Shoelace much harder to use in popular frameworks. To accommodate those users and provide a better developer experience, we decided to change the naming convention while Shoelace is still in beta.
|
||||
|
||||
The following pages demonstrate why this change was necessary.
|
||||
|
||||
- [This Polymer FAQ from Custom Elements Everywhere](https://custom-elements-everywhere.com/#faq-polymer)
|
||||
- [Vue's Event Names documentation](https://vuejs.org/v2/guide/components-custom-events.html#Event-Names)
|
||||
|
||||
## 2.0.0-beta.19
|
||||
|
||||
- Added `input`, `label`, `prefix`, `clear-button`, `suffix`, `help-text` exported parts to `sl-select` to make the input customizable
|
||||
- Added toast notifications through the `toast()` method on `sl-alert`
|
||||
- Fixed a bug where mouse events would bubble up when `sl-button` was disabled, causing tooltips to erroneously appear
|
||||
- Fixed a bug where pressing space would open and immediately close `sl-dropdown` panels in Firefox
|
||||
- Fixed a bug where `sl-tooltip` would throw an error on init
|
||||
- Fixed a bug in custom keyframes animation example
|
||||
- Refactored clear logic in `sl-input`
|
||||
|
||||
## 2.0.0-beta.18
|
||||
|
||||
- Added `name` and `invalid` prop to `sl-color-picker`
|
||||
- Added support for form submission and validation to `sl-color-picker`
|
||||
- Added touch support to demo resizers in the docs
|
||||
- Added `sl-responsive-embed` component
|
||||
- Fixed a bug where swapping an animated element wouldn't restart the animation in `sl-animation`
|
||||
- Fixed a bug where the cursor was incorrect when `sl-select` was disabled
|
||||
- Fixed a bug where `slblur` and `slfocus` were emitted twice in `sl-select`
|
||||
- Fixed a bug where clicking on `sl-menu` wouldn't focus it
|
||||
- Fixed a bug in the popover utility where `onAfterShow` would fire too soon
|
||||
- Fixed a bug where `bottom` and `right` placements didn't render properly in `sl-tab-group`
|
||||
- Improved keyboard logic in `sl-dropdown`, `sl-menu`, and `sl-select`
|
||||
- Updated `sl-animation` to stable
|
||||
- Updated to Stencil 2.0 (you may need to purge `node_modules` and run `npm install` after pulling)
|
||||
- Updated entry points in `package.json` to reflect new filenames generated by Stencil 2
|
||||
|
||||
## 2.0.0-beta.17
|
||||
|
||||
- Added `minlength` and `spellcheck` attributes to `sl-textarea`
|
||||
- Fixed a bug where clicking a tag in `sl-select` wouldn't toggle the menu
|
||||
- Fixed a bug where options where `sl-select` options weren't always visible or scrollable
|
||||
- Fixed a bug where setting `null` on `sl-input`, `sl-textarea`, or `sl-select` would throw an error
|
||||
- Fixed a bug where `role` was on the wrong element and aria attribute weren't explicit in `sl-checkbox`, `sl-switch`, and `sl-radio`
|
||||
- Fixed a bug where dynamically adding/removing a slot wouldn't work as expected in `sl-card`, `sl-dialog`, and `sl-drawer`
|
||||
- Fixed a bug where the value wasn't updated and events weren't emitted when using `setRangeText` in `sl-input` and `sl-textarea`
|
||||
- Optimized `hasSlot` utility by using a simpler selector
|
||||
- Updated Bootstrap Icons to 1.0.0 with many icons redrawn and improved
|
||||
- Updated contribution guidelines
|
||||
|
||||
**Form validation has been reworked and is much more powerful now!**
|
||||
|
||||
- The `invalid` prop now reflects the control's validity as determined by the browser's constraint validation API
|
||||
- Added `required` to `sl-checkbox`, `sl-select`, and `sl-switch`
|
||||
- Added `reportValidity()` and `setCustomValidity()` methods to all form controls
|
||||
- Added validation checking for custom and native form controls to `sl-form`
|
||||
- Added `novalidate` prop to `sl-form` to disable validation
|
||||
- Removed the `valid` prop from all form controls
|
||||
- Removed valid and invalid design tokens and related styles (you can use your own custom styles to achieve this)
|
||||
|
||||
## 2.0.0-beta.16
|
||||
|
||||
- Add `hoist` prop to `sl-color-picker`, `sl-dropdown`, and `sl-select` to work around panel clipping
|
||||
- Add `sl-format-bytes` utility component
|
||||
- Add `clearable` and `required` props to `sl-select`
|
||||
- Add `slclear` event to `sl-input`
|
||||
- Added keyboard support to the preview resizer in the docs
|
||||
- Fixed a bug where the `aria-selected` state was incorrect in `sl-menu-item`
|
||||
- Fixed a bug where custom properties applied to `sl-tooltip` didn't affect show/hide transitions
|
||||
- Fixed a bug where `--sl-input-color-*` custom properties had no affect on `sl-input` and `sl-textarea`
|
||||
- Refactored `sl-dropdown` and `sl-tooltip` to use positioner elements so panels/tooltips can be customized easier
|
||||
|
||||
## 2.0.0-beta.15
|
||||
|
||||
- Added `image-comparer` component
|
||||
- Added `--width`, `--height`, and `--thumb-size` custom props to `sl-switch`
|
||||
- Fixed an `aria-labelledby` attribute typo in a number of components
|
||||
- Fixed a bug where the `change` event wasn't updating the value in `sl-input`
|
||||
- Fixed a bug where `sl-color-picker` had the wrong border color in the dark theme
|
||||
- Fixed a bug where `sl-menu-item` had the wrong color in dark mode when disabled
|
||||
- Fixed a bug where WebKit's autocomplete styles made inputs looks broken
|
||||
- Fixed a bug where aria labels were wrong in `sl-select`
|
||||
- Fixed a bug where clicking the label wouldn't focus the control in `sl-select`
|
||||
|
||||
## 2.0.0-beta.14
|
||||
|
||||
- Added dark theme
|
||||
- Added `--sl-panel-background-color` and `--sl-panel-border-color` tokens
|
||||
- Added `--tabs-border-color` custom property to `sl-tab-group`
|
||||
- Added `--track-color` custom property to `sl-range`
|
||||
- Added `tag` part to `sl-select`
|
||||
- Updated `package.json` so custom elements imports can be consumed from the root
|
||||
- Fixed a bug where scrolling dialogs didn't resize properly in Safari
|
||||
- Fixed a bug where `slshow` and `slhide` would be emitted twice in some components
|
||||
- Fixed a bug where `custom-elements/index.d.ts` was broken due to an unclosed comment (fixed in Stencil 1.17.3)
|
||||
- Fixed bug where inputs were not using border radius tokens
|
||||
- Fixed a bug where the text color was being erroneously set in `sl-progress-ring`
|
||||
- Fixed a bug where `sl-progress-bar` used the wrong part name internally for `indicator`
|
||||
- Removed background color from `sl-menu`
|
||||
- Updated to Stencil 1.17.3
|
||||
|
||||
## 2.0.0-beta.13
|
||||
|
||||
- Added `slactivate` and `sldeactivate` events to `sl-menu-item`
|
||||
- Added experimental `sl-animation` component
|
||||
- Added shields to documentation
|
||||
- Fixed a bug where link buttons would have `type="button"`
|
||||
- Fixed a bug where button groups with tooltips experienced an odd spacing issue in Safari
|
||||
- Fixed a bug where scrolling in dropdowns/selects didn't work properly on Windows (special thanks to [Trendy](http://github.com/trendy) for helping troubleshoot!)
|
||||
- Fixed a bug where selecting a menu item in a dropdown would cause Safari to scroll
|
||||
- Fixed a bug where type to select wouldn't accept symbols
|
||||
- Moved scrolling logic from `sl-menu` to `sl-dropdown`
|
||||
|
||||
## 2.0.0-beta.12
|
||||
|
||||
- Added support for `href`, `target`, and `download` to buttons
|
||||
- Fixed a bug where buttons would have horizontal spacing in Safari
|
||||
- Fixed a bug that caused an import resolution error when using Shoelace in a Stencil app
|
||||
|
||||
## 2.0.0-beta.11
|
||||
|
||||
- Added button group component
|
||||
- Fixed icon button alignment
|
||||
- Fixed a bug where focus visible observer wasn't removed from `sl-details`
|
||||
- Replaced the deprecated `componentDidUnload` lifecycle method with `disconnectedCallback` to prevent issues with frameworks
|
||||
|
||||
## 2.0.0-beta.10
|
||||
|
||||
- Added community page to the docs
|
||||
- Fixed a bug where many components would erroneously receive an `id` when using the custom elements bundle
|
||||
- Fixed a bug where tab groups weren't scrollable with the mouse
|
||||
|
||||
## 2.0.0-beta.9
|
||||
|
||||
- Added the icon button component
|
||||
- Added the skeleton component
|
||||
- Added the `typeToSelect` method to menu so type-to-select behavior can be controlled externally
|
||||
- Added the `pulse` prop to badge
|
||||
- Fixed a bug where hovering over select showed the wrong cursor
|
||||
- Fixed a bug where tabbing into a select control would highlight the label
|
||||
- Fixed a bug where tabbing out of a select control wouldn't close it
|
||||
- Fixed a bug where closing dropdowns wouldn't give focus back to the trigger
|
||||
- Fixed a bug where type-to-select wasn't working after the first letter
|
||||
- Fixed a bug where clicking on menu items and dividers would steal focus from the menu
|
||||
- Fix a bug where the color picker wouldn't parse uppercase values
|
||||
- Removed `noFooter` prop from dialog and drawer (slot detection is automatic, so the prop is not required)
|
||||
- Removed `close-icon` slot from alert
|
||||
- Replaced make-shift icon buttons with `sl-icon-button` in alert, dialog, drawer, and tag
|
||||
- Updated Stencil to 1.17.1
|
||||
- Switched to jsDelivr for better CDN performance
|
||||
|
||||
## 2.0.0-beta.8
|
||||
|
||||
- Added the card component
|
||||
- Added `--focus-ring` custom property to tab
|
||||
- Fixed a bug where range tooltips didn't appear on iOS
|
||||
- Fixed constructor bindings so they don't break the custom elements bundle
|
||||
- Fixed tag color contrast to be AA compliant
|
||||
- Fixed a bug that made it difficult to vertically align rating
|
||||
- Fixed a bug where dropdowns would always close on mousedown when inside a shadow root
|
||||
- Made tag text colors AA compliant
|
||||
- Promoted badge to stable
|
||||
- Refactored `:host` variables and moved non-display props to base elements
|
||||
- Refactored event handler bindings to occur in `connectedCallback` instead of the constructor
|
||||
- Refactored scroll locking logic to use `Set` instead of an array
|
||||
- Updated the custom elements bundle documentation and added bundler examples
|
||||
- Upgraded Stencil to 1.17.0-0 (next) to fix custom elements bundle
|
||||
|
||||
## 2.0.0-beta.7
|
||||
|
||||
- Added links to version 1 resources to the docs
|
||||
- Added rating component
|
||||
- Fixed a bug where some build files were missing
|
||||
- Fixed clearable tags demo
|
||||
- Fixed touch icon size in docs
|
||||
|
||||
## 2.0.0-beta.6
|
||||
|
||||
- Enabled the `dist-custom-elements-bundle` output target
|
||||
- Fixed a bug where nested form controls were ignored in `<sl-form>`
|
||||
|
||||
## 2.0.0-beta.5
|
||||
|
||||
- Fixed bug where `npm install` would fail due to postinstall script
|
||||
- Removed unused dependency
|
||||
|
||||
## 2.0.0-beta.4
|
||||
|
||||
- Added `pill` variation to badges
|
||||
- Fixed a bug where all badges had `pointer-events: none`
|
||||
- Fixed `@since` props to show 2.0 instead of 1.0
|
||||
- Fixed giant cursors in inputs in Safari
|
||||
- Fixed color picker input width in Safari
|
||||
- Fixed initial transitions for drawer, dialog, and popover consumers
|
||||
- Fixed a bug where dialog, dropdown, and drawer would sometimes not transition in on the first open
|
||||
- Fixed various documentation typos
|
||||
|
||||
## 2.0.0-beta.3
|
||||
|
||||
- Fix version in docs
|
||||
- Remove custom elements bundle
|
||||
|
||||
## 2.0.0-beta.2
|
||||
|
||||
- Fix quick start and installation URLs
|
||||
- Switch Docsify theme
|
||||
- Update line heights tokens
|
||||
|
||||
## 2.0.0-beta.1
|
||||
|
||||
- Initial release
|
||||
@@ -6,31 +6,30 @@ Shoelace components can be customized at a high level through design tokens. Thi
|
||||
|
||||
Shoelace makes use of several design tokens to provide a consistent appearance across components. You can customize them and use them in your own application with pure CSS — no preprocessor required.
|
||||
|
||||
Design tokens offer a high-level way to customize the library with minimal effort. There are no component-specific variables, however, as design tokens are intended to be generic and highly reusable. To customize an individual component, refer to the section entitled [Component parts](#component-parts).
|
||||
Design tokens offer a high-level way to customize the library with minimal effort. There are no component-specific variables, however, as design tokens are intended to be generic and highly reusable. To customize an individual component, refer to the section entitled [Component Parts](#component-parts).
|
||||
|
||||
Design tokens are CSS custom properties ("CSS variables") that are defined in the `:root` block of `shoelace.css`. This stylesheet is imported when you install Shoelace, so design tokens are available on your page at that point. Because design tokens are global, they're always prefixed with `--sl` to avoid collisions with other libraries.
|
||||
Design tokens are accessed through CSS custom properties that are defined in your theme. Because design tokens live at the page level, they're prefixed with `--sl-` to avoid collisions with other libraries.
|
||||
|
||||
To customize a design token, simply override it in your stylesheet using a `:root` block.
|
||||
To customize a design token, simply override it in your stylesheet using a `:root` block. Here's an example that changes the primary theme to purple based on existing [color primitives](/tokens/color#primitives).
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Changes the primary color palette to purple */
|
||||
--sl-color-primary-50: #faf5ff;
|
||||
--sl-color-primary-100: #f3e8ff;
|
||||
--sl-color-primary-200: #e9d5ff;
|
||||
--sl-color-primary-300: #d8b4fe;
|
||||
--sl-color-primary-400: #c084fc;
|
||||
--sl-color-primary-500: #a855f7;
|
||||
--sl-color-primary-600: #9333ea;
|
||||
--sl-color-primary-700: #7e22ce;
|
||||
--sl-color-primary-800: #6b21a8;
|
||||
--sl-color-primary-900: #581c87;
|
||||
/* Changes the primary theme color to purple using primitives */
|
||||
--sl-color-primary-50: var(--sl-color-purple-50);
|
||||
--sl-color-primary-100: var(--sl-color-purple-100);
|
||||
--sl-color-primary-200: var(--sl-color-purple-200);
|
||||
--sl-color-primary-300: var(--sl-color-purple-300);
|
||||
--sl-color-primary-400: var(--sl-color-purple-400);
|
||||
--sl-color-primary-500: var(--sl-color-purple-500);
|
||||
--sl-color-primary-600: var(--sl-color-purple-600);
|
||||
--sl-color-primary-700: var(--sl-color-purple-700);
|
||||
--sl-color-primary-800: var(--sl-color-purple-800);
|
||||
--sl-color-primary-900: var(--sl-color-purple-900);
|
||||
--sl-color-primary-950: var(--sl-color-purple-950);
|
||||
}
|
||||
```
|
||||
|
||||
Many design tokens are described further along in this documentation. For a complete list, refer to `shoelace.scss` in the project's [source code](https://github.com/shoelace-style/shoelace/blob/current/src/styles/shoelace.scss).
|
||||
|
||||
!> **Never modify variables directly in `shoelace.css`** because your changes will be overwritten when you upgrade the library. Even if you don't plan on upgrading, it's always better to override design tokens in your own stylesheet for better maintainability.
|
||||
Many design tokens are described further along in this documentation. For a complete list, refer to `src/themes/light.styles.ts` in the project's [source code](https://github.com/shoelace-style/shoelace/blob/current/src/themes/light.styles.ts).
|
||||
|
||||
## Component Parts
|
||||
|
||||
@@ -47,7 +46,7 @@ Here's an example that modifies buttons with the `tomato-button` class.
|
||||
|
||||
<style>
|
||||
.tomato-button::part(base) {
|
||||
background: white;
|
||||
background: rgb(var(--sl-color-neutral-0));
|
||||
border: solid 1px tomato;
|
||||
}
|
||||
|
||||
@@ -106,3 +105,51 @@ Alternatively, you can set them inline directly on the element.
|
||||
```
|
||||
|
||||
Not all components expose CSS custom properties. For those that do, they can be found in the component's API documentation.
|
||||
|
||||
## Animations
|
||||
|
||||
Some components use animation, such as when a dialog is shown or hidden. Animations are performed using the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API) rather than CSS. However, you can still customize them through Shoelace's animation registry. If a component has customizable animations, they'll be listed in the "Animation" section of its documentation.
|
||||
|
||||
To customize a default animation, use the `setDefaultAnimation()` method. The function accepts an animation name (found in the component's docs) and an object with `keyframes` and `options` or `null` to disable the animation.
|
||||
|
||||
This example will make all dialogs use a custom show animation.
|
||||
|
||||
```js
|
||||
import { setDefaultAnimation } from '@shoelace-style/shoelace/dist/utilities/animation-registry.js';
|
||||
|
||||
// Change the default animation for all dialogs
|
||||
setDefaultAnimation('dialog.show', {
|
||||
keyframes: [
|
||||
{ transform: 'rotate(-10deg) scale(0.5)', opacity: '0' },
|
||||
{ transform: 'rotate(0deg) scale(1)', opacity: '1' }
|
||||
],
|
||||
options: {
|
||||
duration: 500
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
If you only want to target a single component, use the `setAnimation()` method instead. This function accepts an element, an animation name, and an object comprised of animation `keyframes` and `options`.
|
||||
|
||||
In this example, only the target dialog will use a custom show animation.
|
||||
|
||||
```js
|
||||
import { setAnimation } from '@shoelace-style/shoelace/dist/utilities/animation-registry.js';
|
||||
|
||||
// Change the animation for a single dialog
|
||||
const dialog = document.querySelector('#my-dialog');
|
||||
|
||||
setAnimation(dialog, 'dialog.show', {
|
||||
keyframes: [
|
||||
{ transform: 'rotate(-10deg) scale(0.5)', opacity: '0' },
|
||||
{ transform: 'rotate(0deg) scale(1)', opacity: '1' }
|
||||
],
|
||||
options: {
|
||||
duration: 500
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
To learn more about creating Web Animations, refer to the documentation for [`Element.animate()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate).
|
||||
|
||||
?> Animations respect the users `prefers-reduced-motion` setting. When this setting is enabled, animations will not be played. To disable animations for all users, pass in `null` instead of a keyframes/options object.
|
||||
|
||||
@@ -1,50 +1,75 @@
|
||||
# Installation
|
||||
|
||||
You can use Shoelace via CDN or by installing it locally.
|
||||
You can use Shoelace via CDN or by installing it locally. You can also [cherry pick](#cherry-picking) individual components for faster load times.
|
||||
|
||||
## CDN Installation (Recommended)
|
||||
|
||||
The easiest way to install Shoelace is with the CDN. Just add the following tags to your page.
|
||||
The easiest way to install Shoelace is with the CDN. Just add the following tags to your page to get all components and the default light theme.
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/base.css">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/all.shoelace.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/light.css">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/shoelace.js"></script>
|
||||
```
|
||||
|
||||
Now you can [start using Shoelace!](/getting-started/usage.md)
|
||||
### Dark Theme
|
||||
|
||||
If you prefer to use the dark theme instead, use this. Note the `sl-theme-dark` class on the `<html>` element. [Learn more about the Dark Theme.](/getting-started/themes#dark-theme)
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/dark.css">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/shoelace.js"></script>
|
||||
```
|
||||
|
||||
### Light & Dark Theme
|
||||
|
||||
If you want to load the light or dark theme based on the user's `prefers-color-scheme` setting, use this. The `media` attributes ensure that only the user's preferred theme stylesheet loads and the `onload` attribute sets the appropriate [theme class](/getting-started/themes) on the `<html>` element.
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" media="(prefers-color-scheme:light)" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/light.css">
|
||||
<link rel="stylesheet" media="(prefers-color-scheme:dark)"
|
||||
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/dark.css"
|
||||
onload="document.documentElement.classList.add('sl-theme-dark');">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/shoelace.js"></script>
|
||||
```
|
||||
|
||||
Now you can [start using Shoelace!](/getting-started/usage)
|
||||
|
||||
## Local Installation
|
||||
|
||||
If you don't want to use the CDN, you can install Shoelace locally with the following command.
|
||||
If you don't want to use the CDN, you can install Shoelace locally with the following command.
|
||||
|
||||
```bash
|
||||
npm install @shoelace-style/shoelace
|
||||
```
|
||||
|
||||
It's up to you to make the source files available to your app. One way to do this is to create a route in your app called `/scripts/shoelace` that serves static files from `node_modules/@shoelace-style/shoelace`.
|
||||
It's up to you to make the source files available to your app. One way to do this is to create a route in your app called `/shoelace` that serves static files from `node_modules/@shoelace-style/shoelace`.
|
||||
|
||||
Once you've done that, add the following tags to your page. Make sure to update `href` and `src` so they point to the route you created.
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="/scripts/shoelace/dist/themes/base.css">
|
||||
<script type="module" src="/scripts/shoelace/dist/all.shoelace.js"></script>
|
||||
<link rel="stylesheet" href="/shoelace/dist/themes/light.css">
|
||||
<script type="module" src="/shoelace/dist/shoelace.js"></script>
|
||||
```
|
||||
|
||||
Alternatively, [you can use a bundler](#bundling).
|
||||
|
||||
?> For clarity, the docs will usually show imports from `@shoelace-style/shoelace`. If you're not using a module resolver or bundler, you'll need to adjust these paths to point to the folder Shoelace is in.
|
||||
|
||||
## Setting the Base Path
|
||||
|
||||
Some components rely on assets (icons, images, etc.) and Shoelace needs to know where they're located. For convenience, Shoelace will try to auto-detect the correct location based on the script you've loaded it from. This assumes assets are colocated with `shoelace.js` and will "just work" for most users.
|
||||
|
||||
However, if you're [cherry picking](#cherry-picking) or [bundling](#bundling) Shoelace, you'll need to set the base path. You can do this one of two ways. The following examples assumes you're serving Shoelace's `dist` directory from `/scripts/shoelace`.
|
||||
However, if you're [cherry picking](#cherry-picking) or [bundling](#bundling) Shoelace, you'll need to set the base path. You can do this one of two ways.
|
||||
|
||||
```html
|
||||
<!-- Option 1: the data-shoelace attribute -->
|
||||
<script src="bundle.js" data-shoelace="/scripts/shoelace"></script>
|
||||
<script src="bundle.js" data-shoelace="/path/to/shoelace"></script>
|
||||
|
||||
<!-- Option 2: the setBasePath() method -->
|
||||
<script src="bundle.js"></script>
|
||||
<script type="module">
|
||||
import { setBasePath } from '/scripts/shoelace/dist/utilities/base-path.js';
|
||||
setBasePath('/scripts/shoelace');
|
||||
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.js';
|
||||
setBasePath('/path/to/shoelace');
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -54,34 +79,31 @@ However, if you're [cherry picking](#cherry-picking) or [bundling](#bundling) Sh
|
||||
|
||||
The previous approach is the _easiest_ way to load Shoelace, but easy isn't always efficient. You'll incur the full size of the library even if you only use a handful of components. This is convenient for prototyping, but may result in longer load times in production. To improve this, you can cherry pick the components you need.
|
||||
|
||||
Cherry picking can be done from your local install or [directly from the CDN](https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/). This will limit the number of files the browser has to download and reduce the amount of bytes being transferred. The disadvantage is that you need to load and register each component manually, including its dependencies.
|
||||
Cherry picking can be done from your local install or [directly from the CDN](https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/). This will limit the number of files the browser has to download and reduce the amount of bytes being transferred. The disadvantage is that you need to load component manually.
|
||||
|
||||
Here's an example that loads only the button component and its dependencies.
|
||||
Here's an example that loads only the button component. Again, if you're not using a module resolver, you'll need to adjust the path to point to the folder Shoelace is in.
|
||||
|
||||
```html
|
||||
<!-- The base stylesheet is always required -->
|
||||
<link rel="stylesheet" href="/scripts/shoelace/dist/themes/base.css">
|
||||
<link rel="stylesheet" href="@shoelace-style/shoelace/dist/themes/light.css">
|
||||
|
||||
<script type="module" data-shoelace="/scripts/shoelace">
|
||||
import SlButton from '/scripts/shoelace/dist/components/button/button.js';
|
||||
import SlSpinner from '/scripts/shoelace/dist/components/spinner/spinner.js';
|
||||
|
||||
SlButton.register();
|
||||
SlSpinner.register(); // spinner is a dependency of button
|
||||
<script type="module" data-shoelace="/path/to/shoelace">
|
||||
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
||||
|
||||
// <sl-button> is ready to use!
|
||||
</script>
|
||||
```
|
||||
|
||||
If a component has dependencies, they'll be listed in the "Dependencies" section of its documentation. These are always Shoelace components, not third-party libraries. For example, `<sl-button>` requires you to load `<sl-spinner>` because it's used internally for its loading state.
|
||||
You can copy and paste the code to import a component from the "Importing" section of the component's documentation. Note that some components have dependencies that are automatically imported when you cherry pick. If a component has dependencies, they will be listed in the "Dependencies" section of its docs.
|
||||
|
||||
!> Never cherry pick from `all.shoelace.js` or `shoelace.js` as this will cause the browser to load the entire library. Instead, cherry pick from component modules as shown above.
|
||||
!> Never cherry pick components or utilities from `shoelace.js` as this will cause the browser to load the entire library. Instead, cherry pick from specific modules as shown above.
|
||||
|
||||
!> You may see files named `chunk.[hash].js` in the `dist` directory. Never reference these files directly, as they change from version to version. Instead, import the corresponding component or utility file.
|
||||
!> You will see files named `chunk.[hash].js` in the `chunks` directory. Never import these files directly, as they are generated and change from version to version.
|
||||
|
||||
## Bundling
|
||||
|
||||
Shoelace is distributed as a collection of standard ES modules that [all modern browsers can understand](https://caniuse.com/es6-module). However, importing a lot of modules can result in a lot of HTTP requests and potentially longer load times. Using a CDN can alleviate this, but some users may wish to further optimize their imports with a bundler.
|
||||
|
||||
To use Shoelace with a bundler, first install Shoelace as well as your bundler of choice.
|
||||
To use Shoelace with a bundler, first install Shoelace along with your bundler of choice.
|
||||
|
||||
```bash
|
||||
npm install @shoelace-style/shoelace
|
||||
@@ -95,18 +117,17 @@ Now it's time to configure your bundler. Configurations vary for each tool, but
|
||||
Once your bundler is configured, you'll be able to import Shoelace components and utilities.
|
||||
|
||||
```js
|
||||
import '@shoelace-style/shoelace/dist/shoelace.css';
|
||||
import { setBasePath, SlButton, SlIcon, SlInput, SlRating } from '@shoelace-style/shoelace';
|
||||
import '@shoelace-style/shoelace/dist/themes/light.css';
|
||||
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
||||
import '@shoelace-style/shoelace/dist/components/icon/icon.js';
|
||||
import '@shoelace-style/shoelace/dist/components/input/input.js';
|
||||
import '@shoelace-style/shoelace/dist/components/rating/rating.js';
|
||||
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.js';
|
||||
|
||||
// Set the pase path to the folder you copied Shoelace's assets to
|
||||
// Set the base path to the folder you copied Shoelace's assets to
|
||||
setBasePath('/dist/shoelace');
|
||||
|
||||
SlButton.register();
|
||||
SlIcon.register();
|
||||
SlInput.register();
|
||||
SlRating.register();
|
||||
|
||||
// <sl-button>, <sl-icon>, <sl-input>, and <sl-rating> are ready to use!
|
||||
```
|
||||
|
||||
Note that you need to register each component manually to add them to the custom element registry. Components aren't automatically registered to prevent bundlers from treeshaking them.
|
||||
!> Component modules include side effects for registration purposes. Because of this, importing directly from `@shoelace-style/shoelace` may result in a larger bundle size than necessary. For optimal tree shaking, always cherry pick, i.e. import components and utilities from their respective files, as shown above.
|
||||
|
||||
@@ -1,36 +1,38 @@
|
||||
<div class="splash">
|
||||
<div class="splash-start">
|
||||
<img class="splash-logo" src="/assets/images/wordmark.svg" alt="Shoelace">
|
||||
<p><strong>A forward-thinking library of web components.</strong></p>
|
||||
<ul>
|
||||
<li>Works with all frameworks 🧩</li>
|
||||
<li>Works with CDNs 🚛</li>
|
||||
<li>Fully customizable with CSS 🎨</li>
|
||||
<li>Includes an official dark theme 🌛</li>
|
||||
<li>Built with accessibility in mind ♿️</li>
|
||||
<li>Open source 😸</li>
|
||||
</ul>
|
||||
<p>Designed in New Hampshire by <a href="https://twitter.com/claviska" rel="noopener" target="_blank">Cory LaViska</a>.</p>
|
||||
</div>
|
||||
<div class="splash-end">
|
||||
<img class="splash-image" src="/assets/images/undraw-content-team.svg" alt="Cartoon of people assembling components while standing on a giant laptop.">
|
||||
</div>
|
||||
<div class="splash-start">
|
||||
<img class="splash-logo" src="/assets/images/wordmark.svg" alt="Shoelace">
|
||||
|
||||
# <span hidden>Shoelace:</span> A forward-thinking library of web components.
|
||||
|
||||
- Works with all frameworks 🧩
|
||||
- Works with CDNs 🚛
|
||||
- Fully customizable with CSS 🎨
|
||||
- Includes a dark theme 🌛
|
||||
- Built with accessibility in mind ♿️
|
||||
- First-party [React wrappers](/getting-started/usage#react)
|
||||
- Open source 😸
|
||||
|
||||
Designed in New Hampshire by [Cory LaViska](https://twitter.com/claviska).
|
||||
</div>
|
||||
<div class="splash-end">
|
||||
<img class="splash-image" src="/assets/images/undraw-content-team.svg" alt="Cartoon of people assembling components while standing on a giant laptop.">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
[](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace)
|
||||
[](https://www.npmjs.com/package/@shoelace-style/shoelace)
|
||||
[](https://github.com/shoelace-style/shoelace/blob/next/LICENSE.md)<br>
|
||||
[](https://discord.gg/mg8f26C)
|
||||
[](https://twitter.com/shoelace_style)
|
||||
[](https://github.com/sponsors/claviska)
|
||||
[](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace)
|
||||
[](https://www.npmjs.com/package/@shoelace-style/shoelace)
|
||||
[](https://github.com/shoelace-style/shoelace/blob/next/LICENSE.md)<br>
|
||||
[](https://discord.gg/mg8f26C)
|
||||
[](https://twitter.com/shoelace_style)
|
||||
[](https://github.com/shoelace-style/shoelace)
|
||||
|
||||
## Quick Start
|
||||
|
||||
Add the following code to your page.
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/base.css">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/all.shoelace.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/light.css">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/shoelace.js"></script>
|
||||
```
|
||||
|
||||
Now you have access to all of Shoelace's components! Try adding a button:
|
||||
@@ -39,7 +41,7 @@ Now you have access to all of Shoelace's components! Try adding a button:
|
||||
<sl-button>Click me</sl-button>
|
||||
```
|
||||
|
||||
See the [installation instructions](getting-started/installation.md) for more details and other ways to install Shoelace.
|
||||
See the [installation instructions](getting-started/installation) for more details and other ways to install Shoelace.
|
||||
|
||||
## New to Web Components?
|
||||
|
||||
@@ -91,40 +93,35 @@ If you need to support IE11 or pre-Chromium Edge, this library isn't for you. Al
|
||||
|
||||
Shoelace is designed in New Hampshire by [Cory LaViska](https://twitter.com/claviska). It's available under the terms of the MIT license.
|
||||
|
||||
Designing, developing, and supporting this library requires a lot of time, effort, and skill. I'd like to keep it open source so everyone can use it, but that doesn't provide me with any income.
|
||||
|
||||
**Therefore, if you're using my software to make a profit,** I respectfully ask that you help [fund its development](https://github.com/sponsors/claviska) by becoming a sponsor. There are multiple tiers to choose from with benefits at every level, including prioritized support, bug fixes, feature requests, and advertising.
|
||||
Designing, developing, and supporting this library requires a lot of time, effort, and skill. If you're using this software to make a profit, I respectfully ask that you help [fund its development](https://github.com/sponsors/claviska) by becoming a sponsor.
|
||||
|
||||
👇 Your support is very much appreciated! 👇
|
||||
|
||||
<a class="repo-button repo-button--sponsor" href="https://github.com/sponsors/claviska" rel="noopener" target="_blank">
|
||||
<sl-button class="repo-button repo-button--sponsor" href="https://github.com/sponsors/claviska" target="_blank">
|
||||
<sl-icon name="heart"></sl-icon> Become a sponsor
|
||||
</a>
|
||||
</sl-button>
|
||||
|
||||
<a class="repo-button repo-button--github" href="https://github.com/shoelace-style/shoelace/stargazers" rel="noopener" target="_blank">
|
||||
<sl-button class="repo-button repo-button--github" href="https://github.com/shoelace-style/shoelace/stargazers" target="_blank">
|
||||
<sl-icon name="github"></sl-icon> <span class="github-star-count">Star</span>
|
||||
</a>
|
||||
</sl-button>
|
||||
|
||||
<a class="repo-button repo-button--twitter" href="https://twitter.com/shoelace_style" rel="noopener" target="_blank">
|
||||
<sl-button class="repo-button repo-button--twitter" href="https://twitter.com/shoelace_style" target="_blank">
|
||||
<sl-icon name="twitter"></sl-icon> Follow
|
||||
</a>
|
||||
</sl-button>
|
||||
|
||||
## Attribution
|
||||
|
||||
Special thanks to the following projects and individuals that helped make Shoelace possible.
|
||||
Special thanks to the following projects and individuals that help make Shoelace possible.
|
||||
|
||||
- Components are built with [Shoemaker](https://github.com/shoelace-style/shoemaker)
|
||||
- Components are built with [LitElement](https://lit-element.polymer-project.org/)
|
||||
- Component metadata is generated by the [Custom Elements Manifest Analyzer](https://github.com/open-wc/custom-elements-manifest)
|
||||
- Documentation is powered by [Docsify](https://docsify.js.org/)
|
||||
- CDN services are provided by [jsDelivr](https://www.jsdelivr.com/)
|
||||
- The default theme is based on color palettes from [Tailwind](https://tailwindcss.com/)
|
||||
- Color primitives are derived from [Tailwind](https://tailwindcss.com/)
|
||||
- Icons are courtesy of [Bootstrap Icons](https://icons.getbootstrap.com/)
|
||||
- The homepage illustration is courtesy of [unDraw](https://undraw.co/)
|
||||
- Positioning of menus, tooltips, et al is handled by [Popper.js](https://popper.js.org/)
|
||||
- The animation component was inspired by [animatable-component](https://github.com/proyecto26/animatable-component)
|
||||
- Animations are courtesy of [animate.css](https://animate.style/)
|
||||
- QR codes are generated with [qr-creator](https://github.com/nimiq/qr-creator)
|
||||
- Search is powered by [Lunr](https://lunrjs.com/)
|
||||
- The Shoelace logo was designed with a single shoelace by [Adam K Olson](https://twitter.com/adamkolson)
|
||||
|
||||
## Previous Versions
|
||||
|
||||
Shoelace v1 has been deprecated, but you can still [view the docs](https://v1.shoelace.style) or [download the source](https://github.com/shoelace-style/shoelace/releases/tag/1.0.0-beta.25) for historical purposes.
|
||||
|
||||
If you're new to this project, please see the [installation instructions](/getting-started/installation.md) for v2 instead.
|
||||
@@ -1,23 +1,129 @@
|
||||
# Themes
|
||||
|
||||
Shoelace ships with a dark theme that complements the default light theme. You can even take things a step further by designing your own custom theme.
|
||||
Shoelace is designed to be highly customizable through pure CSS. Out of the box, you can choose from a light or dark theme. Alternatively, you can design your own theme from scratch.
|
||||
|
||||
The default theme is included as part of `shoelace.css` and should always be loaded first, even if you want to use another theme exclusively. The default theme contains important base tokens and utilities that many components rely on.
|
||||
A theme is nothing more than a stylesheet that uses the Shoelace API to define design tokens and apply custom styles to components. To create a theme, you will need a decent understanding of CSS, including [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) and the [`::part` selector](https://developer.mozilla.org/en-US/docs/Web/CSS/::part).
|
||||
|
||||
## Dark Mode
|
||||
For developers, built-in themes are also available as JavaScript modules that export [Lit CSSResult](https://lit.dev/docs/api/styles/#CSSResult) objects. You can find them in `dist/themes/*.styles.js`.
|
||||
|
||||
To install the dark theme, add the following to the `<head>` section of your app.
|
||||
## Theme Basics
|
||||
|
||||
All themes are scoped to classes using the `sl-theme-{name}` convention, where `{name}` is a lowercase, hyphen-delimited value representing the name of the theme. The included light and dark themes use `sl-theme-light` and `sl-theme-dark`, respectively. A custom theme called "Purple Power", for example, would use the `sl-theme-purple-power` class.
|
||||
|
||||
Every selector must be scoped to the theme's class to ensure interoperability with other themes. You should also scope them to `:host` so they can be imported and applied to custom element shadow roots.
|
||||
|
||||
```css
|
||||
:host,
|
||||
.sl-theme-purple-power {
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
### Activating Themes
|
||||
|
||||
To activate a theme, import it and apply the theme's class to the `<html>` element. This example imports and activates the dark theme, or "dark mode."
|
||||
|
||||
```html
|
||||
<html class="sl-theme-dark">
|
||||
<head>
|
||||
<link rel="stylesheet" href="path/to/shoelace/dist/themes/dark.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
?> There is one exception to this rule — the light theme _does not_ need to be activated. For convenience, the light theme is scoped to `:root` and will be activated by default when imported.
|
||||
|
||||
### Using Multiple Themes
|
||||
|
||||
You can activate themes on various containers throughout the page. This example uses the light theme with a dark-themed sidebar.
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="path/to/shoelace/dist/themes/light.css">
|
||||
<link rel="stylesheet" href="path/to/shoelace/dist/themes/dark.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="sl-theme-dark">
|
||||
<!-- dark-themed sidebar -->
|
||||
</nav>
|
||||
|
||||
<!-- light-themed content -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Creating Themes
|
||||
|
||||
There are two ways to create themes. The easiest way is to customize a built-in theme. The advanced way is to create a new theme from scratch. Which method you choose depends on your project's requirements and the amount of effort you're willing to commit to.
|
||||
|
||||
### Customizing a Built-in Theme
|
||||
|
||||
The easiest way to customize Shoelace is to override one of the built-in themes. You can do this by importing the light or dark theme as-is, then creating a separate stylesheet that overrides the [design tokens](/getting-started/customizing#design-tokens) and adds [component styles](/getting-started/customizing#component-parts) to your liking. You must import your theme _after_ the built-in theme.
|
||||
|
||||
If you're customizing the light theme, you should scope your styles to the following selectors.
|
||||
|
||||
```css
|
||||
:root,
|
||||
:host,
|
||||
.sl-theme-light {
|
||||
/* your custom styles here */
|
||||
}
|
||||
```
|
||||
|
||||
If you're customizing the dark theme, you should scope your styles to the following selectors.
|
||||
|
||||
```css
|
||||
:host,
|
||||
.sl-theme-dark {
|
||||
/* your custom styles here */
|
||||
}
|
||||
```
|
||||
|
||||
By customizing a built-in theme, you'll maintain a smaller stylesheet containing only the changes you've made. Contrast this to [creating a new theme](#creating-a-new-theme), where you need to explicitly define every design token required by the library. This approach is more "future-proof," as new design tokens that emerge in subsequent versions of Shoelace will be accounted for by the built-in theme.
|
||||
|
||||
While this may be easier to maintain, the drawback is that your theme modifies a built-in theme and thus can't be activated independently.
|
||||
|
||||
### Creating a New Theme
|
||||
|
||||
Creating a new theme is more of an undertaking than [customizing an existing one](#customizing-a-built-in-theme). At a minimum, you must implement all of the required design tokens. The easiest way to do this is by "forking" one of the built-in themes and modifying it from there.
|
||||
|
||||
Start by changing the selector to match your theme's name. Assuming your new theme is called "Purple Power", your theme should be scoped like this.
|
||||
|
||||
```css
|
||||
:host,
|
||||
.sl-theme-purple-power {
|
||||
/* your custom styles here */
|
||||
}
|
||||
```
|
||||
|
||||
By creating a new theme, you won't be relying on a built-in theme as a foundation. Because the theme is decoupled from the built-ins, you can activate it independently as an alternative to the built-ins. This is the recommended approach if you're looking to open source your theme for others to use.
|
||||
|
||||
You will, however, need to maintain your theme more carefully, as new versions of Shoelace may introduce new design tokens that your theme won't have accounted for. Because of this, it's recommended that you clearly specify which version(s) of Shoelace your theme is designed to work with and keep it up to date as new versions of Shoelace are released.
|
||||
|
||||
## Dark Theme
|
||||
|
||||
The built-in dark theme uses an inverted + shifted color scale so, if you're using design tokens as intended, you'll get a decent dark mode for free. While this isn't the same as a professionally curated dark theme, it provides an excellent baseline for one and you're encouraged to customize it depending on your needs.
|
||||
|
||||
This was achieved by taking the light theme's [color tokens](/tokens/color) and "flipping" the scale so 100 becomes 900, 200 becomes 800, 300 becomes 700, etc. Next, the luminance of each primitive was increased slightly to avoid true black, a color that is typically undesirable in dark themes. The result is a custom palette that complements the light theme well and makes it easy to offer light and dark variations with minimal effort.
|
||||
|
||||
To install the dark theme, add the following to the `<head>` section of your page.
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/dark.css">
|
||||
```
|
||||
|
||||
**Themes must be activated after importing!** You can do this by adding the `sl-theme-[name]` class to the `<body>` element.
|
||||
To activate the theme, apply the `sl-theme-dark` class to the `<html>` element.
|
||||
|
||||
```html
|
||||
<body class="sl-theme-dark">
|
||||
<html class="sl-theme-dark">
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Detecting the User's Color Scheme Preference
|
||||
@@ -29,71 +135,3 @@ Shoelace doesn't try to auto-detect the user's light/dark mode preference. This
|
||||
- Remember the user's preference and restore it on subsequent logins
|
||||
|
||||
Shoelace avoids using the `prefers-color-scheme` media query because not all apps support dark mode, and it would break things for the ones that don't.
|
||||
|
||||
## Creating a Theme
|
||||
|
||||
A theme is nothing more than a stylesheet that uses the Shoelace API to customize design tokens and/or components. To create a theme, you will need a decent understanding of CSS, including [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) and the [`::part` selector](https://developer.mozilla.org/en-US/docs/Web/CSS/::part).
|
||||
|
||||
The recommended way to create a theme is to piggyback on top of the default theme, adjusting design tokens and styling components as necessary to achieve the look you want. This makes your theme lightweight and "future proof", as upcoming versions of Shoelace may introduce new design tokens and components that your theme won't support initially. The default theme will account for these so components won't appear to be broken.
|
||||
|
||||
Technically, you can roll your own theme from scratch without using the default theme as a baseline, but that approach isn't recommended.
|
||||
|
||||
### Theme Classes
|
||||
|
||||
All theme classes must use the `sl-theme-{name}` convention, where `{name}` is a lowercase, hyphen-delimited value representing the name of your theme. For example, a theme called "Purple Power" would use the `sl-theme-purple-power` class.
|
||||
|
||||
Every selector in a theme must be scoped to the theme's class to ensure interoperability with other themes.
|
||||
|
||||
### Design Tokens
|
||||
|
||||
[Design tokens](/getting-started/customizing?id=design-tokens) give you a high-level way to customize Shoelace components. You can customize them in your theme as shown below.
|
||||
|
||||
```css
|
||||
.sl-theme-purple-power {
|
||||
--sl-color-primary-50: #faf5ff;
|
||||
--sl-color-primary-100: #f3e8ff;
|
||||
--sl-color-primary-200: #e9d5ff;
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
?> Avoid scoping design tokens to `:root`. You may notice that the default theme does this, but that's because it's not technically a theme — it's a set of design tokens and base styles that themes can use as a foundation to build upon.
|
||||
|
||||
### Components
|
||||
|
||||
To customize individual components, use the following syntax. Available "parts" can be found in the CSS Parts section of each component's documentation.
|
||||
|
||||
```css
|
||||
.sl-theme-purple-power sl-button::part(base) {
|
||||
/* your custom button styles here */
|
||||
}
|
||||
```
|
||||
|
||||
?> Pay special attention to each component's CSS Parts API. You almost always need to use a `::part` selector when theming components!
|
||||
|
||||
## Using a Custom Theme
|
||||
|
||||
If a theme adheres to the guidelines above, you can use it by importing the stylesheet and activating it with the `sl-theme-[name]` class.
|
||||
|
||||
```html
|
||||
<head>
|
||||
...
|
||||
<link rel="stylesheet" href="path/to/purple-power.css">
|
||||
</head>
|
||||
|
||||
<body class="sl-theme-purple-power">
|
||||
...
|
||||
</body>
|
||||
```
|
||||
|
||||
If desired, you can import and activate more than one theme on the same page.
|
||||
|
||||
## Submitting a Theme
|
||||
|
||||
**I am very interested in showcasing well-designed themes that complement this library.** To submit a theme for review, please [open an issue](https://github.com/shoelace-style/shoelace/issues/new) on GitHub with the theme linked or attached. Once approved, your theme will be showcased on this page.
|
||||
|
||||
Please note the following requirements before submitting a theme.
|
||||
|
||||
- Themes must be complete and of high quality
|
||||
- Themes must be available under an open source license
|
||||
- Derivative works must be properly credited
|
||||
|
||||
@@ -6,19 +6,19 @@ Shoelace components are just regular HTML elements, or "custom elements" to be p
|
||||
|
||||
### Properties
|
||||
|
||||
Many components have properties ("props") that can be set using attributes. For example, buttons accept a `size` attribute that dictates the button's size.
|
||||
Many components have properties that can be set using attributes. For example, buttons accept a `size` attribute that maps to the `size` property which dictates the button's size.
|
||||
|
||||
```html
|
||||
<sl-button size="small">Click me</sl-button>
|
||||
```
|
||||
|
||||
Some props are booleans, so they only have true/false values. To activate a boolean prop, add the corresponding attribute without a value.
|
||||
Some properties are boolean, so they only have true/false values. To activate a boolean property, add the corresponding attribute without a value.
|
||||
|
||||
```html
|
||||
<sl-button disabled>Click me</sl-button>
|
||||
```
|
||||
|
||||
In rare cases, a prop may require an array, an object, or a function. For example, to customize the color picker's list of preset swatches, you set the `swatches` prop to an array of colors. This can be done with JavaScript.
|
||||
In rare cases, a property may require an array, an object, or a function. For example, to customize the color picker's list of preset swatches, you set the `swatches` property to an array of colors. This can be done with JavaScript.
|
||||
|
||||
```html
|
||||
<sl-color-picker></sl-color-picker>
|
||||
@@ -50,14 +50,14 @@ Refer to a component's documentation for a complete list of its custom events.
|
||||
|
||||
### Methods
|
||||
|
||||
Some components have methods you can call to trigger various behaviors. For example, you can set focus on a Shoelace input using the `setFocus()` method.
|
||||
Some components have methods you can call to trigger various behaviors. For example, you can set focus on a Shoelace input using the `focus()` method.
|
||||
|
||||
```html
|
||||
<sl-input></sl-input>
|
||||
|
||||
<script>
|
||||
const input = document.querySelector('sl-input');
|
||||
input.setFocus();
|
||||
input.focus();
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -102,28 +102,32 @@ Custom elements cannot have self-closing tags. Similar to `<script>` and `<texta
|
||||
|
||||
You might expect similarly named elements to share the same API as native HTML elements. This is not always the case. Shoelace components **are not** designed to be one-to-one replacements for their HTML counterparts.
|
||||
|
||||
For example, `<button>` and `<sl-button>` both have a `type` attribute, but it does different things (the former controls whether the button submits a form and the latter controls the button's appearance). Similarly, you can't call `focus()` on a Shoelace input — you need to use the component's `setFocus()` method instead. There are technical reasons for some of these design decisions that are outside the scope of this page.
|
||||
For example, `<button>` and `<sl-button>` both have a `type` attribute, but it does different things. The former controls whether the button submits a form and the latter controls the button's appearance.
|
||||
|
||||
?> **Don't make assumptions about a component's API!** To prevent unexpected behaviors, please take the time to review the documentation and make sure you understand what each property, method, and event is intended to do.
|
||||
?> **Don't make assumptions about a component's API!** To prevent unexpected behaviors, please take the time to review the documentation and make sure you understand what each attribute, property, method, and event is intended to do.
|
||||
|
||||
## Code Completion
|
||||
|
||||
Shoelace ships with a `custom-elements.json` file that can be used to describe its components to supportive editors, providing code completion (also known as "code hinting" or "IntelliSense"). To enable this, you need to tell your editor where this file is.
|
||||
|
||||
### VS Code
|
||||
|
||||
1. [Install Shoelace locally](/getting-started/installation.md#local-installation)
|
||||
Shoelace ships with a file called `vscode.html-custom-data.json` that can be used to describe its components to Visual Studio Code. This enables code completion for Shoelace components (also known as "code hinting" or "IntelliSense"). To enable it, you need to tell VS Code where the file is.
|
||||
|
||||
1. [Install Shoelace locally](/getting-started/installation#local-installation)
|
||||
2. Create a folder called `.vscode` at the root of your project
|
||||
3. Create a file inside the folder called `settings.json`
|
||||
4. Add the following to the file
|
||||
|
||||
```js
|
||||
{
|
||||
"html.customData": ["./node_modules/@shoelace-style/shoelace/dist/custom-elements.json"]
|
||||
"html.customData": ["./node_modules/@shoelace-style/shoelace/dist/vscode.html-custom-data.json"]
|
||||
}
|
||||
```
|
||||
|
||||
If `settings.json` already exists in your project, simply add the `html.customData` line to the root of the object.
|
||||
If `settings.json` already exists, simply add the above line to the root of the object. Note that you may need to restart VS Code for the changes to take affect.
|
||||
|
||||
### Other Editors
|
||||
|
||||
Most popular editors support custom code completion with a bit of configuration. Please [submit a feature request](https://github.com/shoelace-style/shoelace/issues/new/choose) for your editor of choice. PRs are also welcome!
|
||||
|
||||
## React
|
||||
|
||||
@@ -135,37 +139,28 @@ Event handling can also be cumbersome.
|
||||
|
||||
> Because React implements its own synthetic event system, it cannot listen for DOM events coming from Custom Elements without the use of a workaround. Developers will need to reference their Custom Elements using a ref and manually attach event listeners with addEventListener. This makes working with Custom Elements cumbersome.
|
||||
|
||||
Fortunately, there's a utility that will wrap Shoelace components so you can use them as if they were React components. 👇
|
||||
|
||||
?> If you're starting a new project, consider using [Preact](https://preactjs.com/) as an alternative. It shares the same API as React and [handles custom elements quite well](https://custom-elements-everywhere.com/#preact).
|
||||
|
||||
### Wrapping Components
|
||||
|
||||
You can use [this utility](https://www.npmjs.com/package/@shoelace-style/react-wrapper) to wrap Shoelace components so they work like regular React components. To install it, use this command.
|
||||
Fortunately, there's a package called [@shoelace-style/react](https://www.npmjs.com/package/@shoelace-style/react) that will let you use Shoelace components as if they were React components. You can install it using this command.
|
||||
|
||||
```bash
|
||||
npm install @shoelace-style/react-wrapper
|
||||
npm install @shoelace-style/react
|
||||
```
|
||||
|
||||
Now you can "import" Shoelace components as React components! Remember to [install Shoelace](/getting-started/installation.md) first, otherwise this won't work.
|
||||
|
||||
```js
|
||||
import wrapCustomElement from '@shoelace-style/react-wrapper';
|
||||
|
||||
const ShoelaceButton = wrapCustomElement('sl-button');
|
||||
|
||||
return <ShoelaceButton type="primary">Click me</ShoelaceButton>;
|
||||
```
|
||||
|
||||
A reference ("ref") to the underlying custom element is exposed through the `element` property so you can access it directly. This is useful for calling methods.
|
||||
Include the default theme and any components you want to use in your app.
|
||||
|
||||
```jsx
|
||||
<ShoelaceButton
|
||||
ref={el => this.button = el}
|
||||
onClick={() => this.button.element.current.removeFocus()}
|
||||
>
|
||||
Click me
|
||||
</ShoelaceButton>
|
||||
import '@shoelace-style/shoelace/dist/themes/light.css';
|
||||
|
||||
import SlButton from '@shoelace-style/react/dist/button';
|
||||
|
||||
// ...
|
||||
|
||||
const MyComponent = (props) => {
|
||||
return (
|
||||
<SlButton type="primary">
|
||||
Click me
|
||||
</SlButton>
|
||||
)
|
||||
};
|
||||
```
|
||||
|
||||
## Vue
|
||||
@@ -173,9 +168,14 @@ A reference ("ref") to the underlying custom element is exposed through the `ele
|
||||
Vue [plays nice](https://custom-elements-everywhere.com/#vue) with custom elements. You just have to tell it to ignore Shoelace components. This is pretty easy because they all start with `sl-`.
|
||||
|
||||
```js
|
||||
Vue.config.ignoredElements = [/^sl-/];
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
new Vue({ ... });
|
||||
const app = createApp(App);
|
||||
|
||||
app.config.compilerOptions.isCustomElement = tag => tag.startsWith('sl-');
|
||||
|
||||
app.mount('#app');
|
||||
```
|
||||
|
||||
### Binding Complex Data
|
||||
@@ -198,11 +198,11 @@ One caveat is there's currently [no support for v-model on custom elements](http
|
||||
<sl-input :value="name" @input="name = $event.target.value">
|
||||
```
|
||||
|
||||
If that's too verbose, you can use a custom directive instead. 👇
|
||||
If that's too verbose, you can use a custom directive instead.
|
||||
|
||||
### Using a Custom Directive
|
||||
|
||||
You can use [this utility](https://www.npmjs.com/package/@shoelace-style/vue-sl-model) to add a custom directive to Vue that will work just like `v-model` but for Shoelace components. To install it, use this command.
|
||||
You can use [this utility](https://www.npmjs.com/package/@shoelace-style/vue-sl-model) to add a custom directive that will work just like `v-model` but for Shoelace components. To install it, use this command.
|
||||
|
||||
```bash
|
||||
npm install @shoelace-style/vue-sl-model
|
||||
@@ -212,12 +212,15 @@ Next, import the directive and enable it like this.
|
||||
|
||||
```js
|
||||
import ShoelaceModelDirective from '@shoelace-style/vue-sl-model';
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
Vue.config.ignoredElements = [/^sl-/];
|
||||
Vue.use(ShoelaceModelDirective);
|
||||
const app = createApp(App);
|
||||
app.use(ShoelaceModelDirective);
|
||||
|
||||
// Your init here
|
||||
new Vue({ ... });
|
||||
app.config.compilerOptions.isCustomElement = tag => tag.startsWith('sl-');
|
||||
|
||||
app.mount('#app');
|
||||
```
|
||||
|
||||
Now you can use the `v-sl-model` directive to keep your data in sync!
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
|
||||
/>
|
||||
<meta name="custom-elements-manifest" content="dist/custom-elements.json" />
|
||||
<meta property="og:title" content="Shoelace" />
|
||||
<meta
|
||||
property="og:description"
|
||||
@@ -20,7 +21,6 @@
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://shoelace.style/" />
|
||||
<meta property="og:image" content="https://shoelace.style/assets/images/og-image.png" />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@shoelace_style" />
|
||||
<meta name="twitter:creator" content="@claviska" />
|
||||
@@ -33,20 +33,25 @@
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify@4/themes/pure.css" />
|
||||
<link rel="stylesheet" href="/assets/styles/docs.css" />
|
||||
<link rel="stylesheet" href="/assets/styles/docs-dark.css" />
|
||||
<link rel="stylesheet" href="/assets/styles/demos.css" />
|
||||
<link rel="stylesheet" href="/assets/plugins/code-block/code-block.css" />
|
||||
<link rel="stylesheet" href="/assets/plugins/theme/theme.css" />
|
||||
<link rel="stylesheet" href="/assets/plugins/search/search.css" />
|
||||
<link rel="stylesheet" href="/assets/plugins/theme-picker/theme-picker.css" />
|
||||
<link rel="icon" href="/assets/images/logo.svg" type="image/x-icon" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/assets/images/touch-icon.png" />
|
||||
|
||||
<!-- Import Shoelace -->
|
||||
<link rel="stylesheet" href="/dist/themes/base.css" />
|
||||
<link rel="stylesheet" href="/dist/themes/light.css" />
|
||||
<link rel="stylesheet" href="/dist/themes/dark.css" />
|
||||
<script type="module" src="/dist/all.shoelace.js"></script>
|
||||
<script type="module" src="/dist/shoelace.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script>
|
||||
// Set the initial theme to prevent flashing
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const theme = localStorage.getItem('theme') || 'auto';
|
||||
document.documentElement.classList.toggle('sl-theme-dark', theme === 'dark' || (theme === 'auto' && prefersDark));
|
||||
</script>
|
||||
<script>
|
||||
window.$docsify = {
|
||||
alias: {
|
||||
@@ -54,7 +59,7 @@
|
||||
},
|
||||
auto2top: true,
|
||||
copyCode: {
|
||||
buttonText: 'Copy Code',
|
||||
buttonText: 'Copy',
|
||||
errorText: 'Failed to copy',
|
||||
successText: 'Copied'
|
||||
},
|
||||
@@ -67,6 +72,7 @@
|
||||
maxLevel: 3,
|
||||
subMaxLevel: 2,
|
||||
name: 'Shoelace',
|
||||
nameLink: '/',
|
||||
notFoundPage: '404.md',
|
||||
pagination: {
|
||||
previousText: 'Previous',
|
||||
@@ -74,29 +80,21 @@
|
||||
crossChapter: true,
|
||||
crossChapterText: false
|
||||
},
|
||||
routerMode: location.port ? 'hash' : 'history',
|
||||
search: {
|
||||
maxAge: 86400000, // Expiration time, the default one day
|
||||
paths: 'auto',
|
||||
placeholder: 'Search',
|
||||
noData: 'No Results',
|
||||
depth: 3,
|
||||
namespace: 'shoelace-docs'
|
||||
},
|
||||
themeColor: '#049dff'
|
||||
routerMode: 'history',
|
||||
themeColor: 'rgb(var(--sl-color-primary-500))'
|
||||
};
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/plugins/search.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/plugins/ga.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify-copy-code@2"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify-pagination@2/dist/docsify-pagination.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.19.0/components/prism-bash.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.19.0/components/prism-jsx.min.js"></script>
|
||||
<script src="/assets/plugins/code-block/code-block.js"></script>
|
||||
<script src="/assets/plugins/scroll-position/scroll-position.js"></script>
|
||||
<script src="/assets/plugins/metadata/metadata.js"></script>
|
||||
<script src="/assets/plugins/sidebar/sidebar.js"></script>
|
||||
<script src="/assets/plugins/theme/theme.js"></script>
|
||||
<script src="/assets/plugins/scroll-position/scroll-position.js"></script>
|
||||
<script src="/assets/plugins/search/lunr.min.js"></script>
|
||||
<script src="/assets/plugins/search/search.js"></script>
|
||||
<script src="/assets/plugins/theme-picker/theme-picker.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
825
docs/resources/changelog.md
Normal file
@@ -0,0 +1,825 @@
|
||||
# Changelog
|
||||
|
||||
Shoelace follows [Semantic Versioning](https://semver.org/). Breaking changes in components with the <sl-badge type="primary" pill>Stable</sl-badge> badge will not be accepted until the next major version. As such, all contributions must consider the project's roadmap and take this into consideration. Features that are deemed no longer necessary will be deprecated but not removed.
|
||||
|
||||
Components with the <sl-badge type="warning" pill>Experimental</sl-badge> badge should not be used in production. They are made available as release candidates for development and testing purposes. As such, changes to experimental components will not be subject to semantic versioning.
|
||||
|
||||
_During the beta period, these restrictions may be relaxed in the event of a mission-critical bug._ 🐛
|
||||
|
||||
## Next
|
||||
|
||||
- Added experimental `<sl-context-menu>` component
|
||||
- Added eye dropper to `<sl-color-picker>` when the browser supports the [EyeDropper API](https://wicg.github.io/eyedropper-api/)
|
||||
- Fixed a bug in `<sl-button-group>` where buttons groups with only one button would have an incorrect border radius
|
||||
- Improved the `<sl-color-picker>` trigger's border in dark mode
|
||||
- Refactored positioning logic in `<sl-dropdown>` so Popper is only active when the menu is open
|
||||
- Updated to Lit 2.0.2
|
||||
|
||||
## 2.0.0-beta.58
|
||||
|
||||
This version once again restores the bundled distribution because the unbundled + CDN approach is currently confusing and [not working properly](https://github.com/shoelace-style/shoelace/issues/559#issuecomment-949662331). Unbundling the few dependencies Shoelace has is still a goal of the project, but [this jsDelivr bug](https://github.com/jsdelivr/jsdelivr/issues/18337) needs to be resolved before we can achieve it.
|
||||
|
||||
I sincerely apologize for the instability of the last few beta releases as a result of this effort.
|
||||
|
||||
- Added experimental `<sl-animated-image>` component
|
||||
- Added `label` attribute to `<sl-progress-bar>` and `<sl-progress-ring>` to improve a11y
|
||||
- Fixed a bug where the tooltip would show briefly when clicking a disabled `<sl-range>`
|
||||
- Fixed a bug that caused a console error when `<sl-range>` was used
|
||||
- Fixed a bug where the `nav` part in `<sl-tab-group>` was on the incorrect element [#563](https://github.com/shoelace-style/shoelace/pull/563)
|
||||
- Fixed a bug where non-integer aspect ratios were calculated incorrectly in `<sl-responsive-media>`
|
||||
- Fixed a bug in `<sl-range>` where setting `value` wouldn't update the active and inactive portion of the track [#572](https://github.com/shoelace-style/shoelace/pull/572)
|
||||
- Reverted to publishing the bundled dist and removed `/+esm` links from the docs
|
||||
- Updated to Bootstrap Icons to 1.6.1
|
||||
|
||||
## 2.0.0-beta.57
|
||||
|
||||
- Fix CodePen links and CDN links
|
||||
|
||||
## 2.0.0-beta.56
|
||||
|
||||
This release is the second attempt at unbundling dependencies. This will be a breaking change only if your configuration _does not_ support bare module specifiers. CDN users and bundler users will be unaffected, but note the URLs for modules on the CDN must have the `/+esm` now.
|
||||
|
||||
- Added the `hoist` attribute to `<sl-tooltip>` [#564](https://github.com/shoelace-style/shoelace/issues/564)
|
||||
- Unbundled dependencies and configured external imports to be packaged with bare module specifiers
|
||||
|
||||
## 2.0.0-beta.55
|
||||
|
||||
- Revert unbundling due to issues with the CDN not handling bare module specifiers as expected
|
||||
|
||||
## 2.0.0-beta.54
|
||||
|
||||
Shoelace doesn't have a lot of dependencies, but this release unbundles most of them so you can potentially save some extra kilobytes. This will be a breaking change only if your configuration _does not_ support bare module specifiers. CDN users and bundler users will be unaffected.
|
||||
|
||||
- 🚨 BREAKING: renamed the `sl-clear` event to `sl-remove`, the `clear-button` part to `remove-button`, and the `clearable` property to `removable` in `<sl-tag>`
|
||||
- Added the `disabled` prop to `<sl-resize-observer>`
|
||||
- Fixed a bug in `<sl-mutation-observer>` where setting `disabled` initially didn't work
|
||||
- Unbundled dependencies and configured external imports to be packaged with bare module specifiers
|
||||
|
||||
## 2.0.0-beta.53
|
||||
|
||||
- 🚨 BREAKING: removed `<sl-menu-divider>` (use `<sl-divider>` instead)
|
||||
- 🚨 BREAKING: removed `percentage` attribute from `<sl-progress-bar>` and `<sl-progress-ring>` (use `value`) instead
|
||||
- 🚨 BREAKING: switched the default `type` of `<sl-tag>` from `primary` to `neutral`
|
||||
- Added the experimental `<sl-mutation-observer>` component
|
||||
- Added the `<sl-divider>` component
|
||||
- Added `--sl-surface-base` and `--sl-surface-base-alt` as early surface tokens to improve the appearance of alert, card, and panels in dark mode
|
||||
- Added the `--sl-panel-border-width` design token
|
||||
- Added missing background color to `<sl-details>`
|
||||
- Added the `--padding` custom property to `<sl-tab-panel>`
|
||||
- Added the `outline` variation to `<sl-button>` [#522](https://github.com/shoelace-style/shoelace/issues/522)
|
||||
- Added the `filled` variation to `<sl-input>`, `<sl-textarea>`, and `<sl-select>` and supporting design tokens
|
||||
- Added the `control` part to `<sl-select>` so you can target the main control with CSS [#538](https://github.com/shoelace-style/shoelace/issues/538)
|
||||
- Added a border to `<sl-badge>` to improve contrast when drawn on various background colors
|
||||
- Added `--track-color-active` and `--track-color-inactive` custom properties to `<sl-range>` [#550](https://github.com/shoelace-style/shoelace/issues/550)
|
||||
- Added the undocumented custom properties `--thumb-size`, `--tooltip-offset`, `--track-height` on `<sl-range>`
|
||||
- Changed the default `distance` in `<sl-dropdown>` from `2` to `0` [#538](https://github.com/shoelace-style/shoelace/issues/538)
|
||||
- Fixed a bug where `<sl-select>` would be larger than the viewport when it had lots of options [#544](https://github.com/shoelace-style/shoelace/issues/544)
|
||||
- Fixed a bug where `<sl-progress-ring>` wouldn't animate in Safari
|
||||
- Updated the default height of `<sl-progress-bar>` from `16px` to `1rem` and added a subtle shadow to indicate depth
|
||||
- Removed the `lit-html` dependency and moved corresponding imports to `lit` [#546](https://github.com/shoelace-style/shoelace/issues/546)
|
||||
|
||||
## 2.0.0-beta.52
|
||||
|
||||
- 🚨 BREAKING: changed the `--stroke-width` custom property of `<sl-spinner>` to `--track-width` for consistency
|
||||
- 🚨 BREAKING: removed the `size` and `stroke-width` attributes from `<sl-progress-ring>` so it's fully customizable with CSS (use the `--size` and `--track-width` custom properties instead)
|
||||
- Added the `--speed` custom property to `<sl-spinner>`
|
||||
- Added the `--size` and `--track-width` custom properties to `<sl-progress-ring>`
|
||||
- Added tests for `<sl-badge>` [#530](https://github.com/shoelace-style/shoelace/pull/530)
|
||||
- Fixed a bug where `<sl-tab>` wasn't using a border radius token [#523](https://github.com/shoelace-style/shoelace/issues/523)
|
||||
- Fixed a bug in the Remix Icons example where some icons would 404 [#528](https://github.com/shoelace-style/shoelace/issues/528)
|
||||
- Updated `<sl-progress-ring>` to use only CSS for styling
|
||||
- Updated `<sl-spinner>` to use an SVG and improved the indicator animation
|
||||
- Updated to Lit 2.0 and lit-html 2.0 🔥
|
||||
|
||||
## 2.0.0-beta.51
|
||||
|
||||
A number of users had trouble counting characters that repeat, so this release improves design token patterns so that "t-shirt sizes" are more accessible. For example, `--sl-font-size-xxx-large` has become `--sl-font-size-3x-large`. This change applies to all design tokens that use this scale.
|
||||
|
||||
- 🚨 BREAKING: all t-shirt size design tokens now use `2x`, `3x`, `4x` instead of `xx`, `xxx`, `xxxx`
|
||||
- Added missing `--sl-focus-ring-*` tokens to dark theme
|
||||
- Added an "Importing" section to all components with copy/paste code to make cherry picking easier
|
||||
- Improved the documentation search with a custom plugin powered by [Lunr](https://lunrjs.com/)
|
||||
- Improved the `--sl-shadow-x-small` elevation
|
||||
- Improved visibility of elevations and overlays in dark theme
|
||||
- Reduced the size of `<sl-color-picker>` slightly to better accommodate mobile devices
|
||||
- Removed `<sl-icon>` dependency from `<sl-color-picker>` and improved the copy animation
|
||||
|
||||
## 2.0.0-beta.50
|
||||
|
||||
- Added `<sl-breadcrumb>` and `<sl-breadcrumb-item>` components
|
||||
- Added `--sl-letter-spacing-denser`, `--sl-letter-spacing-looser`, `--sl-line-height-denser`, and `--sl-line-height-looser` design tokens
|
||||
- Fixed a bug where form controls would error out when the value was set to `undefined` [#513](https://github.com/shoelace-style/shoelace/pull/513)
|
||||
|
||||
## 2.0.0-beta.49
|
||||
|
||||
This release changes the way focus states are applied to elements. In browsers that support [`:focus-visible`](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible), it will be used. In unsupportive browsers ([currently only Safari](https://caniuse.com/mdn-css_selectors_focus-visible)), `:focus` will be used instead. This means the browser will determine whether a focus ring should be shown based on how the user interacts with the page.
|
||||
|
||||
This release also fixes a critical bug in the color scale where `--sl-color-neutral-0` and `--sl-color-neutral-1000` were reversed.
|
||||
|
||||
- 🚨 BREAKING: fixed a bug where `--sl-color-neutral-0` and `--sl-color-neutral-1000` were inverted (swap them to update)
|
||||
- 🚨 BREAKING: removed the `no-fieldset` property from `<sl-radio-group>` (fieldsets are now hidden by default; use `fieldset` to show them)
|
||||
- 🚨 BREAKING: removed `--focus-ring` custom property from `<sl-input>`, `<sl-select>`, `<sl-tab>` for consistency with other form controls
|
||||
- Added `--swatch-size` custom property to `<sl-color-picker>`
|
||||
- Added `date` to `<sl-input>` as a supported `type`
|
||||
- Added the `--sl-focus-ring` design token for a more convenient way to apply focus ring styles
|
||||
- Adjusted elevation tokens to use neutral in light mode and black in dark mode
|
||||
- Adjusted `--sl-overlay-background-color` in dark theme to be black instead of gray
|
||||
- Fixed a bug in `<sl-color-picker>` where the opacity slider wasn't showing the current color
|
||||
- Fixed a bug where Edge in Windows would show the native password toggle next to the custom password toggle [#508](https://github.com/shoelace-style/shoelace/issues/508)
|
||||
- Fixed a bug where pressing up/down in `<sl-tab-group>` didn't select the next/previous tab in vertical placements
|
||||
- Improved size of `<sl-color-picker>`
|
||||
- Improved icon contrast in `<sl-input>`
|
||||
- Improved contrast of `<sl-switch>`
|
||||
- Improved `:focus-visible` behavior in many components
|
||||
- Removed elevation from `<sl-color-picker>` when rendered inline
|
||||
- Removed custom `:focus-visible` logic in favor of a directive that outputs `:focus-visible` or `:focus` depending on browser support
|
||||
- Updated to Lit 2.0.0-rc.3
|
||||
- Updated to lit-html 2.0.0-rc.4
|
||||
|
||||
## 2.0.0-beta.48
|
||||
|
||||
This release improves theming by offering both light and dark themes that can be used autonomously. It also improves contrast in most components, adds a variety of new color primitives, and changes the way color tokens are consumed.
|
||||
|
||||
Previously, color tokens were in hexidecimal format. Now, Shoelace now uses an `R G B` format that requires you to use the `rgb()` function in your CSS.
|
||||
|
||||
```css
|
||||
.example {
|
||||
/* rgb() is required now */
|
||||
color: rgb(var(--sl-color-neutral-500));
|
||||
}
|
||||
```
|
||||
|
||||
This is more verbose than previous versions, but it has the advantage of letting you set the alpha channel of any color token.
|
||||
|
||||
```css
|
||||
.example-with-alpha {
|
||||
/* easily adjust opacity for any color token */
|
||||
color: rgb(var(--sl-color-neutral-500) / 50%);
|
||||
}
|
||||
```
|
||||
|
||||
This change applies to all design tokens that implement a color. Refer to the [color tokens](/tokens/color) page for more details.
|
||||
|
||||
- 🚨 BREAKING: all design tokens that implement colors have been converted to `R G B` and must be used with the `rgb()` function
|
||||
- 🚨 BREAKING: removed `--sl-color-black|white` color tokens (use `--sl-color-neutral-0|1000` instead)
|
||||
- 🚨 BREAKING: removed `--sl-color-primary|success|warning|info|danger-text` design tokens (use theme or primitive colors instead)
|
||||
- 🚨 BREAKING: removed `info` variant from `<sl-alert>`, `<sl-badge>`, `<sl-button>`, and `<sl-tag>` (use `neutral` instead)
|
||||
- 🚨 BREAKING: removed `--sl-color-info-*` design token (use `--sl-color-neutral-*` instead)
|
||||
- 🚨 BREAKING: renamed `dist/themes/base.css` to `dist/themes/light.css`
|
||||
- 🚨 BREAKING: removed `--sl-focus-ring-color-primary` tokens (use color tokens and `--sl-focus-ring-width|alpha` instead)
|
||||
- 🚨 BREAKING: removed `--tabs-border-color` from `<sl-tab-group>` (use `--track-color` instead)
|
||||
- 🚨 BREAKING: changed the default value for `effect` to `none` in `<sl-skeleton>` (use `sheen` to restore the original behavior)
|
||||
- Added new color primitives to the base set of design tokens
|
||||
- Added `--sl-color-*-950` swatches to all color palettes
|
||||
- Added a console error that appears when menu items have duplicate values in `<sl-select>`
|
||||
- Added CodePen link to code examples
|
||||
- Added `prefix` and `suffix` slots to `<sl-select>` [#501](https://github.com/shoelace-style/shoelace/pull/501)
|
||||
- Added `--indicator-color` custom property to `<sl-tab-group>`
|
||||
- Exposed base and dark stylesheets so they can be imported via JavaScript [#438](https://github.com/shoelace-style/shoelace/issues/438)
|
||||
- Fixed a bug in `<sl-menu>` where pressing <kbd>Enter</kbd> after using type to select would result in the wrong value
|
||||
- Fixed a bug in `<sl-radio-group>` where clicking a radio button would cause the wrong control to be focused
|
||||
- Fixed a bug in `<sl-button>` and `<sl-icon-button>` where an unintended `ref` attribute was present
|
||||
- Fixed a bug in the focus-visible utility that failed to respond to mouseup events
|
||||
- Fixed a bug where clicking on a menu item would persist its hover/focus state
|
||||
- Fixed a bug in `<sl-select>` where it would erroneously intercept important keyboard shortcuts [#504](https://github.com/shoelace-style/shoelace/issues/504)
|
||||
- Improved contrast throughout all components [#128](https://github.com/shoelace-style/shoelace/issues/128)
|
||||
- Refactored thumb position logic in `<sl-switch>` [#490](https://github.com/shoelace-style/shoelace/pull/490)
|
||||
- Reworked the dark theme to use an inverted + shifted design token approach instead of component-specific selectors
|
||||
|
||||
## 2.0.0-beta.47
|
||||
|
||||
This release improves how component dependencies are imported. If you've been cherry picking, you no longer need to import component dependencies manually. This significantly improves developer experience, making Shoelace even easier to use. For transparency, component dependencies will continue to be listed in the docs.
|
||||
|
||||
- Added "Reflects" column to the properties table
|
||||
- Dependencies are now automatically imported for all components
|
||||
- Fixed a bug where tabbing into `<sl-radio-group>` would not always focus the checked radio
|
||||
- Fixed a bug in component styles that prevented the box sizing reset from being applied
|
||||
- Fixed a regression in `<sl-color-picker>` where dragging the grid handle wasn't smooth
|
||||
- Fixed a bug where slot detection could incorrecly match against slots of child elements [#481](https://github.com/shoelace-style/shoelace/pull/481)
|
||||
- Fixed a bug in `<sl-input>` where focus would move to the end of the input when typing in Safari [#480](https://github.com/shoelace-style/shoelace/issues/480)
|
||||
- Improved base path utility logic
|
||||
|
||||
## 2.0.0-beta.46
|
||||
|
||||
This release improves the developer experience of `<sl-animation>`. Previously, an animation was assumed to be playing unless the `pause` attribute was set. This behavior has been reversed and `pause` has been removed. Now, animations will not play until the new `play` attribute is applied.
|
||||
|
||||
This is a lot more intuitive and makes it easier to activate animations imperatively. In addition, the `play` attribute is automatically removed automatically when the animation finishes or cancels, making it easier to restart finite animations. Lastly, the animation's timing is now accessible through the new `currentTime` property instead of `getCurrentTime()` and `setCurrentTime()`.
|
||||
|
||||
In addition, Shoelace no longer uses Sass. Component styles now use Lit's template literal styles and theme files use pure CSS.
|
||||
|
||||
- 🚨 BREAKING: removed the `pause` attribute from `<sl-animation>` (use `play` to start and stop the animation instead)
|
||||
- 🚨 BREAKING: removed `getCurrentTime()` and `setCurrentTime()` from `<sl-animation>` (use the `currentTime` property instead)
|
||||
- 🚨 BREAKING: removed the `close-on-select` attribute from `<sl-dropdown>` (use `stay-open-on-select` instead)
|
||||
- Added the `currentTime` property to `<sl-animation>` to control the current time without methods
|
||||
- Fixed a bug in `<sl-range>` where the tooltip wasn't showing in Safari [#477](https://github.com/shoelace-style/shoelace/issues/477)
|
||||
- Fixed a bug in `<sl-menu>` where pressing <kbd>Enter</kbd> in a menu didn't work with click handlers
|
||||
- Reworked `<sl-menu>` and `<sl-menu-item>` to use a roving tab index and improve keyboard accessibility
|
||||
- Reworked tabbable logic to be more performant [#466](https://github.com/shoelace-style/shoelace/issues/466)
|
||||
- Switched component stylesheets from Sass to Lit's template literal styles
|
||||
- Switched theme stylesheets from Sass to CSS
|
||||
|
||||
## 2.0.0-beta.45
|
||||
|
||||
This release changes the way component metadata is generated. Previously, the project used TypeDoc to analyze components and generate a very large file with type data. The data was then parsed and converted to an easier-to-consume file called `metadata.json`. Alas, TypeDoc is expensive to run and the metadata format wasn't standard.
|
||||
|
||||
Thanks to an amazing effort by [Pascal Schilp](https://twitter.com/passle_), the world has a simpler, faster way to gather metadata using the [Custom Elements Manifest Analyzer](https://github.com/open-wc/custom-elements-manifest). Not only is this tool faster, but the data follows the evolving `custom-elements.json` format. This is exciting because a standard format for custom elements opens the door for many potential uses, including documentation generation, framework adapters, IDE integrations, third-party uses, and more. [Check out Pascal's great article](https://dev.to/open-wc/introducing-custom-elements-manifest-gkk) for more info about `custom-elements.json` and the new analyzer.
|
||||
|
||||
The docs have been updated to use the new `custom-elements.json` file. If you're relying on the old `metadata.json` file for any purpose, this will be a breaking change for you.
|
||||
|
||||
- 🚨 BREAKING: removed the `sl-overlay-click` event from `<sl-dialog>` and `<sl-drawer>` (use `sl-request-close` instead) [#471](https://github.com/shoelace-style/shoelace/discussions/471)
|
||||
- 🚨 BREAKING: removed `metadata.json` (use `custom-elements.json` instead)
|
||||
- Added `custom-elements.json` for component metadata
|
||||
- Added `sl-request-close` event to `<sl-dialog>` and `<sl-drawer>`
|
||||
- Added `dialog.denyClose` and `drawer.denyClose` animations
|
||||
- Fixed a bug in `<sl-color-picker>` where setting `value` immediately wouldn't trigger an update
|
||||
- Fixed a bug in `<sl-dialog>` and `<sl-drawer>` where setting `open` intially didn't set a focus trap
|
||||
- Fixed a bug that resulted in form controls having incorrect validity when `disabled` was initially set [#473](https://github.com/shoelace-style/shoelace/issues/473)
|
||||
- Fixed a bug in the docs that caused the metadata file to be requested twice
|
||||
- Fixed a bug where tabbing out of a modal would cause the browser to lag [#466](https://github.com/shoelace-style/shoelace/issues/466)
|
||||
- Updated the docs to use the new `custom-elements.json` for component metadata
|
||||
|
||||
## 2.0.0-beta.44
|
||||
|
||||
- 🚨 BREAKING: all `invalid` props on form controls now reflect validity before interaction [#455](https://github.com/shoelace-style/shoelace/issues/455)
|
||||
- Allow `null` to be passed to disable animations in `setDefaultAnimation()` and `setAnimation()`
|
||||
- Converted build scripts to ESM
|
||||
- Fixed a bug in `<sl-checkbox>` where `invalid` did not update properly
|
||||
- Fixed a bug in `<sl-dropdown>` where a `keydown` listener wasn't cleaned up properly
|
||||
- Fixed a bug in `<sl-select>` where `sl-blur` was emitted prematurely [#456](https://github.com/shoelace-style/shoelace/issues/456)
|
||||
- Fixed a bug in `<sl-select>` where no selection with `multiple` resulted in an incorrect value [#457](https://github.com/shoelace-style/shoelace/issues/457)
|
||||
- Fixed a bug in `<sl-select>` where `sl-change` was emitted immediately after connecting to the DOM [#458](https://github.com/shoelace-style/shoelace/issues/458)
|
||||
- Fixed a bug in `<sl-select>` where non-printable keys would cause the menu to open
|
||||
- Fixed a bug in `<sl-select>` where `invalid` was not always updated properly
|
||||
- Reworked the `@watch` decorator to use `update` instead of `updated` resulting in better performance and flexibility
|
||||
|
||||
## 2.0.0-beta.43
|
||||
|
||||
- Added `?` to optional arguments in methods tables in the docs
|
||||
- Added the `scrollPosition()` method to `<sl-textarea>` to get/set scroll position
|
||||
- Added intial tests for `<sl-dialog>`, `<sl-drawer>`, `<sl-dropdown>`, and `<sl-tooltip>`
|
||||
- Fixed a bug in `<sl-tab-group>` where scrollable tab icons were not displaying correctly
|
||||
- Fixed a bug in `<sl-dialog>` and `<sl-drawer>` where preventing clicks on the overlay no longer worked as described [#452](https://github.com/shoelace-style/shoelace/issues/452)
|
||||
- Fixed a bug in `<sl-dialog>` and `<sl-drawer>` where setting initial focus no longer worked as described [#453](https://github.com/shoelace-style/shoelace/issues/453)
|
||||
- Fixed a bug in `<sl-card>` where the `slotchange` listener wasn't attached correctly [#454](https://github.com/shoelace-style/shoelace/issues/454)
|
||||
- Fixed lifecycle bugs in a number of components [#451](https://github.com/shoelace-style/shoelace/issues/451)
|
||||
- Removed `fill: both` from internal animate utility so styles won't "stick" by default [#450](https://github.com/shoelace-style/shoelace/issues/450)
|
||||
|
||||
## 2.0.0-beta.42
|
||||
|
||||
This release addresses an issue with the `open` attribute no longer working in a number of components, as a result of the changes in beta.41. It also removes a small but controversial feature that complicated show/hide logic and led to a poor experience for developers and end users.
|
||||
|
||||
There are two ways to show/hide affected components: by calling `show() | hide()` and by toggling the `open` prop. Previously, it was possible to call `event.preventDefault()` in an `sl-show | sl-hide ` handler to stop the component from showing/hiding. The problem becomes obvious when you set `el.open = false`, the event gets canceled, and in the next cycle `el.open` has reverted to `true`. Not only is this unexpected, but it also doesn't play nicely with frameworks. Additionally, this made it impossible to await `show() | hide()` since there was a chance they'd never resolve.
|
||||
|
||||
Technical reasons aside, canceling these events seldom led to a good user experience, so the decision was made to no longer allow `sl-show | sl-hide` to be cancelable.
|
||||
|
||||
- 🚨 BREAKING: `sl-show` and `sl-hide` events are no longer cancelable
|
||||
- Added Iconoir example to the icon docs
|
||||
- Added Web Test Runner
|
||||
- Added intial tests for `<sl-alert>` and `<sl-details>`
|
||||
- Changed the `cancelable` default to `false` for the internal `@event` decorator
|
||||
- Fixed a bug where toggling `open` stopped working in `<sl-alert>`, `<sl-dialog>`, `<sl-drawer>`, `<sl-dropdown>`, and `<sl-tooltip>`
|
||||
- Fixed a bug in `<sl-range>` where setting a value outside the default `min` or `max` would clamp the value [#448](https://github.com/shoelace-style/shoelace/issues/448)
|
||||
- Fixed a bug in `<sl-dropdown>` where placement wouldn't adjust properly when shown [#447](https://github.com/shoelace-style/shoelace/issues/447)
|
||||
- Fixed a bug in the internal `shimKeyframesHeightAuto` utility that caused `<sl-details>` to measure heights incorrectly [#445](https://github.com/shoelace-style/shoelace/issues/445)
|
||||
- Fixed a number of imports that should have been type imports
|
||||
- Updated Lit to 2.0.0-rc.2
|
||||
- Updated esbuild to 0.12.4
|
||||
|
||||
## 2.0.0-beta.41
|
||||
|
||||
This release changes how components animate. In previous versions, CSS transitions were used for most show/hide animations. Transitions are problematic due to the way `transitionend` works. This event fires once _per transition_, and it's impossible to know which transition to look for when users can customize any possible CSS property. Because of this, components previously required the `opacity` property to transition. If a user were to prevent `opacity` from transitioning, the component wouldn't hide properly and the `sl-after-show|hide` events would never emit.
|
||||
|
||||
CSS animations, on the other hand, have a more reliable `animationend` event. Alas, `@keyframes` don't cascade and can't be injected into a shadow DOM via CSS, so there would be no good way to customize them.
|
||||
|
||||
The most elegant solution I found was to use the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API), which offers more control over animations at the expense of customizations being done in JavaScript. Fortunately, through the [Animation Registry](/getting-started/customizing#animations), you can customize animations globally and/or per component with a minimal amount of code.
|
||||
|
||||
- 🚨 BREAKING: changed `left` and `right` placements to `start` and `end` in `<sl-drawer>`
|
||||
- 🚨 BREAKING: changed `left` and `right` placements to `start` and `end` in `<sl-tab-group>`
|
||||
- 🚨 BREAKING: removed `--hide-duration`, `--hide-timing-function`, `--show-duration`, and `--show-timing-function` custom properties from `<sl-tooltip>` (use the Animation Registry instead)
|
||||
- Added the Animation Registry
|
||||
- Fixed a bug where removing `<sl-dropdown>` from the DOM and adding it back destroyed the popover reference [#443](https://github.com/shoelace-style/shoelace/issues/443)
|
||||
- Updated animations for `<sl-alert>`, `<sl-dialog>`, `<sl-drawer>`, `<sl-dropdown>`, and `<sl-tooltip>` to use the Animation Registry instead of CSS transitions
|
||||
- Improved a11y by respecting `prefers-reduced-motion` for all show/hide animations
|
||||
- Improved `--show-delay` and `--hide-delay` behavior in `<sl-tooltip>` so they only apply on hover
|
||||
- Removed the internal popover utility
|
||||
|
||||
## 2.0.0-beta.40
|
||||
|
||||
- 🚨 BREAKING: renamed `<sl-responsive-embed>` to `<sl-responsive-media>` and added support for images and videos [#436](https://github.com/shoelace-style/shoelace/issues/436)
|
||||
- Fixed a bug where setting properties before an element was defined would render incorrectly [#425](https://github.com/shoelace-style/shoelace/issues/425)
|
||||
- Fixed a bug that caused all modules to be imported when cherry picking certain components [#439](https://github.com/shoelace-style/shoelace/issues/439)
|
||||
- Fixed a bug where the scrollbar would reposition `<sl-dialog>` on hide causing it to jump [#424](https://github.com/shoelace-style/shoelace/issues/424)
|
||||
- Fixed a bug that prevented the project from being built in a Windows environment
|
||||
- Improved a11y in `<sl-progress-ring>`
|
||||
- Removed `src/utilities/index.ts` to prevent tree-shaking confusion (please import utilities directly from their respective modules)
|
||||
- Removed global `[hidden]` styles so they don't affect anything outside of components
|
||||
- Updated to Bootstrap Icons 1.5.0
|
||||
- Updated React docs to use [`@shoelace-style/react`](https://github.com/shoelace-style/react)
|
||||
- Updated NextJS docs [#434](https://github.com/shoelace-style/shoelace/pull/434)
|
||||
- Updated TypeScript to 4.2.4
|
||||
|
||||
## 2.0.0-beta.39
|
||||
|
||||
- Added experimental `<sl-qr-code>` component
|
||||
- Added `system` icon library and updated all components to use this instead of the default icon library [#420](https://github.com/shoelace-style/shoelace/issues/420)
|
||||
- Updated to esbuild 0.8.57
|
||||
- Updated to Lit 2.0.0-rc.1 and lit-html 2.0.0-rc.2
|
||||
|
||||
## 2.0.0-beta.38
|
||||
|
||||
- 🚨 BREAKING: `<sl-radio>` components must be located inside an `<sl-radio-group>` for proper accessibility [#218](https://github.com/shoelace-style/shoelace/issues/218)
|
||||
- Added `<sl-radio-group>` component [#218](https://github.com/shoelace-style/shoelace/issues/218)
|
||||
- Added `--header-spacing`, `--body-spacing`, and `--footer-spacing` custom properties to `<sl-drawer>` and `<sl-dialog>` [#409](https://github.com/shoelace-style/shoelace/issues/409)
|
||||
- Fixed a bug where `<sl-menu-item>` prefix and suffix slots wouldn't always receive the correct spacing
|
||||
- Fixed a bug where `<sl-badge>` used `--sl-color-white` instead of the correct design tokens [#407](https://github.com/shoelace-style/shoelace/issues/407)
|
||||
- Fixed a bug in `<sl-dialog>` and `<sl-drawer>` where the escape key would cause parent components to close
|
||||
- Fixed a race condition bug in `<sl-icon>` [#410](https://github.com/shoelace-style/shoelace/issues/410)
|
||||
- Improved focus trap behavior in `<sl-dialog>` and `<sl-drawer>`
|
||||
- Improved a11y in `<sl-dialog>` and `<sl-drawer>` by restoring focus to trigger on close
|
||||
- Improved a11y in `<sl-radio>` with Windows high contrast mode [#215](https://github.com/shoelace-style/shoelace/issues/215)
|
||||
- Improved a11y in `<sl-select>` by preventing the chevron icon from being announced
|
||||
- Internal: removed the `options` argument from the modal utility as focus trapping is now handled internally
|
||||
|
||||
## 2.0.0-beta.37
|
||||
|
||||
- Added `click()` method to `<sl-checkbox>`, `<sl-radio>`, and `<sl-switch>`
|
||||
- Added the `activation` attribute to `<sl-tab-group>` to allow for automatic and manual tab activation
|
||||
- Added `npm run create <tag>` script to scaffold new components faster
|
||||
- Fixed a bug in `<sl-tooltip>` where events weren't properly cleaned up on disconnect
|
||||
- Fixed a bug in `<sl-tooltip>` where they wouldn't display after toggling `disabled` off and on again [#391](https://github.com/shoelace-style/shoelace/issues/391)
|
||||
- Fixed a bug in `<sl-details>` where `show()` and `hide()` would toggle the control when disabled
|
||||
- Fixed a bug in `<sl-color-picker>` where setting `value` wouldn't update the control
|
||||
- Fixed a bug in `<sl-tab-group>` where tabs that are initially disabled wouldn't receive the indicator on activation [#403](https://github.com/shoelace-style/shoelace/issues/403)
|
||||
- Fixed incorrect event names for `sl-after-show` and `sl-after-hide` in `<sl-details>`
|
||||
- Improved a11y for disabled buttons that are rendered as links
|
||||
- Improved a11y for `<sl-button-group>` by adding the correct `role` attribute
|
||||
- Improved a11y for `<sl-input>`, `<sl-range>`, `<sl-select>`, and `<sl-textarea>` so labels and helper text are read properly by screen readers
|
||||
- Removed `sl-show`, `sl-hide`, `sl-after-show`, `sl-after-hide` events from `<sl-color-picker>` (the color picker's visibility cannot be controlled programmatically so these shouldn't have been exposed; the dropdown events now bubble up so you can listen for those instead)
|
||||
- Reworked `<sl-button-group>` so it doesn't require light DOM styles
|
||||
|
||||
## 2.0.0-beta.36
|
||||
|
||||
- 🚨 BREAKING: renamed `setFocus()` to `focus()` in button, checkbox, input, menu item, radio, range, rating, select, switch, and tab
|
||||
- 🚨 BREAKING: renamed `removeFocus()` to `blur()` in button, checkbox, input, menu item, radio, range, rating, select, switch, and tab
|
||||
- Added `click()` method to `<sl-button>`
|
||||
- Fixed a bug where toggling `open` on `<sl-drawer>` would skip the transition
|
||||
- Fixed a bug where `<sl-color-picker>` could be opened when disabled
|
||||
- Fixed a bug in `<sl-color-picker>` that caused erratic slider behaviors [#388](https://github.com/shoelace-style/shoelace/issues/388) [#389](https://github.com/shoelace-style/shoelace/issues/389)
|
||||
- Fixed a bug where `<sl-details>` wouldn't always render the correct height when open initially [#357](https://github.com/shoelace-style/shoelace/issues/357)
|
||||
- Renamed `components.json` to `metadata.json`
|
||||
- Updated to the prerelease versions of LitElement and lit-html
|
||||
- Updated to Bootstrap Icons 1.4.1
|
||||
|
||||
## 2.0.0-beta.35
|
||||
|
||||
- Fixed a bug in `<sl-animation>` where `sl-cancel` and `sl-finish` events would never fire
|
||||
- Fixed a bug where `<sl-alert>` wouldn't always transition properly
|
||||
- Fixed a bug where using `<sl-menu>` inside a shadow root would break keyboard selections [#382](https://github.com/shoelace-style/shoelace/issues/382)
|
||||
- Fixed a bug where toggling `multiple` in `<sl-select>` would lead to a stale display label
|
||||
- Fixed a bug in `<sl-tab-group>` where changing `placement` could result in the active tab indicator being drawn a few pixels off
|
||||
- Fixed a bug in `<sl-button>` where link buttons threw an error on focus, blur, and click
|
||||
- Improved `@watch` decorator to run after update instead of during
|
||||
- Updated `<sl-menu-item>` checked icon to `check` instead of `check2`
|
||||
- Upgraded the status of `<sl-resize-observer>` from experimental to stable
|
||||
|
||||
## 2.0.0-beta.34
|
||||
|
||||
This release changes the way components are registered if you're [cherry picking](/getting-started/installation?id=cherry-picking) or [using a bundler](/getting-started/installation?id=bundling). This recommendation came from the LitElement team and simplifies Shoelace's dependency graph. It also eliminates the need to call a `register()` function before using each component.
|
||||
|
||||
From now on, importing a component will register it automatically. The caveat is that bundlers may not tree shake the library properly if you import from `@shoelace-style/shoelace`, so the recommendation is to import components and utilities from their corresponding files instead.
|
||||
|
||||
- 🚨 BREAKING: removed `all.shoelace.js` (use `shoelace.js` instead)
|
||||
- 🚨 BREAKING: component modules now have a side effect, so bundlers may not tree shake properly when importing from `@shoelace-style/shoelace` (see the [installation page](/getting-started/installation?id=bundling) for more details and how to update)
|
||||
- Added `sl-clear` event to `<sl-select>`
|
||||
- Fixed a bug where dynamically changing menu items in `<sl-select>` would cause the display label to be blank [#374](https://github.com/shoelace-style/shoelace/discussions/374)
|
||||
- Fixed a bug where setting the `value` attribute or property on `<sl-input>` and `<sl-textarea>` would trigger validation too soon
|
||||
- Fixed the margin in `<sl-menu-label>` to align with menu items
|
||||
- Fixed `autofocus` attributes in `<sl-input>` and `<sl-textarea>`
|
||||
- Improved types for `autocapitalize` in `<sl-input>` and `<sl-textarea>`
|
||||
- Reverted the custom `@tag` decorator in favor of `@customElement` to enable auto-registration
|
||||
|
||||
## 2.0.0-beta.33
|
||||
|
||||
- Fixed a bug where link buttons could have incorrect `target`, `download`, and `rel` props
|
||||
- Fixed `aria-label` and `aria-labelledby` props in `<sl-dialog>` and `<sl-drawer>`
|
||||
- Fixed `tabindex` attribute in `<sl-menu>`
|
||||
- Fixed a bug in `<sl-select>` where tags would always render as pills
|
||||
- Fixed a bug in `<sl-button>` where calling `setFocus()` would throw an error
|
||||
|
||||
## 2.0.0-beta.32
|
||||
|
||||
- Added tag name maps so TypeScript can identify Shoelace elements [#371](https://github.com/shoelace-style/shoelace/pull/371)
|
||||
- Fixed a bug where the active tab indicator wouldn't render properly on tabs styled with `flex-end` [#355](https://github.com/shoelace-style/shoelace/issues/355)
|
||||
- Fixed a bug where `sl-change` wasn't emitted by `<sl-checkbox>` or `<sl-switch>` [#370](https://github.com/shoelace-style/shoelace/issues/370)
|
||||
- Fixed a bug where some props weren't being watched correctly in `<sl-alert>` and `<sl-color-picker>`
|
||||
- Improved `@watch` decorator so watch handlers don't run before the first render
|
||||
- Removed guards that were added due to previous watch handler behavior
|
||||
|
||||
## 2.0.0-beta.31
|
||||
|
||||
- Add touch support to `<sl-rating>` [#362](https://github.com/shoelace-style/shoelace/pull/362)
|
||||
- Fixed a bug where the `open` attribute on `<sl-details>` would prevent it from opening [#357](https://github.com/shoelace-style/shoelace/issues/357)
|
||||
- Fixed event detail type parsing so component class names are shown instead of `default`
|
||||
|
||||
## 2.0.0-beta.30
|
||||
|
||||
- Fix default exports for all components so cherry picking works again [#365](https://github.com/shoelace-style/shoelace/issues/365)
|
||||
- Revert FOUC base style because it interferes with some framework and custom element use cases
|
||||
|
||||
## 2.0.0-beta.29
|
||||
|
||||
**This release migrates component implementations from Shoemaker to LitElement.** Due to feedback from the community, Shoelace will rely on a more heavily tested library for component implementations. This gives you a more solid foundation and reduces my maintenance burden. Thank you for all your comments, concerns, and encouragement! Aside from that, everything else from beta.28 still applies plus the following.
|
||||
|
||||
- 🚨 BREAKING: removed the `symbol` property from `<sl-rating>` and reverted to `getSymbol` for optimal flexibility
|
||||
- Added `vscode.html-custom-data.json` to the build to support IntelliSense (see [the usage section](/getting-started/usage#code-completion) for details)
|
||||
- Added a base style to prevent FOUC before components are defined
|
||||
- Fixed bug where TypeScript types weren't being generated [#364](https://github.com/shoelace-style/shoelace/pull/364)
|
||||
- Improved vertical padding in `<sl-tooltip>`
|
||||
- Moved chunk files into a separate folder
|
||||
- Reverted menu item active styles
|
||||
- Updated esbuild to 0.8.54
|
||||
|
||||
## 2.0.0-beta.28
|
||||
|
||||
**This release includes a major under the hood overhaul of the library and how it's distributed.** Until now, Shoelace was developed with Stencil. This release moves to a lightweight tool called Shoemaker, a homegrown utility that provides declarative templating and data binding while reducing the boilerplate required for said features.
|
||||
|
||||
This change in tooling addresses a number of longstanding bugs and limitations. It also gives us more control over the library and build process while streamlining development and maintenance. Instead of two different distributions, Shoelace now offers a single, standards-compliant collection of ES modules. This may affect how you install and use the library, so please refer to the [installation page](/getting-started/installation) for details.
|
||||
|
||||
!> Due to the large number of internal changes, I would consider this update to be less stable than previous ones. If you're using Shoelace in a production app, consider holding off until the next beta to allow for more exhaustive testing from the community. Please report any bugs you find on the [issue tracker](https://github.com/shoelace-style/shoelace/issues).
|
||||
|
||||
The component API remains the same except for the changes noted below. Thanks for your patience as I work diligently to make Shoelace more stable and future-proof. 🙌
|
||||
|
||||
- 🚨 BREAKING: removed the custom elements bundle (you can import ES modules directly)
|
||||
- 🚨 BREAKING: removed `getAnimationNames()` and `getEasingNames()` methods from `<sl-animation>` (you can import them from `utilities/animation.js` instead)
|
||||
- 🚨 BREAKING: removed the `<sl-icon-library>` component since it required imperative initialization (you can import the `registerIconLibrary()` function from `utilities/icon-library.js` instead)
|
||||
- 🚨 BREAKING: removed the experimental `<sl-theme>` component due to technical limitations (you should set the `sl-theme-{name}` class on the `<body>` instead)
|
||||
- 🚨 BREAKING: moved the base stylesheet from `dist/shoelace.css` to `dist/themes/base.css`
|
||||
- 🚨 BREAKING: moved `icons` into `assets/icons` to make future assets easier to colocate
|
||||
- 🚨 BREAKING: changed `getSymbol` property in `<sl-rating>` to `symbol` (it now accepts a string or a function that returns an icon name)
|
||||
- 🚨 BREAKING: renamed `setAssetPath()` to `setBasePath()` and added the ability to set the library's base path with a `data-shoelace` attribute (`setBasePath()` is exported from `utilities/base-path.js`)
|
||||
- Fixed `min` and `max` types in `<sl-input>` to allow numbers and strings [#330](https://github.com/shoelace-style/shoelace/issues/330)
|
||||
- Fixed a bug where `<sl-checkbox>`, `<sl-radio>`, and `<sl-switch>` controls would shrink with long labels [#325](https://github.com/shoelace-style/shoelace/issues/325)
|
||||
- Fixed a bug in `<sl-select>` where the dropdown menu wouldn't reposition when the box resized [#340](https://github.com/shoelace-style/shoelace/issues/340)
|
||||
- Fixed a bug where ignoring clicks and clicking the overlay would prevent the escape key from closing the dialog/drawer [#344](https://github.com/shoelace-style/shoelace/pull/344)
|
||||
- Removed the lazy loading dist (importing `shoelace.js` will load and register all components now)
|
||||
- Switched from Stencil to Shoemaker
|
||||
- Switched to a custom build powered by [esbuild](https://esbuild.github.io/)
|
||||
- Updated to Bootstrap Icons 1.4.0
|
||||
|
||||
## 2.0.0-beta.27
|
||||
|
||||
- Added `handle-icon` slot to `<sl-image-comparer>` [#311](https://github.com/shoelace-style/shoelace/issues/311)
|
||||
- Added `label` and `helpText` props and slots to `<sl-range>` [#318](https://github.com/shoelace-style/shoelace/issues/318)
|
||||
- Added "Integrating with NextJS" tutorial to the docs, courtesy of [crutchcorn](https://github.com/crutchcorn)
|
||||
- Added `content` slot to `<sl-tooltip>` [#322](https://github.com/shoelace-style/shoelace/pull/322)
|
||||
- Fixed a bug in `<sl-select>` where removing a tag would toggle the dropdown
|
||||
- Fixed a bug in `<sl-input>` and `<sl-textarea>` where the input might not exist when the value watcher is called [#313](https://github.com/shoelace-style/shoelace/issues/313)
|
||||
- Fixed a bug in `<sl-details>` where hidden elements would receive focus when tabbing [#323](https://github.com/shoelace-style/shoelace/issues/323)
|
||||
- Fixed a bug in `<sl-icon>` where `sl-error` would only be emitted for network failures [#326](https://github.com/shoelace-style/shoelace/pull/326)
|
||||
- Reduced the default line-height for `<sl-tooltip>`
|
||||
- Updated `<sl-menu-item>` focus styles
|
||||
- Updated `<sl-select>` so tags will wrap when `multiple` is true
|
||||
- Updated to Stencil 2.4.0
|
||||
|
||||
## 2.0.0-beta.26
|
||||
|
||||
- 🚨 BREAKING: Fixed animations bloat
|
||||
- Removed ~400 baked-in Animista animations because they were causing ~200KB of bloat (they can still be used with custom keyframes)
|
||||
- Reworked animations into a separate module ([`@shoelace-style/animations`](https://github.com/shoelace-style/animations)) so it's more maintainable and animations are sync with the latest version of animate.css
|
||||
- Animation and easing names are now camelcase (e.g. `easeInOut` instead of `ease-in-out`)
|
||||
- Added initial E2E tests [#169](https://github.com/shoelace-style/shoelace/pull/169)
|
||||
- Added the `FocusOptions` argument to all components that have a `setFocus()` method
|
||||
- Added `sl-initial-focus` event to `<sl-dialog>` and `<sl-drawer>` so focus can be customized to a specific element
|
||||
- Added `close-button` part to `<sl-tab>` so the close button can be customized
|
||||
- Added `scroll-button` part to `<sl-tab-group>` so the scroll buttons can be customized
|
||||
- Fixed a bug where `sl-hide` would be emitted twice when closing an alert with `hide()`
|
||||
- Fixed a bug in `<sl-color-picker>` where the toggle button was smaller than the preview button in Safari
|
||||
- Fixed a bug in `<sl-tab-group>` where activating a nested tab group didn't work properly [#299](https://github.com/shoelace-style/shoelace/issues/299)
|
||||
- Fixed a bug in `<sl-tab-group>` where removing tabs would throw an error
|
||||
- Fixed a bug in `<sl-alert>`, `<sl-dialog>`, `<sl-drawer>`, `<sl-select>`, and `<sl-tag>` where the close button's base wasn't exported so it couldn't be styled
|
||||
- Removed `text` type from `<sl-badge>` as it was erroneously copied and never had styles
|
||||
- Updated `<sl-tab-group>` so the `active` property is reflected to its attribute
|
||||
- Updated the docs to show dependencies instead of dependents which is much more useful when working with the custom elements bundle
|
||||
- Updated to Bootstrap Icons 1.3.0
|
||||
|
||||
## 2.0.0-beta.25
|
||||
|
||||
- 🚨 BREAKING: Reworked color tokens
|
||||
- Theme colors are now inspired by Tailwind's professionally-designed color palette
|
||||
- Color token variations now range from 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950
|
||||
- Color token variations were inverted, e.g. 50 is lightest and 950 is darkest
|
||||
- All component styles were adapted to use the new color tokens, but visual changes are subtle
|
||||
- The dark theme was adapted use the new color tokens
|
||||
- HSL is no longer used because it is not perceptually uniform (this may be revisited when all browsers support [LCH colors](https://lea.verou.me/2020/04/lch-colors-in-css-what-why-and-how/))
|
||||
- 🚨 BREAKING: Refactored `<sl-select>` to improve accessibility [#216](https://github.com/shoelace-style/shoelace/issues/216)
|
||||
- Removed the internal `<sl-input>` because it was causing problems with a11y and virtual keyboards
|
||||
- Removed `input`, `prefix` and `suffix` parts
|
||||
- 🚨 BREAKING: Removed `copy-button` part from `<sl-color-picker>` since copying is now done by clicking the preview
|
||||
- Added `getFormattedValue()` method to `<sl-color-picker>` so you can retrieve the current value in any format
|
||||
- Added visual separators between solid buttons in `<sl-button-group>`
|
||||
- Added `help-text` attribute to `<sl-input>`, `<sl-textarea>`, and `<sl-select>`
|
||||
- Fixed a bug where moving the mouse while `<sl-dropdown>` is closing would remove focus from the trigger
|
||||
- Fixed a bug where `<sl-menu-item>` didn't set a default color in the dark theme
|
||||
- Fixed a bug where `<sl-color-picker>` preview wouldn't update in Safari
|
||||
- Fixed a bug where removing an icon's `name` or `src` wouldn't remove the previously rendered SVG [#285](https://github.com/shoelace-style/shoelace/issues/285)
|
||||
- Fixed a bug where disabled link buttons didn't appear disabled
|
||||
- Improved button spacings and added split button example
|
||||
- Improved elevation tokens in dark theme
|
||||
- Improved accessibility in `<sl-tooltip>` by allowing escape to dismiss it [#219](https://github.com/shoelace-style/shoelace/issues/219)
|
||||
- Improved slot detection in `<sl-card>`, `<sl-dialog>`, and `<sl-drawer>`
|
||||
- Made `@types/resize-observer-browser` a dependency so users don't have to install it manually
|
||||
- Refactored internal label + help text logic into a functional component used by `<sl-input>`, `<sl-textarea>`, and `<sl-select>`
|
||||
- Removed `sl-blur` and `sl-focus` events from `<sl-menu>` since menus can't have focus as of 2.0.0-beta.22
|
||||
- Updated `<sl-spinner>` so the indicator is more obvious
|
||||
- Updated to Bootstrap Icons 1.2.2
|
||||
|
||||
## 2.0.0-beta.24
|
||||
|
||||
- Added `<sl-format-date>` component
|
||||
- Added `indeterminate` state to `<sl-progress-bar>` [#274](https://github.com/shoelace-style/shoelace/issues/274)
|
||||
- Added `--track-color`, `--indicator-color`, and `--label-color` to `<sl-progress-bar>` [#276](https://github.com/shoelace-style/shoelace/issues/276)
|
||||
- Added `allow-scripts` attribute to `<sl-include>` [#280](https://github.com/shoelace-style/shoelace/issues/280)
|
||||
- Fixed a bug where `<sl-menu-item>` color variable was incorrect [#272](https://github.com/shoelace-style/shoelace/issues/272)
|
||||
- Fixed a bug where `<sl-dialog>` and `<sl-drawer>` would emit the `sl-hide` event twice [#275](https://github.com/shoelace-style/shoelace/issues/275)
|
||||
- Fixed a bug where calling `event.preventDefault()` on certain form elements wouldn't prevent `<sl-form>` from submitting [#277](https://github.com/shoelace-style/shoelace/issues/277)
|
||||
- Fixed drag handle orientation in `<sl-image-comparer>`
|
||||
- Restyled `<sl-spinner>` so the track is visible and the indicator is smaller.
|
||||
- Removed `resize-observer-polyfill` in favor of `@types/resize-observer-browser` since all target browsers support `ResizeObserver`
|
||||
- Upgraded the status of `<sl-form>`, `<sl-image-comparer>`, and `<sl-include>` from experimental to stable
|
||||
|
||||
## 2.0.0-beta.23
|
||||
|
||||
- Added `<sl-format-number>` component
|
||||
- Added `<sl-relative-time>` component
|
||||
- Added `closable` attribute to `<sl-tab>`
|
||||
- Added experimental `<sl-resize-observer>` utility
|
||||
- Added experimental `<sl-theme>` utility and updated theming documentation
|
||||
- Fixed a bug where `<sl-menu-item>` wouldn't render properly in the dark theme
|
||||
- Fixed a bug where `<sl-select>` would show an autocomplete menu
|
||||
- Improved placeholder contrast in dark theme
|
||||
- Updated to Boostrap Icons 1.1.0
|
||||
- Updated to Stencil 2.3.0
|
||||
|
||||
## 2.0.0-beta.22
|
||||
|
||||
- 🚨 BREAKING: Refactored `<sl-menu>` and `<sl-menu-item>` to improve accessibility by using proper focus states [#217](https://github.com/shoelace-style/shoelace/issues/217)
|
||||
- Moved `tabindex` from `<sl-menu>` to `<sl-menu-item>`
|
||||
- Removed the `active` attribute from `<sl-menu-item>` because synthetic focus states are bad for accessibility
|
||||
- Removed the `sl-activate` and `sl-deactivate` events from `<sl-menu-item>` (listen for `focus` and `blur` instead)
|
||||
- Updated `<sl-select>` so keyboard navigation still works
|
||||
- Added `no-scroll-controls` attribute to `<sl-tab-group>` [#253](https://github.com/shoelace-style/shoelace/issues/253)
|
||||
- Fixed a bug where setting `open` initially wouldn't show `<sl-dialog>` or `<sl-drawer>` [#255](https://github.com/shoelace-style/shoelace/issues/255)
|
||||
- Fixed a bug where `disabled` could be set when buttons are rendered as links
|
||||
- Fixed a bug where hoisted dropdowns would render in the wrong position when placed inside `<sl-dialog>` [#252](https://github.com/shoelace-style/shoelace/issues/252)
|
||||
- Fixed a bug where boolean aria attributes didn't explicitly set `true|false` string values in the DOM
|
||||
- Fixed a bug where `aria-describedby` was never set on tooltip targets in `<sl-tooltip>`
|
||||
- Fixed a bug where setting `position` on `<sl-image-comparer>` wouldn't update the divider's position
|
||||
- Fixed a bug where the check icon was announced to screen readers in `<sl-menu-item>`
|
||||
- Improved `<sl-icon-button>` accessibility by encouraging proper use of `label` and hiding the internal icon from screen readers [#220](https://github.com/shoelace-style/shoelace/issues/220)
|
||||
- Improved `<sl-dropdown>` accessibility by attaching `aria-haspopup` and `aria-expanded` to the slotted trigger
|
||||
- Refactored position logic to remove an unnecessary state variable in `<sl-image-comparer>`
|
||||
- Refactored design tokens to use `rem` instead of `px` for input height and spacing [#221](https://github.com/shoelace-style/shoelace/issues/221)
|
||||
- Removed `console.log` from modal utility
|
||||
- Updated to Stencil 2.2.0
|
||||
|
||||
## 2.0.0-beta.21
|
||||
|
||||
- Added `label` slot to `<sl-input>`, `<sl-select>`, and `<sl-textarea>` [#248](https://github.com/shoelace-style/shoelace/issues/248)
|
||||
- Added `label` slot to `<sl-dialog>` and `<sl-drawer>`
|
||||
- Added experimental `<sl-include>` component
|
||||
- Added status code to the `sl-error` event in `<sl-icon>`
|
||||
- Fixed a bug where initial transitions didn't show in `<sl-dialog>` and `<sl-drawer>` [#247](https://github.com/shoelace-style/shoelace/issues/247)
|
||||
- Fixed a bug where indeterminate checkboxes would maintain the indeterminate state when toggled
|
||||
- Fixed a bug where concurrent active modals (i.e. dialog, drawer) would try to steal focus from each other
|
||||
- Improved `<sl-color-picker>` grid and slider handles [#246](https://github.com/shoelace-style/shoelace/issues/246)
|
||||
- Refactored `<sl-icon>` request logic and removed unused cache map
|
||||
- Reworked show/hide logic in `<sl-alert>`, `<sl-dialog>`, and `<sl-drawer>` to not use reflow hacks and the `hidden` attribute
|
||||
- Reworked slot logic in `<sl-card>`, `<sl-dialog>`, and `<sl-drawer>`
|
||||
- Updated to Popper 2.5.3 to address a fixed position bug in Firefox
|
||||
|
||||
## 2.0.0-beta.20
|
||||
|
||||
- 🚨 BREAKING: Transformed all Shoelace events to lowercase ([details](#why-did-event-names-change))
|
||||
- Added support for dropdowns and non-icon elements to `<sl-input>`
|
||||
- Added `spellcheck` attribute to `<sl-input>`
|
||||
- Added `<sl-icon-library>` to allow custom icon library registration
|
||||
- Added `library` attribute to `<sl-icon>` and `<sl-icon-button>`
|
||||
- Added "Integrating with Rails" tutorial to the docs, courtesy of [ParamagicDev](https://github.com/ParamagicDev)
|
||||
- Fixed a bug where `<sl-progress-ring>` rendered incorrectly when zoomed in Safari [#227](https://github.com/shoelace-style/shoelace/issues/227>)
|
||||
- Fixed a bug where tabbing into slotted elements closes `<sl-dropdown>` when used in a shadow root [#223](https://github.com/shoelace-style/shoelace/issues/223)
|
||||
- Fixed a bug where scroll anchoring caused undesirable scrolling when `<sl-details>` are grouped
|
||||
|
||||
### Why did event names change?
|
||||
|
||||
Shoelace events were updated to use a lowercase, kebab-style naming convention. Instead of event names such as `slChange` and `slAfterShow`, you'll need to use `sl-change` and `sl-after-show` now.
|
||||
|
||||
This change was necessary to address a critical issue in frameworks that use DOM templates with declarative event bindings such as `<sl-button @slChange="handler">`. Due to HTML's case-insensitivity, browsers translate attribute names to lowercase, turning `@slChange` into `@slchange`, making it impossible to listen to `slChange`.
|
||||
|
||||
While declarative event binding is a non-standard feature, not supporting it would make Shoelace much harder to use in popular frameworks. To accommodate those users and provide a better developer experience, we decided to change the naming convention while Shoelace is still in beta.
|
||||
|
||||
The following pages demonstrate why this change was necessary.
|
||||
|
||||
- [This Polymer FAQ from Custom Elements Everywhere](https://custom-elements-everywhere.com/#faq-polymer)
|
||||
- [Vue's Event Names documentation](https://vuejs.org/v2/guide/components-custom-events.html#Event-Names)
|
||||
|
||||
## 2.0.0-beta.19
|
||||
|
||||
- Added `input`, `label`, `prefix`, `clear-button`, `suffix`, `help-text` exported parts to `<sl-select>` to make the input customizable
|
||||
- Added toast notifications through the `toast()` method on `<sl-alert>`
|
||||
- Fixed a bug where mouse events would bubble up when `<sl-button>` was disabled, causing tooltips to erroneously appear
|
||||
- Fixed a bug where pressing space would open and immediately close `<sl-dropdown>` panels in Firefox
|
||||
- Fixed a bug where `<sl-tooltip>` would throw an error on init
|
||||
- Fixed a bug in custom keyframes animation example
|
||||
- Refactored clear logic in `<sl-input>`
|
||||
|
||||
## 2.0.0-beta.18
|
||||
|
||||
- Added `name` and `invalid` attribute to `<sl-color-picker>`
|
||||
- Added support for form submission and validation to `<sl-color-picker>`
|
||||
- Added touch support to demo resizers in the docs
|
||||
- Added `<sl-responsive-embed>` component
|
||||
- Fixed a bug where swapping an animated element wouldn't restart the animation in `<sl-animation>`
|
||||
- Fixed a bug where the cursor was incorrect when `<sl-select>` was disabled
|
||||
- Fixed a bug where `slblur` and `slfocus` were emitted twice in `<sl-select>`
|
||||
- Fixed a bug where clicking on `<sl-menu>` wouldn't focus it
|
||||
- Fixed a bug in the popover utility where `onAfterShow` would fire too soon
|
||||
- Fixed a bug where `bottom` and `right` placements didn't render properly in `<sl-tab-group>`
|
||||
- Improved keyboard logic in `<sl-dropdown>`, `<sl-menu>`, and `<sl-select>`
|
||||
- Updated `<sl-animation>` to stable
|
||||
- Updated to Stencil 2.0 (you may need to purge `node_modules` and run `npm install` after pulling)
|
||||
- Updated entry points in `package.json` to reflect new filenames generated by Stencil 2
|
||||
|
||||
## 2.0.0-beta.17
|
||||
|
||||
- Added `minlength` and `spellcheck` attributes to `<sl-textarea>`
|
||||
- Fixed a bug where clicking a tag in `<sl-select>` wouldn't toggle the menu
|
||||
- Fixed a bug where options where `<sl-select>` options weren't always visible or scrollable
|
||||
- Fixed a bug where setting `null` on `<sl-input>`, `<sl-textarea>`, or `<sl-select>` would throw an error
|
||||
- Fixed a bug where `role` was on the wrong element and aria attribute weren't explicit in `<sl-checkbox>`, `<sl-switch>`, and `<sl-radio>`
|
||||
- Fixed a bug where dynamically adding/removing a slot wouldn't work as expected in `<sl-card>`, `<sl-dialog>`, and `<sl-drawer>`
|
||||
- Fixed a bug where the value wasn't updated and events weren't emitted when using `setRangeText` in `<sl-input>` and `<sl-textarea>`
|
||||
- Optimized `hasSlot` utility by using a simpler selector
|
||||
- Updated Bootstrap Icons to 1.0.0 with many icons redrawn and improved
|
||||
- Updated contribution guidelines
|
||||
|
||||
**Form validation has been reworked and is much more powerful now!**
|
||||
|
||||
- The `invalid` attribute now reflects the control's validity as determined by the browser's constraint validation API
|
||||
- Added `required` to `<sl-checkbox>`, `<sl-select>`, and `<sl-switch>`
|
||||
- Added `reportValidity()` and `setCustomValidity()` methods to all form controls
|
||||
- Added validation checking for custom and native form controls to `<sl-form>`
|
||||
- Added `novalidate` attribute to `<sl-form>` to disable validation
|
||||
- Removed the `valid` attribute from all form controls
|
||||
- Removed valid and invalid design tokens and related styles (you can use your own custom styles to achieve this)
|
||||
|
||||
## 2.0.0-beta.16
|
||||
|
||||
- Added `hoist` attribute to `<sl-color-picker>`, `<sl-dropdown>`, and `<sl-select>` to work around panel clipping
|
||||
- Added `<sl-format-bytes>` utility component
|
||||
- Added `clearable` and `required` props to `<sl-select>`
|
||||
- Added `slclear` event to `<sl-input>`
|
||||
- Added keyboard support to the preview resizer in the docs
|
||||
- Fixed a bug where the `aria-selected` state was incorrect in `<sl-menu-item>`
|
||||
- Fixed a bug where custom properties applied to `<sl-tooltip>` didn't affect show/hide transitions
|
||||
- Fixed a bug where `--sl-input-color-*` custom properties had no effect on `<sl-input>` and `<sl-textarea>`
|
||||
- Refactored `<sl-dropdown>` and `<sl-tooltip>` to use positioner elements so panels/tooltips can be customized easier
|
||||
|
||||
## 2.0.0-beta.15
|
||||
|
||||
- Added `image-comparer` component
|
||||
- Added `--width`, `--height`, and `--thumb-size` custom props to `<sl-switch>`
|
||||
- Fixed an `aria-labelledby` attribute typo in a number of components
|
||||
- Fixed a bug where the `change` event wasn't updating the value in `<sl-input>`
|
||||
- Fixed a bug where `<sl-color-picker>` had the wrong border color in the dark theme
|
||||
- Fixed a bug where `<sl-menu-item>` had the wrong color in dark mode when disabled
|
||||
- Fixed a bug where WebKit's autocomplete styles made inputs looks broken
|
||||
- Fixed a bug where aria labels were wrong in `<sl-select>`
|
||||
- Fixed a bug where clicking the label wouldn't focus the control in `<sl-select>`
|
||||
|
||||
## 2.0.0-beta.14
|
||||
|
||||
- Added dark theme
|
||||
- Added `--sl-panel-background-color` and `--sl-panel-border-color` tokens
|
||||
- Added `--tabs-border-color` custom property to `<sl-tab-group>`
|
||||
- Added `--track-color` custom property to `<sl-range>`
|
||||
- Added `tag` part to `<sl-select>`
|
||||
- Updated `package.json` so custom elements imports can be consumed from the root
|
||||
- Fixed a bug where scrolling dialogs didn't resize properly in Safari
|
||||
- Fixed a bug where `slshow` and `slhide` would be emitted twice in some components
|
||||
- Fixed a bug where `custom-elements/index.d.ts` was broken due to an unclosed comment (fixed in Stencil 1.17.3)
|
||||
- Fixed bug where inputs were not using border radius tokens
|
||||
- Fixed a bug where the text color was being erroneously set in `<sl-progress-ring>`
|
||||
- Fixed a bug where `<sl-progress-bar>` used the wrong part name internally for `indicator`
|
||||
- Removed background color from `<sl-menu>`
|
||||
- Updated to Stencil 1.17.3
|
||||
|
||||
## 2.0.0-beta.13
|
||||
|
||||
- Added `slactivate` and `sldeactivate` events to `<sl-menu-item>`
|
||||
- Added experimental `<sl-animation>` component
|
||||
- Added shields to documentation
|
||||
- Fixed a bug where link buttons would have `type="button"`
|
||||
- Fixed a bug where button groups with tooltips experienced an odd spacing issue in Safari
|
||||
- Fixed a bug where scrolling in dropdowns/selects didn't work properly on Windows (special thanks to [Trendy](http://github.com/trendy) for helping troubleshoot!)
|
||||
- Fixed a bug where selecting a menu item in a dropdown would cause Safari to scroll
|
||||
- Fixed a bug where type to select wouldn't accept symbols
|
||||
- Moved scrolling logic from `<sl-menu>` to `<sl-dropdown>`
|
||||
|
||||
## 2.0.0-beta.12
|
||||
|
||||
- Added support for `href`, `target`, and `download` to buttons
|
||||
- Fixed a bug where buttons would have horizontal spacing in Safari
|
||||
- Fixed a bug that caused an import resolution error when using Shoelace in a Stencil app
|
||||
|
||||
## 2.0.0-beta.11
|
||||
|
||||
- Added button group component
|
||||
- Fixed icon button alignment
|
||||
- Fixed a bug where focus visible observer wasn't removed from `<sl-details>`
|
||||
- Replaced the deprecated `componentDidUnload` lifecycle method with `disconnectedCallback` to prevent issues with frameworks
|
||||
|
||||
## 2.0.0-beta.10
|
||||
|
||||
- Added community page to the docs
|
||||
- Fixed a bug where many components would erroneously receive an `id` when using the custom elements bundle
|
||||
- Fixed a bug where tab groups weren't scrollable with the mouse
|
||||
|
||||
## 2.0.0-beta.9
|
||||
|
||||
- Added the icon button component
|
||||
- Added the skeleton component
|
||||
- Added the `typeToSelect` method to menu so type-to-select behavior can be controlled externally
|
||||
- Added the `pulse` attribute to badge
|
||||
- Fixed a bug where hovering over select showed the wrong cursor
|
||||
- Fixed a bug where tabbing into a select control would highlight the label
|
||||
- Fixed a bug where tabbing out of a select control wouldn't close it
|
||||
- Fixed a bug where closing dropdowns wouldn't give focus back to the trigger
|
||||
- Fixed a bug where type-to-select wasn't working after the first letter
|
||||
- Fixed a bug where clicking on menu items and dividers would steal focus from the menu
|
||||
- Fixed a bug where the color picker wouldn't parse uppercase values
|
||||
- Removed the `no-footer` attribute from dialog and drawer (slot detection is automatic, so the attribute is not required)
|
||||
- Removed `close-icon` slot from alert
|
||||
- Replaced make-shift icon buttons with `<sl-icon-button>` in alert, dialog, drawer, and tag
|
||||
- Updated Stencil to 1.17.1
|
||||
- Switched to jsDelivr for better CDN performance
|
||||
|
||||
## 2.0.0-beta.8
|
||||
|
||||
- Added the card component
|
||||
- Added `--focus-ring` custom property to tab
|
||||
- Fixed a bug where range tooltips didn't appear on iOS
|
||||
- Fixed constructor bindings so they don't break the custom elements bundle
|
||||
- Fixed tag color contrast to be AA compliant
|
||||
- Fixed a bug that made it difficult to vertically align rating
|
||||
- Fixed a bug where dropdowns would always close on mousedown when inside a shadow root
|
||||
- Made tag text colors AA compliant
|
||||
- Promoted badge to stable
|
||||
- Refactored `:host` variables and moved non-display props to base elements
|
||||
- Refactored event handler bindings to occur in `connectedCallback` instead of the constructor
|
||||
- Refactored scroll locking logic to use `Set` instead of an array
|
||||
- Updated the custom elements bundle documentation and added bundler examples
|
||||
- Upgraded Stencil to 1.17.0-0 (next) to fix custom elements bundle
|
||||
|
||||
## 2.0.0-beta.7
|
||||
|
||||
- Added links to version 1 resources to the docs
|
||||
- Added rating component
|
||||
- Fixed a bug where some build files were missing
|
||||
- Fixed clearable tags demo
|
||||
- Fixed touch icon size in docs
|
||||
|
||||
## 2.0.0-beta.6
|
||||
|
||||
- Enabled the `dist-custom-elements-bundle` output target
|
||||
- Fixed a bug where nested form controls were ignored in `<sl-form>`
|
||||
|
||||
## 2.0.0-beta.5
|
||||
|
||||
- Fixed bug where `npm install` would fail due to postinstall script
|
||||
- Removed unused dependency
|
||||
|
||||
## 2.0.0-beta.4
|
||||
|
||||
- Added `pill` variation to badges
|
||||
- Fixed a bug where all badges had `pointer-events: none`
|
||||
- Fixed `@since` props to show 2.0 instead of 1.0
|
||||
- Fixed giant cursors in inputs in Safari
|
||||
- Fixed color picker input width in Safari
|
||||
- Fixed initial transitions for drawer, dialog, and popover consumers
|
||||
- Fixed a bug where dialog, dropdown, and drawer would sometimes not transition in on the first open
|
||||
- Fixed various documentation typos
|
||||
|
||||
## 2.0.0-beta.3
|
||||
|
||||
- Fix version in docs
|
||||
- Remove custom elements bundle
|
||||
|
||||
## 2.0.0-beta.2
|
||||
|
||||
- Fix quick start and installation URLs
|
||||
- Switch Docsify theme
|
||||
- Update line heights tokens
|
||||
|
||||
## 2.0.0-beta.1
|
||||
|
||||
- Initial release
|
||||
@@ -1,6 +1,6 @@
|
||||
# Community
|
||||
|
||||
Shoelace has a budding community of designers and developers that are building amazing things with web components. We'd love for you to become a part of it!
|
||||
Shoelace has a growing community of designers and developers that are building amazing things with web components. We'd love for you to become a part of it!
|
||||
|
||||
Please be respectful of other users and remember that Shoelace is an open source project. We'll try to help when we can, but there's no guarantee we'll be able solve your problem. Please manage your expectations and don't forget to contribute back to the conversation when you can!
|
||||
|
||||
@@ -11,9 +11,10 @@ The [discussion forum](https://github.com/shoelace-style/shoelace/discussions) i
|
||||
- Ask for help
|
||||
- Share ideas and get feedback
|
||||
- Show the community what you're working on
|
||||
- Hang out with other designers, developers, and Shoelace users
|
||||
- Learn more about the project, its values, and its roadmap
|
||||
|
||||
<sl-button type="primary" href="https://github.com/shoelace-style/shoelace/discussions" target="_blank">
|
||||
<sl-icon name="github" slot="prefix"></sl-icon>
|
||||
Join the Discussion
|
||||
</sl-button>
|
||||
|
||||
@@ -24,12 +25,22 @@ The [community chat](https://discord.gg/mg8f26C) is open to the public and power
|
||||
- Ask for help
|
||||
- Share ideas and get feedback
|
||||
- Show the community what you're working on
|
||||
- Hang out with other designers, developers, and Shoelace users
|
||||
- Chat live with other designers, developers, and Shoelace fans
|
||||
|
||||
<sl-button type="primary" href="https://discord.gg/mg8f26C" target="_blank">
|
||||
<sl-icon name="discord" slot="prefix"></sl-icon>
|
||||
Join the Chat
|
||||
</sl-button>
|
||||
|
||||
## Stack Overflow
|
||||
|
||||
You can post questions on Stack Overflow using [the "shoelace" tag](https://stackoverflow.com/questions/tagged/shoelace). This is a public forum where talented developers answer questions. It's a great way to get help, but it is not maintained or actively monitored by the Shoelace author.
|
||||
|
||||
<sl-button type="primary" href="https://stackoverflow.com/questions/ask?tags=shoelace" target="_blank">
|
||||
<sl-icon name="stack-overflow" slot="prefix"></sl-icon>
|
||||
Ask for Help
|
||||
</sl-button>
|
||||
|
||||
## Twitter
|
||||
|
||||
Follow [@shoelace_style](https://twitter.com/shoelace_style) on Twitter for general updates and announcements about Shoelace. This is a great place to say "hi" or to share something you're working on. You're also welcome to follow [@claviska](https://twitter.com/claviska), the creator, for tweets about web components, web development, and life.
|
||||
@@ -37,5 +48,6 @@ Follow [@shoelace_style](https://twitter.com/shoelace_style) on Twitter for gene
|
||||
**Please avoid using Twitter for support questions.** The [discussion forum](https://github.com/shoelace-style/shoelace/discussions) is a much better place to share code snippets, screenshots, and other troubleshooting info. You'll have much better luck there, as more users will have a chance to help you.
|
||||
|
||||
<sl-button type="primary" href="https://twitter.com/shoelace_style" target="_blank">
|
||||
<sl-icon name="twitter" slot="prefix"></sl-icon>
|
||||
Follow on Twitter
|
||||
</sl-button>
|
||||
279
docs/resources/contributing.md
Normal file
@@ -0,0 +1,279 @@
|
||||
# Contributing
|
||||
|
||||
Shoelace is an open source project, meaning everyone can use it and contribute to its development. When you join our community, you'll find a friendly group of enthusiasts at all experience levels who are willing to chat about anything and everything related to Shoelace.
|
||||
|
||||
The easiest way to get started contributing is to join the [community chat](https://discord.gg/mg8f26C). This is where we hang out, discuss new ideas, ask for feedback, and more!
|
||||
|
||||
A common misconception about contributing to an open source project is that you need to know how to code. This simply isn't true. In fact, there are _many_ ways to contribute, and some of the most important contributions come from those who never write a single line of code. Here's a list of ways you can make a meaningful contribution to the project:
|
||||
|
||||
- Submitting well-written bug reports
|
||||
- Submitting feature requests that are within the scope of the project
|
||||
- Improving the documentation
|
||||
- Responding to users that need help in the community chat or discussion forum
|
||||
- Triaging issues on GitHub
|
||||
- Being a developer advocate for the project
|
||||
- Sponsoring the project financially
|
||||
- Writing tests
|
||||
- Sharing ideas
|
||||
- And, of course, contributing code!
|
||||
|
||||
Please take a moment to review these guidelines to make the contribution process as easy as possible for both yourself and the project's maintainers.
|
||||
|
||||
## Using the Issue Tracker
|
||||
|
||||
The [issue tracker](https://github.com/shoelace-style/shoelace/issues) is for bug reports, feature requests, and pull requests.
|
||||
|
||||
- Please **do not** use the issue tracker for personal support requests. Use [the discussion forum](https://github.com/shoelace-style/shoelace/discussions/categories/help) instead.
|
||||
- Please **do not** derail, hijack, or troll issues. Keep the discussion on topic and be respectful of others.
|
||||
- Please **do not** post comments with "+1" or "👍". Use [reactions](https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) instead.
|
||||
- Please **do** use the issue tracker for feature requests, bug reports, and pull requests.
|
||||
|
||||
Issues that do not follow these guidelines are subject to closure. There simply aren't enough resources for the author and contributors to troubleshoot personal support requests.
|
||||
|
||||
### Feature Requests
|
||||
|
||||
Feature requests can be added using the issue tracker.
|
||||
|
||||
- Please **do** search for an existing request before suggesting a new feature.
|
||||
- Please **do** use the "👍" reaction to vote for a feature.
|
||||
- Please **do** share substantial use cases and perspective that support new features if they haven't already been mentioned.
|
||||
- Please **do not** bump, spam, or ping contributors to prioritize your own feature.
|
||||
|
||||
If you would like your feature prioritized, please consider [sponsoring the project](https://github.com/sponsors/claviska).
|
||||
|
||||
### Bug Reports
|
||||
|
||||
A bug is _a demonstrable problem_ caused by code in the library. Bug reports are an important contribution to the quality of the project. When submitting a bug report, there are a few steps you can take to make sure your issues gets attention quickly.
|
||||
|
||||
- Please **do not** paste in large blocks of irrelevant code
|
||||
- Please **do** search for an existing issue before creating a new one
|
||||
- Please **do** explain the bug clearly
|
||||
- Please **do** provide a minimal test case that demonstrates the bug (e.g. [jsfiddle.net](https://jsfiddle.net/) or [CodePen](https://codepen.io/))
|
||||
- Please **do** provide additional information, when necessary, to replicate the bug
|
||||
|
||||
**A minimal test case is critical to a successful bug report.** It demonstrates that the bug exists in the library and not in surrounding code. Contributors should be able to understand the bug without studying your code, otherwise they'll probably move on to another bug.
|
||||
|
||||
If you would like your bug prioritized, please consider [sponsoring the project](https://github.com/sponsors/claviska).
|
||||
|
||||
### Pull Requests
|
||||
|
||||
To keep the project on track, please consider the following guidelines before submitting a PR.
|
||||
|
||||
- Please **do not** submit a PR without opening an issue first, especially for non-trivial changes. This may prevent you from doing work that won't be accepted for various reasons (e.g. someone is already working on it, it's not a good fit for the project, it needs additional planning, etc.)
|
||||
- Please **do** make sure your PR clearly defines what you're changing. Even if you feel your changes are obvious, please explain them so other contributors can more easily review your works. PRs without detailed descriptions are subject to closure pending more details.
|
||||
- Please **do** open your PR against the `next` branch.
|
||||
- Please **do not** edit anything in `dist/`. These files are generated automatically, so you need to edit the source files instead.
|
||||
|
||||
The author reserves the right to reject any PR that's outside the scope of the project or doesn't meet code quality standards.
|
||||
|
||||
### Branches
|
||||
|
||||
`current` - This branch reflects the latest release and powers [shoelace.style](https://shoelace.style/).
|
||||
|
||||
`next` - This is the branch you should submit pull requests against. It reflects what's coming in the _next_ release, which can be previewed at [next.shoelace.style](https://next.shoelace.style/).
|
||||
|
||||
## Developing
|
||||
|
||||
To set up a local dev environment, [fork the repo](https://github.com/shoelace-style/shoelace/fork) on GitHub, clone it locally, and install its dependencies.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/YOUR_GITHUB_USERNAME/shoelace
|
||||
cd shoelace
|
||||
npm install
|
||||
```
|
||||
|
||||
Once you've cloned the repo, run the following command to spin up the Shoelace dev server.
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
After the initial build, a browser will open automatically to a local version of the docs. The documentation is powered by Docsify, which uses raw markdown files to generate pages on the fly.
|
||||
|
||||
### Creating New Components
|
||||
|
||||
To scaffold a new component, run the following command, replacing `sl-tag-name` with the desired tag name.
|
||||
|
||||
```bash
|
||||
npm run create sl-tag-name
|
||||
```
|
||||
|
||||
This will generate a source file, a stylesheet, and a docs page for you. When you start the dev server, you'll find the new component in the "Components" section of the sidebar.
|
||||
|
||||
### Dev Sandbox
|
||||
|
||||
Component development occurs _within_ the local docs site. I've found that offering common variations _in the docs_ is more beneficial for users than segmenting demos and code examples into separate tools such as Storybook. This encourages more thorough documentation, streamlines development for maintainers, and simplifies how the project is built. It also reduces installation and startup times significantly.
|
||||
|
||||
There is currently no hot module reloading (HMR), as browsers don't provide a way to unregister custom elements. However, most changes to the source will reload the browser automatically.
|
||||
|
||||
For more information about running and building the project locally, refer to `README.md` in the project's root.
|
||||
|
||||
### Testing
|
||||
|
||||
Shoelace uses [Web Test Runner](https://modern-web.dev/guides/test-runner/getting-started/) for testing. To launch the test runner during development, open a terminal and launch the dev server.
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
In a second terminal window, launch the test runner.
|
||||
|
||||
```bash
|
||||
npm run test:watch
|
||||
```
|
||||
|
||||
Follow the on-screen instructions to work with the test runner. Tests will automatically re-run as you make changes.
|
||||
|
||||
To run tests only once, make sure to build the project first.
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm run test
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
The following is a non-exhaustive list of conventions, patterns, and best practices we try to follow. As a contributor, we ask that you make a good faith effort to follow them as well. This ensures consistency and maintainability throughout the project.
|
||||
|
||||
If in doubt, use your best judgment and the maintainers will be happy to guide you during the code review process. If you'd like clarification on something before submitting a PR, feel free to reach out on the [community chat](https://discord.gg/mg8f26C).
|
||||
|
||||
?> This section can be a lot to digest in one sitting, so don't feel like you need to take it all in right now. Most contributors will be better off skimming this section and reviewing the relevant content as needed.
|
||||
|
||||
### Accessibility
|
||||
|
||||
Shoelace is built with accessibility in mind. Creating generic components that are fully accessible to users with varying capabilities across a multitude of circumstances is a daunting challenge. Oftentimes, the solution to an a11y problem is not written in black and white and, therefore, we may not get it right the first time around. There are, however, guidelines we can follow in our effort to make Shoelace an accessible foundation from which applications and websites can be built.
|
||||
|
||||
We take this commitment seriously, so please ensure your contributions have this goal in mind. If you need help with anything a11y-related, please [reach out to the community](/resources/community) for assistance. If you discover an accessibility concern within the library, please file a bug on the [issue tracker](https://github.com/shoelace-style/shoelace/issues).
|
||||
|
||||
It's important to remember that, although accessibility starts with foundational components, it doesn't end with them. It everyone's responsibility to encourage best practices and ensure we're providing an optimal experience for all of our users.
|
||||
|
||||
### Documentation
|
||||
|
||||
Maintaining good documentation can be a painstaking task, but poor documentation leads to frustration and makes the project less appealing to users. Fortunately, writing documentation for Shoelace is fast and easy!
|
||||
|
||||
Most of Shoelace's technical documentation is generated with JSDoc comments and TypeScript metadata from the source code. Every property, method, event, etc. is documented this way. In-code comments encourage contributors to keep the documentation up to date as changes occur so the docs are less likely to become stale. Refer to an existing component to see how JSDoc comments are used in Shoelace.
|
||||
|
||||
Instructions, code examples, and interactive demos are hand-curated to give users the best possible experience. Typically, the most relevant information is shown first and less common examples are shown towards the bottom. Edge cases and gotchas should be called out in context with tips or warnings.
|
||||
|
||||
The docs are powered by [Docsify](https://docsify.now.sh/). Check out `docs/_sidebar.md` and `docs/components/` to get an idea of how pages are structured and formatted. If you're creating a new component, it may help to use an existing component's markdown file as a template.
|
||||
|
||||
If you need help with documentation, feel free to reach out on the [community chat](https://discord.gg/mg8f26C).
|
||||
|
||||
### Code Formatting
|
||||
|
||||
Most code formatting is handled automatically by [Prettier](https://prettier.io/) via commit hooks. However, for the best experience, you should [install it in your editor](https://prettier.io/docs/en/editors.html) and enable format on save.
|
||||
|
||||
Please do not make any changes to `prettier.config.cjs` without consulting the maintainers.
|
||||
|
||||
### Composability
|
||||
|
||||
Components should be composable, meaning you can easily reuse them with and within other components. This reduces the overall size of the library, expedites feature development, and maintains a consistent user experience.
|
||||
|
||||
The `<sl-select>` component, for example, makes use of the dropdown, input, menu, and menu item components. Because it's offloading most of its functionality and styles to lower-level components, the select component remains lightweight and its appearance is consistent with other form controls and menus.
|
||||
|
||||
### Component Stucture
|
||||
|
||||
All components have a host element, which is a reference to the `<sl-*>` element itself. Make sure to always set the host element's `display` property to the appropriate value depending on your needs, as the default is `inline` per the custom element spec.
|
||||
|
||||
```css
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
```
|
||||
|
||||
Aside from `display`, avoid setting styles on the host element when possible. The reason for this is that styles applied to the host element are not encapsulated. Instead, create a base element that wraps the component's internals and style that instead. This convention also makes it easier to use BEM in components, as the base element can serve as the "block" entity.
|
||||
|
||||
### Class Names
|
||||
|
||||
All components use a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM), so styles are completely encapsulated from the rest of the document. As a result, class names used _inside_ a component won't conflict with class names _outside_ the component, so we're free to name them anything we want.
|
||||
|
||||
Internally, each component uses the [BEM methodology](http://getbem.com/) for class names. There is no technical requirement to do this — it's purely the preference of the author to enforce consistency and clarity throughout components. As such, all contributions are expected to follow this pattern.
|
||||
|
||||
### Boolean Props
|
||||
|
||||
Boolean props should _always_ default to `false`, otherwise there's no way for the user to unset the, without JavaScript. To keep the API as friendly and consistent as possible, use a name like `noHeader` with a default value of `false` instead of `header` with a default value of `true`.
|
||||
|
||||
### Conditional Slots
|
||||
|
||||
When a component relies on the presence of slotted content to do something, don't assume its initial state is permanent. Slotted content can be added or removed any time and components must be aware of this. A good practice to manage this is:
|
||||
|
||||
- Add `@slotchange={this.handleSlotChange}` to the slots you want to watch
|
||||
- Add a `handleSlotChange` method and use the `hasSlot` utility to update state variables for the the respective slot(s)
|
||||
- Never conditionally render `<slot>` elements in a component — always use `hidden` so the slot remains in the DOM and the `slotchange` event can be captured
|
||||
|
||||
See the source of card, dialog, or drawer for examples.
|
||||
|
||||
### Custom Events
|
||||
|
||||
Components must only emit custom events, and all custom events must start with `sl-` as a namespace. For compatibility with frameworks that utilize DOM templates, custom events must have lowercase, kebab-style names. For example, use `sl-change` instead of `slChange`.
|
||||
|
||||
This convention avoids the problem of browsers lowercasing attributes, causing some frameworks to be unable to listen to them. This problem isn't specific to one framework, but [Vue's documentation](https://vuejs.org/v2/guide/components-custom-events.html#Event-Names) provides a good explanation of the problem.
|
||||
|
||||
### CSS Custom Properties
|
||||
|
||||
To expose custom properties as part of a component's API, scope them to the `:host` block.
|
||||
|
||||
```css
|
||||
:host {
|
||||
--color: rgb(var(--sl-color-primary-500));
|
||||
--background-color: rgb(var(--sl-color-neutral-100));
|
||||
}
|
||||
```
|
||||
|
||||
Then use the following syntax for comments so they appear in the generated docs. Do not use the `--sl-` prefix, as that is reserved for design tokens that live in the global scope.
|
||||
|
||||
```js
|
||||
/**
|
||||
* @cssproperty --color: The component's text color.
|
||||
* @cssproperty --background-color: The component's background color.
|
||||
*/
|
||||
@customElement('sl-example')
|
||||
export default class SlExample {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### When to use a property vs. a CSS custom property
|
||||
|
||||
When designing a component's API, standard properties are generally used to change the _behavior_ of a component, whereas CSS custom properties ("CSS variables") are used to change the _appearance_ of a component. Remember that properties can't respond to media queries, but CSS variables can.
|
||||
|
||||
There are some exceptions to this (e.g. when it significantly improves developer experience), but a good rule of thumbs is "will this need to change based on screen size?" If so, you probably want to use a CSS variable.
|
||||
|
||||
### When to use a CSS custom property vs. a CSS part
|
||||
|
||||
There are two ways to enable customizations for components. One way is with CSS custom properties ("CSS variables"), the other is with CSS parts ("parts").
|
||||
|
||||
CSS variables are scoped to the host element and can be reused throughout the component. A good example of a CSS variable would be `--border-width`, which might get reused throughout a component to ensure borders share the same width for all internal elements.
|
||||
|
||||
Parts let you target a specific element inside the component's shadow DOM but, by design, you can't target a part's children or siblings. You can _only_ customize the part itself. Use a part when you need to allow a single element inside the component to accept styles.
|
||||
|
||||
This convention can be relaxed when the developer experience is greatly improved by not following these suggestions.
|
||||
|
||||
### Design Token Color Values
|
||||
|
||||
All design tokens that implement a color value must do so in the following `R G B` format for consistency.
|
||||
|
||||
```css
|
||||
:root {
|
||||
--sl-color-sky-500: 14 165 233;
|
||||
}
|
||||
```
|
||||
|
||||
This format requires the consumer to use the `rgb()` function in their stylesheets, but it also lets them control each token's alpha channel.
|
||||
|
||||
```css
|
||||
.example {
|
||||
color: rgb(var(--sl-color-sky-500));
|
||||
background-color: rgb(var(--sl-color-sky-500) / 5%); /* 5% opacity */
|
||||
}
|
||||
```
|
||||
|
||||
### Form Controls
|
||||
|
||||
Form controls should support validation through the following conventions:
|
||||
|
||||
- All form controls must have an `invalid` property that reflects their validity
|
||||
- All form controls must have a `setCustomValidity()` method so the user can set a custom validation message
|
||||
- All form controls must have a `reportValidity()` method that report their validity during form submission
|
||||
- All form controls should mirror their native validation attributes such as `required`, `pattern`, `minlength`, `maxlength`, etc. when possible
|
||||
- All form controls must be serialized by `<sl-form>`
|
||||
@@ -1,125 +1,537 @@
|
||||
# Color Tokens
|
||||
|
||||
Color tokens are used to maintain consistent color use throughout your app.
|
||||
Color tokens help maintain consistent use of color throughout your app. Shoelace provides palettes for theme colors and primitives that you can use as a foundation for your design system.
|
||||
|
||||
## Theme Colors
|
||||
## Usage
|
||||
|
||||
Theme colors include primary, gray, success, info, warning, and danger. They are used extensively throughout the library to maintain a consistent appearance across components.
|
||||
Color tokens are referenced using the `--sl-color-{name}-{n}` CSS custom property, where `{name}` is the name of the palette and `{n}` is the numeric value of the desired swatch.
|
||||
|
||||
This will make all colors in the primary color palette various shades of purple.
|
||||
All color tokens are defined as a set of RGB integers, eg. `113 113 122`. CSS doesn't understand this format, however, so you need wrap them in the `rgb()` function.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Changes the primary color palette to purple */
|
||||
--sl-color-primary-50: #faf5ff;
|
||||
--sl-color-primary-100: #f3e8ff;
|
||||
--sl-color-primary-200: #e9d5ff;
|
||||
--sl-color-primary-300: #d8b4fe;
|
||||
--sl-color-primary-400: #c084fc;
|
||||
--sl-color-primary-500: #a855f7;
|
||||
--sl-color-primary-600: #9333ea;
|
||||
--sl-color-primary-700: #7e22ce;
|
||||
--sl-color-primary-800: #6b21a8;
|
||||
--sl-color-primary-900: #581c87;
|
||||
.example {
|
||||
color: rgb(var(--sl-color-neutral-500));
|
||||
}
|
||||
```
|
||||
|
||||
?> Although CSS lets you override custom properties on specific elements, these values _must_ be scoped to the `:root` block for the entire palette to be recalculated. [See this page for details.](https://stackoverflow.com/questions/52015737/css-scoped-custom-property-ignored-when-used-to-calculate-variable-in-outer-scop)
|
||||
This may seem a bit verbose, but it gives us a super power — we can adjust the alpha channel of any color token!
|
||||
|
||||
## Primary
|
||||
## Adjusting Alpha Channels
|
||||
|
||||
| Token | Example |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------- |
|
||||
| `--sl-color-primary-50` | <div class="color-demo" style="background-color: var(--sl-color-primary-50);"></div> |
|
||||
| `--sl-color-primary-100` | <div class="color-demo" style="background-color: var(--sl-color-primary-100);"></div> |
|
||||
| `--sl-color-primary-200` | <div class="color-demo" style="background-color: var(--sl-color-primary-200);"></div> |
|
||||
| `--sl-color-primary-300` | <div class="color-demo" style="background-color: var(--sl-color-primary-300);"></div> |
|
||||
| `--sl-color-primary-400` | <div class="color-demo" style="background-color: var(--sl-color-primary-400);"></div> |
|
||||
| `--sl-color-primary-500` | <div class="color-demo" style="background-color: var(--sl-color-primary-500);"></div> |
|
||||
| `--sl-color-primary-600` | <div class="color-demo" style="background-color: var(--sl-color-primary-600);"></div> |
|
||||
| `--sl-color-primary-700` | <div class="color-demo" style="background-color: var(--sl-color-primary-700);"></div> |
|
||||
| `--sl-color-primary-800` | <div class="color-demo" style="background-color: var(--sl-color-primary-800);"></div> |
|
||||
| `--sl-color-primary-900` | <div class="color-demo" style="background-color: var(--sl-color-primary-900);"></div> |
|
||||
| `--sl-color-primary-950` | <div class="color-demo" style="background-color: var(--sl-color-primary-950);"></div> |
|
||||
By default, color tokens produce an opaque color. With this syntax, you can easily adjust alpha channels.
|
||||
|
||||
## Gray
|
||||
```css
|
||||
.example-with-alpha {
|
||||
color: rgb(var(--sl-color-neutral-500) / 50%);
|
||||
}
|
||||
```
|
||||
|
||||
| Token | Example |
|
||||
| ------------------------ | ------------------------------------------------------------------------------- |
|
||||
| `--sl-color-white` | <div class="color-demo" style="background-color: var(--sl-color-white);"></div> |
|
||||
| `--sl-color-gray-50` | <div class="color-demo" style="background-color: var(--sl-color-gray-50);"></div> |
|
||||
| `--sl-color-gray-100` | <div class="color-demo" style="background-color: var(--sl-color-gray-100);"></div> |
|
||||
| `--sl-color-gray-200` | <div class="color-demo" style="background-color: var(--sl-color-gray-200);"></div> |
|
||||
| `--sl-color-gray-300` | <div class="color-demo" style="background-color: var(--sl-color-gray-300);"></div> |
|
||||
| `--sl-color-gray-400` | <div class="color-demo" style="background-color: var(--sl-color-gray-400);"></div> |
|
||||
| `--sl-color-gray-500` | <div class="color-demo" style="background-color: var(--sl-color-gray-500);"></div> |
|
||||
| `--sl-color-gray-600` | <div class="color-demo" style="background-color: var(--sl-color-gray-600);"></div> |
|
||||
| `--sl-color-gray-700` | <div class="color-demo" style="background-color: var(--sl-color-gray-700);"></div> |
|
||||
| `--sl-color-gray-800` | <div class="color-demo" style="background-color: var(--sl-color-gray-800);"></div> |
|
||||
| `--sl-color-gray-900` | <div class="color-demo" style="background-color: var(--sl-color-gray-900);"></div> |
|
||||
| `--sl-color-gray-950` | <div class="color-demo" style="background-color: var(--sl-color-gray-950);"></div> |
|
||||
| `--sl-color-black` | <div class="color-demo" style="background-color: var(--sl-color-black);"></div> |
|
||||
The browser evaluates this to `rgb(113 113 122 / 50%)`, where 50% is the alpha value. Note the required `/` delimiter after the color token. Alternatively, you can use a decimal such as 0.5 in lieu of a percentage.
|
||||
|
||||
## Success
|
||||
This syntax may not look familiar, but it's perfectly valid per the [CSS Color Module Level 4](https://www.w3.org/TR/css-color-4/#typedef-color) and [well-supported](https://caniuse.com/mdn-css_types_color_space_separated_functional_notation) by modern browsers.
|
||||
|
||||
| Token | Example |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------- |
|
||||
| `--sl-color-success-50` | <div class="color-demo" style="background-color: var(--sl-color-success-50);"></div> |
|
||||
| `--sl-color-success-100` | <div class="color-demo" style="background-color: var(--sl-color-success-100);"></div> |
|
||||
| `--sl-color-success-200` | <div class="color-demo" style="background-color: var(--sl-color-success-200);"></div> |
|
||||
| `--sl-color-success-300` | <div class="color-demo" style="background-color: var(--sl-color-success-300);"></div> |
|
||||
| `--sl-color-success-400` | <div class="color-demo" style="background-color: var(--sl-color-success-400);"></div> |
|
||||
| `--sl-color-success-500` | <div class="color-demo" style="background-color: var(--sl-color-success-500);"></div> |
|
||||
| `--sl-color-success-600` | <div class="color-demo" style="background-color: var(--sl-color-success-600);"></div> |
|
||||
| `--sl-color-success-700` | <div class="color-demo" style="background-color: var(--sl-color-success-700);"></div> |
|
||||
| `--sl-color-success-800` | <div class="color-demo" style="background-color: var(--sl-color-success-800);"></div> |
|
||||
| `--sl-color-success-900` | <div class="color-demo" style="background-color: var(--sl-color-success-900);"></div> |
|
||||
| `--sl-color-success-950` | <div class="color-demo" style="background-color: var(--sl-color-success-950);"></div> |
|
||||
## Theme Tokens
|
||||
|
||||
## Info
|
||||
Theme tokens give you a semantic way to reference colors in your app. The primary palette is typically based on a brand color, whereas success, neutral, warning, and danger are used to visualize actions that correspond to their respective meanings.
|
||||
|
||||
| Token | Example |
|
||||
| ------------------------ | ------------------------------------------------------------------------------- |
|
||||
| `--sl-color-info-50` | <div class="color-demo" style="background-color: var(--sl-color-info-50);"></div> |
|
||||
| `--sl-color-info-100` | <div class="color-demo" style="background-color: var(--sl-color-info-100);"></div> |
|
||||
| `--sl-color-info-200` | <div class="color-demo" style="background-color: var(--sl-color-info-200);"></div> |
|
||||
| `--sl-color-info-300` | <div class="color-demo" style="background-color: var(--sl-color-info-300);"></div> |
|
||||
| `--sl-color-info-400` | <div class="color-demo" style="background-color: var(--sl-color-info-400);"></div> |
|
||||
| `--sl-color-info-500` | <div class="color-demo" style="background-color: var(--sl-color-info-500);"></div> |
|
||||
| `--sl-color-info-600` | <div class="color-demo" style="background-color: var(--sl-color-info-600);"></div> |
|
||||
| `--sl-color-info-700` | <div class="color-demo" style="background-color: var(--sl-color-info-700);"></div> |
|
||||
| `--sl-color-info-800` | <div class="color-demo" style="background-color: var(--sl-color-info-800);"></div> |
|
||||
| `--sl-color-info-900` | <div class="color-demo" style="background-color: var(--sl-color-info-900);"></div> |
|
||||
| `--sl-color-info-950` | <div class="color-demo" style="background-color: var(--sl-color-info-950);"></div> |
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Primary<br>
|
||||
<code>--sl-color-primary-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-primary-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
## Warning
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Success<br>
|
||||
<code>--sl-color-success-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-success-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
| Token | Example |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------- |
|
||||
| `--sl-color-warning-50` | <div class="color-demo" style="background-color: var(--sl-color-warning-50);"></div> |
|
||||
| `--sl-color-warning-100` | <div class="color-demo" style="background-color: var(--sl-color-warning-100);"></div> |
|
||||
| `--sl-color-warning-200` | <div class="color-demo" style="background-color: var(--sl-color-warning-200);"></div> |
|
||||
| `--sl-color-warning-300` | <div class="color-demo" style="background-color: var(--sl-color-warning-300);"></div> |
|
||||
| `--sl-color-warning-400` | <div class="color-demo" style="background-color: var(--sl-color-warning-400);"></div> |
|
||||
| `--sl-color-warning-500` | <div class="color-demo" style="background-color: var(--sl-color-warning-500);"></div> |
|
||||
| `--sl-color-warning-600` | <div class="color-demo" style="background-color: var(--sl-color-warning-600);"></div> |
|
||||
| `--sl-color-warning-700` | <div class="color-demo" style="background-color: var(--sl-color-warning-700);"></div> |
|
||||
| `--sl-color-warning-800` | <div class="color-demo" style="background-color: var(--sl-color-warning-800);"></div> |
|
||||
| `--sl-color-warning-900` | <div class="color-demo" style="background-color: var(--sl-color-warning-900);"></div> |
|
||||
| `--sl-color-warning-950` | <div class="color-demo" style="background-color: var(--sl-color-warning-950);"></div> |
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Warning<br>
|
||||
<code>--sl-color-warning-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warning-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
## Danger
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Danger<br>
|
||||
<code>--sl-color-danger-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-danger-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
| Token | Example |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------- |
|
||||
| `--sl-color-danger-50` | <div class="color-demo" style="background-color: var(--sl-color-danger-50);"></div> |
|
||||
| `--sl-color-danger-100` | <div class="color-demo" style="background-color: var(--sl-color-danger-100);"></div> |
|
||||
| `--sl-color-danger-200` | <div class="color-demo" style="background-color: var(--sl-color-danger-200);"></div> |
|
||||
| `--sl-color-danger-300` | <div class="color-demo" style="background-color: var(--sl-color-danger-300);"></div> |
|
||||
| `--sl-color-danger-400` | <div class="color-demo" style="background-color: var(--sl-color-danger-400);"></div> |
|
||||
| `--sl-color-danger-500` | <div class="color-demo" style="background-color: var(--sl-color-danger-500);"></div> |
|
||||
| `--sl-color-danger-600` | <div class="color-demo" style="background-color: var(--sl-color-danger-600);"></div> |
|
||||
| `--sl-color-danger-700` | <div class="color-demo" style="background-color: var(--sl-color-danger-700);"></div> |
|
||||
| `--sl-color-danger-800` | <div class="color-demo" style="background-color: var(--sl-color-danger-800);"></div> |
|
||||
| `--sl-color-danger-900` | <div class="color-demo" style="background-color: var(--sl-color-danger-900);"></div> |
|
||||
| `--sl-color-danger-950` | <div class="color-demo" style="background-color: var(--sl-color-danger-950);"></div> |
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Neutral<br>
|
||||
<code>--sl-color-neutral-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-neutral-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Black & White<br>
|
||||
<code>--sl-color-neutral-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch color-palette__swatch--border" style="background-color: rgb(var(--sl-color-neutral-0));"></div>0</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch " style="background-color: rgb(var(--sl-color-neutral-1000));"></div>1000</div>
|
||||
</div>
|
||||
|
||||
?> Looking for an easy way to customize your theme? [Try the color token generator!](https://codepen.io/claviska/full/QWveRgL)
|
||||
|
||||
|
||||
## Primitives
|
||||
|
||||
Additional palettes are provided in the form of color primitives. Use these when you need arbitrary colors that don't have semantic meaning. Color primitives are derived from the fantastic [Tailwind color palette](https://tailwindcss.com/docs/customizing-colors).
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Blue Gray<br>
|
||||
<code>--sl-color-blue-gray-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-gray-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Cool Gray<br>
|
||||
<code>--sl-color-cool-gray-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cool-gray-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Gray<br>
|
||||
<code>--sl-color-gray-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-gray-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
True Gray<br>
|
||||
<code>--sl-color-true-gray-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-true-gray-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Warm Gray<br>
|
||||
<code>--sl-color-warm-gray-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-warm-gray-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Red<br>
|
||||
<code>--sl-color-red-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-red-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Orange<br>
|
||||
<code>--sl-color-orange-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-orange-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Amber<br>
|
||||
<code>--sl-color-amber-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-amber-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Yellow<br>
|
||||
<code>--sl-color-yellow-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-yellow-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Lime<br>
|
||||
<code>--sl-color-lime-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-lime-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Green<br>
|
||||
<code>--sl-color-green-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-green-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Emerald<br>
|
||||
<code>--sl-color-emerald-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-emerald-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Teal<br>
|
||||
<code>--sl-color-teal-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-teal-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Cyan<br>
|
||||
<code>--sl-color-cyan-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-cyan-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Sky<br>
|
||||
<code>--sl-color-sky-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-sky-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Blue<br>
|
||||
<code>--sl-color-blue-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-blue-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Indigo<br>
|
||||
<code>--sl-color-indigo-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-indigo-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Violet<br>
|
||||
<code>--sl-color-violet-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-violet-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Purple<br>
|
||||
<code>--sl-color-purple-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-purple-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Fuchsia<br>
|
||||
<code>--sl-color-fuchsia-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-fuchsia-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Pink<br>
|
||||
<code>--sl-color-pink-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-pink-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
<div class="color-palette">
|
||||
<div class="color-palette__name">
|
||||
Rose<br>
|
||||
<code>--sl-color-rose-<em>{n}</em></code>
|
||||
</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-50));"></div>50</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-100));"></div>100</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-200));"></div>200</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-300));"></div>300</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-400));"></div>400</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-500));"></div>500</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-600));"></div>600</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-700));"></div>700</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-800));"></div>800</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-900));"></div>900</div>
|
||||
<div class="color-palette__example"><div class="color-palette__swatch" style="background-color: rgb(var(--sl-color-rose-950));"></div>950</div>
|
||||
</div>
|
||||
|
||||
@@ -4,13 +4,13 @@ Spacing tokens are used to provide consistent spacing between components and con
|
||||
|
||||
| Token | Value | Example |
|
||||
| ------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--sl-spacing-xxx-small` | 0.125rem (2px) | <div class="spacing-demo" style="width: var(--sl-spacing-xxx-small); height: var(--sl-spacing-xxx-small);"></div> |
|
||||
| `--sl-spacing-xx-small` | 0.25rem (4px) | <div class="spacing-demo" style="width: var(--sl-spacing-xx-small); height: var(--sl-spacing-xx-small);"></div> |
|
||||
| `--sl-spacing-3x-small` | 0.125rem (2px) | <div class="spacing-demo" style="width: var(--sl-spacing-3x-small); height: var(--sl-spacing-3x-small);"></div> |
|
||||
| `--sl-spacing-2x-small` | 0.25rem (4px) | <div class="spacing-demo" style="width: var(--sl-spacing-2x-small); height: var(--sl-spacing-2x-small);"></div> |
|
||||
| `--sl-spacing-x-small` | 0.5rem (8px) | <div class="spacing-demo" style="width: var(--sl-spacing-x-small); height: var(--sl-spacing-x-small);"></div> |
|
||||
| `--sl-spacing-small` | 0.75rem (12px) | <div class="spacing-demo" style="width: var(--sl-spacing-small); height: var(--sl-spacing-small);"></div> |
|
||||
| `--sl-spacing-medium` | 1rem (16px) | <div class="spacing-demo" style="width: var(--sl-spacing-medium); height: var(--sl-spacing-medium);"></div> |
|
||||
| `--sl-spacing-large` | 1.25rem (20px) | <div class="spacing-demo" style="width: var(--sl-spacing-large); height: var(--sl-spacing-large);"></div> |
|
||||
| `--sl-spacing-x-large` | 1.75rem (28px) | <div class="spacing-demo" style="width: var(--sl-spacing-x-large); height: var(--sl-spacing-x-large);"></div> |
|
||||
| `--sl-spacing-xx-large` | 2.25rem (36px) | <div class="spacing-demo" style="width: var(--sl-spacing-xx-large); height: var(--sl-spacing-xx-large);"></div> |
|
||||
| `--sl-spacing-xxx-large` | 3rem (48px) | <div class="spacing-demo" style="width: var(--sl-spacing-xxx-large); height: var(--sl-spacing-xxx-large);"></div> |
|
||||
| `--sl-spacing-xxxx-large` | 4.5rem (72px) | <div class="spacing-demo" style="width: var(--sl-spacing-xxxx-large); height: var(--sl-spacing-xxxx-large);"></div> |
|
||||
| `--sl-spacing-2x-large` | 2.25rem (36px) | <div class="spacing-demo" style="width: var(--sl-spacing-2x-large); height: var(--sl-spacing-2x-large);"></div> |
|
||||
| `--sl-spacing-3x-large` | 3rem (48px) | <div class="spacing-demo" style="width: var(--sl-spacing-3x-large); height: var(--sl-spacing-3x-large);"></div> |
|
||||
| `--sl-spacing-4x-large` | 4.5rem (72px) | <div class="spacing-demo" style="width: var(--sl-spacing-4x-large); height: var(--sl-spacing-4x-large);"></div> |
|
||||
|
||||
@@ -18,15 +18,15 @@ Font sizes use `rem` units so they scale with the base font size. The pixel valu
|
||||
|
||||
| Token | Value | Example |
|
||||
| --------------------------- | --------------- | ----------------------------------------------------------------- |
|
||||
| `--sl-font-size-xx-small` | 0.625rem (10px) | <span style="font-size: var(--sl-font-size-xx-small)">Aa</span> |
|
||||
| `--sl-font-size-2x-small` | 0.625rem (10px) | <span style="font-size: var(--sl-font-size-2x-small)">Aa</span> |
|
||||
| `--sl-font-size-x-small` | 0.75rem (12px) | <span style="font-size: var(--sl-font-size-x-small)">Aa</span> |
|
||||
| `--sl-font-size-small` | 0.875rem (14px) | <span style="font-size: var(--sl-font-size-small)">Aa</span> |
|
||||
| `--sl-font-size-medium` | 1rem (16px) | <span style="font-size: var(--sl-font-size-medium)">Aa</span> |
|
||||
| `--sl-font-size-large` | 1.25rem (20px) | <span style="font-size: var(--sl-font-size-large)">Aa</span> |
|
||||
| `--sl-font-size-x-large` | 1.5rem (24px) | <span style="font-size: var(--sl-font-size-x-large)">Aa</span> |
|
||||
| `--sl-font-size-xx-large` | 2.25rem (36px) | <span style="font-size: var(--sl-font-size-xx-large)">Aa</span> |
|
||||
| `--sl-font-size-xxx-large` | 3rem (48px) | <span style="font-size: var(--sl-font-size-xxx-large)">Aa</span> |
|
||||
| `--sl-font-size-xxxx-large` | 4.5rem (72px) | <span style="font-size: var(--sl-font-size-xxxx-large)">Aa</span> |
|
||||
| `--sl-font-size-2x-large` | 2.25rem (36px) | <span style="font-size: var(--sl-font-size-2x-large)">Aa</span> |
|
||||
| `--sl-font-size-3x-large` | 3rem (48px) | <span style="font-size: var(--sl-font-size-3x-large)">Aa</span> |
|
||||
| `--sl-font-size-4x-large` | 4.5rem (72px) | <span style="font-size: var(--sl-font-size-4x-large)">Aa</span> |
|
||||
|
||||
## Font Weight
|
||||
|
||||
@@ -39,16 +39,20 @@ Font sizes use `rem` units so they scale with the base font size. The pixel valu
|
||||
|
||||
## Letter Spacing
|
||||
|
||||
| Token | Value | Example |
|
||||
| ---------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--sl-letter-spacing-dense` | -0.015em | <span style="letter-spacing: var(--sl-letter-spacing-dense);">The quick brown fox jumped over the lazy dog.</span> |
|
||||
| `--sl-letter-spacing-normal` | normal | <span style="letter-spacing: var(--sl-letter-spacing-normal);">The quick brown fox jumped over the lazy dog.</span> |
|
||||
| `--sl-letter-spacing-loose` | 0.075em | <span style="letter-spacing: var(--sl-letter-spacing-loose);">The quick brown fox jumped over the lazy dog.</span> |
|
||||
| Token | Value | Example |
|
||||
| ---------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--sl-letter-spacing-denser` | ? | <span style="letter-spacing: var(--sl-letter-spacing-denser);">The quick brown fox jumped over the lazy dog.</span> |
|
||||
| `--sl-letter-spacing-dense` | -0.015em | <span style="letter-spacing: var(--sl-letter-spacing-dense);">The quick brown fox jumped over the lazy dog.</span> |
|
||||
| `--sl-letter-spacing-normal` | normal | <span style="letter-spacing: var(--sl-letter-spacing-normal);">The quick brown fox jumped over the lazy dog.</span> |
|
||||
| `--sl-letter-spacing-loose` | 0.075em | <span style="letter-spacing: var(--sl-letter-spacing-loose);">The quick brown fox jumped over the lazy dog.</span> |
|
||||
| `--sl-letter-spacing-looser` | ? | <span style="letter-spacing: var(--sl-letter-spacing-looser);">The quick brown fox jumped over the lazy dog.</span> |
|
||||
|
||||
## Line Height
|
||||
|
||||
| Token | Value | Example |
|
||||
| ------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--sl-line-height-dense` | 1.4 | <div style="line-height: var(--sl-line-height-dense);">The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.</div> |
|
||||
| `--sl-line-height-normal` | 1.8 | <div style="line-height: var(--sl-line-height-normal);">The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.</div> |
|
||||
| `--sl-line-height-loose` | 2.2 | <div style="line-height: var(--sl-line-height-loose);">The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.</div> |
|
||||
| Token | Value | Example |
|
||||
| ------------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--sl-line-height-denser` | ? | <div style="line-height: var(--sl-line-height-denser);">The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.</div> |
|
||||
| `--sl-line-height-dense` | 1.4 | <div style="line-height: var(--sl-line-height-dense);">The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.</div> |
|
||||
| `--sl-line-height-normal` | 1.8 | <div style="line-height: var(--sl-line-height-normal);">The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.</div> |
|
||||
| `--sl-line-height-loose` | 2.2 | <div style="line-height: var(--sl-line-height-loose);">The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.</div> |
|
||||
| `--sl-line-height-looser` | ? | <div style="line-height: var(--sl-line-height-looser);">The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.<br>The quick brown fox jumped over the lazy dog.</div> |
|
||||
|
||||