Compare commits
979 Commits
v2.0.0-bet
...
v2.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5990fbd000 | ||
|
|
954d78dcd1 | ||
|
|
3ea31389dd | ||
|
|
d79799043a | ||
|
|
9f8ce58288 | ||
|
|
77abd42d66 | ||
|
|
218e78e947 | ||
|
|
8a1efac9b8 | ||
|
|
f9ae8327f6 | ||
|
|
7f3076d195 | ||
|
|
1fa79e64ae | ||
|
|
dde1010465 | ||
|
|
3a3a7347bc | ||
|
|
77c9750206 | ||
|
|
3d2e618be8 | ||
|
|
79feaae7fc | ||
|
|
b0f7dfb86b | ||
|
|
e1979b8f38 | ||
|
|
7e9ae32b9b | ||
|
|
480a1df246 | ||
|
|
ff798adb49 | ||
|
|
70a64262e9 | ||
|
|
5f65896150 | ||
|
|
c69db4919b | ||
|
|
a526e8a956 | ||
|
|
4970ba065e | ||
|
|
0292ed30c5 | ||
|
|
b64b1c2536 | ||
|
|
8f9eb012ba | ||
|
|
c8fd9f19d2 | ||
|
|
603aa93322 | ||
|
|
74203de094 | ||
|
|
4fa4682a45 | ||
|
|
34e0fb2fc1 | ||
|
|
50972f2b38 | ||
|
|
652ce6c9f1 | ||
|
|
8412b150b2 | ||
|
|
22b8ef4edf | ||
|
|
0865dede6f | ||
|
|
d638d811ad | ||
|
|
bc58472b7b | ||
|
|
226c856b1e | ||
|
|
5b12de1edf | ||
|
|
f79a670ca3 | ||
|
|
e1ec60af62 | ||
|
|
dcbcc4c050 | ||
|
|
0eb3375bb9 | ||
|
|
c26a8810c8 | ||
|
|
872227e345 | ||
|
|
f22c529eab | ||
|
|
3430b33c3e | ||
|
|
1bc2a6ef76 | ||
|
|
5a94f5bf5b | ||
|
|
4277377189 | ||
|
|
d818980dea | ||
|
|
636f61006f | ||
|
|
d93e698baf | ||
|
|
f8d8291caa | ||
|
|
21bef1c2ea | ||
|
|
f0efb9253c | ||
|
|
cfd28f2608 | ||
|
|
a3844fe074 | ||
|
|
65e90f12f4 | ||
|
|
4335289d6a | ||
|
|
86cc721e03 | ||
|
|
4a28825ea7 | ||
|
|
19cf823da5 | ||
|
|
737b55d78d | ||
|
|
8493131db5 | ||
|
|
0d86c2af37 | ||
|
|
d6a7820a52 | ||
|
|
39ca1208f5 | ||
|
|
610a06bcb9 | ||
|
|
b8584c0581 | ||
|
|
ab19afeb66 | ||
|
|
41b5cb367f | ||
|
|
e65b09fdec | ||
|
|
15a4049a01 | ||
|
|
ce708fbba8 | ||
|
|
75bd7784fb | ||
|
|
6e092ccf7a | ||
|
|
b7b73ea3a9 | ||
|
|
9dab91e0d1 | ||
|
|
a3a802a37b | ||
|
|
358ad7bb30 | ||
|
|
0a555c53c7 | ||
|
|
b260a4dc29 | ||
|
|
1f1024f4ca | ||
|
|
9e92d92684 | ||
|
|
527bf79973 | ||
|
|
b281c5bbc1 | ||
|
|
f03de8925b | ||
|
|
776ab2c715 | ||
|
|
df967b7e84 | ||
|
|
a539058253 | ||
|
|
af70d88153 | ||
|
|
8dcffe270f | ||
|
|
c958f2e50a | ||
|
|
cedcd65c72 | ||
|
|
12f62075ad | ||
|
|
b8695b70a9 | ||
|
|
a4e371618a | ||
|
|
039ab175c3 | ||
|
|
7549e50fe4 | ||
|
|
3c2cda699e | ||
|
|
8685ddd049 | ||
|
|
c47ad40802 | ||
|
|
ef1f129b22 | ||
|
|
6bb508ef14 | ||
|
|
3596c8144d | ||
|
|
20903bb638 | ||
|
|
f45fb6848f | ||
|
|
400f9b76d5 | ||
|
|
38a9e98d9b | ||
|
|
e8fe783fb4 | ||
|
|
223ef32b70 | ||
|
|
0793a219a2 | ||
|
|
3bb92c095f | ||
|
|
deec097267 | ||
|
|
873e280700 | ||
|
|
5d047f7a93 | ||
|
|
f24ab23752 | ||
|
|
44ecc8ce56 | ||
|
|
e758b1d9bb | ||
|
|
5cdbaa873d | ||
|
|
e9aca6cedb | ||
|
|
7c3896ed42 | ||
|
|
93158e8e90 | ||
|
|
5f9bbdfa06 | ||
|
|
3a0f486e98 | ||
|
|
29c671c0f4 | ||
|
|
88c4bef5e7 | ||
|
|
6066bc468b | ||
|
|
efd944d822 | ||
|
|
4a3f2caf59 | ||
|
|
511182b41b | ||
|
|
1088a51ed5 | ||
|
|
e3e0842bdd | ||
|
|
e4c908b08b | ||
|
|
f86578a213 | ||
|
|
3c2f5ec48e | ||
|
|
fec7ef17aa | ||
|
|
29ff99dd76 | ||
|
|
6b9b410bdc | ||
|
|
b45a9d55ca | ||
|
|
7ce079b7a1 | ||
|
|
b0ba9ff14f | ||
|
|
f665bf984b | ||
|
|
ac429a62c0 | ||
|
|
dc909d10b6 | ||
|
|
aa65077b12 | ||
|
|
7e37c51856 | ||
|
|
6e26daf804 | ||
|
|
25c2d2d5bf | ||
|
|
edc9e69f30 | ||
|
|
2e7ac38678 | ||
|
|
1a68c825c0 | ||
|
|
2cbdeeade0 | ||
|
|
79624f63ed | ||
|
|
01a8ec36ec | ||
|
|
60324885ed | ||
|
|
0c2f43b837 | ||
|
|
0df27cf730 | ||
|
|
68ed69292c | ||
|
|
62c58b3a8c | ||
|
|
1fbb809057 | ||
|
|
e2d2f5d670 | ||
|
|
acef0da2c1 | ||
|
|
3c66d2ab99 | ||
|
|
31f16c4680 | ||
|
|
8056379fdd | ||
|
|
9a6b9a7841 | ||
|
|
02fc39ebe0 | ||
|
|
a90b22c05d | ||
|
|
f5dd4f2aca | ||
|
|
d5b3489b22 | ||
|
|
8ee5f19184 | ||
|
|
d0a32d48b1 | ||
|
|
bf527437a0 | ||
|
|
ae3070ac45 | ||
|
|
6af68343a7 | ||
|
|
48ccc95dd9 | ||
|
|
c6a6a77bbd | ||
|
|
e632b51eb8 | ||
|
|
c8e633c4a1 | ||
|
|
724f4a59db | ||
|
|
041364fb7d | ||
|
|
fbcb4d8dbd | ||
|
|
27a6b4a8c9 | ||
|
|
c814e9e94e | ||
|
|
0e957c0cd4 | ||
|
|
b330657e0a | ||
|
|
a0fce64fd9 | ||
|
|
b183a04fba | ||
|
|
7645b997b2 | ||
|
|
d81e2f1470 | ||
|
|
f50fe72df2 | ||
|
|
dcca64a986 | ||
|
|
c216cfe0fd | ||
|
|
192f15e3b7 | ||
|
|
01be3daf6d | ||
|
|
d36eec5637 | ||
|
|
121464fa2d | ||
|
|
ee0254e822 | ||
|
|
27f634402c | ||
|
|
67fbe3b34e | ||
|
|
164ebce990 | ||
|
|
571ae704e0 | ||
|
|
ad305fb653 | ||
|
|
fc0541ce53 | ||
|
|
c8555f448c | ||
|
|
96e41198ec | ||
|
|
57064aef4d | ||
|
|
cf200aa58a | ||
|
|
388a4f85a4 | ||
|
|
5f8556b1b2 | ||
|
|
e411b57124 | ||
|
|
0120e7429d | ||
|
|
377dbe28eb | ||
|
|
b25b1d5750 | ||
|
|
0e1b792bf7 | ||
|
|
417f0d17c9 | ||
|
|
d9252fe755 | ||
|
|
c5555ab5fe | ||
|
|
eb61dc7d91 | ||
|
|
a4c522f090 | ||
|
|
a8fe8c3e71 | ||
|
|
87000306c0 | ||
|
|
ae07b7d0a8 | ||
|
|
626b76610f | ||
|
|
b4a1e1b0c9 | ||
|
|
913243f8c1 | ||
|
|
563ed81984 | ||
|
|
fcbf339a86 | ||
|
|
70585e1d2a | ||
|
|
479e568296 | ||
|
|
a473e41ab3 | ||
|
|
92f6a2d8e9 | ||
|
|
06dc5740bf | ||
|
|
fe524e0fac | ||
|
|
ea7de2eb70 | ||
|
|
b8d02537a6 | ||
|
|
24744ef8c5 | ||
|
|
69997466be | ||
|
|
f7d7fdf5b1 | ||
|
|
c0013c5639 | ||
|
|
935040204f | ||
|
|
2ffbf9b017 | ||
|
|
0f67b9a9d1 | ||
|
|
c5dee51233 | ||
|
|
b07238d536 | ||
|
|
e2a65c28f4 | ||
|
|
1f457cdde0 | ||
|
|
46fda5f0a6 | ||
|
|
e22c2f839b | ||
|
|
5bff912162 | ||
|
|
f3010cecbe | ||
|
|
2dc275defd | ||
|
|
9f79445292 | ||
|
|
10cb26b81e | ||
|
|
3722e0ad91 | ||
|
|
f28a0ec743 | ||
|
|
a42b393bf1 | ||
|
|
41f50777bd | ||
|
|
6afc3ba12e | ||
|
|
d8b7040a9e | ||
|
|
59cd70ae6f | ||
|
|
6d9c8561fb | ||
|
|
edb8a92838 | ||
|
|
da3ffe9a60 | ||
|
|
e2b791dee8 | ||
|
|
9178be576b | ||
|
|
752f5cff55 | ||
|
|
3675787ddd | ||
|
|
6284ed0347 | ||
|
|
1ff05c4b3d | ||
|
|
066abe4e52 | ||
|
|
e9134ddcf6 | ||
|
|
0237851aa1 | ||
|
|
1841251fdf | ||
|
|
b1e48406f3 | ||
|
|
4ca51cf11e | ||
|
|
41bd61c3a5 | ||
|
|
c6df057e15 | ||
|
|
1428481a5c | ||
|
|
1c359fbea9 | ||
|
|
0329694760 | ||
|
|
936ec5a23a | ||
|
|
d291506284 | ||
|
|
3877351fdc | ||
|
|
7885572ebd | ||
|
|
2ee926023c | ||
|
|
69e557cd8c | ||
|
|
f2efa73e20 | ||
|
|
2dd57956d5 | ||
|
|
ce86a1c9f2 | ||
|
|
a0f83c3b2b | ||
|
|
80a16ee42a | ||
|
|
31b05fedd3 | ||
|
|
d3a7950483 | ||
|
|
f299621490 | ||
|
|
c62ee3e207 | ||
|
|
a313087937 | ||
|
|
3945571b20 | ||
|
|
c6a044416a | ||
|
|
d2f1b50ad0 | ||
|
|
1f1bae77dd | ||
|
|
829e22dc1e | ||
|
|
8b28ee818f | ||
|
|
afb2e3d5b4 | ||
|
|
fb0adb9ccb | ||
|
|
efea514f5a | ||
|
|
fda9bd52a3 | ||
|
|
01f8ce6b03 | ||
|
|
e10651565f | ||
|
|
35aa56d334 | ||
|
|
31e1f2fc59 | ||
|
|
ee30f7a10b | ||
|
|
a50909d474 | ||
|
|
63115d51e5 | ||
|
|
026036a14b | ||
|
|
22e09a778b | ||
|
|
488088d5f0 | ||
|
|
0c18880e5c | ||
|
|
0b0a571d17 | ||
|
|
ea9e596279 | ||
|
|
fe17c8406b | ||
|
|
e7a4a5135d | ||
|
|
ebf12860be | ||
|
|
4b81778e46 | ||
|
|
28a8a90bb1 | ||
|
|
8dab5a8f04 | ||
|
|
4ac9483213 | ||
|
|
ae3c0d72c0 | ||
|
|
83b73e823d | ||
|
|
da6ae608f1 | ||
|
|
1e39647d7f | ||
|
|
4dc92247d5 | ||
|
|
1b6f982d68 | ||
|
|
81c775ea87 | ||
|
|
09f741e930 | ||
|
|
602a863d89 | ||
|
|
3dd19a7f62 | ||
|
|
bdf890ab0d | ||
|
|
0b7eae0c20 | ||
|
|
f3e273744a | ||
|
|
7f9b0bd5a2 | ||
|
|
6579a95999 | ||
|
|
aaa8e4a01b | ||
|
|
200d4385ec | ||
|
|
50d983a1ab | ||
|
|
1e6d295746 | ||
|
|
5d128c154c | ||
|
|
6c7d7f4b7e | ||
|
|
0cc8fdb8f8 | ||
|
|
4f7d915853 | ||
|
|
61738a3f6a | ||
|
|
9061c1987a | ||
|
|
c40b3a86a9 | ||
|
|
8b2c090bac | ||
|
|
8f2a3bd8bd | ||
|
|
ade05a6262 | ||
|
|
a706e69be6 | ||
|
|
bc6a813c46 | ||
|
|
599373c24a | ||
|
|
daebd08475 | ||
|
|
a3f658938d | ||
|
|
23414fe411 | ||
|
|
c8061fdee9 | ||
|
|
857b21a6a3 | ||
|
|
48be3f46b8 | ||
|
|
66012a57c8 | ||
|
|
0e77d8a459 | ||
|
|
b559c2345a | ||
|
|
d79d7da299 | ||
|
|
b296ac08cf | ||
|
|
36e677dd6b | ||
|
|
6167993941 | ||
|
|
f9d3f0be27 | ||
|
|
7f76cacc10 | ||
|
|
96cac8da85 | ||
|
|
a788e976c9 | ||
|
|
68c1319ed5 | ||
|
|
9db6f256e5 | ||
|
|
33e19c003c | ||
|
|
337d688bd3 | ||
|
|
cc305f8957 | ||
|
|
40cb38e0a0 | ||
|
|
a0d3ac047d | ||
|
|
e399bd19a2 | ||
|
|
f64f144b4b | ||
|
|
197a0c3048 | ||
|
|
e5e6b0d74f | ||
|
|
db1c2ee5cc | ||
|
|
c6a43ba4c2 | ||
|
|
ed45f52433 | ||
|
|
2d478c36fa | ||
|
|
f140007758 | ||
|
|
f03b09a410 | ||
|
|
0d9767596a | ||
|
|
c626706e27 | ||
|
|
58b653f1ae | ||
|
|
5eeb98d39d | ||
|
|
e90b64b463 | ||
|
|
5fd682d83a | ||
|
|
49193c972f | ||
|
|
c027c0a527 | ||
|
|
8160c33aa4 | ||
|
|
7d0226e3c4 | ||
|
|
084c1dc5b5 | ||
|
|
bfa320c5b5 | ||
|
|
4e1cf11461 | ||
|
|
5b4197da2c | ||
|
|
e29b2f12fb | ||
|
|
33a41bb2e4 | ||
|
|
ab754e9409 | ||
|
|
433955acf7 | ||
|
|
55445a80a3 | ||
|
|
9a64ea0670 | ||
|
|
0ff144a787 | ||
|
|
8893045bf1 | ||
|
|
a8de02bd53 | ||
|
|
4db0aec1c2 | ||
|
|
d885087c93 | ||
|
|
065aad2e4c | ||
|
|
9027ce055a | ||
|
|
119b923522 | ||
|
|
3b4d0652c4 | ||
|
|
1301934796 | ||
|
|
a8539bae02 | ||
|
|
8121faa1d4 | ||
|
|
70766b4e68 | ||
|
|
361efd43a2 | ||
|
|
a78b9fe5bd | ||
|
|
0cba4695ba | ||
|
|
22fa81433e | ||
|
|
5458a0e8f5 | ||
|
|
0e67f85995 | ||
|
|
808003f3df | ||
|
|
46c225d50f | ||
|
|
0a3656efc5 | ||
|
|
0aca600063 | ||
|
|
38f05ff010 | ||
|
|
3d4cbbf6ba | ||
|
|
c877e16c14 | ||
|
|
acce8eb146 | ||
|
|
03fe71353a | ||
|
|
8915282082 | ||
|
|
28003ac430 | ||
|
|
f2dcad82a9 | ||
|
|
69ff4f0bbc | ||
|
|
a1c93fd30f | ||
|
|
bdf8c4e669 | ||
|
|
854e576c2c | ||
|
|
cf32064e8c | ||
|
|
1f91d4cb79 | ||
|
|
a7fdb23577 | ||
|
|
39d1bbed2c | ||
|
|
e2e152c373 | ||
|
|
aae74dbaf7 | ||
|
|
6c716db037 | ||
|
|
7c0c0fa244 | ||
|
|
ffd32e52ef | ||
|
|
27868b56e8 | ||
|
|
346f13e5a5 | ||
|
|
69547d4800 | ||
|
|
9fc4185f87 | ||
|
|
08b5da7c56 | ||
|
|
05e026876a | ||
|
|
8d0d0ac4e0 | ||
|
|
972d629883 | ||
|
|
ce12020fca | ||
|
|
29b149cd26 | ||
|
|
7de37b9315 | ||
|
|
237cda3b63 | ||
|
|
51c4abb72b | ||
|
|
3a6890af81 | ||
|
|
7cc2c89f92 | ||
|
|
bb55c93b1a | ||
|
|
a3d00a92a0 | ||
|
|
5eccce625a | ||
|
|
0c3a25d2ad | ||
|
|
d225aaa2ff | ||
|
|
c6b7c24ed7 | ||
|
|
827c36bb1d | ||
|
|
d9f48a5f2a | ||
|
|
ccbdc6c014 | ||
|
|
b6edba912b | ||
|
|
4cc5baaa0b | ||
|
|
c2bbb0e8a4 | ||
|
|
352cade421 | ||
|
|
708977acf7 | ||
|
|
bab5749788 | ||
|
|
c6d0b27f0d | ||
|
|
ee31f3f682 | ||
|
|
105bb08ee1 | ||
|
|
ca64d26d77 | ||
|
|
23b2f9335b | ||
|
|
dfdd7c75c2 | ||
|
|
156a2812ae | ||
|
|
e42beab336 | ||
|
|
098db9c3fa | ||
|
|
81d393fbc1 | ||
|
|
2696b1a9ec | ||
|
|
322f23ba56 | ||
|
|
09224041b8 | ||
|
|
326816e7b7 | ||
|
|
4117b6d219 | ||
|
|
af9905acff | ||
|
|
e0727cc72c | ||
|
|
624297f624 | ||
|
|
1996037acc | ||
|
|
8fa665d3e7 | ||
|
|
f0a3972ef6 | ||
|
|
c8f42c5bde | ||
|
|
7a6144d8c4 | ||
|
|
ea71155b8f | ||
|
|
20e9e3c320 | ||
|
|
bcf2139fe7 | ||
|
|
48f864475e | ||
|
|
32f24a881e | ||
|
|
0163edd8a3 | ||
|
|
81620f0199 | ||
|
|
d850b0f507 | ||
|
|
19b2cde0d9 | ||
|
|
87e252940d | ||
|
|
c6d30ae1b5 | ||
|
|
23bb45b1b6 | ||
|
|
70f59aa4ba | ||
|
|
237230961a | ||
|
|
b669ab7b74 | ||
|
|
040e8ce5e1 | ||
|
|
a74de59687 | ||
|
|
186f57cdde | ||
|
|
c94db27f07 | ||
|
|
578a58042b | ||
|
|
b3b3956ff5 | ||
|
|
ce2abb97e0 | ||
|
|
6fc71601dd | ||
|
|
fd3da7e773 | ||
|
|
70700b1ab5 | ||
|
|
eb9107bf2b | ||
|
|
d0820178c9 | ||
|
|
a8e8325ea7 | ||
|
|
4b9e35313d | ||
|
|
dc1394483a | ||
|
|
4b32b9461c | ||
|
|
308c8228aa | ||
|
|
d74d2dec2e | ||
|
|
c9f3497a8a | ||
|
|
8e57d0075c | ||
|
|
73c8eba269 | ||
|
|
1c0ffa7a24 | ||
|
|
014354efde | ||
|
|
13ec55ba07 | ||
|
|
d6508a1262 | ||
|
|
9ebb5c8ec7 | ||
|
|
2093568981 | ||
|
|
bd5ca9034c | ||
|
|
7ae454f8ca | ||
|
|
b9fcd09209 | ||
|
|
cf2915a591 | ||
|
|
9e625752be | ||
|
|
147d1f048b | ||
|
|
801c4f70ec | ||
|
|
bcc9081247 | ||
|
|
3919ea97e9 | ||
|
|
876078b725 | ||
|
|
c765a1df9b | ||
|
|
a1bc784bc7 | ||
|
|
d14b9e12ed | ||
|
|
ab0fdd66b4 | ||
|
|
bf730f5bd2 | ||
|
|
8c667791fa | ||
|
|
d07a8cfaea | ||
|
|
23deda2253 | ||
|
|
1c6cf769d4 | ||
|
|
2add23d5d2 | ||
|
|
26693b2256 | ||
|
|
f31d13c424 | ||
|
|
59182db564 | ||
|
|
1bae224f80 | ||
|
|
9b3240a14f | ||
|
|
860224c894 | ||
|
|
a8b2eb2bb0 | ||
|
|
cea69beca9 | ||
|
|
4b7da8f510 | ||
|
|
6d31b1d63d | ||
|
|
7b55b38aa4 | ||
|
|
bf1121d126 | ||
|
|
fb2d419ab0 | ||
|
|
7179b60499 | ||
|
|
ad00d8840e | ||
|
|
3d9fd3b889 | ||
|
|
90f4d77ed6 | ||
|
|
36d1e7c52e | ||
|
|
2a1895a125 | ||
|
|
d5a352465e | ||
|
|
088ab99d02 | ||
|
|
42ed7f5cbb | ||
|
|
66e8259421 | ||
|
|
1f34b63a2e | ||
|
|
cf3b4fa501 | ||
|
|
73c190217f | ||
|
|
b2986e89b0 | ||
|
|
2bf68e8a32 | ||
|
|
f392ab4270 | ||
|
|
eefb8f6a6b | ||
|
|
8b2ddc984b | ||
|
|
f5bcd03c3f | ||
|
|
92a73f21eb | ||
|
|
4dbc3d2c8f | ||
|
|
90aac9abe9 | ||
|
|
589021c40f | ||
|
|
1cc65b145a | ||
|
|
f6fbde3c96 | ||
|
|
caf25773f0 | ||
|
|
b904bb0736 | ||
|
|
28ecc90e7f | ||
|
|
72fb9c7293 | ||
|
|
d69712530c | ||
|
|
71a39600f5 | ||
|
|
0291d7c28d | ||
|
|
ed2417d974 | ||
|
|
85fd8a5204 | ||
|
|
6446bb1013 | ||
|
|
2f8852245e | ||
|
|
401b46bad8 | ||
|
|
ae3efaf8ae | ||
|
|
98746c86e4 | ||
|
|
268aef1711 | ||
|
|
d765cef376 | ||
|
|
23ed3d5647 | ||
|
|
1a7fbbfab4 | ||
|
|
47388d4a3f | ||
|
|
ce09869ea2 | ||
|
|
33587f51d3 | ||
|
|
ed76d8aecc | ||
|
|
33d2ec0597 | ||
|
|
b4ae6ed1aa | ||
|
|
b6839254d4 | ||
|
|
8ee811af58 | ||
|
|
f34ffdac55 | ||
|
|
d7e7ff6101 | ||
|
|
1c36a7bcd4 | ||
|
|
7a77be017e | ||
|
|
5b5c6710fe | ||
|
|
04f7d2e182 | ||
|
|
36ee3c8a70 | ||
|
|
98eec84422 | ||
|
|
bc08a4c005 | ||
|
|
41580992f6 | ||
|
|
9b7ce98ec0 | ||
|
|
864d567572 | ||
|
|
cf360b3b3f | ||
|
|
673dc29dfe | ||
|
|
849b643cfc | ||
|
|
c39c4a9e9f | ||
|
|
92c36c65cb | ||
|
|
b6f25e09d2 | ||
|
|
71119c963d | ||
|
|
ecf5ab5aad | ||
|
|
7e581e6ad7 | ||
|
|
36fa84e4b0 | ||
|
|
3fb4cba856 | ||
|
|
00f98cc505 | ||
|
|
d9f719196a | ||
|
|
4b0c7245bd | ||
|
|
ced3a2a45a | ||
|
|
e6838e0a1f | ||
|
|
9e637ce0db | ||
|
|
acbee743a0 | ||
|
|
fa179fa30b | ||
|
|
2376f75f1d | ||
|
|
ca95822bba | ||
|
|
6fbcd2158a | ||
|
|
389b78f748 | ||
|
|
99368b9fdd | ||
|
|
a5a4621e25 | ||
|
|
fe95ebaa95 | ||
|
|
01c7ca27fe | ||
|
|
96ab3146be | ||
|
|
3c920cfed2 | ||
|
|
db7caf1997 | ||
|
|
808815bdab | ||
|
|
8a8fd7f5a9 | ||
|
|
3b3cb6d61d | ||
|
|
30a45f1d14 | ||
|
|
d10f628f1d | ||
|
|
615da18dc9 | ||
|
|
be11c13f67 | ||
|
|
cb7f0aa41e | ||
|
|
b2cf3a5505 | ||
|
|
0d19c46d18 | ||
|
|
c05832db67 | ||
|
|
e76dbef5f5 | ||
|
|
25c00c80b7 | ||
|
|
012206e4d8 | ||
|
|
de9da437f1 | ||
|
|
153fe15ed3 | ||
|
|
b58374aff1 | ||
|
|
31ae084538 | ||
|
|
f980126e81 | ||
|
|
cb1ada1bd7 | ||
|
|
200d340123 | ||
|
|
5c2f4dd84e | ||
|
|
953d175b44 | ||
|
|
f52a463728 | ||
|
|
5f25049abc | ||
|
|
8edaf67197 | ||
|
|
41c1979283 | ||
|
|
9840891cdc | ||
|
|
7d22e18bfb | ||
|
|
07af6f2741 | ||
|
|
60d9819088 | ||
|
|
9549539f5d | ||
|
|
1c23daa3b1 | ||
|
|
4a6c37ae0c | ||
|
|
f1bfd58dd2 | ||
|
|
4446814114 | ||
|
|
1ae6236e90 | ||
|
|
624a8bbe71 | ||
|
|
ca876b291a | ||
|
|
c850a7eae1 | ||
|
|
5613a3cef3 | ||
|
|
d3b161fc25 | ||
|
|
7659e45cc1 | ||
|
|
8a28d66393 | ||
|
|
c8d92e41b2 | ||
|
|
9b39c90849 | ||
|
|
5c8a34696e | ||
|
|
3e5da7c25a | ||
|
|
b1e6770712 | ||
|
|
fd49fd6456 | ||
|
|
d0ff2fef35 | ||
|
|
4c3313e275 | ||
|
|
4e0bc36b02 | ||
|
|
01eb84e3a6 | ||
|
|
70c97e2ae4 | ||
|
|
c165c8e71f | ||
|
|
6dd9773f2c | ||
|
|
15dbb0a634 | ||
|
|
ce09ac2a92 | ||
|
|
425f936254 | ||
|
|
7a9e4b0e8f | ||
|
|
48f10011e1 | ||
|
|
f6d3f799dd | ||
|
|
2157f4a385 | ||
|
|
0f76d05546 | ||
|
|
293f49e178 | ||
|
|
4d2de2dd57 | ||
|
|
46dc965cd0 | ||
|
|
707aeb6d65 | ||
|
|
96c63c60a2 | ||
|
|
9539123fc3 | ||
|
|
ea07346ae6 | ||
|
|
af1e440103 | ||
|
|
0cea7d23f0 | ||
|
|
ea8c88a31a | ||
|
|
b4e5544ff8 | ||
|
|
04d534cd30 | ||
|
|
7cb247976f | ||
|
|
3cbf9e14e6 | ||
|
|
3bd6516440 | ||
|
|
e3f691fbda | ||
|
|
ae76bea220 | ||
|
|
ca81a507b6 | ||
|
|
3f2382cfdc | ||
|
|
c1ccae315f | ||
|
|
92cb4e3d29 | ||
|
|
9dd8c45c57 | ||
|
|
fa84a84a40 | ||
|
|
9e747e7c2e | ||
|
|
79306e0618 | ||
|
|
139073dc3e | ||
|
|
18d441ef2e | ||
|
|
e07058ef5a | ||
|
|
f02941445b | ||
|
|
37b172dbfd | ||
|
|
4b2fc37015 | ||
|
|
ae219c83fb | ||
|
|
e60c5c4546 | ||
|
|
f57adb33eb | ||
|
|
25821c1294 | ||
|
|
8904e9d709 | ||
|
|
35885ef59f | ||
|
|
c19eb5847a | ||
|
|
c591f1d23e | ||
|
|
fd1f76169a | ||
|
|
8814746738 | ||
|
|
7bb6c4f0c1 | ||
|
|
6c14282223 | ||
|
|
7333760ada | ||
|
|
cb0b5feef8 | ||
|
|
01369464fa | ||
|
|
c2ceaa9a3f | ||
|
|
36716508c3 | ||
|
|
d683a76a49 | ||
|
|
4a0f6ef8af | ||
|
|
92b735b7fa | ||
|
|
240db01e75 | ||
|
|
04bacccfea | ||
|
|
25b6e8c2d7 | ||
|
|
1e2ceb8252 | ||
|
|
329a5aec32 | ||
|
|
c86ae623cb | ||
|
|
ce8dbc4302 | ||
|
|
72972c76af | ||
|
|
d55813fffb | ||
|
|
1f92e96079 | ||
|
|
2cb3c1fc9f | ||
|
|
caaf2b0d1e | ||
|
|
a635e4cd30 | ||
|
|
aa336fb525 | ||
|
|
c0dc08116c | ||
|
|
a5b3334222 | ||
|
|
8fd2491b9c | ||
|
|
deea93acad | ||
|
|
ba92feee4a | ||
|
|
e6458c26d6 | ||
|
|
4befbfafc5 | ||
|
|
fc938ea3eb | ||
|
|
5e444a4f7c | ||
|
|
1250627862 | ||
|
|
a588bdc7b3 | ||
|
|
44a4d13bad | ||
|
|
7467806969 | ||
|
|
9f844a8b91 | ||
|
|
83435a47de | ||
|
|
33612590ed | ||
|
|
7475e9576c | ||
|
|
56d114f13d | ||
|
|
50f702e9f1 | ||
|
|
43a361a52d | ||
|
|
85976a1f35 | ||
|
|
167cc6862a | ||
|
|
5ca57e4110 | ||
|
|
988d09ed2a | ||
|
|
bafa5fad54 | ||
|
|
a2e816253f | ||
|
|
68603f9aed | ||
|
|
46ac480713 | ||
|
|
35cad794e9 | ||
|
|
ee1a0c2c59 | ||
|
|
6f2ded4ce8 | ||
|
|
756b86a416 | ||
|
|
4b22fd2095 | ||
|
|
368854ba41 | ||
|
|
af4d25ee37 | ||
|
|
cb460ee7ba | ||
|
|
300cbd090f | ||
|
|
e32c15204c | ||
|
|
b8b68af316 | ||
|
|
0a5fb5e9e7 | ||
|
|
99f475b56f | ||
|
|
0b1ff75f1b | ||
|
|
ca653cd245 | ||
|
|
84563bdcd4 | ||
|
|
49215503a6 | ||
|
|
9a8aafc189 | ||
|
|
347808e86c | ||
|
|
f34960d82a | ||
|
|
c6165ee502 | ||
|
|
f676949460 | ||
|
|
73cfaee5ec | ||
|
|
a6983d2d99 | ||
|
|
43e4a5b250 | ||
|
|
7b2c027c26 | ||
|
|
e2069889b4 | ||
|
|
499b3f1ff4 | ||
|
|
b4713f9bc6 | ||
|
|
5132ee3559 | ||
|
|
2a702d1cb5 | ||
|
|
23a4859e0e | ||
|
|
ae94aecdd7 | ||
|
|
a6edf34a92 | ||
|
|
c26b1335f5 | ||
|
|
fdeb7689d7 | ||
|
|
2d5e765193 | ||
|
|
29d82736a7 | ||
|
|
e493c65b12 | ||
|
|
ada6f533b7 | ||
|
|
5ea578b8c8 | ||
|
|
67cb6abe56 | ||
|
|
3ff6a02391 | ||
|
|
dde83e7f67 | ||
|
|
fe527ff5dd | ||
|
|
4f99bbace9 | ||
|
|
ad0ac34f9d | ||
|
|
ba3306b497 | ||
|
|
7ff8b34e80 | ||
|
|
fc4b1464b9 | ||
|
|
485347e20b | ||
|
|
34676105a1 | ||
|
|
339eacb01f | ||
|
|
27a047976b | ||
|
|
3289129782 | ||
|
|
afa715c860 | ||
|
|
ae0eddfb25 | ||
|
|
13b2f8018d | ||
|
|
eb66ce2d4b | ||
|
|
ad16b0b5a6 | ||
|
|
c81f519b7c | ||
|
|
6450c0bee6 | ||
|
|
87d1db760f | ||
|
|
1c903f4d26 | ||
|
|
b84a8bc76a | ||
|
|
e77f059685 | ||
|
|
4e108d434a | ||
|
|
0f626bebbf | ||
|
|
cff57b6562 | ||
|
|
5cb9212fa4 | ||
|
|
c2910d742a | ||
|
|
e8174f7462 | ||
|
|
f245d97fc0 | ||
|
|
469c03f5e7 | ||
|
|
3144c45688 | ||
|
|
99e746ba81 | ||
|
|
7527b9f9b1 | ||
|
|
5e6add724d | ||
|
|
a5cd9a4968 | ||
|
|
c5fe481c33 | ||
|
|
38b0ace0ca | ||
|
|
1819f38ccb | ||
|
|
4834ecbddb | ||
|
|
3aa5fdba55 | ||
|
|
8ae987ea69 | ||
|
|
d77f543c8f | ||
|
|
517415f743 | ||
|
|
b9770e7e73 | ||
|
|
93cb8a2411 | ||
|
|
4866d2d190 | ||
|
|
80a9d05ff3 | ||
|
|
1db7aa3f26 | ||
|
|
ff1e11022d | ||
|
|
b55bf31fdc | ||
|
|
75c557ec63 | ||
|
|
2116ba19f6 | ||
|
|
8b9375ea68 | ||
|
|
9a024c6146 | ||
|
|
642de684e8 | ||
|
|
eb18d759f1 | ||
|
|
3fa41ea8d9 | ||
|
|
1147d6ba4a | ||
|
|
b0bebcd162 | ||
|
|
12dedf2047 | ||
|
|
9af8184221 | ||
|
|
62eeb06abe | ||
|
|
e60b5f670a | ||
|
|
6b2e64ef96 | ||
|
|
d6bfc773de | ||
|
|
a1e4b50b29 | ||
|
|
38c8762f64 | ||
|
|
ddd5b581fa | ||
|
|
e2afe4b787 | ||
|
|
b24ff33fe0 | ||
|
|
0922ee202a | ||
|
|
946fcf2b25 | ||
|
|
a517a8038f | ||
|
|
faca17ff78 | ||
|
|
d4e6126ec3 | ||
|
|
5c0da06d66 | ||
|
|
0d3bcb0b2c | ||
|
|
e0ab8fc8e2 | ||
|
|
011f12a7e4 | ||
|
|
f7f146df04 | ||
|
|
803a6d8a25 | ||
|
|
fa907a7f2b | ||
|
|
033a3a9db9 | ||
|
|
4a0dbde6b7 | ||
|
|
e41e08f2af | ||
|
|
c738f715a3 | ||
|
|
0d2572d37d | ||
|
|
a0df846493 | ||
|
|
01a6d60890 | ||
|
|
8721999a22 | ||
|
|
2b505466ce | ||
|
|
17627d0775 | ||
|
|
0f87fb86a9 |
@@ -1,4 +1,4 @@
|
||||
# http://editorconfig.org
|
||||
# https://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
|
||||
@@ -7,3 +7,4 @@ examples
|
||||
node_modules
|
||||
src/react
|
||||
scripts
|
||||
|
||||
|
||||
107
.eslintrc.cjs
@@ -1,7 +1,16 @@
|
||||
/* eslint-env node */
|
||||
|
||||
module.exports = {
|
||||
plugins: ['@typescript-eslint', 'wc', 'lit', 'lit-a11y', 'chai-expect', 'chai-friendly', 'import'],
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
'wc',
|
||||
'lit',
|
||||
'lit-a11y',
|
||||
'chai-expect',
|
||||
'chai-friendly',
|
||||
'import',
|
||||
'sort-imports-es6-autofix'
|
||||
],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:wc/recommended',
|
||||
@@ -13,7 +22,6 @@ module.exports = {
|
||||
es2021: true,
|
||||
browser: true
|
||||
},
|
||||
reportUnusedDisableDirectives: true,
|
||||
parserOptions: {
|
||||
sourceType: 'module'
|
||||
},
|
||||
@@ -64,26 +72,16 @@ module.exports = {
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/consistent-type-imports': 'warn',
|
||||
// These are commented out for now as we may want to add them to improve function boundary safety
|
||||
// "@typescript-eslint/explicit-function-return-type": [
|
||||
// "error",
|
||||
// {
|
||||
// allowTypedFunctionExpressions: true,
|
||||
// },
|
||||
// ],
|
||||
// "@typescript-eslint/explicit-member-accessibility": "warn",
|
||||
// "@typescript-eslint/explicit-module-boundary-types": "error",
|
||||
'@typescript-eslint/no-base-to-string': 'error',
|
||||
'@typescript-eslint/no-confusing-non-null-assertion': 'error',
|
||||
'@typescript-eslint/no-invalid-void-type': 'error',
|
||||
'@typescript-eslint/no-require-imports': 'error',
|
||||
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn',
|
||||
'@typescript-eslint/no-unnecessary-condition': 'warn',
|
||||
'@typescript-eslint/no-unnecessary-condition': 'off',
|
||||
'@typescript-eslint/no-unnecessary-qualifier': 'warn',
|
||||
'@typescript-eslint/non-nullable-type-assertion-style': 'warn',
|
||||
'@typescript-eslint/prefer-for-of': 'warn',
|
||||
'@typescript-eslint/prefer-optional-chain': 'warn',
|
||||
'@typescript-eslint/prefer-readonly': 'warn',
|
||||
'@typescript-eslint/prefer-ts-expect-error': 'warn',
|
||||
'@typescript-eslint/prefer-return-this-type': 'error',
|
||||
'@typescript-eslint/prefer-string-starts-ends-with': 'warn',
|
||||
@@ -93,34 +91,6 @@ module.exports = {
|
||||
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
||||
'@typescript-eslint/member-delimiter-style': 'warn',
|
||||
'@typescript-eslint/method-signature-style': 'warn',
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'warn',
|
||||
{
|
||||
selector: 'default',
|
||||
format: ['camelCase']
|
||||
},
|
||||
{
|
||||
selector: ['function', 'enumMember', 'property'],
|
||||
format: ['camelCase', 'PascalCase']
|
||||
},
|
||||
{
|
||||
selector: 'variable',
|
||||
modifiers: ['const'],
|
||||
format: ['camelCase', 'PascalCase', 'UPPER_CASE']
|
||||
},
|
||||
{
|
||||
selector: 'typeLike',
|
||||
format: ['PascalCase']
|
||||
},
|
||||
{
|
||||
selector: 'typeProperty',
|
||||
format: ['camelCase', 'PascalCase', 'UPPER_CASE']
|
||||
},
|
||||
{
|
||||
selector: 'objectLiteralProperty',
|
||||
format: null
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/no-extraneous-class': 'error',
|
||||
'@typescript-eslint/no-parameter-properties': 'error',
|
||||
'@typescript-eslint/strict-boolean-expressions': 'off'
|
||||
@@ -130,6 +100,7 @@ module.exports = {
|
||||
extends: ['plugin:chai-expect/recommended', 'plugin:chai-friendly/recommended'],
|
||||
files: ['*.test.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': 'off'
|
||||
}
|
||||
}
|
||||
@@ -137,10 +108,12 @@ module.exports = {
|
||||
rules: {
|
||||
'no-template-curly-in-string': 'error',
|
||||
'array-callback-return': 'error',
|
||||
'comma-dangle': 'off',
|
||||
'consistent-return': 'error',
|
||||
curly: 'off',
|
||||
'default-param-last': 'error',
|
||||
eqeqeq: 'error',
|
||||
'lit-a11y/click-events-have-key-events': 'off',
|
||||
'no-constructor-return': 'error',
|
||||
'no-empty-function': 'warn',
|
||||
'no-eval': 'error',
|
||||
@@ -169,7 +142,7 @@ module.exports = {
|
||||
'no-useless-concat': 'error',
|
||||
'no-useless-return': 'warn',
|
||||
'prefer-promise-reject-errors': 'error',
|
||||
radix: 'error',
|
||||
radix: 'off',
|
||||
'require-await': 'error',
|
||||
'wrap-iife': ['warn', 'inside'],
|
||||
'no-shadow': 'error',
|
||||
@@ -185,37 +158,15 @@ module.exports = {
|
||||
'prefer-object-spread': 'warn',
|
||||
'prefer-rest-params': 'warn',
|
||||
'prefer-spread': 'warn',
|
||||
'prefer-template': 'warn',
|
||||
'no-else-return': 'warn',
|
||||
'prefer-template': 'off',
|
||||
'no-else-return': 'off',
|
||||
'func-names': ['warn', 'never'],
|
||||
'func-style': ['warn', 'declaration'],
|
||||
'one-var': ['warn', 'never'],
|
||||
'operator-assignment': 'warn',
|
||||
'prefer-arrow-callback': 'warn',
|
||||
'no-restricted-syntax': [
|
||||
'warn',
|
||||
{
|
||||
selector: "CallExpression[callee.name='String']",
|
||||
message: "Don't use the String function. Use .toString() instead."
|
||||
},
|
||||
{
|
||||
selector: "CallExpression[callee.name='Number']",
|
||||
message: "Don't use the Number function. Use parseInt or parseFloat instead."
|
||||
},
|
||||
{
|
||||
selector: "CallExpression[callee.name='Boolean']",
|
||||
message: "Don't use the Boolean function. Use a strict comparison instead."
|
||||
}
|
||||
],
|
||||
'no-restricted-imports': [
|
||||
'warn',
|
||||
{
|
||||
patterns: [
|
||||
{
|
||||
group: ['../*'],
|
||||
message: 'Usage of relative parent imports is not allowed.'
|
||||
}
|
||||
],
|
||||
paths: [
|
||||
{
|
||||
name: '.',
|
||||
@@ -229,26 +180,12 @@ module.exports = {
|
||||
}
|
||||
],
|
||||
'import/no-duplicates': 'warn',
|
||||
'import/order': [
|
||||
'warn',
|
||||
'sort-imports-es6-autofix/sort-imports-es6': [
|
||||
2,
|
||||
{
|
||||
groups: ['builtin', 'external', ['parent', 'sibling', 'internal', 'index']],
|
||||
pathGroups: [
|
||||
{
|
||||
pattern: '~/**',
|
||||
group: 'internal'
|
||||
},
|
||||
{
|
||||
pattern: 'dist/**',
|
||||
group: 'external'
|
||||
}
|
||||
],
|
||||
alphabetize: {
|
||||
order: 'asc',
|
||||
caseInsensitive: true
|
||||
},
|
||||
'newlines-between': 'never',
|
||||
warnOnUnassignedImports: true
|
||||
ignoreCase: true,
|
||||
ignoreMemberSort: false,
|
||||
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single']
|
||||
}
|
||||
],
|
||||
'wc/guard-super-call': 'off'
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -29,8 +29,8 @@ If applicable, add screenshots to help explain the bug.
|
||||
|
||||
### Browser / OS
|
||||
- OS: [e.g. Mac, Windows]
|
||||
- Browser [e.g. Chrome, Firefox, Safari]
|
||||
- Browser version [e.g. 22]
|
||||
- Browser: [e.g. Chrome, Firefox, Safari]
|
||||
- Browser version: [e.g. 22]
|
||||
|
||||
### Additional information
|
||||
Provide any additional information about the bug here.
|
||||
|
||||
2
.github/SECURITY.md
vendored
@@ -4,4 +4,4 @@ We take security issues in Shoelace very seriously and appreciate your efforts t
|
||||
|
||||
To report a security issue, email [cory@abeautifulsite.net](mailto:cory@abeautifulsite.net) and include "SHOELACE SECURITY" in the subject line.
|
||||
|
||||
Well respond as soon as possible and keep you updated throughout the process.
|
||||
We'll respond as soon as possible and keep you updated throughout the process.
|
||||
|
||||
6
.github/workflows/node.js.yml
vendored
@@ -15,13 +15,13 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x, 16.x]
|
||||
node-version: [18.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
1
.gitignore
vendored
@@ -3,6 +3,5 @@
|
||||
docs/dist
|
||||
docs/search.json
|
||||
dist
|
||||
examples
|
||||
node_modules
|
||||
src/react
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
*.hbs
|
||||
*.md
|
||||
.cache
|
||||
.github
|
||||
cspell.json
|
||||
dist
|
||||
docs/*.md
|
||||
docs/search.json
|
||||
src/components/icon/icons
|
||||
src/react/index.ts
|
||||
|
||||
5
.vscode/settings.json
vendored
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
}
|
||||
}
|
||||
|
||||
41
cspell.json
@@ -1,25 +1,33 @@
|
||||
{
|
||||
"version": "0.2",
|
||||
"words": [
|
||||
"activedescendant",
|
||||
"allowfullscreen",
|
||||
"animationend",
|
||||
"Animista",
|
||||
"apos",
|
||||
"atrule",
|
||||
"autocorrect",
|
||||
"autofix",
|
||||
"autoplay",
|
||||
"bezier",
|
||||
"boxicons",
|
||||
"callout",
|
||||
"callouts",
|
||||
"chatbubble",
|
||||
"checkmark",
|
||||
"claviska",
|
||||
"Clippy",
|
||||
"codebases",
|
||||
"codepen",
|
||||
"colocated",
|
||||
"colour",
|
||||
"combobox",
|
||||
"Composability",
|
||||
"Consolas",
|
||||
"contenteditable",
|
||||
"copydir",
|
||||
"Cotte",
|
||||
"coverpage",
|
||||
"crossorigin",
|
||||
"crutchcorn",
|
||||
@@ -30,14 +38,23 @@
|
||||
"Docsify",
|
||||
"dropdowns",
|
||||
"easings",
|
||||
"enterkeyhint",
|
||||
"eqeqeq",
|
||||
"erroneou",
|
||||
"errormessage",
|
||||
"esbuild",
|
||||
"exportparts",
|
||||
"fieldsets",
|
||||
"formaction",
|
||||
"formdata",
|
||||
"formenctype",
|
||||
"formmethod",
|
||||
"formnovalidate",
|
||||
"formtarget",
|
||||
"FOUC",
|
||||
"FOUCE",
|
||||
"fullscreen",
|
||||
"gestern",
|
||||
"giga",
|
||||
"globby",
|
||||
"Grayscale",
|
||||
@@ -46,26 +63,36 @@
|
||||
"hexa",
|
||||
"Iconoir",
|
||||
"Iframes",
|
||||
"iife",
|
||||
"inputmode",
|
||||
"ionicon",
|
||||
"ionicons",
|
||||
"jsDelivr",
|
||||
"jsfiddle",
|
||||
"jsonata",
|
||||
"keydown",
|
||||
"keyframes",
|
||||
"Kool",
|
||||
"labelledby",
|
||||
"Laravel",
|
||||
"LaViska",
|
||||
"listbox",
|
||||
"listitem",
|
||||
"litelement",
|
||||
"lowercasing",
|
||||
"Lucide",
|
||||
"maxlength",
|
||||
"Menlo",
|
||||
"menuitemcheckbox",
|
||||
"menuitemradio",
|
||||
"middlewares",
|
||||
"minlength",
|
||||
"monospace",
|
||||
"mousedown",
|
||||
"mouseup",
|
||||
"multiselectable",
|
||||
"nextjs",
|
||||
"nocheck",
|
||||
"noopener",
|
||||
"noreferrer",
|
||||
"novalidate",
|
||||
@@ -73,7 +100,6 @@
|
||||
"ParamagicDev",
|
||||
"peta",
|
||||
"petabit",
|
||||
"popperjs",
|
||||
"progressbar",
|
||||
"radiogroup",
|
||||
"Railsbyte",
|
||||
@@ -84,8 +110,13 @@
|
||||
"rgba",
|
||||
"roadmap",
|
||||
"Roboto",
|
||||
"roledescription",
|
||||
"Sapan",
|
||||
"saturationl",
|
||||
"Schilp",
|
||||
"scrollbars",
|
||||
"scrollend",
|
||||
"scroller",
|
||||
"Segoe",
|
||||
"semibold",
|
||||
"slotchange",
|
||||
@@ -93,15 +124,20 @@
|
||||
"stylesheet",
|
||||
"Tabbable",
|
||||
"tabindex",
|
||||
"tabler",
|
||||
"tablist",
|
||||
"tabpanel",
|
||||
"templating",
|
||||
"tera",
|
||||
"testid",
|
||||
"textareas",
|
||||
"textfield",
|
||||
"tinycolor",
|
||||
"transitionend",
|
||||
"treeitem",
|
||||
"Triaging",
|
||||
"ttsc",
|
||||
"turbolinks",
|
||||
"typeof",
|
||||
"unbundles",
|
||||
"unbundling",
|
||||
"unicons",
|
||||
@@ -116,6 +152,7 @@
|
||||
"ignorePaths": [
|
||||
"package.json",
|
||||
"package-lock.json",
|
||||
"docs/assets/examples/include.html",
|
||||
".vscode/**",
|
||||
"src/translations/!(en).ts",
|
||||
"**/*.min.js"
|
||||
|
||||
@@ -1,11 +1,29 @@
|
||||
import fs from 'fs';
|
||||
import { generateCustomData } from 'cem-plugin-vs-code-custom-data-generator';
|
||||
import { parse } from 'comment-parser';
|
||||
import { pascalCase } from 'pascal-case';
|
||||
import commandLineArgs from 'command-line-args';
|
||||
import fs from 'fs';
|
||||
|
||||
const packageData = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||
const { name, description, version, author, homepage, license } = packageData;
|
||||
// eslint-disable-next-line func-style
|
||||
const noDash = string => string.replace(/^\s?-/, '').trim();
|
||||
|
||||
const { outdir } = commandLineArgs([
|
||||
{ name: 'litelement', type: String },
|
||||
{ name: 'analyze', defaultOption: true },
|
||||
{ name: 'outdir', type: String }
|
||||
]);
|
||||
|
||||
function noDash(string) {
|
||||
return string.replace(/^\s?-/, '').trim();
|
||||
}
|
||||
|
||||
function replace(string, terms) {
|
||||
terms.forEach(({ from, to }) => {
|
||||
string = string?.replace(from, to);
|
||||
});
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
export default {
|
||||
globs: ['src/components/**/*.ts'],
|
||||
@@ -27,7 +45,7 @@ export default {
|
||||
case ts.SyntaxKind.ClassDeclaration: {
|
||||
const className = node.name.getText();
|
||||
const classDoc = moduleDoc?.declarations?.find(declaration => declaration.name === className);
|
||||
const customTags = ['animation', 'dependency', 'since', 'status'];
|
||||
const customTags = ['animation', 'dependency', 'documentation', 'since', 'status', 'title'];
|
||||
let customComments = '/**';
|
||||
|
||||
node.jsDoc?.forEach(jsDoc => {
|
||||
@@ -63,8 +81,10 @@ export default {
|
||||
break;
|
||||
|
||||
// Value-only metadata tags
|
||||
case 'documentation':
|
||||
case 'since':
|
||||
case 'status':
|
||||
case 'title':
|
||||
classDoc[t.tag] = t.name;
|
||||
break;
|
||||
|
||||
@@ -85,7 +105,6 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'shoelace-react-event-names',
|
||||
analyzePhase({ ts, node, moduleDoc }) {
|
||||
@@ -102,6 +121,47 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'shoelace-translate-module-paths',
|
||||
packageLinkPhase({ customElementsManifest }) {
|
||||
customElementsManifest?.modules?.forEach(mod => {
|
||||
//
|
||||
// CEM paths look like this:
|
||||
//
|
||||
// src/components/button/button.ts
|
||||
//
|
||||
// But we want them to look like this:
|
||||
//
|
||||
// components/button/button.js
|
||||
//
|
||||
const terms = [
|
||||
{ from: /^src\//, to: '' }, // Strip the src/ prefix
|
||||
{ from: /\.(t|j)sx?$/, to: '.js' } // Convert .ts to .js
|
||||
];
|
||||
|
||||
mod.path = replace(mod.path, terms);
|
||||
|
||||
for (const ex of mod.exports ?? []) {
|
||||
ex.declaration.module = replace(ex.declaration.module, terms);
|
||||
}
|
||||
|
||||
for (const dec of mod.declarations ?? []) {
|
||||
if (dec.kind === 'class') {
|
||||
for (const member of dec.members ?? []) {
|
||||
if (member.inheritedFrom) {
|
||||
member.inheritedFrom.module = replace(member.inheritedFrom.module, terms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
// Generate custom VS Code data
|
||||
generateCustomData({
|
||||
outdir,
|
||||
cssFileName: null
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
- Getting Started
|
||||
|
||||
- [Overview](/)
|
||||
- [Installation](/getting-started/installation)
|
||||
- [Usage](/getting-started/usage)
|
||||
@@ -8,17 +9,20 @@
|
||||
- [Localization](/getting-started/localization)
|
||||
|
||||
- Frameworks
|
||||
|
||||
- [React](/frameworks/react)
|
||||
- [Vue](/frameworks/vue)
|
||||
- [Angular](/frameworks/angular)
|
||||
|
||||
- Resources
|
||||
|
||||
- [Community](/resources/community)
|
||||
- [Accessibility](/resources/accessibility)
|
||||
- [Contributing](/resources/contributing)
|
||||
- [Changelog](/resources/changelog)
|
||||
|
||||
- Components
|
||||
|
||||
- [Alert](/components/alert)
|
||||
- [Avatar](/components/avatar)
|
||||
- [Badge](/components/badge)
|
||||
@@ -27,6 +31,8 @@
|
||||
- [Button](/components/button)
|
||||
- [Button Group](/components/button-group)
|
||||
- [Card](/components/card)
|
||||
- [Carousel](/components/carousel)
|
||||
- [Carousel Item](/components/carousel-item)
|
||||
- [Checkbox](/components/checkbox)
|
||||
- [Color Picker](/components/color-picker)
|
||||
- [Details](/components/details)
|
||||
@@ -41,10 +47,12 @@
|
||||
- [Menu](/components/menu)
|
||||
- [Menu Item](/components/menu-item)
|
||||
- [Menu Label](/components/menu-label)
|
||||
- [Option](/components/option)
|
||||
- [Progress Bar](/components/progress-bar)
|
||||
- [Progress Ring](/components/progress-ring)
|
||||
- [QR Code](/components/qr-code)
|
||||
- [Radio](/components/radio)
|
||||
- [Radio Button](/components/radio-button)
|
||||
- [Radio Group](/components/radio-group)
|
||||
- [Range](/components/range)
|
||||
- [Rating](/components/rating)
|
||||
@@ -59,9 +67,12 @@
|
||||
- [Tag](/components/tag)
|
||||
- [Textarea](/components/textarea)
|
||||
- [Tooltip](/components/tooltip)
|
||||
- [Tree](/components/tree)
|
||||
- [Tree Item](/components/tree-item)
|
||||
<!--plop:component-->
|
||||
|
||||
- Utilities
|
||||
|
||||
- [Animated Image](/components/animated-image)
|
||||
- [Animation](/components/animation)
|
||||
- [Format Bytes](/components/format-bytes)
|
||||
@@ -69,12 +80,13 @@
|
||||
- [Format Number](/components/format-number)
|
||||
- [Include](/components/include)
|
||||
- [Mutation Observer](/components/mutation-observer)
|
||||
- [Popup](/components/popup)
|
||||
- [Relative Time](/components/relative-time)
|
||||
- [Resize Observer](/components/resize-observer)
|
||||
- [Responsive Media](/components/responsive-media)
|
||||
- [Visually Hidden](/components/visually-hidden)
|
||||
|
||||
- Design Tokens
|
||||
|
||||
- [Typography](/tokens/typography)
|
||||
- [Color](/tokens/color)
|
||||
- [Spacing](/tokens/spacing)
|
||||
@@ -82,8 +94,10 @@
|
||||
- [Border Radius](/tokens/border-radius)
|
||||
- [Transition](/tokens/transition)
|
||||
- [Z-index](/tokens/z-index)
|
||||
- [More](/tokens/more)
|
||||
|
||||
- Tutorials
|
||||
|
||||
- [Integrating with Laravel](/tutorials/integrating-with-laravel)
|
||||
- [Integrating with NextJS](/tutorials/integrating-with-nextjs)
|
||||
- [Integrating with Rails](/tutorials/integrating-with-rails)
|
||||
- [Integrating with Rails](/tutorials/integrating-with-rails)
|
||||
|
||||
BIN
docs/assets/examples/carousel/field.jpg
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
docs/assets/examples/carousel/mountains.jpg
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
docs/assets/examples/carousel/sunset.jpg
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
docs/assets/examples/carousel/valley.jpg
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
docs/assets/examples/carousel/waterfall.jpg
Normal file
|
After Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 861 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
@@ -41,7 +41,7 @@
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" cx="103.34581" cy="426.732" rx="10.90314" ry="4.08868"></ellipse>
|
||||
<circle id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="86.99113" cy="358.86008" r="14.71922"></circle>
|
||||
<circle id="Oval" fill="#3F3D56" fill-rule="nonzero" cx="86.99113" cy="358.86008" r="4.90642"></circle>
|
||||
<path d="M44.12401,329.71183 C40.64653,314.13804 51.76268,298.4014 68.95262,294.56302 C86.14256,290.72464 102.89683,300.23813 106.37431,315.81192 C109.85179,331.38571 98.45939,337.12961 81.26945,340.96792 C64.07951,344.80623 47.60154,345.28568 44.12401,329.71183 Z" id="Path" fill="#E6E6E6" fill-rule="nonzero"></path>
|
||||
<path d="M44.12401,329.71183 C40.64653,314.13804 51.76268,298.4014 68.95262,294.56302 C86.14256,290.72464 102.89683,300.23813 106.37431,315.81192 C109.85179,331.38571 98.45939,337.12961 81.26945,340.96792 C64.07951,344.80623 47.60154,345.28568 44.12401,329.71183 Z" id="Path" fill="#12a5e9" fill-rule="nonzero"></path>
|
||||
<ellipse id="Oval" fill="#2F2E41" fill-rule="nonzero" transform="translate(110.988725, 213.490755) rotate(-69.082170) translate(-110.988725, -213.490755) " cx="110.988725" cy="213.490755" rx="21.53369" ry="6.76007"></ellipse>
|
||||
<circle id="Oval" fill="#2F2E41" fill-rule="nonzero" transform="translate(71.181568, 246.012788) rotate(-80.782520) translate(-71.181568, -246.012788) " cx="71.1815681" cy="246.012788" r="43.06735"></circle>
|
||||
<rect id="Rectangle" fill="#2F2E41" fill-rule="nonzero" x="51.55595" y="279.81244" width="13.08374" height="23.44171"></rect>
|
||||
@@ -67,13 +67,13 @@
|
||||
<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="#11a5e9" 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="#9358ff" 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>
|
||||
<circle id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="764.18602" cy="224.18353" r="18"></circle>
|
||||
<rect id="Rectangle" fill="#3F3D56" fill-rule="nonzero" transform="translate(653.262165, 167.923576) rotate(7.892770) translate(-653.262165, -167.923576) " x="642.262129" y="156.923541" width="22.0000711" height="22.0000711"></rect>
|
||||
<path d="M768.18655,374.08068 C771.66403,358.50689 760.54788,342.77022 743.35794,338.93184 C726.168,335.09346 709.41373,344.60692 705.93625,360.18071 C702.45877,375.7545 713.85117,381.49837 731.04111,385.33671 C748.23105,389.17505 764.70908,389.6545 768.18655,374.08068 Z" id="Path" fill="#F2F2F2" fill-rule="nonzero"></path>
|
||||
<rect id="Rectangle" fill="#FFFFFF" fill-rule="nonzero" transform="translate(653.262165, 167.923576) rotate(7.892770) translate(-653.262165, -167.923576) " x="642.262129" y="156.923541" width="22.0000711" height="22.0000711"></rect>
|
||||
<path d="M768.18655,374.08068 C771.66403,358.50689 760.54788,342.77022 743.35794,338.93184 C726.168,335.09346 709.41373,344.60692 705.93625,360.18071 C702.45877,375.7545 713.85117,381.49837 731.04111,385.33671 C748.23105,389.17505 764.70908,389.6545 768.18655,374.08068 Z" id="Path" fill="#12a5e9" fill-rule="nonzero"></path>
|
||||
<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>
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
@@ -132,17 +132,13 @@
|
||||
box-shadow: 0 0 0 1px var(--sl-color-primary-400);
|
||||
border-right-color: transparent;
|
||||
background-color: var(--sl-color-primary-50);
|
||||
color: var(--sl-color-primary-700);
|
||||
color: var(--sl-color-primary-600);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.code-block__button:focus-visible {
|
||||
outline: none;
|
||||
color: var(--sl-color-primary-600);
|
||||
border-color: var(--sl-color-primary-400);
|
||||
border-right-color: transparent;
|
||||
background-color: var(--sl-color-primary-50);
|
||||
box-shadow: 0 0 0 1px var(--sl-color-primary-400), var(--sl-focus-ring);
|
||||
outline: var(--sl-focus-ring);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
@@ -210,7 +206,8 @@
|
||||
}
|
||||
|
||||
.markdown-section .docsify-copy-code-button:focus-visible {
|
||||
box-shadow: var(--sl-focus-ring);
|
||||
outline: var(--sl-focus-ring);
|
||||
outline-offset: var(--sl-focus-ring-offset);
|
||||
}
|
||||
|
||||
.markdown-section .docsify-copy-code-button:active {
|
||||
|
||||
@@ -146,8 +146,6 @@
|
||||
</div>
|
||||
|
||||
<div class="code-block__buttons">
|
||||
${hasReact ? ` ${htmlButton} ${reactButton} ` : ''}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="code-block__button code-block__toggle"
|
||||
@@ -167,6 +165,8 @@
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
${hasReact ? ` ${htmlButton} ${reactButton} ` : ''}
|
||||
|
||||
${!code.classList.contains('no-codepen') ? codePenButton : ''}
|
||||
</div>
|
||||
</div>
|
||||
@@ -202,10 +202,10 @@
|
||||
startWidth = parseInt(document.defaultView.getComputedStyle(preview).width, 10);
|
||||
preview.classList.add('code-block__preview--dragging');
|
||||
event.preventDefault();
|
||||
document.documentElement.addEventListener('mousemove', dragMove, false);
|
||||
document.documentElement.addEventListener('touchmove', dragMove, false);
|
||||
document.documentElement.addEventListener('mouseup', dragStop, false);
|
||||
document.documentElement.addEventListener('touchend', dragStop, false);
|
||||
document.documentElement.addEventListener('mousemove', dragMove);
|
||||
document.documentElement.addEventListener('touchmove', dragMove);
|
||||
document.documentElement.addEventListener('mouseup', dragStop);
|
||||
document.documentElement.addEventListener('touchend', dragStop);
|
||||
}
|
||||
|
||||
function dragMove(event) {
|
||||
@@ -214,10 +214,10 @@
|
||||
|
||||
function dragStop() {
|
||||
preview.classList.remove('code-block__preview--dragging');
|
||||
document.documentElement.removeEventListener('mousemove', dragMove, false);
|
||||
document.documentElement.removeEventListener('touchmove', dragMove, false);
|
||||
document.documentElement.removeEventListener('mouseup', dragStop, false);
|
||||
document.documentElement.removeEventListener('touchend', dragStop, false);
|
||||
document.documentElement.removeEventListener('mousemove', dragMove);
|
||||
document.documentElement.removeEventListener('touchmove', dragMove);
|
||||
document.documentElement.removeEventListener('mouseup', dragStop);
|
||||
document.documentElement.removeEventListener('touchend', dragStop);
|
||||
}
|
||||
|
||||
function setWidth(width) {
|
||||
@@ -225,43 +225,52 @@
|
||||
}
|
||||
|
||||
resizer.addEventListener('mousedown', dragStart);
|
||||
resizer.addEventListener('touchstart', dragStart);
|
||||
resizer.addEventListener('touchstart', dragStart, { passive: true });
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
// Toggle source mode
|
||||
document.addEventListener('click', event => {
|
||||
const button = event.target.closest('button');
|
||||
const button = event.target.closest('.code-block__button');
|
||||
const codeBlock = button?.closest('.code-block');
|
||||
|
||||
if (button?.classList.contains('code-block__button--html')) {
|
||||
// Show HTML
|
||||
setFlavor('html');
|
||||
toggleSource(codeBlock, true);
|
||||
} else if (button?.classList.contains('code-block__button--react')) {
|
||||
// Show React
|
||||
setFlavor('react');
|
||||
toggleSource(codeBlock, true);
|
||||
} else if (button?.classList.contains('code-block__toggle')) {
|
||||
// Toggle source
|
||||
toggleSource(codeBlock);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update flavor buttons
|
||||
[...document.querySelectorAll('.code-block')].forEach(codeBlock => {
|
||||
codeBlock
|
||||
.querySelector('.code-block__button--html')
|
||||
?.classList.toggle('code-block__button--selected', flavor === 'html');
|
||||
codeBlock
|
||||
.querySelector('.code-block__button--react')
|
||||
?.classList.toggle('code-block__button--selected', flavor === 'react');
|
||||
[...document.querySelectorAll('.code-block')].forEach(cb => {
|
||||
cb.querySelector('.code-block__button--html')?.classList.toggle(
|
||||
'code-block__button--selected',
|
||||
flavor === 'html'
|
||||
);
|
||||
cb.querySelector('.code-block__button--react')?.classList.toggle(
|
||||
'code-block__button--selected',
|
||||
flavor === 'react'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Expand and collapse code blocks
|
||||
document.addEventListener('click', event => {
|
||||
const toggle = event.target.closest('.code-block__toggle');
|
||||
function toggleSource(codeBlock, force) {
|
||||
const toggle = codeBlock.querySelector('.code-block__toggle');
|
||||
|
||||
if (toggle) {
|
||||
const codeBlock = event.target.closest('.code-block');
|
||||
codeBlock.classList.toggle('code-block--expanded');
|
||||
codeBlock.classList.toggle('code-block--expanded', force === undefined ? undefined : force);
|
||||
event.target.setAttribute('aria-expanded', codeBlock.classList.contains('code-block--expanded'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Show pulse when copying
|
||||
document.addEventListener('click', event => {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
function createPropsTable(props) {
|
||||
const table = document.createElement('table');
|
||||
table.classList.add('metadata-table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -48,7 +49,7 @@
|
||||
${escapeHtml(prop.description)}
|
||||
</td>
|
||||
<td style="text-align: center;">${
|
||||
prop.reflects ? '<sl-icon label="yes" name="check"></sl-icon>' : ''
|
||||
prop.reflects ? '<sl-icon label="yes" name="check-lg"></sl-icon>' : ''
|
||||
}</td>
|
||||
<td>${prop.type?.text ? `<code>${escapeHtml(prop.type?.text || '')}</code>` : '-'}</td>
|
||||
<td>${prop.default ? `<code>${escapeHtml(prop.default)}</code>` : '-'}</td>
|
||||
@@ -56,7 +57,18 @@
|
||||
`;
|
||||
})
|
||||
.join('')}
|
||||
</tbody>
|
||||
|
||||
<tr>
|
||||
<td class="nowrap"><code>updateComplete</code></td>
|
||||
<td>
|
||||
A read-only promise that resolves when the component has
|
||||
<a href="/getting-started/usage?id=component-rendering-and-updating">finished updating</a>.
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
`;
|
||||
|
||||
return table.outerHTML;
|
||||
@@ -64,6 +76,7 @@
|
||||
|
||||
function createEventsTable(events) {
|
||||
const table = document.createElement('table');
|
||||
table.classList.add('metadata-table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -94,6 +107,7 @@
|
||||
|
||||
function createMethodsTable(methods) {
|
||||
const table = document.createElement('table');
|
||||
table.classList.add('metadata-table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -107,14 +121,14 @@
|
||||
.map(
|
||||
method => `
|
||||
<tr>
|
||||
<td class="nowrap"><code>${escapeHtml(method.name)}</code></td>
|
||||
<td class="nowrap"><code>${escapeHtml(method.name)}()</code></td>
|
||||
<td>${escapeHtml(method.description)}</td>
|
||||
<td>
|
||||
${
|
||||
method.parameters?.length
|
||||
? `
|
||||
<code>${escapeHtml(
|
||||
method.parameters.map(param => `${param.name}: ${param.type.text}`).join(', ')
|
||||
method.parameters.map(param => `${param.name}: ${param.type?.text || ''}`).join(', ')
|
||||
)}</code>
|
||||
`
|
||||
: '-'
|
||||
@@ -132,6 +146,7 @@
|
||||
|
||||
function createSlotsTable(slots) {
|
||||
const table = document.createElement('table');
|
||||
table.classList.add('metadata-table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -158,6 +173,7 @@
|
||||
|
||||
function createCustomPropertiesTable(styles) {
|
||||
const table = document.createElement('table');
|
||||
table.classList.add('metadata-table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -186,6 +202,7 @@
|
||||
|
||||
function createPartsTable(parts) {
|
||||
const table = document.createElement('table');
|
||||
table.classList.add('metadata-table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -212,6 +229,7 @@
|
||||
|
||||
function createAnimationsTable(animations) {
|
||||
const table = document.createElement('table');
|
||||
table.classList.add('metadata-table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -276,6 +294,7 @@
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2" rel="noopener noreferrer" target="_blank">$1</a>')
|
||||
.replace(/`(.*?)`/g, '<code>$1</code>');
|
||||
}
|
||||
|
||||
@@ -325,7 +344,7 @@
|
||||
<sl-icon slot="prefix" 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 slot="prefix" name="github"></sl-icon> <span class="github-star-count">Star</span>
|
||||
<sl-icon slot="prefix" name="github"></sl-icon> Star
|
||||
</sl-button>
|
||||
<sl-button size="small" class="repo-button repo-button--twitter" href="https://twitter.com/shoelace_style" target="_blank">
|
||||
<sl-icon slot="prefix" name="twitter"></sl-icon> Follow
|
||||
@@ -367,7 +386,7 @@
|
||||
result += `
|
||||
<div class="component-header">
|
||||
<div class="component-header__tag">
|
||||
<code><${component.tagName}> | ${component.name}</code>
|
||||
<code><${component.tagName}> | ${component.title ?? component.name}</code>
|
||||
</div>
|
||||
|
||||
<div class="component-header__info">
|
||||
@@ -379,6 +398,10 @@
|
||||
${component.status}
|
||||
</sl-badge>
|
||||
</div>
|
||||
|
||||
<div class="component-header__summary">
|
||||
${component.summary ? `<p>${marked(component.summary)}</p>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -423,7 +446,7 @@
|
||||
To import this component from [the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace) using a script tag:
|
||||
|
||||
\`\`\`html
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${metadata.package.version}/${component.path}"></script>
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${metadata.package.version}/dist/${component.path}"></script>
|
||||
\`\`\`
|
||||
</sl-tab-panel>
|
||||
|
||||
@@ -431,14 +454,14 @@
|
||||
To import this component from [the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace) using a JavaScript import:
|
||||
|
||||
\`\`\`js
|
||||
import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${metadata.package.version}/${component.path}';
|
||||
import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${metadata.package.version}/dist/${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}';
|
||||
import '@shoelace-style/shoelace/dist/${component.path}';
|
||||
\`\`\`
|
||||
</sl-tab-panel>
|
||||
|
||||
@@ -449,39 +472,27 @@
|
||||
\`\`\`
|
||||
</sl-tab-panel>
|
||||
</sl-tab-group>
|
||||
`;
|
||||
}
|
||||
|
||||
if (props?.length) {
|
||||
result += `
|
||||
## Properties
|
||||
${createPropsTable(props)}
|
||||
`;
|
||||
}
|
||||
<div class="sponsor-callout">
|
||||
<p>
|
||||
Shoelace is designed, developed, and maintained by <a href="https://twitter.com/claviska" target="_blank">Cory LaViska</a>.
|
||||
Please sponsor my open source work on GitHub. Your support will keep this project alive and growing!
|
||||
</p>
|
||||
|
||||
if (component.events?.length) {
|
||||
result += `
|
||||
## Events
|
||||
${createEventsTable(component.events)}
|
||||
`;
|
||||
}
|
||||
<p>
|
||||
<sl-button class="repo-button repo-button--sponsor" href="https://github.com/sponsors/claviska" target="_blank">
|
||||
<sl-icon slot="prefix" name="heart"></sl-icon> Sponsor <span class="sponsor-callout__secondary-label">Development</span>
|
||||
</sl-button>
|
||||
|
||||
if (methods?.length) {
|
||||
result += `
|
||||
## Methods
|
||||
<sl-button class="repo-button repo-button--github" href="https://github.com/shoelace-style/shoelace/stargazers" target="_blank">
|
||||
<sl-icon slot="prefix" name="github"></sl-icon> Star <span class="sponsor-callout__secondary-label">on GitHub</span>
|
||||
</sl-button>
|
||||
|
||||
<p data-flavor="html">
|
||||
Methods can be called by obtaining a reference to the element and calling
|
||||
<code>el.methodName()</code>.
|
||||
</p>
|
||||
|
||||
|
||||
<p data-flavor="react">
|
||||
Methods can be called by obtaining a <code>ref</code> to the element and calling
|
||||
<code>ref.current.methodName()</code>.
|
||||
</p>
|
||||
|
||||
${createMethodsTable(methods)}
|
||||
<sl-button class="repo-button repo-button--twitter" href="https://twitter.com/shoelace_style" target="_blank">
|
||||
<sl-icon slot="prefix" name="twitter"></sl-icon> Follow <span class="sponsor-callout__secondary-label">on Twitter</span>
|
||||
</sl-button>
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -489,6 +500,36 @@
|
||||
result += `
|
||||
## Slots
|
||||
${createSlotsTable(component.slots)}
|
||||
|
||||
_Learn more about [using slots](/getting-started/usage#slots)._
|
||||
`;
|
||||
}
|
||||
|
||||
if (props?.length) {
|
||||
result += `
|
||||
## Attributes & Properties
|
||||
${createPropsTable(props)}
|
||||
|
||||
_Learn more about [attributes and properties](/getting-started/usage#properties)._
|
||||
`;
|
||||
}
|
||||
|
||||
if (component.events?.length) {
|
||||
result += `
|
||||
## Events
|
||||
${createEventsTable(component.events)}
|
||||
|
||||
_Learn more about [listening to events](/getting-started/usage#events)._
|
||||
`;
|
||||
}
|
||||
|
||||
if (methods?.length) {
|
||||
result += `
|
||||
## Methods
|
||||
|
||||
${createMethodsTable(methods)}
|
||||
|
||||
_Learn more about [calling methods](/getting-started/usage#methods)._
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -496,6 +537,8 @@
|
||||
result += `
|
||||
## CSS Custom Properties
|
||||
${createCustomPropertiesTable(component.cssProperties)}
|
||||
|
||||
_Learn more about [customizing CSS Custom Properties](/getting-started/customizing#custom-properties)._
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -503,6 +546,8 @@
|
||||
result += `
|
||||
## CSS Parts
|
||||
${createPartsTable(component.cssParts)}
|
||||
|
||||
_Learn more about [customizing CSS Parts](/getting-started/customizing#component-parts)._
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -511,7 +556,7 @@
|
||||
## Animations
|
||||
${createAnimationsTable(component.animations)}
|
||||
|
||||
Learn how to [customize animations](/getting-started/customizing#animations).
|
||||
_Learn more about [customizing animations](/getting-started/customizing#animations)._
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -519,7 +564,7 @@
|
||||
result += `
|
||||
## Dependencies
|
||||
|
||||
This component imports the following dependencies.
|
||||
This component automatically imports the following dependencies.
|
||||
|
||||
${createDependenciesList(component.tagName, getAllComponents(metadata))}
|
||||
`;
|
||||
|
||||
@@ -178,3 +178,15 @@ body.site-search-visible {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Forced colors mode */
|
||||
@media (forced-colors: active) {
|
||||
.site-search__panel {
|
||||
border: solid 1px var(--sl-color-neutral-0);
|
||||
}
|
||||
|
||||
.site-search__results li[aria-selected='true'] a {
|
||||
outline: dashed 1px SelectedItem;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,7 @@
|
||||
const searchBox = document.createElement('div');
|
||||
searchBox.classList.add('search-box');
|
||||
searchBox.innerHTML = `
|
||||
<sl-input
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
clearable
|
||||
pill
|
||||
>
|
||||
<sl-input type="search" placeholder="Search" pill>
|
||||
<sl-icon slot="prefix" name="search"></sl-icon>
|
||||
<kbd slot="suffix" title="Press / to search">/</kbd>
|
||||
</sl-input>
|
||||
@@ -52,12 +47,21 @@
|
||||
siteSearch.hidden = true;
|
||||
siteSearch.innerHTML = `
|
||||
<div class="site-search__overlay"></div>
|
||||
<div class="site-search__panel">
|
||||
<div
|
||||
id="site-search-panel"
|
||||
class="site-search__panel"
|
||||
role="combobox"
|
||||
aria-expanded="false"
|
||||
aria-owns="site-search-results"
|
||||
aria-activedescendant=""
|
||||
>
|
||||
<header class="site-search__header">
|
||||
<sl-input
|
||||
class="site-search__input"
|
||||
type="search"
|
||||
placeholder="Search this site"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="site-search-results"
|
||||
size="large"
|
||||
clearable
|
||||
>
|
||||
@@ -65,7 +69,13 @@
|
||||
</sl-input>
|
||||
</header>
|
||||
<div class="site-search__body">
|
||||
<ul class="site-search__results"></ul>
|
||||
<ul
|
||||
id="site-search-results"
|
||||
class="site-search__results"
|
||||
role="listbox"
|
||||
aria-labelledby="site-search-panel"
|
||||
>
|
||||
</ul>
|
||||
<div class="site-search__empty">No results found.</div>
|
||||
</div>
|
||||
<footer class="site-search__footer">
|
||||
@@ -100,7 +110,7 @@
|
||||
isShowing = true;
|
||||
document.body.classList.add('site-search-visible');
|
||||
siteSearch.hidden = false;
|
||||
input.focus();
|
||||
requestAnimationFrame(() => input.focus());
|
||||
updateResults();
|
||||
|
||||
await Promise.all([
|
||||
@@ -205,6 +215,9 @@
|
||||
// Update the selected item
|
||||
items.forEach(item => {
|
||||
if (item === nextEl) {
|
||||
const a = nextEl.querySelector('a');
|
||||
panel.setAttribute('aria-activedescendant', a.id);
|
||||
|
||||
item.setAttribute('aria-selected', 'true');
|
||||
nextEl.scrollIntoView({ block: 'nearest' });
|
||||
} else {
|
||||
@@ -219,7 +232,11 @@
|
||||
await searchIndex;
|
||||
|
||||
const hasQuery = query.length > 0;
|
||||
const matches = hasQuery ? searchIndex.search(`t:*${query}*^20 h:*${query}*^10 ${query}~1^5 *${query}*^0`) : [];
|
||||
const searchTokens = query
|
||||
.split(' ')
|
||||
.map((term, index, arr) => `${term}${index === arr.length - 1 ? `* ${term}~1` : '~1'}`)
|
||||
.join(' ');
|
||||
const matches = hasQuery ? searchIndex.search(`${query} ${searchTokens}`) : [];
|
||||
const hasResults = hasQuery && matches.length > 0;
|
||||
siteSearch.classList.toggle('site-search--has-results', hasQuery && hasResults);
|
||||
siteSearch.classList.toggle('site-search--no-results', hasQuery && !hasResults);
|
||||
@@ -233,6 +250,9 @@
|
||||
const a = document.createElement('a');
|
||||
let icon = 'file-text';
|
||||
|
||||
a.setAttribute('role', 'option');
|
||||
a.setAttribute('id', `search-result-item-${match.ref}`);
|
||||
|
||||
if (page.url.includes('getting-started/')) {
|
||||
icon = 'lightbulb';
|
||||
}
|
||||
@@ -275,9 +295,12 @@
|
||||
|
||||
// Show the search panel slash is pressed outside of a form element
|
||||
document.addEventListener('keydown', event => {
|
||||
const isSlash = event.key === '/';
|
||||
const isCtrlK = (event.metaKey || event.ctrlKey) && event.key === 'k';
|
||||
|
||||
if (
|
||||
!isShowing &&
|
||||
event.key === '/' &&
|
||||
(isSlash || isCtrlK) &&
|
||||
!event.composedPath().some(el => ['input', 'textarea'].includes(el?.tagName?.toLowerCase()))
|
||||
) {
|
||||
event.preventDefault();
|
||||
|
||||
@@ -47,10 +47,10 @@
|
||||
</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-menu-item type="checkbox" value="light">Light</sl-menu-item>
|
||||
<sl-menu-item type="checkbox" value="dark">Dark</sl-menu-item>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="auto">Auto</sl-menu-item>
|
||||
<sl-menu-item type="checkbox" value="auto">Auto</sl-menu-item>
|
||||
</sl-menu>
|
||||
`;
|
||||
document.querySelector('.sidebar-toggle').insertAdjacentElement('afterend', dropdown);
|
||||
|
||||
@@ -50,6 +50,8 @@ strong {
|
||||
}
|
||||
|
||||
.sidebar-buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -74,8 +76,8 @@ strong {
|
||||
}
|
||||
|
||||
.sidebar-toggle:focus {
|
||||
outline: none;
|
||||
box-shadow: var(--sl-focus-ring);
|
||||
outline: var(--sl-focus-ring);
|
||||
outline-offset: var(--sl-focus-ring-offset);
|
||||
}
|
||||
|
||||
.sidebar-toggle span:last-child {
|
||||
@@ -290,10 +292,6 @@ strong {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.markdown-section tr:nth-child(2n) code {
|
||||
background-color: var(--sl-color-neutral-100);
|
||||
}
|
||||
|
||||
kbd,
|
||||
.markdown-section kbd {
|
||||
font-family: var(--sl-font-mono);
|
||||
@@ -316,7 +314,7 @@ kbd,
|
||||
display: block;
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
color: var(--sl-color-neutral-800);
|
||||
color: var(--sl-color-neutral-900);
|
||||
padding: var(--sl-spacing-medium);
|
||||
overflow: auto;
|
||||
hyphens: none;
|
||||
@@ -331,11 +329,11 @@ kbd,
|
||||
.markdown-section pre .token.doctype,
|
||||
.markdown-section pre .token.cdata,
|
||||
.markdown-section pre .token.operator {
|
||||
color: var(--sl-color-neutral-600);
|
||||
color: var(--sl-color-neutral-700);
|
||||
}
|
||||
|
||||
.markdown-section pre .token.punctuation {
|
||||
color: var(--sl-color-neutral-600);
|
||||
color: var(--sl-color-neutral-700);
|
||||
}
|
||||
|
||||
.namespace {
|
||||
@@ -346,12 +344,12 @@ kbd,
|
||||
.markdown-section pre .token.keyword,
|
||||
.markdown-section pre .token.tag,
|
||||
.markdown-section pre .token.url {
|
||||
color: var(--sl-color-blue-600);
|
||||
color: var(--sl-color-sky-800);
|
||||
}
|
||||
|
||||
.markdown-section pre .token.symbol,
|
||||
.markdown-section pre .token.deleted {
|
||||
color: var(--sl-color-pink-600);
|
||||
color: var(--sl-color-pink-700);
|
||||
}
|
||||
|
||||
.markdown-section pre .token.boolean,
|
||||
@@ -362,7 +360,7 @@ kbd,
|
||||
.markdown-section pre .token.char,
|
||||
.markdown-section pre .token.builtin,
|
||||
.markdown-section pre .token.inserted {
|
||||
color: var(--sl-color-emerald-600);
|
||||
color: var(--sl-color-emerald-700);
|
||||
}
|
||||
|
||||
.markdown-section pre .token.atrule,
|
||||
@@ -375,11 +373,11 @@ kbd,
|
||||
.markdown-section pre .token.function,
|
||||
.markdown-section pre .token.class-name,
|
||||
.markdown-section pre .token.regex {
|
||||
color: var(--sl-color-orange-600);
|
||||
color: var(--sl-color-orange-700);
|
||||
}
|
||||
|
||||
.markdown-section pre .token.important {
|
||||
color: var(--sl-color-red-600);
|
||||
color: var(--sl-color-red-700);
|
||||
}
|
||||
|
||||
.markdown-section pre .token.important,
|
||||
@@ -412,7 +410,7 @@ kbd,
|
||||
}
|
||||
|
||||
.markdown-section tr:nth-child(2n) {
|
||||
background: var(--sl-color-neutral-50);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.markdown-section th {
|
||||
@@ -426,6 +424,7 @@ kbd,
|
||||
border-bottom: solid 1px var(--sl-color-neutral-200);
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
padding: 0.75rem 0.5rem;
|
||||
}
|
||||
|
||||
.markdown-section table .nowrap {
|
||||
@@ -437,6 +436,10 @@ kbd,
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.markdown-section .metadata-table {
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
|
||||
/* Iframes */
|
||||
.markdown-section iframe {
|
||||
border: none;
|
||||
@@ -487,14 +490,26 @@ kbd,
|
||||
.markdown-section p.tip code,
|
||||
.markdown-section p.warn code {
|
||||
background-color: var(--sl-color-neutral-100);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Sponsorship callouts */
|
||||
.sponsor-callout {
|
||||
background: var(--sl-color-warning-100);
|
||||
border-left: solid 3px var(--sl-color-warning-300);
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
padding: 0.5rem 1.5rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 950px) {
|
||||
.sponsor-callout__secondary-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Component headers */
|
||||
.component-header {
|
||||
border-bottom: solid 1px var(--sl-color-neutral-200);
|
||||
padding-bottom: 2rem;
|
||||
margin-top: -1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.component-header__tag {
|
||||
@@ -503,6 +518,13 @@ kbd,
|
||||
margin: 0.75rem 0 0.25rem 0;
|
||||
}
|
||||
|
||||
.component-header__summary {
|
||||
font-size: var(--sl-font-size-large);
|
||||
line-height: 1.6;
|
||||
border-top: solid 1px var(--sl-color-neutral-200);
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.markdown-section .component-header__tag code {
|
||||
background: none;
|
||||
color: var(--sl-color-neutral-600);
|
||||
@@ -515,12 +537,6 @@ kbd,
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
/* Lead sentences that occur immediately after the header */
|
||||
.component-header + p {
|
||||
font-size: var(--sl-font-size-large);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Repo buttons */
|
||||
.repo-button--sponsor sl-icon {
|
||||
color: var(--sl-color-pink-600);
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-alert]
|
||||
|
||||
Alerts are used to display important messages inline or as toast notifications.
|
||||
|
||||
```html preview
|
||||
<sl-alert open>
|
||||
<sl-icon slot="icon" name="info-circle"></sl-icon>
|
||||
@@ -33,40 +31,40 @@ Set the `variant` attribute to change the alert's variant.
|
||||
```html preview
|
||||
<sl-alert variant="primary" open>
|
||||
<sl-icon slot="icon" name="info-circle"></sl-icon>
|
||||
<strong>This is super informative</strong><br>
|
||||
<strong>This is super informative</strong><br />
|
||||
You can tell by how pretty the alert is.
|
||||
</sl-alert>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<sl-alert variant="success" open>
|
||||
<sl-icon slot="icon" name="check2-circle"></sl-icon>
|
||||
<strong>Your changes have been saved</strong><br>
|
||||
<strong>Your changes have been saved</strong><br />
|
||||
You can safely exit the app now.
|
||||
</sl-alert>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<sl-alert variant="neutral" open>
|
||||
<sl-icon slot="icon" name="gear"></sl-icon>
|
||||
<strong>Your settings have been updated</strong><br>
|
||||
<strong>Your settings have been updated</strong><br />
|
||||
Settings will take affect on next login.
|
||||
</sl-alert>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<sl-alert variant="warning" open>
|
||||
<sl-icon slot="icon" name="exclamation-triangle"></sl-icon>
|
||||
<strong>Your session has ended</strong><br>
|
||||
<strong>Your session has ended</strong><br />
|
||||
Please login again to continue.
|
||||
</sl-alert>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<sl-alert variant="danger" open>
|
||||
<sl-icon slot="icon" name="exclamation-octagon"></sl-icon>
|
||||
<strong>Your account has been deleted</strong><br>
|
||||
We're very sorry to see you go!
|
||||
<strong>Your account has been deleted</strong><br />
|
||||
We're very sorry to see you go!
|
||||
</sl-alert>
|
||||
```
|
||||
|
||||
@@ -77,7 +75,8 @@ const App = () => (
|
||||
<>
|
||||
<SlAlert variant="primary" open>
|
||||
<SlIcon slot="icon" name="info-circle" />
|
||||
<strong>This is super informative</strong><br />
|
||||
<strong>This is super informative</strong>
|
||||
<br />
|
||||
You can tell by how pretty the alert is.
|
||||
</SlAlert>
|
||||
|
||||
@@ -85,7 +84,8 @@ const App = () => (
|
||||
|
||||
<SlAlert variant="success" open>
|
||||
<SlIcon slot="icon" name="check2-circle" />
|
||||
<strong>Your changes have been saved</strong><br />
|
||||
<strong>Your changes have been saved</strong>
|
||||
<br />
|
||||
You can safely exit the app now.
|
||||
</SlAlert>
|
||||
|
||||
@@ -93,7 +93,8 @@ const App = () => (
|
||||
|
||||
<SlAlert variant="neutral" open>
|
||||
<SlIcon slot="icon" name="gear" />
|
||||
<strong>Your settings have been updated</strong><br />
|
||||
<strong>Your settings have been updated</strong>
|
||||
<br />
|
||||
Settings will take affect on next login.
|
||||
</SlAlert>
|
||||
|
||||
@@ -101,7 +102,8 @@ const App = () => (
|
||||
|
||||
<SlAlert variant="warning" open>
|
||||
<SlIcon slot="icon" name="exclamation-triangle" />
|
||||
<strong>Your session has ended</strong><br />
|
||||
<strong>Your session has ended</strong>
|
||||
<br />
|
||||
Please login again to continue.
|
||||
</SlAlert>
|
||||
|
||||
@@ -109,8 +111,9 @@ const App = () => (
|
||||
|
||||
<SlAlert variant="danger" open>
|
||||
<SlIcon slot="icon" name="exclamation-octagon" />
|
||||
<strong>Your account has been deleted</strong><br />
|
||||
We're very sorry to see you go!
|
||||
<strong>Your account has been deleted</strong>
|
||||
<br />
|
||||
We're very sorry to see you go!
|
||||
</SlAlert>
|
||||
</>
|
||||
);
|
||||
@@ -129,7 +132,7 @@ Add the `closable` attribute to show a close button that will hide the alert.
|
||||
<script>
|
||||
const alert = document.querySelector('.alert-closable');
|
||||
alert.addEventListener('sl-after-hide', () => {
|
||||
setTimeout(() => alert.open = true, 2000);
|
||||
setTimeout(() => (alert.open = true), 2000);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -147,11 +150,7 @@ const App = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<SlAlert
|
||||
open={open}
|
||||
closable
|
||||
onSlAfterHide={handleHide}
|
||||
>
|
||||
<SlAlert open={open} closable onSlAfterHide={handleHide}>
|
||||
<SlIcon slot="icon" name="info-circle" />
|
||||
You can close this alert any time!
|
||||
</SlAlert>
|
||||
@@ -164,9 +163,7 @@ const App = () => {
|
||||
Icons are optional. Simply omit the `icon` slot if you don't want them.
|
||||
|
||||
```html preview
|
||||
<sl-alert variant="primary" open>
|
||||
Nothing fancy here, just a simple alert.
|
||||
</sl-alert>
|
||||
<sl-alert variant="primary" open> Nothing fancy here, just a simple alert. </sl-alert>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
@@ -210,11 +207,7 @@ Set the `duration` attribute to automatically hide an alert after a period of ti
|
||||
|
||||
```jsx react
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
SlAlert,
|
||||
SlButton,
|
||||
SlIcon
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlAlert, SlButton, SlIcon } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const css = `
|
||||
.alert-duration sl-alert {
|
||||
@@ -228,15 +221,11 @@ const App = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="alert-duration">
|
||||
<SlButton variant="primary" onClick={() => setOpen(true)}>Show Alert</SlButton>
|
||||
<SlButton variant="primary" onClick={() => setOpen(true)}>
|
||||
Show Alert
|
||||
</SlButton>
|
||||
|
||||
<SlAlert
|
||||
variant="primary"
|
||||
duration="3000"
|
||||
open={open}
|
||||
closable
|
||||
onSlAfterHide={() => setOpen(false)}
|
||||
>
|
||||
<SlAlert variant="primary" duration="3000" open={open} closable onSlAfterHide={() => setOpen(false)}>
|
||||
<SlIcon slot="icon" name="info-circle" />
|
||||
This alert will automatically hide itself after three seconds, unless you interact with it.
|
||||
</SlAlert>
|
||||
@@ -261,34 +250,34 @@ You should always use the `closable` attribute so users can dismiss the notifica
|
||||
<sl-button variant="neutral">Neutral</sl-button>
|
||||
<sl-button variant="warning">Warning</sl-button>
|
||||
<sl-button variant="danger">Danger</sl-button>
|
||||
|
||||
|
||||
<sl-alert variant="primary" duration="3000" closable>
|
||||
<sl-icon slot="icon" name="info-circle"></sl-icon>
|
||||
<strong>This is super informative</strong><br>
|
||||
<strong>This is super informative</strong><br />
|
||||
You can tell by how pretty the alert is.
|
||||
</sl-alert>
|
||||
|
||||
<sl-alert variant="success" duration="3000" closable>
|
||||
<sl-icon slot="icon" name="check2-circle"></sl-icon>
|
||||
<strong>Your changes have been saved</strong><br>
|
||||
<strong>Your changes have been saved</strong><br />
|
||||
You can safely exit the app now.
|
||||
</sl-alert>
|
||||
|
||||
<sl-alert variant="neutral" duration="3000" closable>
|
||||
<sl-icon slot="icon" name="gear"></sl-icon>
|
||||
<strong>Your settings have been updated</strong><br>
|
||||
<strong>Your settings have been updated</strong><br />
|
||||
Settings will take affect on next login.
|
||||
</sl-alert>
|
||||
|
||||
<sl-alert variant="warning" duration="3000" closable>
|
||||
<sl-icon slot="icon" name="exclamation-triangle"></sl-icon>
|
||||
<strong>Your session has ended</strong><br>
|
||||
<strong>Your session has ended</strong><br />
|
||||
Please login again to continue.
|
||||
</sl-alert>
|
||||
|
||||
<sl-alert variant="danger" duration="3000" closable>
|
||||
<sl-icon slot="icon" name="exclamation-octagon"></sl-icon>
|
||||
<strong>Your account has been deleted</strong><br>
|
||||
<strong>Your account has been deleted</strong><br />
|
||||
We're very sorry to see you go!
|
||||
</sl-alert>
|
||||
</div>
|
||||
@@ -307,11 +296,7 @@ You should always use the `closable` attribute so users can dismiss the notifica
|
||||
|
||||
```jsx react
|
||||
import { useRef } from 'react';
|
||||
import {
|
||||
SlAlert,
|
||||
SlButton,
|
||||
SlIcon
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlAlert, SlButton, SlIcon } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
function showToast(alert) {
|
||||
alert.toast();
|
||||
@@ -348,31 +333,36 @@ const App = () => {
|
||||
|
||||
<SlAlert ref={primary} variant="primary" duration="3000" closable>
|
||||
<SlIcon slot="icon" name="info-circle" />
|
||||
<strong>This is super informative</strong><br />
|
||||
<strong>This is super informative</strong>
|
||||
<br />
|
||||
You can tell by how pretty the alert is.
|
||||
</SlAlert>
|
||||
|
||||
<SlAlert ref={success} variant="success" duration="3000" closable>
|
||||
<SlIcon slot="icon" name="check2-circle" />
|
||||
<strong>Your changes have been saved</strong><br />
|
||||
<strong>Your changes have been saved</strong>
|
||||
<br />
|
||||
You can safely exit the app now.
|
||||
</SlAlert>
|
||||
|
||||
<SlAlert ref={neutral} variant="neutral" duration="3000" closable>
|
||||
<SlIcon slot="icon" name="gear" />
|
||||
<strong>Your settings have been updated</strong><br />
|
||||
<strong>Your settings have been updated</strong>
|
||||
<br />
|
||||
Settings will take affect on next login.
|
||||
</SlAlert>
|
||||
|
||||
<SlAlert ref={warning} variant="warning" duration="3000" closable>
|
||||
<SlIcon slot="icon" name="exclamation-triangle" />
|
||||
<strong>Your session has ended</strong><br />
|
||||
<strong>Your session has ended</strong>
|
||||
<br />
|
||||
Please login again to continue.
|
||||
</SlAlert>
|
||||
|
||||
<SlAlert ref={danger} variant="danger" duration="3000" closable>
|
||||
<SlIcon slot="icon" name="exclamation-octagon" />
|
||||
<strong>Your account has been deleted</strong><br />
|
||||
<strong>Your account has been deleted</strong>
|
||||
<br />
|
||||
We're very sorry to see you go!
|
||||
</SlAlert>
|
||||
</>
|
||||
@@ -399,7 +389,7 @@ For convenience, you can create a utility that emits toast notifications with a
|
||||
const div = document.createElement('div');
|
||||
div.textContent = html;
|
||||
return div.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
// Custom function to emit toast notifications
|
||||
function notify(message, variant = 'primary', icon = 'info-circle', duration = 3000) {
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
|
||||
[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="https://shoelace.style/assets/images/walk.gif"
|
||||
<sl-animated-image
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
alt="Animation of untied shoes walking on pavement"
|
||||
></sl-animated-image>
|
||||
```
|
||||
@@ -16,7 +14,7 @@ import { SlAnimatedImage } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlAnimatedImage
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
alt="Animation of untied shoes walking on pavement"
|
||||
/>
|
||||
);
|
||||
@@ -31,8 +29,8 @@ const App = () => (
|
||||
Both GIF and WEBP images are supported.
|
||||
|
||||
```html preview
|
||||
<sl-animated-image
|
||||
src="https://shoelace.style/assets/images/tie.webp"
|
||||
<sl-animated-image
|
||||
src="https://shoelace.style/assets/images/tie.webp"
|
||||
alt="Animation of a shoe being tied"
|
||||
></sl-animated-image>
|
||||
```
|
||||
@@ -41,10 +39,7 @@ Both GIF and WEBP images are supported.
|
||||
import { SlAnimatedImage } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlAnimatedImage
|
||||
src="https://shoelace.style/assets/images/tie.webp"
|
||||
alt="Animation of a shoe being tied"
|
||||
/>
|
||||
<SlAnimatedImage src="https://shoelace.style/assets/images/tie.webp" alt="Animation of a shoe being tied" />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -53,8 +48,8 @@ const App = () => (
|
||||
To set a custom size, apply a width and/or height to the host element.
|
||||
|
||||
```html preview
|
||||
<sl-animated-image
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
<sl-animated-image
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
alt="Animation of untied shoes walking on pavement"
|
||||
style="width: 150px; height: 200px;"
|
||||
>
|
||||
@@ -66,7 +61,7 @@ import { SlAnimatedImage } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlAnimatedImage
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
alt="Animation of untied shoes walking on pavement"
|
||||
style={{ width: '150px', height: '200px' }}
|
||||
/>
|
||||
@@ -78,8 +73,8 @@ const App = () => (
|
||||
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="https://shoelace.style/assets/images/walk.gif"
|
||||
<sl-animated-image
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
alt="Animation of untied shoes walking on pavement"
|
||||
class="animated-image-custom-control-box"
|
||||
></sl-animated-image>
|
||||
@@ -116,7 +111,7 @@ const App = () => (
|
||||
<>
|
||||
<SlAnimatedImage
|
||||
className="animated-image-custom-control-box"
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
src="https://shoelace.style/assets/images/walk.gif"
|
||||
alt="Animation of untied shoes walking on pavement"
|
||||
/>
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-animation]
|
||||
|
||||
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 an animation `name`. The animation will not start until you add the `play` attribute. Refer to the [properties table](#properties) for a list of all animation options.
|
||||
|
||||
```html preview
|
||||
@@ -41,13 +39,21 @@ const css = `
|
||||
const App = () => (
|
||||
<>
|
||||
<div class="animation-overview">
|
||||
<SlAnimation name="bounce" duration={2000} play><div class="box" /></SlAnimation>
|
||||
<SlAnimation name="jello" duration={2000} play><div class="box" /></SlAnimation>
|
||||
<SlAnimation name="heartBeat" duration={2000} play><div class="box" /></SlAnimation>
|
||||
<SlAnimation name="flip" duration={2000} play><div class="box" /></SlAnimation>
|
||||
<SlAnimation name="bounce" duration={2000} play>
|
||||
<div class="box" />
|
||||
</SlAnimation>
|
||||
<SlAnimation name="jello" duration={2000} play>
|
||||
<div class="box" />
|
||||
</SlAnimation>
|
||||
<SlAnimation name="heartBeat" duration={2000} play>
|
||||
<div class="box" />
|
||||
</SlAnimation>
|
||||
<SlAnimation name="flip" duration={2000} play>
|
||||
<div class="box" />
|
||||
</SlAnimation>
|
||||
</div>
|
||||
|
||||
<style>{css}</style>
|
||||
<style>{css}</style>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -85,24 +91,24 @@ This example demonstrates all of the baked-in animations and easings. Animations
|
||||
const easings = getEasingNames();
|
||||
|
||||
animations.map(name => {
|
||||
const menuItem = Object.assign(document.createElement('sl-menu-item'), {
|
||||
const option = Object.assign(document.createElement('sl-option'), {
|
||||
textContent: name,
|
||||
value: name
|
||||
});
|
||||
animationName.appendChild(menuItem);
|
||||
});
|
||||
|
||||
easings.map(name => {
|
||||
const menuItem = Object.assign(document.createElement('sl-menu-item'), {
|
||||
textContent: name,
|
||||
value: name
|
||||
});
|
||||
easingName.appendChild(menuItem);
|
||||
animationName.appendChild(option);
|
||||
});
|
||||
|
||||
animationName.addEventListener('sl-change', () => animation.name = animationName.value);
|
||||
easingName.addEventListener('sl-change', () => animation.easing = easingName.value);
|
||||
playbackRate.addEventListener('sl-input', () => animation.playbackRate = playbackRate.value);
|
||||
easings.map(name => {
|
||||
const option = Object.assign(document.createElement('sl-option'), {
|
||||
textContent: name,
|
||||
value: name
|
||||
});
|
||||
easingName.appendChild(option);
|
||||
});
|
||||
|
||||
animationName.addEventListener('sl-change', () => (animation.name = animationName.value));
|
||||
easingName.addEventListener('sl-change', () => (animation.easing = easingName.value));
|
||||
playbackRate.addEventListener('sl-input', () => (animation.playbackRate = playbackRate.value));
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -156,7 +162,7 @@ Use an [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: var(--sl-color-primary-600);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@@ -182,16 +188,14 @@ const App = () => {
|
||||
const box = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (entries[0].isIntersecting) {
|
||||
animation.current.play = true;
|
||||
} else {
|
||||
animation.current.play = false;
|
||||
animation.current.currentTime = 0;
|
||||
}
|
||||
const observer = new IntersectionObserver(entries => {
|
||||
if (entries[0].isIntersecting) {
|
||||
animation.current.play = true;
|
||||
} else {
|
||||
animation.current.play = false;
|
||||
animation.current.currentTime = 0;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
if (box.current) {
|
||||
observer.observe(box.current);
|
||||
@@ -201,17 +205,12 @@ const App = () => {
|
||||
return (
|
||||
<>
|
||||
<div class="animation-scroll">
|
||||
<SlAnimation
|
||||
ref={animation}
|
||||
name="jackInTheBox"
|
||||
duration={2000}
|
||||
iterations={1}
|
||||
>
|
||||
<SlAnimation ref={animation} name="jackInTheBox" duration={2000} iterations={1}>
|
||||
<div ref={box} class="box" />
|
||||
</SlAnimation>
|
||||
</div>
|
||||
|
||||
<style>{css}</style>
|
||||
<style>{css}</style>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -271,9 +270,9 @@ const css = `
|
||||
const App = () => (
|
||||
<>
|
||||
<div class="animation-keyframes">
|
||||
<SlAnimation
|
||||
easing="ease-in-out"
|
||||
duration={2000}
|
||||
<SlAnimation
|
||||
easing="ease-in-out"
|
||||
duration={2000}
|
||||
play
|
||||
keyframes={[
|
||||
{
|
||||
@@ -296,7 +295,7 @@ const App = () => (
|
||||
</SlAnimation>
|
||||
</div>
|
||||
|
||||
<style>{css}</style>
|
||||
<style>{css}</style>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -332,13 +331,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<div class="animation-form">
|
||||
<SlAnimation
|
||||
name="rubberBand"
|
||||
duration={1000}
|
||||
iterations={1}
|
||||
play={play}
|
||||
onSlFinish={() => setPlay(false)}
|
||||
>
|
||||
<SlAnimation name="rubberBand" duration={1000} iterations={1} play={play} onSlFinish={() => setPlay(false)}>
|
||||
<SlButton variant="primary" onClick={() => setPlay(true)}>
|
||||
Click me
|
||||
</SlButton>
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
[component-header:sl-avatar]
|
||||
|
||||
Avatars are used to represent a person or object.
|
||||
|
||||
Like [images](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img), you should always provide `alt` text for avatars as alternate text for assistive devices.
|
||||
By default, a generic icon will be shown. You can personalize avatars by adding custom icons, initials, and images. You should always provide a `label` for assistive devices.
|
||||
|
||||
```html preview
|
||||
<sl-avatar label="User avatar"></sl-avatar>
|
||||
@@ -13,22 +11,26 @@ Like [images](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img), yo
|
||||
```jsx react
|
||||
import { SlAvatar } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlAvatar label="User avatar" />
|
||||
);
|
||||
const App = () => <SlAvatar label="User avatar" />;
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Images
|
||||
|
||||
To use an image for the avatar, set the `image` and `alt` attributes. This will take priority and be shown over initials and icons.
|
||||
To use an image for the avatar, set the `image` and `label` attributes. This will take priority and be shown over initials and icons.
|
||||
Avatar images can be lazily loaded by setting the `loading` attribute to `lazy`.
|
||||
|
||||
```html preview
|
||||
<sl-avatar
|
||||
image="https://images.unsplash.com/photo-1529778873920-4da4926a72c2?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"
|
||||
label="Avatar of a gray tabby kitten looking down"
|
||||
></sl-avatar>
|
||||
<sl-avatar
|
||||
image="https://images.unsplash.com/photo-1591871937573-74dbba515c4c?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"
|
||||
label="Avatar of a white and grey kitten on grey textile"
|
||||
loading="lazy"
|
||||
></sl-avatar>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
@@ -39,6 +41,11 @@ const App = () => (
|
||||
image="https://images.unsplash.com/photo-1529778873920-4da4926a72c2?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"
|
||||
label="Avatar of a gray tabby kitten looking down"
|
||||
/>
|
||||
<SlAvatar
|
||||
image="https://images.unsplash.com/photo-1591871937573-74dbba515c4c?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"
|
||||
label="Avatar of a white and grey kitten on grey textile"
|
||||
loading="lazy"
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -53,9 +60,7 @@ When you don't have an image to use, you can set the `initials` attribute to sho
|
||||
```jsx react
|
||||
import { SlAvatar } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlAvatar initials="SL" label="Avatar with initials: SL" />
|
||||
);
|
||||
const App = () => <SlAvatar initials="SL" label="Avatar with initials: SL" />;
|
||||
```
|
||||
|
||||
### Custom Icons
|
||||
@@ -124,22 +129,22 @@ You can group avatars with a few lines of CSS.
|
||||
|
||||
```html preview
|
||||
<div class="avatar-group">
|
||||
<sl-avatar
|
||||
<sl-avatar
|
||||
image="https://images.unsplash.com/photo-1490150028299-bf57d78394e0?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&q=80&crop=right"
|
||||
label="Avatar 1 of 4"
|
||||
></sl-avatar>
|
||||
|
||||
<sl-avatar
|
||||
<sl-avatar
|
||||
image="https://images.unsplash.com/photo-1503454537195-1dcabb73ffb9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&crop=left&q=80"
|
||||
label="Avatar 2 of 4"
|
||||
></sl-avatar>
|
||||
|
||||
<sl-avatar
|
||||
<sl-avatar
|
||||
image="https://images.unsplash.com/photo-1456439663599-95b042d50252?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&crop=left&q=80"
|
||||
label="Avatar 3 of 4"
|
||||
></sl-avatar>
|
||||
|
||||
<sl-avatar
|
||||
<sl-avatar
|
||||
image="https://images.unsplash.com/flagged/photo-1554078875-e37cb8b0e27d?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&crop=top&q=80"
|
||||
label="Avatar 4 of 4"
|
||||
></sl-avatar>
|
||||
@@ -172,28 +177,28 @@ const css = `
|
||||
const App = () => (
|
||||
<>
|
||||
<div className="avatar-group">
|
||||
<SlAvatar
|
||||
image="https://images.unsplash.com/photo-1490150028299-bf57d78394e0?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&q=80&crop=right"
|
||||
label="Avatar 1 of 4"
|
||||
<SlAvatar
|
||||
image="https://images.unsplash.com/photo-1490150028299-bf57d78394e0?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&q=80&crop=right"
|
||||
label="Avatar 1 of 4"
|
||||
/>
|
||||
|
||||
<SlAvatar
|
||||
image="https://images.unsplash.com/photo-1503454537195-1dcabb73ffb9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&crop=left&q=80"
|
||||
label="Avatar 2 of 4"
|
||||
<SlAvatar
|
||||
image="https://images.unsplash.com/photo-1503454537195-1dcabb73ffb9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&crop=left&q=80"
|
||||
label="Avatar 2 of 4"
|
||||
/>
|
||||
|
||||
<SlAvatar
|
||||
image="https://images.unsplash.com/photo-1456439663599-95b042d50252?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&crop=left&q=80"
|
||||
label="Avatar 3 of 4"
|
||||
|
||||
<SlAvatar
|
||||
image="https://images.unsplash.com/photo-1456439663599-95b042d50252?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&crop=left&q=80"
|
||||
label="Avatar 3 of 4"
|
||||
/>
|
||||
|
||||
<SlAvatar
|
||||
image="https://images.unsplash.com/flagged/photo-1554078875-e37cb8b0e27d?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&crop=top&q=80"
|
||||
label="Avatar 4 of 4"
|
||||
|
||||
<SlAvatar
|
||||
image="https://images.unsplash.com/flagged/photo-1554078875-e37cb8b0e27d?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=256&h=256&crop=top&q=80"
|
||||
label="Avatar 4 of 4"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style>{css}</style>
|
||||
<style>{css}</style>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-badge]
|
||||
|
||||
Badges are used to draw attention and display statuses or counts.
|
||||
|
||||
```html preview
|
||||
<sl-badge>Badge</sl-badge>
|
||||
```
|
||||
@@ -11,9 +9,7 @@ Badges are used to draw attention and display statuses or counts.
|
||||
```jsx react
|
||||
import { SlBadge } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlBadge>Badge</SlBadge>
|
||||
);
|
||||
const App = () => <SlBadge>Badge</SlBadge>;
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -39,7 +35,7 @@ const App = () => (
|
||||
<SlBadge variant="success">Success</SlBadge>
|
||||
<SlBadge variant="neutral">Neutral</SlBadge>
|
||||
<SlBadge variant="warning">Warning</SlBadge>
|
||||
<SlBadge variant="danger">Danger</SlBadge>
|
||||
<SlBadge variant="danger">Danger</SlBadge>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -61,11 +57,21 @@ import { SlBadge } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlBadge variant="primary" pill>Primary</SlBadge>
|
||||
<SlBadge variant="success" pill>Success</SlBadge>
|
||||
<SlBadge variant="neutral" pill>Neutral</SlBadge>
|
||||
<SlBadge variant="warning" pill>Warning</SlBadge>
|
||||
<SlBadge variant="danger" pill>Danger</SlBadge>
|
||||
<SlBadge variant="primary" pill>
|
||||
Primary
|
||||
</SlBadge>
|
||||
<SlBadge variant="success" pill>
|
||||
Success
|
||||
</SlBadge>
|
||||
<SlBadge variant="neutral" pill>
|
||||
Neutral
|
||||
</SlBadge>
|
||||
<SlBadge variant="warning" pill>
|
||||
Warning
|
||||
</SlBadge>
|
||||
<SlBadge variant="danger" pill>
|
||||
Danger
|
||||
</SlBadge>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -102,11 +108,21 @@ const css = `
|
||||
const App = () => (
|
||||
<>
|
||||
<div className="badge-pulse">
|
||||
<SlBadge variant="primary" pill pulse>1</SlBadge>
|
||||
<SlBadge variant="success" pill pulse>1</SlBadge>
|
||||
<SlBadge variant="neutral" pill pulse>1</SlBadge>
|
||||
<SlBadge variant="warning" pill pulse>1</SlBadge>
|
||||
<SlBadge variant="danger" pill pulse>1</SlBadge>
|
||||
<SlBadge variant="primary" pill pulse>
|
||||
1
|
||||
</SlBadge>
|
||||
<SlBadge variant="success" pill pulse>
|
||||
1
|
||||
</SlBadge>
|
||||
<SlBadge variant="neutral" pill pulse>
|
||||
1
|
||||
</SlBadge>
|
||||
<SlBadge variant="warning" pill pulse>
|
||||
1
|
||||
</SlBadge>
|
||||
<SlBadge variant="danger" pill pulse>
|
||||
1
|
||||
</SlBadge>
|
||||
</div>
|
||||
|
||||
<style>{css}</style>
|
||||
@@ -124,12 +140,12 @@ One of the most common use cases for badges is attaching them to buttons. To mak
|
||||
<sl-badge pill>30</sl-badge>
|
||||
</sl-button>
|
||||
|
||||
<sl-button style="margin-left: 1rem;">
|
||||
<sl-button style="margin-inline-start: 1rem;">
|
||||
Warnings
|
||||
<sl-badge variant="warning" pill>8</sl-badge>
|
||||
</sl-button>
|
||||
|
||||
<sl-button style="margin-left: 1rem;">
|
||||
<sl-button style="margin-inline-start: 1rem;">
|
||||
Errors
|
||||
<sl-badge variant="danger" pill>6</sl-badge>
|
||||
</sl-button>
|
||||
@@ -145,14 +161,18 @@ const App = () => (
|
||||
<SlBadge pill>30</SlBadge>
|
||||
</SlButton>
|
||||
|
||||
<SlButton style={{ marginLeft: '1rem' }}>
|
||||
<SlButton style={{ marginInlineStart: '1rem' }}>
|
||||
Warnings
|
||||
<SlBadge variant="warning" pill>8</SlBadge>
|
||||
<SlBadge variant="warning" pill>
|
||||
8
|
||||
</SlBadge>
|
||||
</SlButton>
|
||||
|
||||
<SlButton style={{ marginLeft: '1rem' }}>
|
||||
<SlButton style={{ marginInlineStart: '1rem' }}>
|
||||
Errors
|
||||
<SlBadge variant="danger" pill>6</SlBadge>
|
||||
<SlBadge variant="danger" pill>
|
||||
6
|
||||
</SlBadge>
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
@@ -163,7 +183,7 @@ const App = () => (
|
||||
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;">
|
||||
<sl-menu-label>Messages</sl-menu-label>
|
||||
<sl-menu-item>Comments <sl-badge slot="suffix" variant="neutral" pill>4</sl-badge></sl-menu-item>
|
||||
<sl-menu-item>Replies <sl-badge slot="suffix" variant="neutral" pill>12</sl-badge></sl-menu-item>
|
||||
@@ -174,7 +194,7 @@ When including badges in menu items, use the `suffix` slot to make sure they're
|
||||
import { SlBadge, SlButton, SlMenu, SlMenuItem, SlMenuLabel } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlMenu
|
||||
<SlMenu
|
||||
style={{
|
||||
maxWidth: '240px',
|
||||
border: 'solid 1px var(--sl-panel-border-color)',
|
||||
@@ -182,8 +202,18 @@ const App = () => (
|
||||
}}
|
||||
>
|
||||
<SlMenuLabel>Messages</SlMenuLabel>
|
||||
<SlMenuItem>Comments <SlBadge slot="suffix" variant="neutral" pill>4</SlBadge></SlMenuItem>
|
||||
<SlMenuItem>Replies <SlBadge slot="suffix" variant="neutral" pill>12</SlBadge></SlMenuItem>
|
||||
<SlMenuItem>
|
||||
Comments
|
||||
<SlBadge slot="suffix" variant="neutral" pill>
|
||||
4
|
||||
</SlBadge>
|
||||
</SlMenuItem>
|
||||
<SlMenuItem>
|
||||
Replies
|
||||
<SlBadge slot="suffix" variant="neutral" pill>
|
||||
12
|
||||
</SlBadge>
|
||||
</SlMenuItem>
|
||||
</SlMenu>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-breadcrumb-item]
|
||||
|
||||
Breadcrumb Items are used inside [breadcrumbs](/components/breadcrumb) to represent different links.
|
||||
|
||||
```html preview
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb-item>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[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
|
||||
@@ -38,21 +36,13 @@ For websites, you'll probably want to use links instead. You can make any breadc
|
||||
|
||||
```html preview
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb-item href="https://example.com/home">
|
||||
Homepage
|
||||
</sl-breadcrumb-item>
|
||||
<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">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">Digital Media</sl-breadcrumb-item>
|
||||
|
||||
<sl-breadcrumb-item href="https://example.com/home/services/digital/web-design">
|
||||
Web Design
|
||||
</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item href="https://example.com/home/services/digital/web-design">Web Design</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
@@ -61,21 +51,13 @@ import { SlBreadcrumb, SlBreadcrumbItem } from '@shoelace-style/shoelace/dist/re
|
||||
|
||||
const App = () => (
|
||||
<SlBreadcrumb>
|
||||
<SlBreadcrumbItem href="https://example.com/home">
|
||||
Homepage
|
||||
</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem href="https://example.com/home">Homepage</SlBreadcrumbItem>
|
||||
|
||||
<SlBreadcrumbItem href="https://example.com/home/services">
|
||||
Our Services
|
||||
</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem href="https://example.com/home/services">Our Services</SlBreadcrumbItem>
|
||||
|
||||
<SlBreadcrumbItem href="https://example.com/home/services/digital">
|
||||
Digital Media
|
||||
</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem href="https://example.com/home/services/digital">Digital Media</SlBreadcrumbItem>
|
||||
|
||||
<SlBreadcrumbItem href="https://example.com/home/services/digital/web-design">
|
||||
Web Design
|
||||
</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem href="https://example.com/home/services/digital/web-design">Web Design</SlBreadcrumbItem>
|
||||
</SlBreadcrumb>
|
||||
);
|
||||
```
|
||||
@@ -89,25 +71,25 @@ Use the `separator` slot to change the separator that goes between breadcrumb it
|
||||
<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-item>Third</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
|
||||
<br>
|
||||
<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-item>Third</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
|
||||
<br>
|
||||
<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-item>Third</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
@@ -121,7 +103,7 @@ const App = () => (
|
||||
<sl-icon name="dot" slot="separator" />
|
||||
<SlBreadcrumbItem>First</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Second</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Third</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Third</SlBreadcrumbItem>
|
||||
</SlBreadcrumb>
|
||||
|
||||
<br />
|
||||
@@ -130,7 +112,7 @@ const App = () => (
|
||||
<sl-icon name="arrow-right" slot="separator" />
|
||||
<SlBreadcrumbItem>First</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Second</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Third</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Third</SlBreadcrumbItem>
|
||||
</SlBreadcrumb>
|
||||
|
||||
<br />
|
||||
@@ -139,7 +121,7 @@ const App = () => (
|
||||
<span slot="separator">/</span>
|
||||
<SlBreadcrumbItem>First</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Second</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Third</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Third</SlBreadcrumbItem>
|
||||
</SlBreadcrumb>
|
||||
</>
|
||||
);
|
||||
@@ -221,19 +203,19 @@ Dropdown menus can be placed in a prefix or suffix slot to provide additional op
|
||||
<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-item type="checkbox" checked>Web Design</sl-menu-item>
|
||||
<sl-menu-item type="checkbox">Web Development</sl-menu-item>
|
||||
<sl-menu-item type="checkbox">Marketing</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
</sl-dropdown>
|
||||
</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlBreadcrumb,
|
||||
SlBreadcrumbItem,
|
||||
import {
|
||||
SlBreadcrumb,
|
||||
SlBreadcrumbItem,
|
||||
SlButton,
|
||||
SlDropdown,
|
||||
SlIcon,
|
||||
@@ -253,11 +235,13 @@ const App = () => (
|
||||
<SlIcon label="More options" name="three-dots"></SlIcon>
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem checked>Web Design</SlMenuItem>
|
||||
<SlMenuItem>Web Development</SlMenuItem>
|
||||
<SlMenuItem>Marketing</SlMenuItem>
|
||||
<SlMenuItem type="checkbox" checked>
|
||||
Web Design
|
||||
</SlMenuItem>
|
||||
<SlMenuItem type="checkbox">Web Development</SlMenuItem>
|
||||
<SlMenuItem type="checkbox">Marketing</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlDropdown>
|
||||
</SlDropdown>
|
||||
</SlBreadcrumbItem>
|
||||
</SlBreadcrumb>
|
||||
);
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
[component-header:sl-button-group]
|
||||
|
||||
Button groups can be used to group related buttons into sections.
|
||||
|
||||
```html preview
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button>Left</sl-button>
|
||||
<sl-button>Center</sl-button>
|
||||
<sl-button>Right</sl-button>
|
||||
@@ -16,7 +14,7 @@ Button groups can be used to group related buttons into sections.
|
||||
import { SlButton, SlButtonGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton>Left</SlButton>
|
||||
<SlButton>Center</SlButton>
|
||||
<SlButton>Right</SlButton>
|
||||
@@ -31,23 +29,23 @@ const App = () => (
|
||||
All button sizes are supported, but avoid mixing sizes within the same button group.
|
||||
|
||||
```html preview
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button size="small">Left</sl-button>
|
||||
<sl-button size="small">Center</sl-button>
|
||||
<sl-button size="small">Right</sl-button>
|
||||
</sl-button-group>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button size="medium">Left</sl-button>
|
||||
<sl-button size="medium">Center</sl-button>
|
||||
<sl-button size="medium">Right</sl-button>
|
||||
</sl-button-group>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button size="large">Left</sl-button>
|
||||
<sl-button size="large">Center</sl-button>
|
||||
<sl-button size="large">Right</sl-button>
|
||||
@@ -59,23 +57,25 @@ import { SlButton, SlButtonGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton size="small">Left</SlButton>
|
||||
<SlButton size="small">Center</SlButton>
|
||||
<SlButton size="small">Right</SlButton>
|
||||
</SlButtonGroup>
|
||||
|
||||
<br /><br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton size="medium">Left</SlButton>
|
||||
<SlButton size="medium">Center</SlButton>
|
||||
<SlButton size="medium">Right</SlButton>
|
||||
</SlButtonGroup>
|
||||
|
||||
<br /><br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton size="large">Left</SlButton>
|
||||
<SlButton size="large">Center</SlButton>
|
||||
<SlButton size="large">Right</SlButton>
|
||||
@@ -86,42 +86,42 @@ const App = () => (
|
||||
|
||||
### Theme Buttons
|
||||
|
||||
Theme buttons are supported through the button's `type` attribute.
|
||||
Theme buttons are supported through the button's `variant` attribute.
|
||||
|
||||
```html preview
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button variant="primary">Left</sl-button>
|
||||
<sl-button variant="primary">Center</sl-button>
|
||||
<sl-button variant="primary">Right</sl-button>
|
||||
</sl-button-group>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button variant="success">Left</sl-button>
|
||||
<sl-button variant="success">Center</sl-button>
|
||||
<sl-button variant="success">Right</sl-button>
|
||||
</sl-button-group>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button variant="neutral">Left</sl-button>
|
||||
<sl-button variant="neutral">Center</sl-button>
|
||||
<sl-button variant="neutral">Right</sl-button>
|
||||
</sl-button-group>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button variant="warning">Left</sl-button>
|
||||
<sl-button variant="warning">Center</sl-button>
|
||||
<sl-button variant="warning">Right</sl-button>
|
||||
</sl-button-group>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button variant="danger">Left</sl-button>
|
||||
<sl-button variant="danger">Center</sl-button>
|
||||
<sl-button variant="danger">Right</sl-button>
|
||||
@@ -133,39 +133,43 @@ import { SlButton, SlButtonGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton variant="primary">Left</SlButton>
|
||||
<SlButton variant="primary">Center</SlButton>
|
||||
<SlButton variant="primary">Right</SlButton>
|
||||
</SlButtonGroup>
|
||||
|
||||
<br /><br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton variant="success">Left</SlButton>
|
||||
<SlButton variant="success">Center</SlButton>
|
||||
<SlButton variant="success">Right</SlButton>
|
||||
</SlButtonGroup>
|
||||
|
||||
<br /><br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton variant="neutral">Left</SlButton>
|
||||
<SlButton variant="neutral">Center</SlButton>
|
||||
<SlButton variant="neutral">Right</SlButton>
|
||||
</SlButtonGroup>
|
||||
|
||||
<br /><br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton variant="warning">Left</SlButton>
|
||||
<SlButton variant="warning">Center</SlButton>
|
||||
<SlButton variant="warning">Right</SlButton>
|
||||
</SlButtonGroup>
|
||||
|
||||
<br /><br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton variant="danger">Left</SlButton>
|
||||
<SlButton variant="danger">Center</SlButton>
|
||||
<SlButton variant="danger">Right</SlButton>
|
||||
@@ -179,23 +183,23 @@ const App = () => (
|
||||
Pill buttons are supported through the button's `pill` attribute.
|
||||
|
||||
```html preview
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button size="small" pill>Left</sl-button>
|
||||
<sl-button size="small" pill>Center</sl-button>
|
||||
<sl-button size="small" pill>Right</sl-button>
|
||||
</sl-button-group>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button size="medium" pill>Left</sl-button>
|
||||
<sl-button size="medium" pill>Center</sl-button>
|
||||
<sl-button size="medium" pill>Right</sl-button>
|
||||
</sl-button-group>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-button size="large" pill>Left</sl-button>
|
||||
<sl-button size="large" pill>Center</sl-button>
|
||||
<sl-button size="large" pill>Right</sl-button>
|
||||
@@ -207,26 +211,46 @@ import { SlButton, SlButtonGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButtonGroup>
|
||||
<SlButton size="small" pill>Left</SlButton>
|
||||
<SlButton size="small" pill>Center</SlButton>
|
||||
<SlButton size="small" pill>Right</SlButton>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton size="small" pill>
|
||||
Left
|
||||
</SlButton>
|
||||
<SlButton size="small" pill>
|
||||
Center
|
||||
</SlButton>
|
||||
<SlButton size="small" pill>
|
||||
Right
|
||||
</SlButton>
|
||||
</SlButtonGroup>
|
||||
|
||||
<br /><br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButtonGroup>
|
||||
<SlButton size="medium" pill>Left</SlButton>
|
||||
<SlButton size="medium" pill>Center</SlButton>
|
||||
<SlButton size="medium" pill>Right</SlButton>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton size="medium" pill>
|
||||
Left
|
||||
</SlButton>
|
||||
<SlButton size="medium" pill>
|
||||
Center
|
||||
</SlButton>
|
||||
<SlButton size="medium" pill>
|
||||
Right
|
||||
</SlButton>
|
||||
</SlButtonGroup>
|
||||
|
||||
<br /><br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButtonGroup>
|
||||
<SlButton size="large" pill>Left</SlButton>
|
||||
<SlButton size="large" pill>Center</SlButton>
|
||||
<SlButton size="large" pill>Right</SlButton>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlButton size="large" pill>
|
||||
Left
|
||||
</SlButton>
|
||||
<SlButton size="large" pill>
|
||||
Center
|
||||
</SlButton>
|
||||
<SlButton size="large" pill>
|
||||
Right
|
||||
</SlButton>
|
||||
</SlButtonGroup>
|
||||
</>
|
||||
);
|
||||
@@ -237,7 +261,7 @@ const App = () => (
|
||||
Dropdowns can be placed inside button groups as long as the trigger is an `<sl-button>` element.
|
||||
|
||||
```html preview
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Example Button Group">
|
||||
<sl-button>Button</sl-button>
|
||||
<sl-button>Button</sl-button>
|
||||
<sl-dropdown>
|
||||
@@ -252,20 +276,16 @@ Dropdowns can be placed inside button groups as long as the trigger is an `<sl-b
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlButtonGroup,
|
||||
SlDropdown,
|
||||
SlMenu,
|
||||
SlMenuItem,
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlButtonGroup, SlDropdown, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Example Button Group">
|
||||
<SlButton>Button</SlButton>
|
||||
<SlButton>Button</SlButton>
|
||||
<SlDropdown>
|
||||
<SlButton slot="trigger" caret>Dropdown</SlButton>
|
||||
<SlButton slot="trigger" caret>
|
||||
Dropdown
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem>Item 1</SlMenuItem>
|
||||
<SlMenuItem>Item 2</SlMenuItem>
|
||||
@@ -278,13 +298,15 @@ const App = () => (
|
||||
|
||||
### Split Buttons
|
||||
|
||||
Create a split button using a button and a dropdown.
|
||||
Create a split button using a button and a dropdown. Use a [visually hidden](/components/visually-hidden) label to ensure the dropdown is accessible to users with assistive devices.
|
||||
|
||||
```html preview
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Example Button Group">
|
||||
<sl-button variant="primary">Save</sl-button>
|
||||
<sl-dropdown placement="bottom-end">
|
||||
<sl-button slot="trigger" variant="primary" caret></sl-button>
|
||||
<sl-button slot="trigger" variant="primary" caret>
|
||||
<sl-visually-hidden>More options</sl-visually-hidden>
|
||||
</sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-item>Save</sl-menu-item>
|
||||
<sl-menu-item>Save as…</sl-menu-item>
|
||||
@@ -295,16 +317,10 @@ Create a split button using a button and a dropdown.
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlButtonGroup,
|
||||
SlDropdown,
|
||||
SlMenu,
|
||||
SlMenuItem,
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlButtonGroup, SlDropdown, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Example Button Group">
|
||||
<SlButton variant="primary">Save</SlButton>
|
||||
<SlDropdown placement="bottom-end">
|
||||
<SlButton slot="trigger" variant="primary" caret></SlButton>
|
||||
@@ -323,7 +339,7 @@ const App = () => (
|
||||
Buttons can be wrapped in tooltips to provide more detail when the user interacts with them.
|
||||
|
||||
```html preview
|
||||
<sl-button-group>
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-tooltip content="I'm on the left">
|
||||
<sl-button>Left</sl-button>
|
||||
</sl-tooltip>
|
||||
@@ -339,15 +355,11 @@ Buttons can be wrapped in tooltips to provide more detail when the user interact
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlButtonGroup,
|
||||
SlTooltip
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlButtonGroup, SlTooltip } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButtonGroup>
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlTooltip content="I'm on the left">
|
||||
<SlButton>Left</SlButton>
|
||||
</SlTooltip>
|
||||
@@ -372,34 +384,34 @@ Create interactive toolbars with button groups.
|
||||
<div class="button-group-toolbar">
|
||||
<sl-button-group label="History">
|
||||
<sl-tooltip content="Undo">
|
||||
<sl-button><sl-icon name="arrow-counterclockwise"></sl-icon></sl-button>
|
||||
<sl-button><sl-icon name="arrow-counterclockwise" label="Undo"></sl-icon></sl-button>
|
||||
</sl-tooltip>
|
||||
<sl-tooltip content="Redo">
|
||||
<sl-button><sl-icon name="arrow-clockwise"></sl-icon></sl-button>
|
||||
<sl-button><sl-icon name="arrow-clockwise" label="Redo"></sl-icon></sl-button>
|
||||
</sl-tooltip>
|
||||
</sl-button-group>
|
||||
|
||||
<sl-button-group label="Formatting">
|
||||
<sl-tooltip content="Bold">
|
||||
<sl-button><sl-icon name="type-bold"></sl-icon></sl-button>
|
||||
<sl-button><sl-icon name="type-bold" label="Bold"></sl-icon></sl-button>
|
||||
</sl-tooltip>
|
||||
<sl-tooltip content="Italic">
|
||||
<sl-button><sl-icon name="type-italic"></sl-icon></sl-button>
|
||||
<sl-button><sl-icon name="type-italic" label="Italic"></sl-icon></sl-button>
|
||||
</sl-tooltip>
|
||||
<sl-tooltip content="Underline">
|
||||
<sl-button><sl-icon name="type-underline"></sl-icon></sl-button>
|
||||
<sl-button><sl-icon name="type-underline" label="Underline"></sl-icon></sl-button>
|
||||
</sl-tooltip>
|
||||
</sl-button-group>
|
||||
|
||||
<sl-button-group label="Alignment">
|
||||
<sl-tooltip content="Align Left">
|
||||
<sl-button><sl-icon name="justify-left"></sl-icon></sl-button>
|
||||
<sl-button><sl-icon name="justify-left" label="Align Left"></sl-icon></sl-button>
|
||||
</sl-tooltip>
|
||||
<sl-tooltip content="Align Center">
|
||||
<sl-button><sl-icon name="justify"></sl-icon></sl-button>
|
||||
<sl-button><sl-icon name="justify" label="Align Center"></sl-icon></sl-button>
|
||||
</sl-tooltip>
|
||||
<sl-tooltip content="Align Right">
|
||||
<sl-button><sl-icon name="justify-right"></sl-icon></sl-button>
|
||||
<sl-button><sl-icon name="justify-right" label="Align Right"></sl-icon></sl-button>
|
||||
</sl-tooltip>
|
||||
</sl-button-group>
|
||||
</div>
|
||||
@@ -412,12 +424,7 @@ Create interactive toolbars with button groups.
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlButtonGroup,
|
||||
SlIcon,
|
||||
SlTooltip
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlButtonGroup, SlIcon, SlTooltip } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const css = `
|
||||
.button-group-toolbar sl-button-group:not(:last-of-type) {
|
||||
@@ -430,34 +437,50 @@ const App = () => (
|
||||
<div className="button-group-toolbar">
|
||||
<SlButtonGroup label="History">
|
||||
<SlTooltip content="Undo">
|
||||
<SlButton><SlIcon name="arrow-counterclockwise"></SlIcon></SlButton>
|
||||
<SlButton>
|
||||
<SlIcon name="arrow-counterclockwise"></SlIcon>
|
||||
</SlButton>
|
||||
</SlTooltip>
|
||||
<SlTooltip content="Redo">
|
||||
<SlButton><SlIcon name="arrow-clockwise"></SlIcon></SlButton>
|
||||
<SlButton>
|
||||
<SlIcon name="arrow-clockwise"></SlIcon>
|
||||
</SlButton>
|
||||
</SlTooltip>
|
||||
</SlButtonGroup>
|
||||
|
||||
<SlButtonGroup label="Formatting">
|
||||
<SlTooltip content="Bold">
|
||||
<SlButton><SlIcon name="type-bold"></SlIcon></SlButton>
|
||||
<SlButton>
|
||||
<SlIcon name="type-bold"></SlIcon>
|
||||
</SlButton>
|
||||
</SlTooltip>
|
||||
<SlTooltip content="Italic">
|
||||
<SlButton><SlIcon name="type-italic"></SlIcon></SlButton>
|
||||
<SlButton>
|
||||
<SlIcon name="type-italic"></SlIcon>
|
||||
</SlButton>
|
||||
</SlTooltip>
|
||||
<SlTooltip content="Underline">
|
||||
<SlButton><SlIcon name="type-underline"></SlIcon></SlButton>
|
||||
<SlButton>
|
||||
<SlIcon name="type-underline"></SlIcon>
|
||||
</SlButton>
|
||||
</SlTooltip>
|
||||
</SlButtonGroup>
|
||||
|
||||
<SlButtonGroup label="Alignment">
|
||||
<SlTooltip content="Align Left">
|
||||
<SlButton><SlIcon name="justify-left"></SlIcon></SlButton>
|
||||
<SlButton>
|
||||
<SlIcon name="justify-left"></SlIcon>
|
||||
</SlButton>
|
||||
</SlTooltip>
|
||||
<SlTooltip content="Align Center">
|
||||
<SlButton><SlIcon name="justify"></SlIcon></SlButton>
|
||||
<SlButton>
|
||||
<SlIcon name="justify"></SlIcon>
|
||||
</SlButton>
|
||||
</SlTooltip>
|
||||
<SlTooltip content="Align Right">
|
||||
<SlButton><SlIcon name="justify-right"></SlIcon></SlButton>
|
||||
<SlButton>
|
||||
<SlIcon name="justify-right"></SlIcon>
|
||||
</SlButton>
|
||||
</SlTooltip>
|
||||
</SlButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-button]
|
||||
|
||||
Buttons represent actions that are available to the user.
|
||||
|
||||
```html preview
|
||||
<sl-button>Button</sl-button>
|
||||
```
|
||||
@@ -11,9 +9,7 @@ Buttons represent actions that are available to the user.
|
||||
```jsx react
|
||||
import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlButton>Button</SlButton>
|
||||
);
|
||||
const App = () => <SlButton>Button</SlButton>;
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -41,7 +37,7 @@ const App = () => (
|
||||
<SlButton variant="success">Success</SlButton>
|
||||
<SlButton variant="neutral">Neutral</SlButton>
|
||||
<SlButton variant="warning">Warning</SlButton>
|
||||
<SlButton variant="danger">Danger</SlButton>
|
||||
<SlButton variant="danger">Danger</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -86,12 +82,24 @@ import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButton variant="default" outline>Default</SlButton>
|
||||
<SlButton variant="primary" outline>Primary</SlButton>
|
||||
<SlButton variant="success" outline>Success</SlButton>
|
||||
<SlButton variant="neutral" outline>Neutral</SlButton>
|
||||
<SlButton variant="warning" outline>Warning</SlButton>
|
||||
<SlButton variant="danger" outline>Danger</SlButton>
|
||||
<SlButton variant="default" outline>
|
||||
Default
|
||||
</SlButton>
|
||||
<SlButton variant="primary" outline>
|
||||
Primary
|
||||
</SlButton>
|
||||
<SlButton variant="success" outline>
|
||||
Success
|
||||
</SlButton>
|
||||
<SlButton variant="neutral" outline>
|
||||
Neutral
|
||||
</SlButton>
|
||||
<SlButton variant="warning" outline>
|
||||
Warning
|
||||
</SlButton>
|
||||
<SlButton variant="danger" outline>
|
||||
Danger
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -111,21 +119,35 @@ import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButton size="small" pill>Small</SlButton>
|
||||
<SlButton size="medium" pill>Medium</SlButton>
|
||||
<SlButton size="large" pill>Large</SlButton>
|
||||
<SlButton size="small" pill>
|
||||
Small
|
||||
</SlButton>
|
||||
<SlButton size="medium" pill>
|
||||
Medium
|
||||
</SlButton>
|
||||
<SlButton size="large" pill>
|
||||
Large
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Circle Buttons
|
||||
|
||||
Use the `circle` attribute to create circular icon buttons.
|
||||
Use the `circle` attribute to create circular icon buttons. When this attribute is set, the button expects a single `<sl-icon>` in the default slot.
|
||||
|
||||
```html preview
|
||||
<sl-button variant="default" size="small" circle><sl-icon name="gear"></sl-icon></sl-button>
|
||||
<sl-button variant="default" size="medium" circle><sl-icon name="gear"></sl-icon></sl-button>
|
||||
<sl-button variant="default" size="large" circle><sl-icon name="gear"></sl-icon></sl-button>
|
||||
<sl-button variant="default" size="small" circle>
|
||||
<sl-icon name="gear" label="Settings"></sl-icon>
|
||||
</sl-button>
|
||||
|
||||
<sl-button variant="default" size="medium" circle>
|
||||
<sl-icon name="gear" label="Settings"></sl-icon>
|
||||
</sl-button>
|
||||
|
||||
<sl-button variant="default" size="large" circle>
|
||||
<sl-icon name="gear" label="Settings"></sl-icon>
|
||||
</sl-button>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
@@ -133,9 +155,15 @@ import { SlButton, SlIcon } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButton variant="default" size="small" circle><SlIcon name="gear" /></SlButton>
|
||||
<SlButton variant="default" size="medium" circle><SlIcon name="gear" /></SlButton>
|
||||
<SlButton variant="default" size="large" circle><SlIcon name="gear" /></SlButton>
|
||||
<SlButton variant="default" size="small" circle>
|
||||
<SlIcon name="gear" />
|
||||
</SlButton>
|
||||
<SlButton variant="default" size="medium" circle>
|
||||
<SlIcon name="gear" />
|
||||
</SlButton>
|
||||
<SlButton variant="default" size="large" circle>
|
||||
<SlIcon name="gear" />
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -155,9 +183,15 @@ import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButton variant="text" size="small">Text</SlButton>
|
||||
<SlButton variant="text" size="medium">Text</SlButton>
|
||||
<SlButton variant="text" size="large">Text</SlButton>
|
||||
<SlButton variant="text" size="small">
|
||||
Text
|
||||
</SlButton>
|
||||
<SlButton variant="text" size="medium">
|
||||
Text
|
||||
</SlButton>
|
||||
<SlButton variant="text" size="large">
|
||||
Text
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -179,9 +213,15 @@ import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButton href="https://example.com/">Link</SlButton>
|
||||
<SlButton href="https://example.com/" target="_blank">New Window</SlButton>
|
||||
<SlButton href="/assets/images/wordmark.svg" download="shoelace.svg">Download</SlButton>
|
||||
<SlButton href="https://example.com/" disabled>Disabled</SlButton>
|
||||
<SlButton href="https://example.com/" target="_blank">
|
||||
New Window
|
||||
</SlButton>
|
||||
<SlButton href="/assets/images/wordmark.svg" download="shoelace.svg">
|
||||
Download
|
||||
</SlButton>
|
||||
<SlButton href="https://example.com/" disabled>
|
||||
Disabled
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -203,9 +243,15 @@ import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButton variant="default" size="small" style={{ width: '100%', marginBottom: '1rem' }}>Small</SlButton>
|
||||
<SlButton variant="default" size="medium" style={{ width: '100%', marginBottom: '1rem' }}>Medium</SlButton>
|
||||
<SlButton variant="default" size="large" style={{ width: '100%' }}>Large</SlButton>
|
||||
<SlButton variant="default" size="small" style={{ width: '100%', marginBottom: '1rem' }}>
|
||||
Small
|
||||
</SlButton>
|
||||
<SlButton variant="default" size="medium" style={{ width: '100%', marginBottom: '1rem' }}>
|
||||
Medium
|
||||
</SlButton>
|
||||
<SlButton variant="default" size="large" style={{ width: '100%' }}>
|
||||
Large
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -231,7 +277,7 @@ Use the `prefix` and `suffix` slots to add icons.
|
||||
Open
|
||||
</sl-button>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button variant="default">
|
||||
<sl-icon slot="prefix" name="gear"></sl-icon>
|
||||
@@ -249,7 +295,7 @@ Use the `prefix` and `suffix` slots to add icons.
|
||||
Open
|
||||
</sl-button>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<sl-button variant="default" size="large">
|
||||
<sl-icon slot="prefix" name="gear"></sl-icon>
|
||||
@@ -289,7 +335,8 @@ const App = () => (
|
||||
Open
|
||||
</SlButton>
|
||||
|
||||
<br /><br/ >
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButton variant="default">
|
||||
<SlIcon slot="prefix" name="gear"></SlIcon>
|
||||
@@ -307,7 +354,8 @@ const App = () => (
|
||||
Open
|
||||
</SlButton>
|
||||
|
||||
<br /><br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<SlButton variant="default" size="large">
|
||||
<SlIcon slot="prefix" name="gear"></SlIcon>
|
||||
@@ -343,9 +391,15 @@ import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButton size="small" caret>Small</SlButton>
|
||||
<SlButton size="medium" caret>Medium</SlButton>
|
||||
<SlButton size="large" caret>Large</SlButton>
|
||||
<SlButton size="small" caret>
|
||||
Small
|
||||
</SlButton>
|
||||
<SlButton size="medium" caret>
|
||||
Medium
|
||||
</SlButton>
|
||||
<SlButton size="large" caret>
|
||||
Large
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -368,12 +422,24 @@ import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButton variant="default" loading>Default</SlButton>
|
||||
<SlButton variant="primary" loading>Primary</SlButton>
|
||||
<SlButton variant="success" loading>Success</SlButton>
|
||||
<SlButton variant="neutral" loading>Neutral</SlButton>
|
||||
<SlButton variant="warning" loading>Warning</SlButton>
|
||||
<SlButton variant="danger" loading>Danger</SlButton>
|
||||
<SlButton variant="default" loading>
|
||||
Default
|
||||
</SlButton>
|
||||
<SlButton variant="primary" loading>
|
||||
Primary
|
||||
</SlButton>
|
||||
<SlButton variant="success" loading>
|
||||
Success
|
||||
</SlButton>
|
||||
<SlButton variant="neutral" loading>
|
||||
Neutral
|
||||
</SlButton>
|
||||
<SlButton variant="warning" loading>
|
||||
Warning
|
||||
</SlButton>
|
||||
<SlButton variant="danger" loading>
|
||||
Danger
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -396,12 +462,29 @@ import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlButton variant="default" disabled>Default</SlButton>
|
||||
<SlButton variant="primary" disabled>Primary</SlButton>
|
||||
<SlButton variant="success" disabled>Success</SlButton>
|
||||
<SlButton variant="neutral" disabled>Neutral</SlButton>
|
||||
<SlButton variant="warning" disabled>Warning</SlButton>
|
||||
<SlButton variant="danger" disabled>Danger</SlButton>
|
||||
<SlButton variant="default" disabled>
|
||||
Default
|
||||
</SlButton>
|
||||
|
||||
<SlButton variant="primary" disabled>
|
||||
Primary
|
||||
</SlButton>
|
||||
|
||||
<SlButton variant="success" disabled>
|
||||
Success
|
||||
</SlButton>
|
||||
|
||||
<SlButton variant="neutral" disabled>
|
||||
Neutral
|
||||
</SlButton>
|
||||
|
||||
<SlButton variant="warning" disabled>
|
||||
Warning
|
||||
</SlButton>
|
||||
|
||||
<SlButton variant="danger" disabled>
|
||||
Danger
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -418,7 +501,7 @@ This example demonstrates how to style buttons using a custom class. This is the
|
||||
/* 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;
|
||||
|
||||
@@ -2,18 +2,16 @@
|
||||
|
||||
[component-header:sl-card]
|
||||
|
||||
Cards can be used to group related subjects in a container.
|
||||
|
||||
```html preview
|
||||
<sl-card class="card-overview">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
alt="A kitten sits patiently between a terracotta pot and decorative grasses."
|
||||
>
|
||||
/>
|
||||
|
||||
<strong>Mittens</strong><br>
|
||||
This kitten is as cute as he is playful. Bring him home today!<br>
|
||||
<strong>Mittens</strong><br />
|
||||
This kitten is as cute as he is playful. Bring him home today!<br />
|
||||
<small>6 weeks old</small>
|
||||
|
||||
<div slot="footer">
|
||||
@@ -31,20 +29,16 @@ Cards can be used to group related subjects in a container.
|
||||
color: var(--sl-color-neutral-500);
|
||||
}
|
||||
|
||||
.card-overview [slot="footer"] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.card-overview [slot='footer'] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlCard,
|
||||
SlRating
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlCard, SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const css = `
|
||||
.card-overview {
|
||||
@@ -65,18 +59,20 @@ const css = `
|
||||
const App = () => (
|
||||
<>
|
||||
<SlCard className="card-overview">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
alt="A kitten sits patiently between a terracotta pot and decorative grasses."
|
||||
/>
|
||||
|
||||
<strong>Mittens</strong><br />
|
||||
This kitten is as cute as he is playful. Bring him home today!<br />
|
||||
<strong>Mittens</strong>
|
||||
<br />
|
||||
This kitten is as cute as he is playful. Bring him home today!
|
||||
<br />
|
||||
<small>6 weeks old</small>
|
||||
|
||||
<div slot="footer">
|
||||
<SlButton variant="primary" pill>More Info</SlButton>
|
||||
<SlButton variant="primary" pill>
|
||||
More Info
|
||||
</SlButton>
|
||||
<SlRating></SlRating>
|
||||
</div>
|
||||
</SlCard>
|
||||
@@ -132,8 +128,7 @@ Headers can be used to display titles and more.
|
||||
<sl-card class="card-header">
|
||||
<div slot="header">
|
||||
Header Title
|
||||
|
||||
<sl-icon-button name="gear"></sl-icon-button>
|
||||
<sl-icon-button name="gear" label="Settings"></sl-icon-button>
|
||||
</div>
|
||||
|
||||
This card has a header. You can put all sorts of things in it!
|
||||
@@ -144,9 +139,9 @@ Headers can be used to display titles and more.
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.card-header [slot="header"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.card-header [slot='header'] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@@ -188,10 +183,8 @@ const App = () => (
|
||||
<SlCard className="card-header">
|
||||
<div slot="header">
|
||||
Header Title
|
||||
|
||||
<SlIconButton name="gear"></SlIconButton>
|
||||
</div>
|
||||
|
||||
This card has a header. You can put all sorts of things in it!
|
||||
</SlCard>
|
||||
|
||||
@@ -210,7 +203,7 @@ Footers can be used to display actions, summaries, or other relevant content.
|
||||
|
||||
<div slot="footer">
|
||||
<sl-rating></sl-rating>
|
||||
<sl-button slot="footer" variant="primary">Preview</sl-button>
|
||||
<sl-button variant="primary">Preview</sl-button>
|
||||
</div>
|
||||
</sl-card>
|
||||
|
||||
@@ -219,20 +212,16 @@ Footers can be used to display actions, summaries, or other relevant content.
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.card-footer [slot="footer"] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.card-footer [slot='footer'] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlCard,
|
||||
SlRating
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlCard, SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const css = `
|
||||
.card-footer {
|
||||
@@ -250,10 +239,11 @@ const App = () => (
|
||||
<>
|
||||
<SlCard className="card-footer">
|
||||
This card has a footer. You can put all sorts of things in it!
|
||||
|
||||
<div slot="footer">
|
||||
<SlRating></SlRating>
|
||||
<SlButton slot="footer" variant="primary">Preview</SlButton>
|
||||
<SlButton slot="footer" variant="primary">
|
||||
Preview
|
||||
</SlButton>
|
||||
</div>
|
||||
</SlCard>
|
||||
|
||||
@@ -268,11 +258,11 @@ Cards accept an `image` slot. The image is displayed atop the card and stretches
|
||||
|
||||
```html preview
|
||||
<sl-card class="card-image">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1547191783-94d5f8f6d8b1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=80"
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1547191783-94d5f8f6d8b1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=80"
|
||||
alt="A kitten walks towards camera on top of pallet."
|
||||
>
|
||||
/>
|
||||
This is a kitten, but not just any kitten. This kitten likes walking along pallets.
|
||||
</sl-card>
|
||||
|
||||
@@ -295,9 +285,9 @@ const css = `
|
||||
const App = () => (
|
||||
<>
|
||||
<SlCard className="card-image">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1547191783-94d5f8f6d8b1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=80"
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1547191783-94d5f8f6d8b1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=80"
|
||||
alt="A kitten walks towards camera on top of pallet."
|
||||
/>
|
||||
This is a kitten, but not just any kitten. This kitten likes walking along pallets.
|
||||
|
||||
81
docs/components/carousel-item.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Carousel Item
|
||||
|
||||
[component-header:sl-carousel-item]
|
||||
|
||||
```html preview
|
||||
<sl-carousel pagination>
|
||||
<sl-carousel-item>
|
||||
<img
|
||||
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||
src="/assets/examples/carousel/mountains.jpg"
|
||||
/>
|
||||
</sl-carousel-item>
|
||||
<sl-carousel-item>
|
||||
<img
|
||||
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
||||
src="/assets/examples/carousel/waterfall.jpg"
|
||||
/>
|
||||
</sl-carousel-item>
|
||||
<sl-carousel-item>
|
||||
<img
|
||||
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
||||
src="/assets/examples/carousel/sunset.jpg"
|
||||
/>
|
||||
</sl-carousel-item>
|
||||
<sl-carousel-item>
|
||||
<img
|
||||
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
||||
src="/assets/examples/carousel/field.jpg"
|
||||
/>
|
||||
</sl-carousel-item>
|
||||
<sl-carousel-item>
|
||||
<img
|
||||
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
||||
src="/assets/examples/carousel/valley.jpg"
|
||||
/>
|
||||
</sl-carousel-item>
|
||||
</sl-carousel>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlCarousel, SlCarouselItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlCarousel pagination>
|
||||
<SlCarouselItem>
|
||||
<img
|
||||
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||
src="/assets/examples/carousel/mountains.jpg"
|
||||
/>
|
||||
</SlCarouselItem>
|
||||
<SlCarouselItem>
|
||||
<img
|
||||
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
||||
src="/assets/examples/carousel/waterfall.jpg"
|
||||
/>
|
||||
</SlCarouselItem>
|
||||
<SlCarouselItem>
|
||||
<img
|
||||
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
||||
src="/assets/examples/carousel/sunset.jpg"
|
||||
/>
|
||||
</SlCarouselItem>
|
||||
<SlCarouselItem>
|
||||
<img
|
||||
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
||||
src="/assets/examples/carousel/field.jpg"
|
||||
/>
|
||||
</SlCarouselItem>
|
||||
<SlCarouselItem>
|
||||
<img
|
||||
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
||||
src="/assets/examples/carousel/valley.jpg"
|
||||
/>
|
||||
</SlCarouselItem>
|
||||
</SlCarousel>
|
||||
);
|
||||
```
|
||||
|
||||
?> Additional demonstrations can be found in the [carousel examples](/components/carousel).
|
||||
|
||||
[component-metadata:sl-carousel-item]
|
||||
1216
docs/components/carousel.md
Normal file
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-checkbox]
|
||||
|
||||
Checkboxes allow the user to toggle an option on or off.
|
||||
|
||||
```html preview
|
||||
<sl-checkbox>Checkbox</sl-checkbox>
|
||||
```
|
||||
@@ -11,9 +9,7 @@ Checkboxes allow the user to toggle an option on or off.
|
||||
```jsx react
|
||||
import { SlCheckbox } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlCheckbox>Checkbox</SlCheckbox>
|
||||
);
|
||||
const App = () => <SlCheckbox>Checkbox</SlCheckbox>;
|
||||
```
|
||||
|
||||
?> This component works with standard `<form>` elements. Please refer to the section on [form controls](/getting-started/form-controls) to learn more about form submission and client-side validation.
|
||||
@@ -31,9 +27,7 @@ Use the `checked` attribute to activate the checkbox.
|
||||
```jsx react
|
||||
import { SlCheckbox } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlCheckbox checked>Checked</SlCheckbox>
|
||||
);
|
||||
const App = () => <SlCheckbox checked>Checked</SlCheckbox>;
|
||||
```
|
||||
|
||||
### Indeterminate
|
||||
@@ -47,9 +41,7 @@ Use the `indeterminate` attribute to make the checkbox indeterminate.
|
||||
```jsx react
|
||||
import { SlCheckbox } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlCheckbox indeterminate>Indeterminate</SlCheckbox>
|
||||
);
|
||||
const App = () => <SlCheckbox indeterminate>Indeterminate</SlCheckbox>;
|
||||
```
|
||||
|
||||
### Disabled
|
||||
@@ -63,9 +55,101 @@ Use the `disabled` attribute to disable the checkbox.
|
||||
```jsx react
|
||||
import { SlCheckbox } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlCheckbox disabled>Disabled</SlCheckbox>;
|
||||
```
|
||||
|
||||
## Sizes
|
||||
|
||||
Use the `size` attribute to change a checkbox's size.
|
||||
|
||||
```html preview
|
||||
<sl-checkbox size="small">Small</sl-checkbox>
|
||||
<br />
|
||||
<sl-checkbox size="medium">Medium</sl-checkbox>
|
||||
<br />
|
||||
<sl-checkbox size="large">Large</sl-checkbox>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlCheckbox } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlCheckbox disabled>Disabled</SlCheckbox>
|
||||
<>
|
||||
<SlCheckbox size="small">Small</SlCheckbox>
|
||||
<br />
|
||||
<SlCheckbox size="medium">Medium</SlCheckbox>
|
||||
<br />
|
||||
<SlCheckbox size="large">Large</SlCheckbox>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Custom Validity
|
||||
|
||||
Use the `setCustomValidity()` method to set a custom validation message. This will prevent the form from submitting and make the browser display the error message you provide. To clear the error, call this function with an empty string.
|
||||
|
||||
```html preview
|
||||
<form class="custom-validity">
|
||||
<sl-checkbox>Check me</sl-checkbox>
|
||||
<br />
|
||||
<sl-button type="submit" variant="primary" style="margin-top: 1rem;">Submit</sl-button>
|
||||
</form>
|
||||
<script>
|
||||
const form = document.querySelector('.custom-validity');
|
||||
const checkbox = form.querySelector('sl-checkbox');
|
||||
const errorMessage = `Don't forget to check me!`;
|
||||
|
||||
// Set initial validity as soon as the element is defined
|
||||
customElements.whenDefined('sl-checkbox').then(() => {
|
||||
checkbox.setCustomValidity(errorMessage);
|
||||
});
|
||||
|
||||
// Update validity on change
|
||||
checkbox.addEventListener('sl-change', () => {
|
||||
checkbox.setCustomValidity(checkbox.checked ? '' : errorMessage);
|
||||
});
|
||||
|
||||
// Handle submit
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { SlButton, SlCheckbox } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const checkbox = useRef(null);
|
||||
const errorMessage = `Don't forget to check me!`;
|
||||
|
||||
function handleChange() {
|
||||
checkbox.current.setCustomValidity(checkbox.current.checked ? '' : errorMessage);
|
||||
}
|
||||
|
||||
function handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
checkbox.current.setCustomValidity(errorMessage);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<form class="custom-validity" onSubmit={handleSubmit}>
|
||||
<SlCheckbox ref={checkbox} onSlChange={handleChange}>
|
||||
Check me
|
||||
</SlCheckbox>
|
||||
<br />
|
||||
<SlButton type="submit" variant="primary" style={{ marginTop: '1rem' }}>
|
||||
Submit
|
||||
</SlButton>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
[component-metadata:sl-checkbox]
|
||||
|
||||
@@ -2,50 +2,59 @@
|
||||
|
||||
[component-header:sl-color-picker]
|
||||
|
||||
Color pickers allow the user to select a color.
|
||||
|
||||
```html preview
|
||||
<sl-color-picker></sl-color-picker>
|
||||
<sl-color-picker label="Select a color"></sl-color-picker>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlColorPicker } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlColorPicker />
|
||||
);
|
||||
const App = () => <SlColorPicker label="Select a color" />;
|
||||
```
|
||||
|
||||
?> This component works with standard `<form>` elements. Please refer to the section on [form controls](/getting-started/form-controls) to learn more about form submission and client-side validation.
|
||||
|
||||
## Examples
|
||||
|
||||
### Opacity
|
||||
### Initial Value
|
||||
|
||||
Use the `opacity` attribute to enable the opacity slider. When this is enabled, the value will be displayed as HEXA, RGBA, or HSLA based on `format`.
|
||||
Use the `value` attribute to set an initial value for the color picker.
|
||||
|
||||
```html preview
|
||||
<sl-color-picker opacity></sl-color-picker>
|
||||
<sl-color-picker value="#4a90e2" label="Select a color"></sl-color-picker>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlColorPicker } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlColorPicker opacity />
|
||||
);
|
||||
const App = () => <SlColorPicker value="#4a90e2" label="Select a color" />;
|
||||
```
|
||||
|
||||
### Opacity
|
||||
|
||||
Use the `opacity` attribute to enable the opacity slider. When this is enabled, the value will be displayed as HEXA, RGBA, HSLA, or HSVA based on `format`.
|
||||
|
||||
```html preview
|
||||
<sl-color-picker value="#f5a623ff" opacity label="Select a color"></sl-color-picker>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlColorPicker } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlColorPicker opacity label="Select a color" />;
|
||||
```
|
||||
|
||||
### Formats
|
||||
|
||||
Set the color picker's format with the `format` attribute. Valid options include `hex`, `rgb`, and `hsl`. Note that the color picker's input will accept any parsable format (including CSS color names) regardless of this option.
|
||||
Set the color picker's format with the `format` attribute. Valid options include `hex`, `rgb`, `hsl`, and `hsv`. Note that the color picker's input will accept any parsable format (including CSS color names) regardless of this option.
|
||||
|
||||
To prevent users from toggling the format themselves, add the `no-format-toggle` attribute.
|
||||
|
||||
```html preview
|
||||
<sl-color-picker format="hex" value="#4a90e2"></sl-color-picker>
|
||||
<sl-color-picker format="rgb" value="rgb(80, 227, 194)"></sl-color-picker>
|
||||
<sl-color-picker format="hsl" value="hsl(290, 87%, 47%)"></sl-color-picker>
|
||||
<sl-color-picker format="hex" value="#4a90e2" label="Select a color"></sl-color-picker>
|
||||
<sl-color-picker format="rgb" value="rgb(80, 227, 194)" label="Select a color"></sl-color-picker>
|
||||
<sl-color-picker format="hsl" value="hsl(290, 87%, 47%)" label="Select a color"></sl-color-picker>
|
||||
<sl-color-picker format="hsv" value="hsv(55, 89%, 97%)" label="Select a color"></sl-color-picker>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
@@ -56,18 +65,47 @@ const App = () => (
|
||||
<SlColorPicker format="hex" value="#4a90e2" />
|
||||
<SlColorPicker format="rgb" value="rgb(80, 227, 194)" />
|
||||
<SlColorPicker format="hsl" value="hsl(290, 87%, 47%)" />
|
||||
<SlColorPicker format="hsv" value="hsv(55, 89%, 97%)" />
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Swatches
|
||||
|
||||
Use the `swatches` attribute to add convenient presets to the color picker. Any format the color picker can parse is acceptable (including CSS color names), but each value must be separated by a semicolon (`;`). Alternatively, you can pass an array of color values to this property using JavaScript.
|
||||
|
||||
```html preview
|
||||
<sl-color-picker
|
||||
label="Select a color"
|
||||
swatches="
|
||||
#d0021b; #f5a623; #f8e71c; #8b572a; #7ed321; #417505; #bd10e0; #9013fe;
|
||||
#4a90e2; #50e3c2; #b8e986; #000; #444; #888; #ccc; #fff;
|
||||
"
|
||||
></sl-color-picker>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlColorPicker } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlColorPicker
|
||||
label="Select a color"
|
||||
swatches="
|
||||
#d0021b; #f5a623; #f8e71c; #8b572a; #7ed321; #417505; #bd10e0; #9013fe;
|
||||
#4a90e2; #50e3c2; #b8e986; #000; #444; #888; #ccc; #fff;
|
||||
"
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Sizes
|
||||
|
||||
Use the `size` attribute to change the color picker's trigger size.
|
||||
|
||||
```html preview
|
||||
<sl-color-picker size="small"></sl-color-picker>
|
||||
<sl-color-picker size="medium"></sl-color-picker>
|
||||
<sl-color-picker size="large"></sl-color-picker>
|
||||
<sl-color-picker size="small" label="Select a color"></sl-color-picker>
|
||||
<sl-color-picker size="medium" label="Select a color"></sl-color-picker>
|
||||
<sl-color-picker size="large" label="Select a color"></sl-color-picker>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
@@ -75,9 +113,9 @@ import { SlColorPicker } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlColorPicker size="small" />
|
||||
<SlColorPicker size="medium" />
|
||||
<SlColorPicker size="large" />
|
||||
<SlColorPicker size="small" label="Select a color" />
|
||||
<SlColorPicker size="medium" label="Select a color" />
|
||||
<SlColorPicker size="large" label="Select a color" />
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -87,15 +125,13 @@ const App = () => (
|
||||
The color picker can be rendered inline instead of in a dropdown using the `inline` attribute.
|
||||
|
||||
```html preview
|
||||
<sl-color-picker inline></sl-color-picker>
|
||||
<sl-color-picker inline label="Select a color"></sl-color-picker>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlColorPicker } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlColorPicker inline />
|
||||
);
|
||||
const App = () => <SlColorPicker inline label="Select a color" />;
|
||||
```
|
||||
|
||||
[component-metadata:sl-color-picker]
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
[component-header:sl-details]
|
||||
|
||||
Details show a brief summary and expand to show additional content.
|
||||
|
||||
```html preview
|
||||
<sl-details summary="Toggle Me">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
||||
@@ -48,6 +46,52 @@ const App = () => (
|
||||
);
|
||||
```
|
||||
|
||||
### Customizing the Summary Icon
|
||||
|
||||
Use the `expand-icon` and `collapse-icon` slots to change the expand and collapse icons, respectively. To disable the animation, override the `rotate` property on the `summary-icon` part as shown below.
|
||||
|
||||
```html preview
|
||||
<sl-details summary="Toggle Me" class="custom-icons">
|
||||
<sl-icon name="plus-square" slot="expand-icon"></sl-icon>
|
||||
<sl-icon name="dash-square" slot="collapse-icon"></sl-icon>
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
||||
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</sl-details>
|
||||
|
||||
<style>
|
||||
sl-details.custom-icons::part(summary-icon) {
|
||||
/* Disable the expand/collapse animation */
|
||||
rotate: none;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlDetails, SlIcon } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const css = `
|
||||
sl-details.custom-icon::part(summary-icon) {
|
||||
/* Disable the expand/collapse animation */
|
||||
rotate: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlDetails summary="Toggle Me" class="custom-icon">
|
||||
<SlIcon name="plus-square" slot="expand-icon" />
|
||||
<SlIcon name="dash-square" slot="collapse-icon" />
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
|
||||
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.
|
||||
</SlDetails>
|
||||
|
||||
<style>{css}</style>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Grouping Details
|
||||
|
||||
Details are designed to function independently, but you can simulate a group or "accordion" where only one is shown at a time by listening for the `sl-show` event.
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
[component-header:sl-dialog]
|
||||
|
||||
Dialogs, sometimes called "modals", appear above the page and require the user's immediate attention.
|
||||
|
||||
```html preview
|
||||
<sl-dialog label="Dialog" class="dialog-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
@@ -153,6 +151,59 @@ const App = () => {
|
||||
};
|
||||
```
|
||||
|
||||
### Header Actions
|
||||
|
||||
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/components/icon-button) if needed.
|
||||
|
||||
```html preview
|
||||
<sl-dialog label="Dialog" class="dialog-header-actions">
|
||||
<sl-icon-button class="new-window" slot="header-actions" name="box-arrow-up-right"></sl-icon-button>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<sl-button slot="footer" variant="primary">Close</sl-button>
|
||||
</sl-dialog>
|
||||
|
||||
<sl-button>Open Dialog</sl-button>
|
||||
|
||||
<script>
|
||||
const dialog = document.querySelector('.dialog-header-actions');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
const newWindowButton = dialog.querySelector('.new-window');
|
||||
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
newWindowButton.addEventListener('click', () => window.open(location.href));
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { useState } from 'react';
|
||||
import { SlButton, SlDialog, SlIconButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlDialog label="Dialog" open={open} onSlAfterHide={() => setOpen(false)}>
|
||||
<SlIconButton
|
||||
class="new-window"
|
||||
slot="header-actions"
|
||||
name="box-arrow-up-right"
|
||||
onClick={() => window.open(location.href)}
|
||||
/>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<SlButton slot="footer" variant="primary" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
</SlButton>
|
||||
</SlDialog>
|
||||
|
||||
<SlButton onClick={() => setOpen(true)}>Open Dialog</SlButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Preventing the Dialog from Closing
|
||||
|
||||
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.
|
||||
@@ -202,12 +253,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlDialog
|
||||
label="Dialog"
|
||||
open={open}
|
||||
onSlRequestClose={handleRequestClose}
|
||||
onSlAfterHide={() => setOpen(false)}
|
||||
>
|
||||
<SlDialog label="Dialog" open={open} onSlRequestClose={handleRequestClose} onSlAfterHide={() => setOpen(false)}>
|
||||
This dialog will not close when you click on the overlay.
|
||||
<SlButton slot="footer" variant="primary" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -222,11 +268,11 @@ const App = () => {
|
||||
|
||||
### Customizing Initial Focus
|
||||
|
||||
By default, the dialog's panel will gain focus when opened. This allows a subsequent 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.
|
||||
By default, the dialog's panel will gain focus when opened. This allows a subsequent tab press to focus on the first tabbable element in the dialog. If you want a different element to have focus, add the `autofocus` attribute to it as shown below.
|
||||
|
||||
```html preview
|
||||
<sl-dialog label="Dialog" class="dialog-focus">
|
||||
<sl-input placeholder="I will have focus when the dialog is opened"></sl-input>
|
||||
<sl-input autofocus placeholder="I will have focus when the dialog is opened"></sl-input>
|
||||
<sl-button slot="footer" variant="primary">Close</sl-button>
|
||||
</sl-dialog>
|
||||
|
||||
@@ -240,31 +286,20 @@ By default, the dialog's panel will gain focus when opened. This allows a subseq
|
||||
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
|
||||
dialog.addEventListener('sl-initial-focus', event => {
|
||||
event.preventDefault();
|
||||
input.focus({ preventScroll: true });
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { useRef, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { SlButton, SlDialog, SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const input = useRef(null);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
function handleInitialFocus(event) {
|
||||
event.preventDefault();
|
||||
input.current.focus();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlDialog label="Dialog" open={open} onSlInitialFocus={handleInitialFocus} onSlAfterHide={() => setOpen(false)}>
|
||||
<SlInput ref={input} placeholder="I will have focus when the dialog is opened" />
|
||||
<SlDialog label="Dialog" open={open} onSlAfterHide={() => setOpen(false)}>
|
||||
<SlInput autofocus placeholder="I will have focus when the dialog is opened" />
|
||||
<SlButton slot="footer" variant="primary" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
</SlButton>
|
||||
@@ -276,4 +311,6 @@ const App = () => {
|
||||
};
|
||||
```
|
||||
|
||||
?> You can further customize initial focus behavior by canceling the `sl-initial-focus` event and setting focus yourself inside the event handler.
|
||||
|
||||
[component-metadata:sl-dialog]
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-divider]
|
||||
|
||||
Dividers are used to visually separate or group elements.
|
||||
|
||||
```html preview
|
||||
<sl-divider></sl-divider>
|
||||
```
|
||||
@@ -11,10 +9,9 @@ Dividers are used to visually separate or group elements.
|
||||
```jsx react
|
||||
import { SlDivider } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlDivider />
|
||||
);
|
||||
const App = () => <SlDivider />;
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Width
|
||||
@@ -28,9 +25,7 @@ Use the `--width` custom property to change the width of the divider.
|
||||
```jsx react
|
||||
import { SlDivider } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlDivider style={{ '--width': '4px' }} />
|
||||
);
|
||||
const App = () => <SlDivider style={{ '--width': '4px' }} />;
|
||||
```
|
||||
|
||||
### Color
|
||||
@@ -44,9 +39,7 @@ Use the `--color` custom property to change the color of the divider.
|
||||
```jsx react
|
||||
import { SlDivider } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlDivider style={{ '--color': 'tomato' }} />
|
||||
);
|
||||
const App = () => <SlDivider style={{ '--color': 'tomato' }} />;
|
||||
```
|
||||
|
||||
### Spacing
|
||||
@@ -91,10 +84,10 @@ Add the `vertical` attribute to draw the divider in a vertical orientation. The
|
||||
import { SlDivider } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
height: '2rem'
|
||||
}}
|
||||
>
|
||||
@@ -112,7 +105,7 @@ const App = () => (
|
||||
Use dividers in [menus](/components/menu) to visually group menu items.
|
||||
|
||||
```html preview
|
||||
<sl-menu style="max-width: 200px; border: solid 1px var(--sl-panel-border-color); background: var(--sl-panel-background-color); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu style="max-width: 200px;">
|
||||
<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>
|
||||
@@ -124,20 +117,10 @@ Use dividers in [menus](/components/menu) to visually group menu items.
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlDivider,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlDivider, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlMenu
|
||||
style={{
|
||||
maxWidth: '200px',
|
||||
border: 'solid 1px var(--sl-panel-border-color)',
|
||||
borderRadius: 'var(--sl-border-radius-medium)'
|
||||
}}
|
||||
>
|
||||
<SlMenu style={{ maxWidth: '200px' }}>
|
||||
<SlMenuItem value="1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="3">Option 3</SlMenuItem>
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
[component-header:sl-drawer]
|
||||
|
||||
Drawers slide in from a container to expose additional options and information.
|
||||
|
||||
```html preview
|
||||
<sl-drawer label="Drawer" class="drawer-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
@@ -182,7 +180,9 @@ const App = () => {
|
||||
|
||||
### 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` attribute and `position: relative` to the parent.
|
||||
By default, drawers slide out of their [containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#Identifying_the_containing_block), which is usually the viewport. To make a drawer slide out of a parent element, add the `contained` attribute to the drawer and apply `position: relative` to its parent.
|
||||
|
||||
Unlike normal drawers, contained drawers are not modal. This means they do not show an overlay, they do not trap focus, and they are not dismissible with <kbd>Escape</kbd>. This is intentional to allow users to interact with elements outside of the drawer.
|
||||
|
||||
```html preview
|
||||
<div
|
||||
@@ -196,14 +196,14 @@ By default, the drawer slides out of its [containing block](https://developer.mo
|
||||
</sl-drawer>
|
||||
</div>
|
||||
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
<sl-button>Toggle Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
const drawer = document.querySelector('.drawer-contained');
|
||||
const openButton = drawer.parentElement.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[variant="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
openButton.addEventListener('click', () => (drawer.open = !drawer.open));
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
</script>
|
||||
```
|
||||
@@ -228,7 +228,14 @@ const App = () => {
|
||||
>
|
||||
The drawer will be contained to this box. This content won't shift or be affected in any way when the drawer
|
||||
opens.
|
||||
<SlDrawer label="Drawer" contained open={open} onSlAfterHide={() => setOpen(false)} style={{ '--size': '50%' }}>
|
||||
<SlDrawer
|
||||
label="Drawer"
|
||||
contained
|
||||
no-modal
|
||||
open={open}
|
||||
onSlAfterHide={() => setOpen(false)}
|
||||
style={{ '--size': '50%' }}
|
||||
>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<SlButton slot="footer" variant="primary" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -340,6 +347,54 @@ const App = () => {
|
||||
};
|
||||
```
|
||||
|
||||
### Header Actions
|
||||
|
||||
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/components/icon-button) if needed.
|
||||
|
||||
```html preview
|
||||
<sl-drawer label="Drawer" class="drawer-header-actions">
|
||||
<sl-icon-button class="new-window" slot="header-actions" name="box-arrow-up-right"></sl-icon-button>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<sl-button slot="footer" variant="primary">Close</sl-button>
|
||||
</sl-drawer>
|
||||
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
const drawer = document.querySelector('.drawer-header-actions');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[variant="primary"]');
|
||||
const newWindowButton = drawer.querySelector('.new-window');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
newWindowButton.addEventListener('click', () => window.open(location.href));
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { useState } from 'react';
|
||||
import { SlButton, SlDrawer, SlIconButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlDrawer label="Drawer" open={open} onSlAfterHide={() => setOpen(false)}>
|
||||
<SlIconButton slot="header-actions" name="box-arrow-up-right" onClick={() => window.open(location.href)} />
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<SlButton slot="footer" variant="primary" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
</SlButton>
|
||||
</SlDrawer>
|
||||
|
||||
<SlButton onClick={() => setOpen(true)}>Open Drawer</SlButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### 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.
|
||||
@@ -370,7 +425,6 @@ You can use `event.detail.source` to determine what triggered the request to clo
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -390,12 +444,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlDrawer
|
||||
label="Drawer"
|
||||
open={open}
|
||||
onSlRequestClose={handleRequestClose}
|
||||
onSlAfterHide={() => setOpen(false)}
|
||||
>
|
||||
<SlDrawer label="Drawer" open={open} onSlRequestClose={handleRequestClose} onSlAfterHide={() => setOpen(false)}>
|
||||
This drawer will not close when you click on the overlay.
|
||||
<SlButton slot="footer" variant="primary" onClick={() => setOpen(false)}>
|
||||
Save & Close
|
||||
@@ -410,11 +459,11 @@ const App = () => {
|
||||
|
||||
### Customizing Initial Focus
|
||||
|
||||
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.
|
||||
By default, the drawer's panel will gain focus when opened. This allows a subsequent tab press to focus on the first tabbable element in the drawer. If you want a different element to have focus, add the `autofocus` attribute to it as shown below.
|
||||
|
||||
```html preview
|
||||
<sl-drawer label="Drawer" class="drawer-focus">
|
||||
<sl-input placeholder="I will have focus when the drawer is opened"></sl-input>
|
||||
<sl-input autofocus placeholder="I will have focus when the drawer is opened"></sl-input>
|
||||
<sl-button slot="footer" variant="primary">Close</sl-button>
|
||||
</sl-drawer>
|
||||
|
||||
@@ -428,31 +477,20 @@ By default, the drawer's panel will gain focus when opened. This allows the firs
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
|
||||
drawer.addEventListener('sl-initial-focus', event => {
|
||||
event.preventDefault();
|
||||
input.focus({ preventScroll: true });
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { useRef, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { SlButton, SlDrawer, SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const input = useRef(null);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
function handleInitialFocus(event) {
|
||||
event.preventDefault();
|
||||
input.current.focus();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlDrawer label="Drawer" open={open} onSlInitialFocus={handleInitialFocus} onSlAfterHide={() => setOpen(false)}>
|
||||
<SlInput ref={input} placeholder="I will have focus when the drawer is opened" />
|
||||
<SlDrawer label="Drawer" open={open} onSlAfterHide={() => setOpen(false)}>
|
||||
<SlInput autofocus placeholder="I will have focus when the drawer is opened" />
|
||||
<SlButton slot="footer" variant="primary" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
</SlButton>
|
||||
@@ -464,4 +502,5 @@ const App = () => {
|
||||
};
|
||||
```
|
||||
|
||||
?> You can further customize initial focus behavior by canceling the `sl-initial-focus` event and setting focus yourself inside the event handler.
|
||||
[component-metadata:sl-drawer]
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-dropdown]
|
||||
|
||||
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) 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.
|
||||
@@ -16,7 +14,7 @@ Dropdowns are designed to work well with [menus](/components/menu) to provide a
|
||||
<sl-menu-item>Dropdown Item 2</sl-menu-item>
|
||||
<sl-menu-item>Dropdown Item 3</sl-menu-item>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item checked>Checked</sl-menu-item>
|
||||
<sl-menu-item type="checkbox" checked>Checkbox</sl-menu-item>
|
||||
<sl-menu-item disabled>Disabled</sl-menu-item>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item>
|
||||
@@ -32,24 +30,21 @@ Dropdowns are designed to work well with [menus](/components/menu) to provide a
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlDivider,
|
||||
SlDropdown,
|
||||
SlIcon,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlDivider, SlDropdown, SlIcon, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlDropdown>
|
||||
<SlButton slot="trigger" caret>Dropdown</SlButton>
|
||||
<SlButton slot="trigger" caret>
|
||||
Dropdown
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem>Dropdown Item 1</SlMenuItem>
|
||||
<SlMenuItem>Dropdown Item 2</SlMenuItem>
|
||||
<SlMenuItem>Dropdown Item 3</SlMenuItem>
|
||||
<SlDivider />
|
||||
<SlMenuItem checked>Checked</SlMenuItem>
|
||||
<SlMenuItem type="checkbox" checked>
|
||||
Checkbox
|
||||
</SlMenuItem>
|
||||
<SlMenuItem disabled>Disabled</SlMenuItem>
|
||||
<SlDivider />
|
||||
<SlMenuItem>
|
||||
@@ -61,7 +56,7 @@ const App = () => (
|
||||
<SlIcon slot="suffix" name="heart" />
|
||||
</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlDropdown>
|
||||
</SlDropdown>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -69,7 +64,7 @@ const App = () => (
|
||||
|
||||
### 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.
|
||||
When dropdowns are used with [menus](/components/menu), you can listen for the [`sl-select`](/components/menu#events) 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">
|
||||
@@ -95,12 +90,7 @@ When dropdowns are used with [menus](/components/menu), you can listen for the `
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlDropdown,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlDropdown, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
function handleSelect(event) {
|
||||
@@ -110,13 +100,15 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<SlDropdown>
|
||||
<SlButton slot="trigger" caret>Edit</SlButton>
|
||||
<SlButton slot="trigger" caret>
|
||||
Edit
|
||||
</SlButton>
|
||||
<SlMenu onSlSelect={handleSelect}>
|
||||
<SlMenuItem value="cut">Cut</SlMenuItem>
|
||||
<SlMenuItem value="copy">Copy</SlMenuItem>
|
||||
<SlMenuItem value="paste">Paste</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlDropdown>
|
||||
</SlDropdown>
|
||||
);
|
||||
};
|
||||
```
|
||||
@@ -148,12 +140,7 @@ Alternatively, you can listen for the `click` event on individual menu items. No
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlDropdown,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlDropdown, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
function handleCut() {
|
||||
@@ -170,13 +157,15 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<SlDropdown>
|
||||
<SlButton slot="trigger" caret>Edit</SlButton>
|
||||
<SlButton slot="trigger" caret>
|
||||
Edit
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem onClick={handleCut}>Cut</SlMenuItem>
|
||||
<SlMenuItem onClick={handleCopy}>Copy</SlMenuItem>
|
||||
<SlMenuItem onClick={handlePaste}>Paste</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlDropdown>
|
||||
</SlDropdown>
|
||||
);
|
||||
};
|
||||
```
|
||||
@@ -200,17 +189,13 @@ The preferred placement of the dropdown can be set with the `placement` attribut
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlDivider,
|
||||
SlDropdown,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlDivider, SlDropdown, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlDropdown placement="top-start">
|
||||
<SlButton slot="trigger" caret>Edit</SlButton>
|
||||
<SlButton slot="trigger" caret>
|
||||
Edit
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem>Cut</SlMenuItem>
|
||||
<SlMenuItem>Copy</SlMenuItem>
|
||||
@@ -219,7 +204,7 @@ const App = () => (
|
||||
<SlMenuItem>Find</SlMenuItem>
|
||||
<SlMenuItem>Replace</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlDropdown>
|
||||
</SlDropdown>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -242,17 +227,13 @@ The distance from the panel to the trigger can be customized using the `distance
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlDivider,
|
||||
SlDropdown,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlDivider, SlDropdown, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlDropdown distance={30}>
|
||||
<SlButton slot="trigger" caret>Edit</SlButton>
|
||||
<SlButton slot="trigger" caret>
|
||||
Edit
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem>Cut</SlMenuItem>
|
||||
<SlMenuItem>Copy</SlMenuItem>
|
||||
@@ -261,7 +242,7 @@ const App = () => (
|
||||
<SlMenuItem>Find</SlMenuItem>
|
||||
<SlMenuItem>Replace</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlDropdown>
|
||||
</SlDropdown>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -284,17 +265,13 @@ The offset of the panel along the trigger can be customized using the `skidding`
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlDivider,
|
||||
SlDropdown,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlDivider, SlDropdown, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlDropdown skidding={30}>
|
||||
<SlButton slot="trigger" caret>Edit</SlButton>
|
||||
<SlButton slot="trigger" caret>
|
||||
Edit
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem>Cut</SlMenuItem>
|
||||
<SlMenuItem>Copy</SlMenuItem>
|
||||
@@ -303,7 +280,7 @@ const App = () => (
|
||||
<SlMenuItem>Find</SlMenuItem>
|
||||
<SlMenuItem>Replace</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlDropdown>
|
||||
</SlDropdown>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -334,6 +311,7 @@ Dropdown panels will be clipped if they're inside a container that has `overflow
|
||||
|
||||
<style>
|
||||
.dropdown-hoist {
|
||||
position: relative;
|
||||
border: solid 2px var(--sl-panel-border-color);
|
||||
padding: var(--sl-spacing-medium);
|
||||
overflow: hidden;
|
||||
@@ -342,14 +320,7 @@ Dropdown panels will be clipped if they're inside a container that has `overflow
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlDivider,
|
||||
SlDropdown,
|
||||
SlIcon,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlDivider, SlDropdown, SlIcon, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const css = `
|
||||
.dropdown-hoist {
|
||||
@@ -363,7 +334,9 @@ const App = () => (
|
||||
<>
|
||||
<div className="dropdown-hoist">
|
||||
<SlDropdown>
|
||||
<SlButton slot="trigger" caret>No Hoist</SlButton>
|
||||
<SlButton slot="trigger" caret>
|
||||
No Hoist
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem>Item 1</SlMenuItem>
|
||||
<SlMenuItem>Item 2</SlMenuItem>
|
||||
@@ -372,7 +345,9 @@ const App = () => (
|
||||
</SlDropdown>
|
||||
|
||||
<SlDropdown hoist>
|
||||
<SlButton slot="trigger" caret>Hoist</SlButton>
|
||||
<SlButton slot="trigger" caret>
|
||||
Hoist
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem>Item 1</SlMenuItem>
|
||||
<SlMenuItem>Item 2</SlMenuItem>
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
|
||||
[component-header:sl-format-bytes]
|
||||
|
||||
Formats a number as a human readable bytes value.
|
||||
|
||||
```html preview
|
||||
<div class="format-bytes-overview">
|
||||
The file is <sl-format-bytes value="1000"></sl-format-bytes> in size.
|
||||
<br><br>
|
||||
<sl-input type="number" value="1000" label="Number to Format" style="max-width: 180px;"></sl-input>
|
||||
The file is <sl-format-bytes value="1000"></sl-format-bytes> in size. <br /><br />
|
||||
<sl-input type="number" value="1000" label="Number to Format" style="max-width: 180px;"></sl-input>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -16,18 +13,13 @@ Formats a number as a human readable bytes value.
|
||||
const formatter = container.querySelector('sl-format-bytes');
|
||||
const input = container.querySelector('sl-input');
|
||||
|
||||
input.addEventListener('sl-input', () => formatter.value = input.value || 0);
|
||||
input.addEventListener('sl-input', () => (formatter.value = input.value || 0));
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
```jsx react
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
SlButton,
|
||||
SlFormatBytes,
|
||||
SlInput
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlFormatBytes, SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const [value, setValue] = useState(1000);
|
||||
@@ -35,11 +27,12 @@ const App = () => {
|
||||
return (
|
||||
<>
|
||||
The file is <SlFormatBytes value={value} /> in size.
|
||||
<br /><br />
|
||||
<SlInput
|
||||
type="number"
|
||||
<br />
|
||||
<br />
|
||||
<SlInput
|
||||
type="number"
|
||||
value={value}
|
||||
label="Number to Format"
|
||||
label="Number to Format"
|
||||
style={{ maxWidth: '180px' }}
|
||||
onSlInput={event => setValue(event.target.value)}
|
||||
/>
|
||||
@@ -55,21 +48,23 @@ const App = () => {
|
||||
Set the `value` attribute to a number to get the value in bytes.
|
||||
|
||||
```html preview
|
||||
<sl-format-bytes value="12"></sl-format-bytes><br>
|
||||
<sl-format-bytes value="1200"></sl-format-bytes><br>
|
||||
<sl-format-bytes value="1200000"></sl-format-bytes><br>
|
||||
<sl-format-bytes value="12"></sl-format-bytes><br />
|
||||
<sl-format-bytes value="1200"></sl-format-bytes><br />
|
||||
<sl-format-bytes value="1200000"></sl-format-bytes><br />
|
||||
<sl-format-bytes value="1200000000"></sl-format-bytes>
|
||||
```
|
||||
|
||||
|
||||
```jsx react
|
||||
import { SlFormatBytes } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlFormatBytes value="12" /><br />
|
||||
<SlFormatBytes value="1200" /><br />
|
||||
<SlFormatBytes value="1200000" /><br />
|
||||
<SlFormatBytes value="12" />
|
||||
<br />
|
||||
<SlFormatBytes value="1200" />
|
||||
<br />
|
||||
<SlFormatBytes value="1200000" />
|
||||
<br />
|
||||
<SlFormatBytes value="1200000000" />
|
||||
</>
|
||||
);
|
||||
@@ -80,9 +75,9 @@ const App = () => (
|
||||
To get the value in bits, set the `unit` attribute to `bit`.
|
||||
|
||||
```html preview
|
||||
<sl-format-bytes value="12" unit="bit"></sl-format-bytes><br>
|
||||
<sl-format-bytes value="1200" unit="bit"></sl-format-bytes><br>
|
||||
<sl-format-bytes value="1200000" unit="bit"></sl-format-bytes><br>
|
||||
<sl-format-bytes value="12" unit="bit"></sl-format-bytes><br />
|
||||
<sl-format-bytes value="1200" unit="bit"></sl-format-bytes><br />
|
||||
<sl-format-bytes value="1200000" unit="bit"></sl-format-bytes><br />
|
||||
<sl-format-bytes value="1200000000" unit="bit"></sl-format-bytes>
|
||||
```
|
||||
|
||||
@@ -91,9 +86,12 @@ import { SlFormatBytes } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlFormatBytes value="12" unit="bit" /><br />
|
||||
<SlFormatBytes value="1200" unit="bit" /><br />
|
||||
<SlFormatBytes value="1200000" unit="bit" /><br />
|
||||
<SlFormatBytes value="12" unit="bit" />
|
||||
<br />
|
||||
<SlFormatBytes value="1200" unit="bit" />
|
||||
<br />
|
||||
<SlFormatBytes value="1200000" unit="bit" />
|
||||
<br />
|
||||
<SlFormatBytes value="1200000000" unit="bit" />
|
||||
</>
|
||||
);
|
||||
@@ -104,9 +102,9 @@ const App = () => (
|
||||
Use the `lang` attribute to set the number formatting locale.
|
||||
|
||||
```html preview
|
||||
<sl-format-bytes value="12" lang="de"></sl-format-bytes><br>
|
||||
<sl-format-bytes value="1200" lang="de"></sl-format-bytes><br>
|
||||
<sl-format-bytes value="1200000" lang="de"></sl-format-bytes><br>
|
||||
<sl-format-bytes value="12" lang="de"></sl-format-bytes><br />
|
||||
<sl-format-bytes value="1200" lang="de"></sl-format-bytes><br />
|
||||
<sl-format-bytes value="1200000" lang="de"></sl-format-bytes><br />
|
||||
<sl-format-bytes value="1200000000" lang="de"></sl-format-bytes>
|
||||
```
|
||||
|
||||
@@ -115,9 +113,12 @@ import { SlFormatBytes } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlFormatBytes value="12" lang="de" /><br />
|
||||
<SlFormatBytes value="1200" lang="de" /><br />
|
||||
<SlFormatBytes value="1200000" lang="de" /><br />
|
||||
<SlFormatBytes value="12" lang="de" />
|
||||
<br />
|
||||
<SlFormatBytes value="1200" lang="de" />
|
||||
<br />
|
||||
<SlFormatBytes value="1200000" lang="de" />
|
||||
<br />
|
||||
<SlFormatBytes value="1200000000" lang="de" />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-format-date]
|
||||
|
||||
Formats a date/time using the specified locale and options.
|
||||
|
||||
Localization is handled by the browser's [`Intl.DateTimeFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat). No language packs are required.
|
||||
|
||||
```html preview
|
||||
@@ -14,9 +12,7 @@ Localization is handled by the browser's [`Intl.DateTimeFormat` API](https://dev
|
||||
```jsx react
|
||||
import { SlFormatDate } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlFormatDate date="2020-07-15T09:17:00-04:00" />
|
||||
);
|
||||
const App = () => <SlFormatDate date="2020-07-15T09:17:00-04:00" />;
|
||||
```
|
||||
|
||||
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.
|
||||
@@ -31,19 +27,19 @@ Formatting options are based on those found in the [`Intl.DateTimeFormat` API](h
|
||||
|
||||
```html preview
|
||||
<!-- Human-readable date -->
|
||||
<sl-format-date month="long" day="numeric" year="numeric"></sl-format-date><br>
|
||||
<sl-format-date month="long" day="numeric" year="numeric"></sl-format-date><br />
|
||||
|
||||
<!-- Time -->
|
||||
<sl-format-date hour="numeric" minute="numeric"></sl-format-date><br>
|
||||
<sl-format-date hour="numeric" minute="numeric"></sl-format-date><br />
|
||||
|
||||
<!-- Weekday -->
|
||||
<sl-format-date weekday="long"></sl-format-date><br>
|
||||
<sl-format-date weekday="long"></sl-format-date><br />
|
||||
|
||||
<!-- Month -->
|
||||
<sl-format-date month="long"></sl-format-date><br>
|
||||
<sl-format-date month="long"></sl-format-date><br />
|
||||
|
||||
<!-- Year -->
|
||||
<sl-format-date year="numeric"></sl-format-date><br>
|
||||
<sl-format-date year="numeric"></sl-format-date><br />
|
||||
|
||||
<!-- No formatting options -->
|
||||
<sl-format-date></sl-format-date>
|
||||
@@ -55,19 +51,24 @@ import { SlFormatDate } from '@shoelace-style/shoelace/dist/react';
|
||||
const App = () => (
|
||||
<>
|
||||
{/* Human-readable date */}
|
||||
<SlFormatDate month="long" day="numeric" year="numeric" /><br />
|
||||
<SlFormatDate month="long" day="numeric" year="numeric" />
|
||||
<br />
|
||||
|
||||
{/* Time */}
|
||||
<SlFormatDate hour="numeric" minute="numeric" /><br />
|
||||
<SlFormatDate hour="numeric" minute="numeric" />
|
||||
<br />
|
||||
|
||||
{/* Weekday */}
|
||||
<SlFormatDate weekday="long" /><br />
|
||||
<SlFormatDate weekday="long" />
|
||||
<br />
|
||||
|
||||
{/* Month */}
|
||||
<SlFormatDate month="long" /><br />
|
||||
<SlFormatDate month="long" />
|
||||
<br />
|
||||
|
||||
{/* Year */}
|
||||
<SlFormatDate year="numeric" /><br />
|
||||
<SlFormatDate year="numeric" />
|
||||
<br />
|
||||
|
||||
{/* No formatting options */}
|
||||
<SlFormatDate />
|
||||
@@ -80,7 +81,7 @@ const App = () => (
|
||||
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>
|
||||
<sl-format-date hour="numeric" minute="numeric" hour-format="12"></sl-format-date><br />
|
||||
<sl-format-date hour="numeric" minute="numeric" hour-format="24"></sl-format-date>
|
||||
```
|
||||
|
||||
@@ -89,7 +90,8 @@ import { SlFormatDate } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlFormatDate hour="numeric" minute="numeric" hour-format="12" /><br />
|
||||
<SlFormatDate hour="numeric" minute="numeric" hour-format="12" />
|
||||
<br />
|
||||
<SlFormatDate hour="numeric" minute="numeric" hour-format="24" />
|
||||
</>
|
||||
);
|
||||
@@ -100,8 +102,8 @@ const App = () => (
|
||||
Use the `lang` attribute to set the date/time formatting locale.
|
||||
|
||||
```html preview
|
||||
English: <sl-format-date lang="en"></sl-format-date><br>
|
||||
French: <sl-format-date lang="fr"></sl-format-date><br>
|
||||
English: <sl-format-date lang="en"></sl-format-date><br />
|
||||
French: <sl-format-date lang="fr"></sl-format-date><br />
|
||||
Russian: <sl-format-date lang="ru"></sl-format-date>
|
||||
```
|
||||
|
||||
@@ -110,8 +112,10 @@ import { SlFormatDate } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
English: <SlFormatDate lang="en" /><br />
|
||||
French: <SlFormatDate lang="fr" /><br />
|
||||
English: <SlFormatDate lang="en" />
|
||||
<br />
|
||||
French: <SlFormatDate lang="fr" />
|
||||
<br />
|
||||
Russian: <SlFormatDate lang="ru" />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,15 +2,13 @@
|
||||
|
||||
[component-header:sl-format-number]
|
||||
|
||||
Formats a number using the specified locale and options.
|
||||
|
||||
Localization is handled by the browser's [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat). No language packs are required.
|
||||
|
||||
```html preview
|
||||
<div class="format-number-overview">
|
||||
<sl-format-number value="1000"></sl-format-number>
|
||||
<br><br>
|
||||
<sl-input type="number" value="1000" label="Number to Format" style="max-width: 180px;"></sl-input>
|
||||
<sl-format-number value="1000"></sl-format-number>
|
||||
<br /><br />
|
||||
<sl-input type="number" value="1000" label="Number to Format" style="max-width: 180px;"></sl-input>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -18,7 +16,7 @@ Localization is handled by the browser's [`Intl.NumberFormat` API](https://devel
|
||||
const formatter = container.querySelector('sl-format-number');
|
||||
const input = container.querySelector('sl-input');
|
||||
|
||||
input.addEventListener('sl-input', () => formatter.value = input.value || 0);
|
||||
input.addEventListener('sl-input', () => (formatter.value = input.value || 0));
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -32,11 +30,12 @@ const App = () => {
|
||||
return (
|
||||
<>
|
||||
<SlFormatNumber value={value} />
|
||||
<br /><br />
|
||||
<SlInput
|
||||
type="number"
|
||||
value={value}
|
||||
label="Number to Format"
|
||||
<br />
|
||||
<br />
|
||||
<SlInput
|
||||
type="number"
|
||||
value={value}
|
||||
label="Number to Format"
|
||||
style={{ maxWidth: '180px' }}
|
||||
onSlInput={event => setValue(event.target.value)}
|
||||
/>
|
||||
@@ -52,10 +51,10 @@ const App = () => {
|
||||
To get the value as a percent, set the `type` attribute to `percent`.
|
||||
|
||||
```html preview
|
||||
<sl-format-number type="percent" value="0"></sl-format-number><br>
|
||||
<sl-format-number type="percent" value="0.25"></sl-format-number><br>
|
||||
<sl-format-number type="percent" value="0.50"></sl-format-number><br>
|
||||
<sl-format-number type="percent" value="0.75"></sl-format-number><br>
|
||||
<sl-format-number type="percent" value="0"></sl-format-number><br />
|
||||
<sl-format-number type="percent" value="0.25"></sl-format-number><br />
|
||||
<sl-format-number type="percent" value="0.50"></sl-format-number><br />
|
||||
<sl-format-number type="percent" value="0.75"></sl-format-number><br />
|
||||
<sl-format-number type="percent" value="1"></sl-format-number>
|
||||
```
|
||||
|
||||
@@ -64,11 +63,15 @@ import { SlFormatNumber } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlFormatNumber type="percent" value={0} /><br />
|
||||
<SlFormatNumber type="percent" value={0.25} /><br />
|
||||
<SlFormatNumber type="percent" value={0.50} /><br />
|
||||
<SlFormatNumber type="percent" value={0.75} /><br />
|
||||
<SlFormatNumber type="percent" value={1} />
|
||||
<SlFormatNumber type="percent" value={0} />
|
||||
<br />
|
||||
<SlFormatNumber type="percent" value={0.25} />
|
||||
<br />
|
||||
<SlFormatNumber type="percent" value={0.5} />
|
||||
<br />
|
||||
<SlFormatNumber type="percent" value={0.75} />
|
||||
<br />
|
||||
<SlFormatNumber type="percent" value={1} />
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -78,8 +81,8 @@ const App = () => (
|
||||
Use the `lang` attribute to set the number formatting locale.
|
||||
|
||||
```html preview
|
||||
English: <sl-format-number value="2000" lang="en" minimum-fraction-digits="2"></sl-format-number><br>
|
||||
German: <sl-format-number value="2000" lang="de" minimum-fraction-digits="2"></sl-format-number><br>
|
||||
English: <sl-format-number value="2000" lang="en" minimum-fraction-digits="2"></sl-format-number><br />
|
||||
German: <sl-format-number value="2000" lang="de" minimum-fraction-digits="2"></sl-format-number><br />
|
||||
Russian: <sl-format-number value="2000" lang="ru" minimum-fraction-digits="2"></sl-format-number>
|
||||
```
|
||||
|
||||
@@ -88,8 +91,10 @@ import { SlFormatNumber } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
English: <SlFormatNumber value="2000" lang="en" minimum-fraction-digits="2" /><br />
|
||||
German: <SlFormatNumber value="2000" lang="de" minimum-fraction-digits="2" /><br />
|
||||
English: <SlFormatNumber value="2000" lang="en" minimum-fraction-digits="2" />
|
||||
<br />
|
||||
German: <SlFormatNumber value="2000" lang="de" minimum-fraction-digits="2" />
|
||||
<br />
|
||||
Russian: <SlFormatNumber value="2000" lang="ru" minimum-fraction-digits="2" />
|
||||
</>
|
||||
);
|
||||
@@ -100,10 +105,10 @@ const App = () => (
|
||||
To format a number as a monetary value, set the `type` attribute to `currency` and set the `currency` attribute to the desired ISO 4217 currency code. You should also specify `lang` to ensure the the number is formatted correctly for the target locale.
|
||||
|
||||
```html preview
|
||||
<sl-format-number type="currency" currency="USD" value="2000" lang="en-US"></sl-format-number><br>
|
||||
<sl-format-number type="currency" currency="GBP" value="2000" lang="en-GB"></sl-format-number><br>
|
||||
<sl-format-number type="currency" currency="EUR" value="2000" lang="de"></sl-format-number><br>
|
||||
<sl-format-number type="currency" currency="RUB" value="2000" lang="ru"></sl-format-number><br>
|
||||
<sl-format-number type="currency" currency="USD" value="2000" lang="en-US"></sl-format-number><br />
|
||||
<sl-format-number type="currency" currency="GBP" value="2000" lang="en-GB"></sl-format-number><br />
|
||||
<sl-format-number type="currency" currency="EUR" value="2000" lang="de"></sl-format-number><br />
|
||||
<sl-format-number type="currency" currency="RUB" value="2000" lang="ru"></sl-format-number><br />
|
||||
<sl-format-number type="currency" currency="CNY" value="2000" lang="zh-cn"></sl-format-number>
|
||||
```
|
||||
|
||||
@@ -112,10 +117,14 @@ import { SlFormatNumber } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlFormatNumber type="currency" currency="USD" value="2000" lang="en-US" /><br />
|
||||
<SlFormatNumber type="currency" currency="GBP" value="2000" lang="en-GB" /><br />
|
||||
<SlFormatNumber type="currency" currency="EUR" value="2000" lang="de" /><br />
|
||||
<SlFormatNumber type="currency" currency="RUB" value="2000" lang="ru" /><br />
|
||||
<SlFormatNumber type="currency" currency="USD" value="2000" lang="en-US" />
|
||||
<br />
|
||||
<SlFormatNumber type="currency" currency="GBP" value="2000" lang="en-GB" />
|
||||
<br />
|
||||
<SlFormatNumber type="currency" currency="EUR" value="2000" lang="de" />
|
||||
<br />
|
||||
<SlFormatNumber type="currency" currency="RUB" value="2000" lang="ru" />
|
||||
<br />
|
||||
<SlFormatNumber type="currency" currency="CNY" value="2000" lang="zh-cn" />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-icon-button]
|
||||
|
||||
Icons buttons are simple, icon-only buttons that can be used for actions and in toolbars.
|
||||
|
||||
For a full list of icons that come bundled with Shoelace, refer to the [icon component](/components/icon).
|
||||
|
||||
```html preview
|
||||
@@ -13,9 +11,7 @@ For a full list of icons that come bundled with Shoelace, refer to the [icon com
|
||||
```jsx react
|
||||
import { SlIconButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlIconButton name="gear" label="Settings" />
|
||||
);
|
||||
const App = () => <SlIconButton name="gear" label="Settings" />;
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -111,14 +107,7 @@ Use the `href` attribute to convert the button to a link.
|
||||
```jsx react
|
||||
import { SlIconButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlIconButton
|
||||
name="gear"
|
||||
label="Settings"
|
||||
href="https://example.com"
|
||||
target="_blank"
|
||||
/>
|
||||
);
|
||||
const App = () => <SlIconButton name="gear" label="Settings" href="https://example.com" target="_blank" />;
|
||||
```
|
||||
|
||||
### Icon Button with Tooltip
|
||||
@@ -152,9 +141,7 @@ Use the `disabled` attribute to disable the icon button.
|
||||
```jsx react
|
||||
import { SlIconButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlIconButton name="gear" label="Settings" disabled />
|
||||
);
|
||||
const App = () => <SlIconButton name="gear" label="Settings" disabled />;
|
||||
```
|
||||
|
||||
[component-metadata:sl-icon-button]
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
[component-header:sl-icon]
|
||||
|
||||
Icons are symbols that can be used to represent various options within an application.
|
||||
|
||||
Shoelace comes bundled with over 1,500 icons courtesy of the [Bootstrap Icons](https://icons.getbootstrap.com/) project. These icons are part of the `default` icon library. If you prefer, you can register [custom icon libraries](#icon-libraries) as well.
|
||||
|
||||
Click or tap on an icon below to copy its name and use it like this.
|
||||
?> Depending on how you're loading Shoelace, you may need to copy icon assets and/or [set the base path](getting-started/installation#setting-the-base-path) so Shoelace knows where to load them from. Otherwise, icons may not appear and you'll see 404 Not Found errors in the dev console.
|
||||
|
||||
## Default Icons
|
||||
|
||||
All available icons in the `default` icon library are shown below. Click or tap on any icon to copy its name, then you can use it in your HTML like this.
|
||||
|
||||
```html
|
||||
<sl-icon name="icon-name-here"></sl-icon>
|
||||
@@ -18,17 +20,81 @@ Click or tap on an icon below to copy its name and use it like this.
|
||||
<sl-icon slot="prefix" name="search"></sl-icon>
|
||||
</sl-input>
|
||||
<sl-select value="outline">
|
||||
<sl-menu-item value="outline">Outlined</sl-menu-item>
|
||||
<sl-menu-item value="fill">Filled</sl-menu-item>
|
||||
<sl-menu-item value="all">All icons</sl-menu-item>
|
||||
<sl-option value="outline">Outlined</sl-option>
|
||||
<sl-option value="fill">Filled</sl-option>
|
||||
<sl-option value="all">All icons</sl-option>
|
||||
</sl-select>
|
||||
</div>
|
||||
<div class="icon-list"></div>
|
||||
<input type="text" class="icon-copy-input">
|
||||
<input type="text" class="icon-copy-input" aria-hidden="true" tabindex="-1">
|
||||
</div>
|
||||
|
||||
## Examples
|
||||
|
||||
### Colors
|
||||
|
||||
Icons inherit their color from the current text color. Thus, you can set the `color` property on the `<sl-icon>` element or an ancestor to change the color.
|
||||
|
||||
```html preview
|
||||
<div style="color: #4a90e2;">
|
||||
<sl-icon name="exclamation-triangle"></sl-icon>
|
||||
<sl-icon name="archive"></sl-icon>
|
||||
<sl-icon name="battery-charging"></sl-icon>
|
||||
<sl-icon name="bell"></sl-icon>
|
||||
</div>
|
||||
<div style="color: #9013fe;">
|
||||
<sl-icon name="clock"></sl-icon>
|
||||
<sl-icon name="cloud"></sl-icon>
|
||||
<sl-icon name="download"></sl-icon>
|
||||
<sl-icon name="file-earmark"></sl-icon>
|
||||
</div>
|
||||
<div style="color: #417505;">
|
||||
<sl-icon name="flag"></sl-icon>
|
||||
<sl-icon name="heart"></sl-icon>
|
||||
<sl-icon name="image"></sl-icon>
|
||||
<sl-icon name="lightning"></sl-icon>
|
||||
</div>
|
||||
<div style="color: #f5a623;">
|
||||
<sl-icon name="mic"></sl-icon>
|
||||
<sl-icon name="search"></sl-icon>
|
||||
<sl-icon name="star"></sl-icon>
|
||||
<sl-icon name="trash"></sl-icon>
|
||||
</div>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlIcon } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<div style={{ color: '#4a90e2' }}>
|
||||
<SlIcon name="exclamation-triangle"></SlIcon>
|
||||
<SlIcon name="archive"></SlIcon>
|
||||
<SlIcon name="battery-charging"></SlIcon>
|
||||
<SlIcon name="bell"></SlIcon>
|
||||
</div>
|
||||
<div style={{ color: '#9013fe' }}>
|
||||
<SlIcon name="clock"></SlIcon>
|
||||
<SlIcon name="cloud"></SlIcon>
|
||||
<SlIcon name="download"></SlIcon>
|
||||
<SlIcon name="file-earmark"></SlIcon>
|
||||
</div>
|
||||
<div style={{ color: '#417505' }}>
|
||||
<SlIcon name="flag"></SlIcon>
|
||||
<SlIcon name="heart"></SlIcon>
|
||||
<SlIcon name="image"></SlIcon>
|
||||
<SlIcon name="lightning"></SlIcon>
|
||||
</div>
|
||||
<div style={{ color: '#f5a623' }}>
|
||||
<SlIcon name="mic"></SlIcon>
|
||||
<SlIcon name="search"></SlIcon>
|
||||
<SlIcon name="star"></SlIcon>
|
||||
<SlIcon name="trash"></SlIcon>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Sizing
|
||||
|
||||
Icons are sized relative to the current font size. To change their size, set the `font-size` property on the icon itself or on a parent element as shown below.
|
||||
@@ -75,7 +141,7 @@ const App = () => (
|
||||
<SlIcon name="search" />
|
||||
<SlIcon name="star" />
|
||||
<SlIcon name="trash" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -90,9 +156,7 @@ For non-decorative icons, use the `label` attribute to announce it to assistive
|
||||
```jsx react
|
||||
import { SlIcon } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlIcon name="star-fill" label="Add to favorites" />
|
||||
);
|
||||
const App = () => <SlIcon name="star-fill" label="Add to favorites" />;
|
||||
```
|
||||
|
||||
### Custom Icons
|
||||
@@ -103,13 +167,10 @@ Custom icons can be loaded individually with the `src` attribute. Only SVGs on a
|
||||
<sl-icon src="https://shoelace.style/assets/images/shoe.svg" style="font-size: 8rem;"></sl-icon>
|
||||
```
|
||||
|
||||
|
||||
```jsx react
|
||||
import { SlIcon } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlIcon src="https://shoelace.style/assets/images/shoe.svg" style={{ fontSize: '8rem' }}></SlIcon>
|
||||
);
|
||||
const App = () => <SlIcon src="https://shoelace.style/assets/images/shoe.svg" style={{ fontSize: '8rem' }}></SlIcon>;
|
||||
```
|
||||
|
||||
## Icon Libraries
|
||||
@@ -163,7 +224,7 @@ Icons in this library are licensed under the [Creative Commons 4.0 License](http
|
||||
if (name.substring(0, 4) === 'bxl-') folder = 'logos';
|
||||
return `https://cdn.jsdelivr.net/npm/boxicons@2.0.5/svg/${folder}/${name}.svg`;
|
||||
},
|
||||
mutator:svg => svg.setAttribute('fill', 'currentColor')
|
||||
mutator: svg => svg.setAttribute('fill', 'currentColor')
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -174,14 +235,14 @@ Icons in this library are licensed under the [Creative Commons 4.0 License](http
|
||||
<sl-icon library="boxicons" name="bx-save"></sl-icon>
|
||||
<sl-icon library="boxicons" name="bx-server"></sl-icon>
|
||||
<sl-icon library="boxicons" name="bx-wine"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="boxicons" name="bxs-bot"></sl-icon>
|
||||
<sl-icon library="boxicons" name="bxs-cookie"></sl-icon>
|
||||
<sl-icon library="boxicons" name="bxs-joystick"></sl-icon>
|
||||
<sl-icon library="boxicons" name="bxs-save"></sl-icon>
|
||||
<sl-icon library="boxicons" name="bxs-server"></sl-icon>
|
||||
<sl-icon library="boxicons" name="bxs-wine"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="boxicons" name="bxl-apple"></sl-icon>
|
||||
<sl-icon library="boxicons" name="bxl-chrome"></sl-icon>
|
||||
<sl-icon library="boxicons" name="bxl-edge"></sl-icon>
|
||||
@@ -245,20 +306,20 @@ Icons in this library are licensed under the [Font Awesome Free License](https:/
|
||||
<sl-icon library="fa" name="far-hdd"></sl-icon>
|
||||
<sl-icon library="fa" name="far-heart"></sl-icon>
|
||||
<sl-icon library="fa" name="far-star"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="fa" name="fas-archive"></sl-icon>
|
||||
<sl-icon library="fa" name="fas-book"></sl-icon>
|
||||
<sl-icon library="fa" name="fas-chess-knight"></sl-icon>
|
||||
<sl-icon library="fa" name="fas-dice"></sl-icon>
|
||||
<sl-icon library="fa" name="fas-pizza-slice"></sl-icon>
|
||||
<sl-icon library="fa" name="fas-scroll"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="fa" name="fab-apple"></sl-icon>
|
||||
<sl-icon library="fa" name="fab-chrome"></sl-icon>
|
||||
<sl-icon library="fa" name="fab-edge"></sl-icon>
|
||||
<sl-icon library="fa" name="fab-firefox"></sl-icon>
|
||||
<sl-icon library="fa" name="fab-opera"></sl-icon>
|
||||
<sl-icon library="fa" name="fab-microsoft"></sl-icon>
|
||||
<sl-icon library="fa" name="fab-microsoft"></sl-icon>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -273,17 +334,17 @@ Icons in this library are licensed under the [MIT License](https://github.com/ta
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('heroicons', {
|
||||
resolver: name => `https://cdn.jsdelivr.net/npm/heroicons@0.4.2/outline/${name}.svg`
|
||||
resolver: name => `https://cdn.jsdelivr.net/npm/heroicons@2.0.1/24/outline/${name}.svg`
|
||||
});
|
||||
</script>
|
||||
|
||||
<div style="font-size: 24px;">
|
||||
<sl-icon library="heroicons" name="chat"></sl-icon>
|
||||
<sl-icon library="heroicons" name="chat-bubble-left"></sl-icon>
|
||||
<sl-icon library="heroicons" name="cloud"></sl-icon>
|
||||
<sl-icon library="heroicons" name="cog"></sl-icon>
|
||||
<sl-icon library="heroicons" name="document-text"></sl-icon>
|
||||
<sl-icon library="heroicons" name="gift"></sl-icon>
|
||||
<sl-icon library="heroicons" name="volume-up"></sl-icon>
|
||||
<sl-icon library="heroicons" name="speaker-wave"></sl-icon>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -340,14 +401,14 @@ Icons in this library are licensed under the [MIT License](https://github.com/io
|
||||
<sl-icon library="ionicons" name="chatbubble"></sl-icon>
|
||||
<sl-icon library="ionicons" name="settings"></sl-icon>
|
||||
<sl-icon library="ionicons" name="warning"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="ionicons" name="alarm-outline"></sl-icon>
|
||||
<sl-icon library="ionicons" name="american-football-outline"></sl-icon>
|
||||
<sl-icon library="ionicons" name="bug-outline"></sl-icon>
|
||||
<sl-icon library="ionicons" name="chatbubble-outline"></sl-icon>
|
||||
<sl-icon library="ionicons" name="settings-outline"></sl-icon>
|
||||
<sl-icon library="ionicons" name="warning-outline"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="ionicons" name="alarm-sharp"></sl-icon>
|
||||
<sl-icon library="ionicons" name="american-football-sharp"></sl-icon>
|
||||
<sl-icon library="ionicons" name="bug-sharp"></sl-icon>
|
||||
@@ -380,7 +441,7 @@ Icons in this library are licensed under the [MIT License](https://github.com/mi
|
||||
<sl-icon library="jam" name="leaf"></sl-icon>
|
||||
<sl-icon library="jam" name="picture"></sl-icon>
|
||||
<sl-icon library="jam" name="set-square"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="jam" name="calendar-f"></sl-icon>
|
||||
<sl-icon library="jam" name="camera-f"></sl-icon>
|
||||
<sl-icon library="jam" name="filter-f"></sl-icon>
|
||||
@@ -416,14 +477,14 @@ Icons in this library are licensed under the [Apache 2.0 License](https://github
|
||||
<sl-icon library="material" name="volume_up"></sl-icon>
|
||||
<sl-icon library="material" name="settings"></sl-icon>
|
||||
<sl-icon library="material" name="shopping_basket"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="material" name="notifications_round"></sl-icon>
|
||||
<sl-icon library="material" name="email_round"></sl-icon>
|
||||
<sl-icon library="material" name="delete_round"></sl-icon>
|
||||
<sl-icon library="material" name="volume_up_round"></sl-icon>
|
||||
<sl-icon library="material" name="settings_round"></sl-icon>
|
||||
<sl-icon library="material" name="shopping_basket_round"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="material" name="notifications_sharp"></sl-icon>
|
||||
<sl-icon library="material" name="email_sharp"></sl-icon>
|
||||
<sl-icon library="material" name="delete_sharp"></sl-icon>
|
||||
@@ -460,13 +521,45 @@ Icons in this library are licensed under the [Apache 2.0 License](https://github
|
||||
<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>
|
||||
<br />
|
||||
<sl-icon library="remixicon" name="business/cloud-fill"></sl-icon>
|
||||
<sl-icon library="remixicon" name="design/brush-fill"></sl-icon>
|
||||
<sl-icon library="remixicon" name="business/pie-chart-fill"></sl-icon>
|
||||
<sl-icon library="remixicon" name="development/bug-fill"></sl-icon>
|
||||
<sl-icon library="remixicon" name="media/image-fill"></sl-icon>
|
||||
<sl-icon library="remixicon" name="system/alert-fill"></sl-icon>
|
||||
<sl-icon library="remixicon" name="system/alert-fill"></sl-icon>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Tabler Icons
|
||||
|
||||
This will register the [Tabler Icons](https://tabler-icons.io/) library using the jsDelivr CDN. This library features over 1,950 open source icons.
|
||||
|
||||
Icons in this library are licensed under the [MIT License](https://github.com/tabler/tabler-icons/blob/master/LICENSE).
|
||||
|
||||
```html preview
|
||||
<script type="module">
|
||||
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
|
||||
|
||||
registerIconLibrary('tabler', {
|
||||
resolver: name => `https://cdn.jsdelivr.net/npm/@tabler/icons@1.68.0/icons/${name}.svg`
|
||||
});
|
||||
</script>
|
||||
|
||||
<div style="font-size: 24px;">
|
||||
<sl-icon library="tabler" name="alert-triangle"></sl-icon>
|
||||
<sl-icon library="tabler" name="arrow-back"></sl-icon>
|
||||
<sl-icon library="tabler" name="at"></sl-icon>
|
||||
<sl-icon library="tabler" name="ball-baseball"></sl-icon>
|
||||
<sl-icon library="tabler" name="cake"></sl-icon>
|
||||
<sl-icon library="tabler" name="files"></sl-icon>
|
||||
<br />
|
||||
<sl-icon library="tabler" name="keyboard"></sl-icon>
|
||||
<sl-icon library="tabler" name="moon"></sl-icon>
|
||||
<sl-icon library="tabler" name="pig"></sl-icon>
|
||||
<sl-icon library="tabler" name="printer"></sl-icon>
|
||||
<sl-icon library="tabler" name="ship"></sl-icon>
|
||||
<sl-icon library="tabler" name="toilet-paper"></sl-icon>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -483,7 +576,9 @@ Icons in this library are licensed under the [Apache 2.0 License](https://github
|
||||
registerIconLibrary('unicons', {
|
||||
resolver: name => {
|
||||
const match = name.match(/^(.*?)(-s)?$/);
|
||||
return `https://cdn.jsdelivr.net/npm/@iconscout/unicons@3.0.3/svg/${match[2] === '-s' ? 'solid' : 'line'}/${match[1]}.svg`;
|
||||
return `https://cdn.jsdelivr.net/npm/@iconscout/unicons@3.0.3/svg/${match[2] === '-s' ? 'solid' : 'line'}/${
|
||||
match[1]
|
||||
}.svg`;
|
||||
},
|
||||
mutator: svg => svg.setAttribute('fill', 'currentColor')
|
||||
});
|
||||
@@ -496,12 +591,12 @@ Icons in this library are licensed under the [Apache 2.0 License](https://github
|
||||
<sl-icon library="unicons" name="polygon"></sl-icon>
|
||||
<sl-icon library="unicons" name="rocket"></sl-icon>
|
||||
<sl-icon library="unicons" name="star"></sl-icon>
|
||||
<br>
|
||||
<br />
|
||||
<sl-icon library="unicons" name="clock-s"></sl-icon>
|
||||
<sl-icon library="unicons" name="graph-bar-s"></sl-icon>
|
||||
<sl-icon library="unicons" name="padlock-s"></sl-icon>
|
||||
<sl-icon library="unicons" name="polygon-s"></sl-icon>
|
||||
<sl-icon library="unicons" name="rocket-s"></sl-icon>
|
||||
<sl-icon library="unicons" name="rocket-s"></sl-icon>
|
||||
<sl-icon library="unicons" name="star-s"></sl-icon>
|
||||
</div>
|
||||
```
|
||||
@@ -540,6 +635,19 @@ If you want to change the icons Shoelace uses internally, you can register an ic
|
||||
|
||||
<!-- Supporting scripts and styles for the search utility -->
|
||||
<script>
|
||||
function wrapWithTooltip(item) {
|
||||
const tooltip = document.createElement('sl-tooltip');
|
||||
tooltip.content = item.getAttribute('data-name');
|
||||
|
||||
// Close open tooltips
|
||||
document.querySelectorAll('.icon-list sl-tooltip[open]').forEach(tooltip => tooltip.hide());
|
||||
|
||||
// Wrap it with a tooltip and trick it into showing up
|
||||
item.parentNode.insertBefore(tooltip, item);
|
||||
tooltip.appendChild(item);
|
||||
requestAnimationFrame(() => tooltip.dispatchEvent(new MouseEvent('mouseover')));
|
||||
}
|
||||
|
||||
fetch('/dist/assets/icons/icons.json')
|
||||
.then(res => res.json())
|
||||
.then(icons => {
|
||||
@@ -563,19 +671,23 @@ If you want to change the icons Shoelace uses internally, you can register an ic
|
||||
<use xlink:href="/assets/icons/sprite.svg#${i.name}"></use>
|
||||
</svg>
|
||||
`;
|
||||
list.appendChild(item);
|
||||
|
||||
const tooltip = document.createElement('sl-tooltip');
|
||||
tooltip.content = i.name;
|
||||
|
||||
tooltip.appendChild(item);
|
||||
list.appendChild(tooltip);
|
||||
// Wrap it with a tooltip the first time the mouse lands on it. We do this instead of baking them into the DOM
|
||||
// to improve this page's performance. See: https://github.com/shoelace-style/shoelace/issues/1122
|
||||
item.addEventListener('mouseover', () => wrapWithTooltip(item), { once: true });
|
||||
|
||||
// Copy on click
|
||||
item.addEventListener('click', () => {
|
||||
const tooltip = item.closest('sl-tooltip');
|
||||
copyInput.value = i.name;
|
||||
copyInput.select();
|
||||
document.execCommand('copy');
|
||||
tooltip.content = 'Copied!';
|
||||
setTimeout(() => tooltip.content = i.name, 1000);
|
||||
|
||||
if (tooltip) {
|
||||
tooltip.content = 'Copied!';
|
||||
setTimeout(() => tooltip.content = i.name, 1000);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -2,14 +2,20 @@
|
||||
|
||||
[component-header:sl-image-comparer]
|
||||
|
||||
Compare visual differences between similar photos with a sliding panel.
|
||||
|
||||
For best results, use images that share the same dimensions. The slider can be controlled by dragging or pressing the left and right arrow keys. (Tip: press shift + arrows to move the slider in larger intervals, or home + end to jump to the beginning or end.)
|
||||
|
||||
```html preview
|
||||
<sl-image-comparer>
|
||||
<img slot="before" src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&sat=-100&bri=-5" alt="Grayscale version of kittens in a basket looking around.">
|
||||
<img slot="after" src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80" alt="Color version of kittens in a basket looking around.">
|
||||
<img
|
||||
slot="before"
|
||||
src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&sat=-100&bri=-5"
|
||||
alt="Grayscale version of kittens in a basket looking around."
|
||||
/>
|
||||
<img
|
||||
slot="after"
|
||||
src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80"
|
||||
alt="Color version of kittens in a basket looking around."
|
||||
/>
|
||||
</sl-image-comparer>
|
||||
```
|
||||
|
||||
@@ -18,8 +24,16 @@ import { SlImageComparer } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlImageComparer>
|
||||
<img slot="before" src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&sat=-100&bri=-5" alt="Grayscale version of kittens in a basket looking around." />
|
||||
<img slot="after" src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80" alt="Color version of kittens in a basket looking around." />
|
||||
<img
|
||||
slot="before"
|
||||
src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&sat=-100&bri=-5"
|
||||
alt="Grayscale version of kittens in a basket looking around."
|
||||
/>
|
||||
<img
|
||||
slot="after"
|
||||
src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80"
|
||||
alt="Color version of kittens in a basket looking around."
|
||||
/>
|
||||
</SlImageComparer>
|
||||
);
|
||||
```
|
||||
@@ -32,8 +46,16 @@ Use the `position` attribute to set the initial position of the slider. This is
|
||||
|
||||
```html preview
|
||||
<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.">
|
||||
<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>
|
||||
```
|
||||
|
||||
@@ -42,8 +64,16 @@ import { SlImageComparer } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlImageComparer 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." />
|
||||
<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."
|
||||
/>
|
||||
</SlImageComparer>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-include]
|
||||
|
||||
Includes give you the power to embed external HTML files into the page.
|
||||
|
||||
Included files are asynchronously requested using `window.fetch()`. Requests are cached, so the same file can be included multiple times, but only one request will be made.
|
||||
|
||||
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.
|
||||
@@ -15,9 +13,7 @@ The included content will be inserted into the `<sl-include>` element's default
|
||||
```jsx react
|
||||
import { SlInclude } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlInclude src="https://shoelace.style/assets/examples/include.html" />
|
||||
);
|
||||
const App = () => <SlInclude src="https://shoelace.style/assets/examples/include.html" />;
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -33,13 +29,17 @@ If the request fails, the `sl-error` event will be emitted. In this case, `event
|
||||
|
||||
<script>
|
||||
const include = document.querySelector('sl-include');
|
||||
|
||||
include.addEventListener('sl-load', () => {
|
||||
console.log('Success');
|
||||
|
||||
include.addEventListener('sl-load', event => {
|
||||
if (event.eventPhase === Event.AT_TARGET) {
|
||||
console.log('Success');
|
||||
}
|
||||
});
|
||||
|
||||
include.addEventListener('sl-error', event => {
|
||||
console.log('Error', event.detail.status);
|
||||
if (event.eventPhase === Event.AT_TARGET) {
|
||||
console.log('Error', event.detail.status);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-input]
|
||||
|
||||
Inputs collect data from the user.
|
||||
|
||||
```html preview
|
||||
<sl-input></sl-input>
|
||||
```
|
||||
@@ -11,15 +9,41 @@ Inputs collect data from the user.
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlInput />
|
||||
);
|
||||
const App = () => <SlInput />;
|
||||
```
|
||||
|
||||
?> This component works with standard `<form>` elements. Please refer to the section on [form controls](/getting-started/form-controls) to learn more about form submission and client-side validation.
|
||||
|
||||
## Examples
|
||||
|
||||
### Labels
|
||||
|
||||
Use the `label` attribute to give the input an accessible label. For labels that contain HTML, use the `label` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-input label="What is your name?"></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlIcon, SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlInput label="What is your name?" />;
|
||||
```
|
||||
|
||||
### Help Text
|
||||
|
||||
Add descriptive help text to an input with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-input label="Nickname" help-text="What would you like people to call you?"></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlIcon, SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlInput label="Nickname" help-text="What would you like people to call you?" />;
|
||||
```
|
||||
|
||||
### Placeholders
|
||||
|
||||
Use the `placeholder` attribute to add a placeholder.
|
||||
@@ -31,9 +55,7 @@ Use the `placeholder` attribute to add a placeholder.
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlInput placeholder="Type something" />
|
||||
);
|
||||
const App = () => <SlInput placeholder="Type something" />;
|
||||
```
|
||||
|
||||
### Clearable
|
||||
@@ -47,35 +69,21 @@ Add the `clearable` attribute to add a clear button when the input has content.
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlInput placeholder="Clearable" clearable />
|
||||
);
|
||||
const App = () => <SlInput placeholder="Clearable" clearable />;
|
||||
```
|
||||
|
||||
### Toggle Password
|
||||
|
||||
Add the `toggle-password` attribute to add a toggle button that will show the password when activated.
|
||||
Add the `password-toggle` 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>
|
||||
<br>
|
||||
<sl-input type="password" placeholder="Password Toggle" size="medium" toggle-password></sl-input>
|
||||
<br>
|
||||
<sl-input type="password" placeholder="Password Toggle" size="large" toggle-password></sl-input>
|
||||
<sl-input type="password" placeholder="Password Toggle" password-toggle></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlInput type="password" placeholder="Password Toggle" size="small" toggle-password />
|
||||
<br />
|
||||
<SlInput type="password" placeholder="Password Toggle" size="medium" toggle-password />
|
||||
<br />
|
||||
<SlInput type="password" placeholder="Password Toggle" size="large" toggle-password />
|
||||
</>
|
||||
);
|
||||
const App = () => <SlInput type="password" placeholder="Password Toggle" size="medium" password-toggle />;
|
||||
```
|
||||
|
||||
### Filled Inputs
|
||||
@@ -89,8 +97,46 @@ Add the `filled` attribute to draw a filled input.
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlInput placeholder="Type something" filled />;
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to disable an input.
|
||||
|
||||
```html preview
|
||||
<sl-input placeholder="Disabled" disabled></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlInput placeholder="Disabled" disabled />;
|
||||
```
|
||||
|
||||
### Sizes
|
||||
|
||||
Use the `size` attribute to change an input's size.
|
||||
|
||||
```html preview
|
||||
<sl-input placeholder="Small" size="small"></sl-input>
|
||||
<br />
|
||||
<sl-input placeholder="Medium" size="medium"></sl-input>
|
||||
<br />
|
||||
<sl-input placeholder="Large" size="large"></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlInput placeholder="Type something" filled />
|
||||
<>
|
||||
<SlInput placeholder="Small" size="small" />
|
||||
<br />
|
||||
<SlInput placeholder="Medium" size="medium" />
|
||||
<br />
|
||||
<SlInput placeholder="Large" size="large" />
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -100,9 +146,9 @@ Use the `pill` attribute to give inputs rounded edges.
|
||||
|
||||
```html preview
|
||||
<sl-input placeholder="Small" size="small" pill></sl-input>
|
||||
<br>
|
||||
<br />
|
||||
<sl-input placeholder="Medium" size="medium" pill></sl-input>
|
||||
<br>
|
||||
<br />
|
||||
<sl-input placeholder="Large" size="large" pill></sl-input>
|
||||
```
|
||||
|
||||
@@ -125,11 +171,11 @@ const App = () => (
|
||||
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>
|
||||
<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>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
@@ -137,63 +183,11 @@ import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlInput type="email" Placeholder="Email" />
|
||||
<SlInput type="email" placeholder="Email" />
|
||||
<br />
|
||||
<SlInput type="number" Placeholder="Number" />
|
||||
<SlInput type="number" placeholder="Number" />
|
||||
<br />
|
||||
<SlInput type="date" Placeholder="Date" />
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to disable an input.
|
||||
|
||||
```html preview
|
||||
<sl-input placeholder="Disabled" size="small" disabled></sl-input>
|
||||
<br>
|
||||
<sl-input placeholder="Disabled" size="medium" disabled></sl-input>
|
||||
<br>
|
||||
<sl-input placeholder="Disabled" size="large" disabled></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlInput placeholder="Disabled" size="small" disabled />
|
||||
<br />
|
||||
<SlInput placeholder="Disabled" size="medium" disabled />
|
||||
<br />
|
||||
<SlInput placeholder="Disabled" size="large" disabled />
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Sizes
|
||||
|
||||
Use the `size` attribute to change an input's size.
|
||||
|
||||
```html preview
|
||||
<sl-input placeholder="Small" size="small"></sl-input>
|
||||
<br>
|
||||
<sl-input placeholder="Medium" size="medium"></sl-input>
|
||||
<br>
|
||||
<sl-input placeholder="Large" size="large"></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlInput placeholder="Small" size="small" />
|
||||
<br />
|
||||
<SlInput placeholder="Medium" size="medium" />
|
||||
<br />
|
||||
<SlInput placeholder="Large" size="large" />
|
||||
<SlInput type="date" placeholder="Date" />
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -207,12 +201,12 @@ Use the `prefix` and `suffix` slots to add icons.
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-icon name="chat" slot="suffix"></sl-icon>
|
||||
</sl-input>
|
||||
<br>
|
||||
<br />
|
||||
<sl-input placeholder="Medium" size="medium">
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-icon name="chat" slot="suffix"></sl-icon>
|
||||
</sl-input>
|
||||
<br>
|
||||
<br />
|
||||
<sl-input placeholder="Large" size="large">
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-icon name="chat" slot="suffix"></sl-icon>
|
||||
@@ -242,42 +236,40 @@ const App = () => (
|
||||
);
|
||||
```
|
||||
|
||||
### Labels
|
||||
### Customizing Label Position
|
||||
|
||||
Use the `label` attribute to give the input an accessible label. For labels that contain HTML, use the `label` slot instead.
|
||||
Use [CSS parts](#css-parts) to customize the way form controls are drawn. This example uses CSS grid to position the label to the left of the control, but the possible orientations are nearly endless. The same technique works for inputs, textareas, radio groups, and similar form controls.
|
||||
|
||||
```html preview
|
||||
<sl-input label="What is your name?"></sl-input>
|
||||
```
|
||||
<sl-input class="label-on-left" label="Name" help-text="Enter your name""></sl-input>
|
||||
<sl-input class="label-on-left" label="Email" type="email" help-text="Enter your email"></sl-input>
|
||||
<sl-textarea class="label-on-left" label="Bio" help-text="Tell us something about yourself"></sl-textarea>
|
||||
|
||||
```jsx react
|
||||
import { SlIcon, SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
<style>
|
||||
.label-on-left {
|
||||
--label-width: 3.75rem;
|
||||
--gap-width: 1rem;
|
||||
}
|
||||
|
||||
const App = () => (
|
||||
<SlInput label="What is your name?" />
|
||||
);
|
||||
```
|
||||
.label-on-left + .label-on-left {
|
||||
margin-top: var(--sl-spacing-medium);
|
||||
}
|
||||
|
||||
### Help Text
|
||||
.label-on-left::part(form-control) {
|
||||
display: grid;
|
||||
grid: auto / var(--label-width) 1fr;
|
||||
gap: var(--sl-spacing-3x-small) var(--gap-width);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
Add descriptive help text to an input with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
.label-on-left::part(form-control-label) {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
```html preview
|
||||
<sl-input
|
||||
label="Nickname"
|
||||
help-text="What would you like people to call you?"
|
||||
></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlIcon, SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlInput
|
||||
label="Nickname"
|
||||
help-text="What would you like people to call you?"
|
||||
/>
|
||||
);
|
||||
.label-on-left::part(form-control-help-text) {
|
||||
grid-column-start: 2;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
[component-metadata:sl-input]
|
||||
|
||||
@@ -2,15 +2,13 @@
|
||||
|
||||
[component-header:sl-menu-item]
|
||||
|
||||
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); background: var(--sl-panel-background-color); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu style="max-width: 200px;">
|
||||
<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-divider></sl-divider>
|
||||
<sl-menu-item checked>Checked</sl-menu-item>
|
||||
<sl-menu-item type="checkbox" checked>Checkbox</sl-menu-item>
|
||||
<sl-menu-item disabled>Disabled</sl-menu-item>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item>
|
||||
@@ -25,26 +23,17 @@ Menu items provide options for the user to pick from in a menu.
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlDivider,
|
||||
SlIcon,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlDivider, SlIcon, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlMenu
|
||||
style={{
|
||||
maxWidth: '200px',
|
||||
border: 'solid 1px var(--sl-panel-border-color)',
|
||||
borderRadius: 'var(--sl-border-radius-medium)'
|
||||
}}
|
||||
>
|
||||
<SlMenu style={{ maxWidth: '200px' }}>
|
||||
<SlMenuItem>Option 1</SlMenuItem>
|
||||
<SlMenuItem>Option 2</SlMenuItem>
|
||||
<SlMenuItem>Option 3</SlMenuItem>
|
||||
<SlDivider />
|
||||
<SlMenuItem checked>Checked</SlMenuItem>
|
||||
<SlMenuItem type="checkbox" checked>
|
||||
Checkbox
|
||||
</SlMenuItem>
|
||||
<SlMenuItem disabled>Disabled</SlMenuItem>
|
||||
<SlDivider />
|
||||
<SlMenuItem>
|
||||
@@ -55,51 +44,18 @@ const App = () => (
|
||||
Suffix Icon
|
||||
<SlIcon slot="suffix" name="heart" />
|
||||
</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlMenu>
|
||||
);
|
||||
```
|
||||
|
||||
## 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 var(--sl-panel-border-color); background: var(--sl-panel-background-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>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlMenu
|
||||
style={{
|
||||
maxWidth: '200px',
|
||||
border: 'solid 1px var(--sl-panel-border-color)',
|
||||
borderRadius: 'var(--sl-border-radius-medium)'
|
||||
}}
|
||||
>
|
||||
<SlMenuItem>Option 1</SlMenuItem>
|
||||
<SlMenuItem checked>Option 2</SlMenuItem>
|
||||
<SlMenuItem>Option 3</SlMenuItem>
|
||||
</SlMenu>
|
||||
);
|
||||
```
|
||||
|
||||
### 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 var(--sl-panel-border-color); background: var(--sl-panel-background-color); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu style="max-width: 200px;">
|
||||
<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>
|
||||
@@ -107,23 +63,14 @@ Add the `disabled` attribute to disable the menu item so it cannot be selected.
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlMenu
|
||||
style={{
|
||||
maxWidth: '200px',
|
||||
border: 'solid 1px var(--sl-panel-border-color)',
|
||||
borderRadius: 'var(--sl-border-radius-medium)'
|
||||
}}
|
||||
>
|
||||
<SlMenu style={{ maxWidth: '200px' }}>
|
||||
<SlMenuItem>Option 1</SlMenuItem>
|
||||
<SlMenuItem disabled>Option 2</SlMenuItem>
|
||||
<SlMenuItem>Option 3</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlMenu>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -132,7 +79,7 @@ const App = () => (
|
||||
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 var(--sl-panel-border-color); background: var(--sl-panel-background-color); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu style="max-width: 200px;">
|
||||
<sl-menu-item>
|
||||
<sl-icon slot="prefix" name="house"></sl-icon>
|
||||
Home
|
||||
@@ -154,22 +101,10 @@ Add content to the start and end of menu items using the `prefix` and `suffix` s
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlBadge,
|
||||
SlDivider,
|
||||
SlIcon,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlBadge, SlDivider, SlIcon, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlMenu
|
||||
style={{
|
||||
maxWidth: '200px',
|
||||
border: 'solid 1px var(--sl-panel-border-color)',
|
||||
borderRadius: 'var(--sl-border-radius-medium)'
|
||||
}}
|
||||
>
|
||||
<SlMenu style={{ maxWidth: '200px' }}>
|
||||
<SlMenuItem>
|
||||
<SlIcon slot="prefix" name="house" />
|
||||
Home
|
||||
@@ -178,7 +113,9 @@ const App = () => (
|
||||
<SlMenuItem>
|
||||
<SlIcon slot="prefix" name="envelope" />
|
||||
Messages
|
||||
<SlBadge slot="suffix" variant="primary" pill>12</SlBadge>
|
||||
<SlBadge slot="suffix" variant="primary" pill>
|
||||
12
|
||||
</SlBadge>
|
||||
</SlMenuItem>
|
||||
|
||||
<SlDivider />
|
||||
@@ -187,7 +124,35 @@ const App = () => (
|
||||
<SlIcon slot="prefix" name="gear" />
|
||||
Settings
|
||||
</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlMenu>
|
||||
);
|
||||
```
|
||||
|
||||
### Checkbox Menu Items
|
||||
|
||||
Set the `type` attribute to `checkbox` to create a menu item that will toggle on and off when selected. You can use the `checked` attribute to set the initial state.
|
||||
|
||||
Checkbox menu items are visually indistinguishable from regular menu items. Their ability to be toggled is primarily inferred from context, much like you'd find in the menu of a native app.
|
||||
|
||||
```html preview
|
||||
<sl-menu style="max-width: 200px;">
|
||||
<sl-menu-item type="checkbox">Autosave</sl-menu-item>
|
||||
<sl-menu-item type="checkbox" checked>Check Spelling</sl-menu-item>
|
||||
<sl-menu-item type="checkbox">Word Wrap</sl-menu-item>
|
||||
</sl-menu>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlMenu style={{ maxWidth: '200px' }}>
|
||||
<SlMenuItem type="checkbox">Autosave</SlMenuItem>
|
||||
<SlMenuItem type="checkbox" checked>
|
||||
Check Spelling
|
||||
</SlMenuItem>
|
||||
<SlMenuItem type="checkbox">Word Wrap</SlMenuItem>
|
||||
</SlMenu>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -196,10 +161,14 @@ const App = () => (
|
||||
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 var(--sl-panel-border-color); background: var(--sl-panel-background-color); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu class="menu-value" style="max-width: 200px;">
|
||||
<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-divider></sl-divider>
|
||||
<sl-menu-item type="checkbox" value="opt-4">Checkbox 4</sl-menu-item>
|
||||
<sl-menu-item type="checkbox" value="opt-5">Checkbox 5</sl-menu-item>
|
||||
<sl-menu-item type="checkbox" value="opt-6">Checkbox 6</sl-menu-item>
|
||||
</sl-menu>
|
||||
|
||||
<script>
|
||||
@@ -208,23 +177,20 @@ The `value` attribute can be used to assign a hidden value, such as a unique ide
|
||||
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}`);
|
||||
if (item.type === 'checkbox') {
|
||||
console.log(`Selected value: ${item.value} (${item.checked ? 'checked' : 'unchecked'})`);
|
||||
} else {
|
||||
console.log(`Selected value: ${item.value}`);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
|
||||
function handleSelect(event) {
|
||||
const item = event.detail.item;
|
||||
|
||||
@@ -236,14 +202,7 @@ const App = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<SlMenu
|
||||
style={{
|
||||
maxWidth: '200px',
|
||||
border: 'solid 1px var(--sl-panel-border-color)',
|
||||
borderRadius: 'var(--sl-border-radius-medium)'
|
||||
}}
|
||||
onSlSelect={handleSelect}
|
||||
>
|
||||
<SlMenu style={{ maxWidth: '200px' }} onSlSelect={handleSelect}>
|
||||
<SlMenuItem value="opt-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="opt-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="opt-3">Option 3</SlMenuItem>
|
||||
|
||||
@@ -2,12 +2,8 @@
|
||||
|
||||
[component-header:sl-menu-label]
|
||||
|
||||
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); background: var(--sl-panel-background-color); border-radius: var(--sl-border-radius-medium);"
|
||||
>
|
||||
<sl-menu style="max-width: 200px;">
|
||||
<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>
|
||||
@@ -21,21 +17,10 @@ Menu labels are used to describe a group of menu items.
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlDivider,
|
||||
SlMenu,
|
||||
SlMenuLabel,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlDivider, SlMenu, SlMenuLabel, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlMenu
|
||||
style={{
|
||||
maxWidth: '200px',
|
||||
border: 'solid 1px var(--sl-panel-border-color)',
|
||||
borderRadius: 'var(--sl-border-radius-medium)'
|
||||
}}
|
||||
>
|
||||
<SlMenu style={{ maxWidth: '200px' }}>
|
||||
<SlMenuLabel>Fruits</SlMenuLabel>
|
||||
<SlMenuItem value="apple">Apple</SlMenuItem>
|
||||
<SlMenuItem value="banana">Banana</SlMenuItem>
|
||||
@@ -45,7 +30,7 @@ const App = () => (
|
||||
<SlMenuItem value="broccoli">Broccoli</SlMenuItem>
|
||||
<SlMenuItem value="carrot">Carrot</SlMenuItem>
|
||||
<SlMenuItem value="zucchini">Zucchini</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlMenu>
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
@@ -2,12 +2,10 @@
|
||||
|
||||
[component-header:sl-menu]
|
||||
|
||||
Menus provide a list of options for the user to choose from.
|
||||
|
||||
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); background: var(--sl-panel-background-color); border-radius: var(--sl-border-radius-medium);">
|
||||
<sl-menu style="max-width: 200px;">
|
||||
<sl-menu-item value="undo">Undo</sl-menu-item>
|
||||
<sl-menu-item value="redo">Redo</sl-menu-item>
|
||||
<sl-divider></sl-divider>
|
||||
@@ -19,20 +17,10 @@ You can use [menu items](/components/menu-item), [menu labels](/components/menu-
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlDivider,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlDivider, SlMenu, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlMenu
|
||||
style={{
|
||||
maxWidth: '200px',
|
||||
border: 'solid 1px var(--sl-panel-border-color)',
|
||||
borderRadius: 'var(--sl-border-radius-medium)'
|
||||
}}
|
||||
>
|
||||
<SlMenu style={{ maxWidth: '200px' }}>
|
||||
<SlMenuItem value="undo">Undo</SlMenuItem>
|
||||
<SlMenuItem value="redo">Redo</SlMenuItem>
|
||||
<SlDivider />
|
||||
@@ -40,7 +28,7 @@ const App = () => (
|
||||
<SlMenuItem value="copy">Copy</SlMenuItem>
|
||||
<SlMenuItem value="paste">Paste</SlMenuItem>
|
||||
<SlMenuItem value="delete">Delete</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlMenu>
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[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
|
||||
@@ -12,14 +10,14 @@ The mutation observer will report changes to the content it wraps through the `s
|
||||
<sl-button variant="primary">Click to mutate</sl-button>
|
||||
</sl-mutation-observer>
|
||||
|
||||
<br>
|
||||
<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 variants = ['primary', 'success', 'neutral', 'warning', 'danger'];
|
||||
const variants = ['primary', 'success', 'neutral', 'warning', 'danger'];
|
||||
let clicks = 0;
|
||||
|
||||
// Change the button's variant attribute
|
||||
@@ -57,7 +55,7 @@ const css = `
|
||||
}
|
||||
`;
|
||||
|
||||
const variants = ['primary', 'success', 'neutral', 'warning', 'danger'];
|
||||
const variants = ['primary', 'success', 'neutral', 'warning', 'danger'];
|
||||
let clicks = 0;
|
||||
|
||||
const App = () => {
|
||||
@@ -70,11 +68,10 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlMutationObserver
|
||||
attr="*"
|
||||
onSlMutation={event => console.log(event.detail)}
|
||||
>
|
||||
<SlButton variant={variant} onClick={handleClick}>Click to mutate</SlButton>
|
||||
<SlMutationObserver attr="*" onSlMutation={event => console.log(event.detail)}>
|
||||
<SlButton variant={variant} onClick={handleClick}>
|
||||
Click to mutate
|
||||
</SlButton>
|
||||
</SlMutationObserver>
|
||||
|
||||
<style>{css}</style>
|
||||
@@ -134,7 +131,7 @@ Use the `child-list` attribute to watch for new child elements that are added or
|
||||
<style>
|
||||
.mutation-child-list .buttons {
|
||||
display: flex;
|
||||
gap: .25rem;
|
||||
gap: 0.25rem;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -171,12 +168,11 @@ const App = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="mutation-child-list">
|
||||
<SlMutationObserver
|
||||
child-list
|
||||
onSlMutation={event => console.log(event.detail)}
|
||||
>
|
||||
<SlMutationObserver child-list onSlMutation={event => console.log(event.detail)}>
|
||||
<div className="buttons">
|
||||
<SlButton variant="primary" onClick={addButton}>Add button</SlButton>
|
||||
<SlButton variant="primary" onClick={addButton}>
|
||||
Add button
|
||||
</SlButton>
|
||||
{buttonIds.map(id => (
|
||||
<SlButton key={id} variant="default" onClick={() => removeButton(id)}>
|
||||
{id}
|
||||
@@ -185,7 +181,6 @@ const App = () => {
|
||||
</div>
|
||||
</SlMutationObserver>
|
||||
</div>
|
||||
|
||||
👆 Add and remove buttons and watch the console
|
||||
<style>{css}</style>
|
||||
</>
|
||||
|
||||
79
docs/components/option.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Option
|
||||
|
||||
[component-header:sl-option]
|
||||
|
||||
```html preview
|
||||
<sl-select label="Select one">
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to disable an option and prevent it from being selected.
|
||||
|
||||
```html preview
|
||||
<sl-select label="Select one">
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2" disabled>Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2" disabled>
|
||||
Option 2
|
||||
</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
### Prefix & Suffix
|
||||
|
||||
Add icons to the start and end of menu items using the `prefix` and `suffix` slots.
|
||||
|
||||
```html preview
|
||||
<sl-select label="Select one">
|
||||
<sl-option value="option-1">
|
||||
<sl-icon slot="prefix" name="envelope"></sl-icon>
|
||||
Email
|
||||
<sl-icon slot="suffix" name="patch-check"></sl-icon>
|
||||
</sl-option>
|
||||
|
||||
<sl-option value="option-2">
|
||||
<sl-icon slot="prefix" name="telephone"></sl-icon>
|
||||
Phone
|
||||
<sl-icon slot="suffix" name="patch-check"></sl-icon>
|
||||
</sl-option>
|
||||
|
||||
<sl-option value="option-3">
|
||||
<sl-icon slot="prefix" name="chat-dots"></sl-icon>
|
||||
Chat
|
||||
<sl-icon slot="suffix" name="patch-check"></sl-icon>
|
||||
</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
[component-metadata:sl-option]
|
||||
1508
docs/components/popup.md
Normal file
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-progress-bar]
|
||||
|
||||
Progress bars are used to show the status of an ongoing operation.
|
||||
|
||||
```html preview
|
||||
<sl-progress-bar value="50"></sl-progress-bar>
|
||||
```
|
||||
@@ -11,32 +9,11 @@ Progress bars are used to show the status of an ongoing operation.
|
||||
```jsx react
|
||||
import { SlProgressBar } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlProgressBar value={50} />
|
||||
);
|
||||
const App = () => <SlProgressBar value={50} />;
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Custom Height
|
||||
|
||||
Use the `--height` custom property to set the progress bar's height.
|
||||
|
||||
```html preview
|
||||
<sl-progress-bar value="50" style="--height: 6px;"></sl-progress-bar>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlProgressBar } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlProgressBar
|
||||
value={50}
|
||||
style={{ '--height': '6px' }}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Labels
|
||||
|
||||
Use the `label` attribute to label the progress bar and tell assistive devices how to announce it.
|
||||
@@ -48,12 +25,21 @@ Use the `label` attribute to label the progress bar and tell assistive devices h
|
||||
```jsx react
|
||||
import { SlProgressBar } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlProgressBar
|
||||
value="50"
|
||||
label="Upload progress"
|
||||
/>
|
||||
);
|
||||
const App = () => <SlProgressBar value="50" label="Upload progress" />;
|
||||
```
|
||||
|
||||
### Custom Height
|
||||
|
||||
Use the `--height` custom property to set the progress bar's height.
|
||||
|
||||
```html preview
|
||||
<sl-progress-bar value="50" style="--height: 6px;"></sl-progress-bar>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlProgressBar } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlProgressBar value={50} style={{ '--height': '6px' }} />;
|
||||
```
|
||||
|
||||
### Showing Values
|
||||
@@ -63,10 +49,10 @@ Use the default slot to show a value.
|
||||
```html preview
|
||||
<sl-progress-bar value="50" class="progress-bar-values">50%</sl-progress-bar>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<sl-button circle><sl-icon name="dash"></sl-icon></sl-button>
|
||||
<sl-button circle><sl-icon name="plus"></sl-icon></sl-button>
|
||||
<sl-button circle><sl-icon name="dash" label="Decrease"></sl-icon></sl-button>
|
||||
<sl-button circle><sl-icon name="plus" label="Increase"></sl-icon></sl-button>
|
||||
|
||||
<script>
|
||||
const progressBar = document.querySelector('.progress-bar-values');
|
||||
@@ -80,7 +66,7 @@ Use the default slot to show a value.
|
||||
});
|
||||
|
||||
subtractButton.addEventListener('click', () => {
|
||||
const value = Math.max(0, progressBar.value - 10)
|
||||
const value = Math.max(0, progressBar.value - 10);
|
||||
progressBar.value = value;
|
||||
progressBar.textContent = `${value}%`;
|
||||
});
|
||||
@@ -89,11 +75,7 @@ Use the default slot to show a value.
|
||||
|
||||
```jsx react
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
SlButton,
|
||||
SlIcon,
|
||||
SlProgressBar
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlIcon, SlProgressBar } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const [value, setValue] = useState(50);
|
||||
@@ -107,18 +89,16 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlProgressBar value={value}>
|
||||
{value}%
|
||||
</SlProgressBar>
|
||||
<SlProgressBar value={value}>{value}%</SlProgressBar>
|
||||
|
||||
<br />
|
||||
|
||||
<SlButton circle onClick={() => adjustValue(-10)}>
|
||||
<SlIcon name="dash" />
|
||||
<SlIcon name="dash" label="Decrease" />
|
||||
</SlButton>
|
||||
|
||||
<SlButton circle onClick={() => adjustValue(10)}>
|
||||
<SlIcon name="plus" />
|
||||
<SlIcon name="plus" label="Increase" />
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
@@ -136,9 +116,7 @@ The `indeterminate` attribute can be used to inform the user that the operation
|
||||
```jsx react
|
||||
import { SlProgressBar } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlProgressBar indeterminate />
|
||||
);
|
||||
const App = () => <SlProgressBar indeterminate />;
|
||||
```
|
||||
|
||||
[component-metadata:sl-progress-bar]
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-progress-ring]
|
||||
|
||||
Progress rings are used to show the progress of a determinate operation in a circular fashion.
|
||||
|
||||
```html preview
|
||||
<sl-progress-ring value="25"></sl-progress-ring>
|
||||
```
|
||||
@@ -11,9 +9,7 @@ Progress rings are used to show the progress of a determinate operation in a cir
|
||||
```jsx react
|
||||
import { SlProgressRing } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlProgressRing value="25" />
|
||||
);
|
||||
const App = () => <SlProgressRing value="25" />;
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -29,31 +25,21 @@ Use the `--size` custom property to set the diameter of the progress ring.
|
||||
```jsx react
|
||||
import { SlProgressRing } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlProgressRing
|
||||
value="50"
|
||||
style={{ '--size': '200px' }}
|
||||
/>
|
||||
);
|
||||
const App = () => <SlProgressRing value="50" style={{ '--size': '200px' }} />;
|
||||
```
|
||||
|
||||
### Track Width
|
||||
### Track and Indicator Width
|
||||
|
||||
Use the `--track-width` custom property to set the width of the progress ring's track.
|
||||
Use the `--track-width` and `--indicator-width` custom properties to set the width of the progress ring's track and indicator.
|
||||
|
||||
```html preview
|
||||
<sl-progress-ring value="50" style="--track-width: 10px;"></sl-progress-ring>
|
||||
<sl-progress-ring value="50" style="--track-width: 6px; --indicator-width: 12px;"></sl-progress-ring>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlProgressRing } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlProgressRing
|
||||
value="50"
|
||||
style={{ '--track-width': '10px' }}
|
||||
/>
|
||||
);
|
||||
const App = () => <SlProgressRing value="50" style={{ '--track-width': '6px', '--indicator-width': '12px' }} />;
|
||||
```
|
||||
|
||||
### Colors
|
||||
@@ -61,8 +47,8 @@ const App = () => (
|
||||
To change the color, use the `--track-color` and `--indicator-color` custom properties.
|
||||
|
||||
```html preview
|
||||
<sl-progress-ring
|
||||
value="50"
|
||||
<sl-progress-ring
|
||||
value="50"
|
||||
style="
|
||||
--track-color: pink;
|
||||
--indicator-color: deeppink;
|
||||
@@ -74,9 +60,9 @@ To change the color, use the `--track-color` and `--indicator-color` custom prop
|
||||
import { SlProgressRing } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlProgressRing
|
||||
value="50"
|
||||
style={{
|
||||
<SlProgressRing
|
||||
value="50"
|
||||
style={{
|
||||
'--track-color': 'pink',
|
||||
'--indicator-color': 'deeppink'
|
||||
}}
|
||||
@@ -95,12 +81,7 @@ Use the `label` attribute to label the progress ring and tell assistive devices
|
||||
```jsx react
|
||||
import { SlProgressRing } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlProgressRing
|
||||
value="50"
|
||||
label="Upload progress"
|
||||
/>
|
||||
);
|
||||
const App = () => <SlProgressRing value="50" label="Upload progress" />;
|
||||
```
|
||||
|
||||
### Showing Values
|
||||
@@ -110,10 +91,10 @@ Use the default slot to show a label inside the progress ring.
|
||||
```html preview
|
||||
<sl-progress-ring value="50" class="progress-ring-values" style="margin-bottom: .5rem;">50%</sl-progress-ring>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<sl-button circle><sl-icon name="dash"></sl-icon></sl-button>
|
||||
<sl-button circle><sl-icon name="plus"></sl-icon></sl-button>
|
||||
<sl-button circle><sl-icon name="dash" label="Decrease"></sl-icon></sl-button>
|
||||
<sl-button circle><sl-icon name="plus" label="Increase"></sl-icon></sl-button>
|
||||
|
||||
<script>
|
||||
const progressRing = document.querySelector('.progress-ring-values');
|
||||
@@ -127,7 +108,7 @@ Use the default slot to show a label inside the progress ring.
|
||||
});
|
||||
|
||||
subtractButton.addEventListener('click', () => {
|
||||
const value = Math.max(0, progressRing.value - 10)
|
||||
const value = Math.max(0, progressRing.value - 10);
|
||||
progressRing.value = value;
|
||||
progressRing.textContent = `${value}%`;
|
||||
});
|
||||
@@ -136,11 +117,7 @@ Use the default slot to show a label inside the progress ring.
|
||||
|
||||
```jsx react
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
SlButton,
|
||||
SlIcon,
|
||||
SlProgressRing
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlIcon, SlProgressRing } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const [value, setValue] = useState(50);
|
||||
@@ -154,21 +131,18 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlProgressRing
|
||||
value={value}
|
||||
style={{ marginBottom: '.5rem' }}
|
||||
>
|
||||
<SlProgressRing value={value} style={{ marginBottom: '.5rem' }}>
|
||||
{value}%
|
||||
</SlProgressRing>
|
||||
|
||||
<br />
|
||||
|
||||
<SlButton circle onClick={() => adjustValue(-10)}>
|
||||
<SlIcon name="dash" />
|
||||
<SlIcon name="dash" label="Decrease" />
|
||||
</SlButton>
|
||||
|
||||
<SlButton circle onClick={() => adjustValue(10)}>
|
||||
<SlIcon name="plus" />
|
||||
<SlIcon name="plus" label="Increase" />
|
||||
</SlButton>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,16 +2,14 @@
|
||||
|
||||
[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>
|
||||
<br />
|
||||
|
||||
<sl-input maxlength="255" clearable></sl-input>
|
||||
<sl-input maxlength="255" clearable label="Value"></sl-input>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -20,7 +18,7 @@ QR codes are useful for providing small pieces of information to users who can q
|
||||
const input = container.querySelector('sl-input');
|
||||
|
||||
input.value = qrCode.value;
|
||||
input.addEventListener('sl-input', () => qrCode.value = input.value);
|
||||
input.addEventListener('sl-input', () => (qrCode.value = input.value));
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -79,9 +77,7 @@ Use the `fill` and `background` attributes to modify the QR code's colors. You s
|
||||
```jsx react
|
||||
import { SlQrCode } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlQrCode value="https://shoelace.style/" fill="deeppink" background="white" />
|
||||
);
|
||||
const App = () => <SlQrCode value="https://shoelace.style/" fill="deeppink" background="white" />;
|
||||
```
|
||||
|
||||
### Size
|
||||
@@ -95,9 +91,7 @@ Use the `size` attribute to change the size of the QR code.
|
||||
```jsx react
|
||||
import { SlQrCode } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlQrCode value="https://shoelace.style/" size="64" />
|
||||
);
|
||||
const App = () => <SlQrCode value="https://shoelace.style/" size="64" />;
|
||||
```
|
||||
|
||||
### Radius
|
||||
@@ -111,9 +105,7 @@ Create a rounded effect with the `radius` attribute.
|
||||
```jsx react
|
||||
import { SlQrCode } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlQrCode value="https://shoelace.style/" radius="0.5" />
|
||||
);
|
||||
const App = () => <SlQrCode value="https://shoelace.style/" radius="0.5" />;
|
||||
```
|
||||
|
||||
### Error Correction
|
||||
|
||||
295
docs/components/radio-button.md
Normal file
@@ -0,0 +1,295 @@
|
||||
# Radio Button
|
||||
|
||||
[component-header:sl-radio-button]
|
||||
|
||||
Radio buttons are designed to be used with [radio groups](/components/radio-group). When a radio button has focus, the arrow keys can be used to change the selected option just like standard radio controls.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button value="2">Option 2</sl-radio-button>
|
||||
<sl-radio-button value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRadioButton, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton value="2">Option 2</SlRadioButton>
|
||||
<SlRadioButton value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Checked States
|
||||
|
||||
To set the initial value and checked state, use the `value` attribute on the containing radio group.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button value="2">Option 2</sl-radio-button>
|
||||
<sl-radio-button value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRadioButton, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton value="2">Option 2</SlRadioButton>
|
||||
<SlRadioButton value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to disable a radio button.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button value="2" disabled>Option 2</sl-radio-button>
|
||||
<sl-radio-button value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRadioButton, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton value="2" disabled>
|
||||
Option 2
|
||||
</SlRadioButton>
|
||||
<SlRadioButton value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
### Sizes
|
||||
|
||||
Use the `size` attribute to change a radio button's size.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button size="small" value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button size="small" value="2">Option 2</sl-radio-button>
|
||||
<sl-radio-button size="small" value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
|
||||
<br />
|
||||
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button size="medium" value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button size="medium" value="2">Option 2</sl-radio-button>
|
||||
<sl-radio-button size="medium" value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
|
||||
<br />
|
||||
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button size="large" value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button size="large" value="2">Option 2</sl-radio-button>
|
||||
<sl-radio-button size="large" value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRadioButton, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton size="small" value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton size="small" value="2">Option 2</SlRadioButton>
|
||||
<SlRadioButton size="small" value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
|
||||
<br />
|
||||
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton size="medium" value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton size="medium" value="2">Option 2</SlRadioButton>
|
||||
<SlRadioButton size="medium" value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
|
||||
<br />
|
||||
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton size="large" value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton size="large" value="2">Option 2</SlRadioButton>
|
||||
<SlRadioButton size="large" value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
### Pill Buttons
|
||||
|
||||
Use the `pill` attribute to give radio buttons rounded edges.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button pill size="small" value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button pill size="small" value="2">Option 2</sl-radio-button>
|
||||
<sl-radio-button pill size="small" value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
|
||||
<br />
|
||||
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button pill size="medium" value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button pill size="medium" value="2">Option 2</sl-radio-button>
|
||||
<sl-radio-button pill size="medium" value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
|
||||
<br />
|
||||
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button pill size="large" value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button pill size="large" value="2">Option 2</sl-radio-button>
|
||||
<sl-radio-button pill size="large" value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRadioButton, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton pill size="small" value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton pill size="small" value="2">Option 2</SlRadioButton>
|
||||
<SlRadioButton pill size="small" value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
|
||||
<br />
|
||||
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton pill size="medium" value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton pill size="medium" value="2">Option 2</SlRadioButton>
|
||||
<SlRadioButton pill size="medium" value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
|
||||
<br />
|
||||
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton pill size="large" value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton pill size="large" value="2">Option 2</SlRadioButton>
|
||||
<SlRadioButton pill size="large" value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
### Prefix and Suffix Icons
|
||||
|
||||
Use the `prefix` and `suffix` slots to add icons.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio-button value="1">
|
||||
<sl-icon slot="prefix" name="archive"></sl-icon>
|
||||
Option 1
|
||||
</sl-radio-button>
|
||||
|
||||
<sl-radio-button value="2">
|
||||
<sl-icon slot="suffix" name="bag"></sl-icon>
|
||||
Option 2
|
||||
</sl-radio-button>
|
||||
|
||||
<sl-radio-button value="3">
|
||||
<sl-icon slot="prefix" name="gift"></sl-icon>
|
||||
<sl-icon slot="suffix" name="cart"></sl-icon>
|
||||
Option 3
|
||||
</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlIcon, SlRadioButton, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton value="1">
|
||||
<SlIcon slot="prefix" name="archive" />
|
||||
Option 1
|
||||
</SlRadioButton>
|
||||
|
||||
<SlRadioButton value="2">
|
||||
<SlIcon slot="suffix" name="bag" />
|
||||
Option 2
|
||||
</SlRadioButton>
|
||||
|
||||
<SlRadioButton value="3">
|
||||
<SlIcon slot="prefix" name="gift" />
|
||||
<SlIcon slot="suffix" name="cart" />
|
||||
Option 3
|
||||
</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
### Buttons with Icons
|
||||
|
||||
You can omit button labels and use icons instead. Make sure to set a `label` attribute on each icon so screen readers will announce each option correctly.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" name="a" value="neutral">
|
||||
<sl-radio-button value="angry">
|
||||
<sl-icon name="emoji-angry" label="Angry"></sl-icon>
|
||||
</sl-radio-button>
|
||||
|
||||
<sl-radio-button value="sad">
|
||||
<sl-icon name="emoji-frown" label="Sad"></sl-icon>
|
||||
</sl-radio-button>
|
||||
|
||||
<sl-radio-button value="neutral">
|
||||
<sl-icon name="emoji-neutral" label="Neutral"></sl-icon>
|
||||
</sl-radio-button>
|
||||
|
||||
<sl-radio-button value="happy">
|
||||
<sl-icon name="emoji-smile" label="Happy"></sl-icon>
|
||||
</sl-radio-button>
|
||||
|
||||
<sl-radio-button value="laughing">
|
||||
<sl-icon name="emoji-laughing" label="Laughing"></sl-icon>
|
||||
</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlIcon, SlRadioButton, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="neutral">
|
||||
<SlRadioButton value="angry">
|
||||
<SlIcon name="emoji-angry" label="Angry" />
|
||||
</SlRadioButton>
|
||||
|
||||
<SlRadioButton value="sad">
|
||||
<SlIcon name="emoji-frown" label="Sad" />
|
||||
</SlRadioButton>
|
||||
|
||||
<SlRadioButton value="neutral">
|
||||
<SlIcon name="emoji-neutral" label="Neutral" />
|
||||
</SlRadioButton>
|
||||
|
||||
<SlRadioButton value="happy">
|
||||
<SlIcon name="emoji-smile" label="Happy" />
|
||||
</SlRadioButton>
|
||||
|
||||
<SlRadioButton value="laughing">
|
||||
<SlIcon name="emoji-laughing" label="Laughing" />
|
||||
</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
[component-metadata:sl-radio-button]
|
||||
@@ -2,11 +2,9 @@
|
||||
|
||||
[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 option">
|
||||
<sl-radio value="1" checked>Option 1</sl-radio>
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio value="1">Option 1</sl-radio>
|
||||
<sl-radio value="2">Option 2</sl-radio>
|
||||
<sl-radio value="3">Option 3</sl-radio>
|
||||
</sl-radio-group>
|
||||
@@ -16,8 +14,8 @@ Radio Groups are used to group multiple radios so they function as a single cont
|
||||
import { SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option">
|
||||
<SlRadio value="1" checked>Option 1</SlRadio>
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadio value="1">Option 1</SlRadio>
|
||||
<SlRadio value="2">Option 2</SlRadio>
|
||||
<SlRadio value="3">Option 3</SlRadio>
|
||||
</SlRadioGroup>
|
||||
@@ -26,13 +24,13 @@ const App = () => (
|
||||
|
||||
## Examples
|
||||
|
||||
### Showing the Fieldset
|
||||
### Help Text
|
||||
|
||||
You can show a fieldset and legend that wraps the radio group using the `fieldset` attribute.
|
||||
Add descriptive help text to a radio group with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" fieldset>
|
||||
<sl-radio value="1" checked>Option 1</sl-radio>
|
||||
<sl-radio-group label="Select an option" help-text="Choose the most appropriate option." name="a" value="1">
|
||||
<sl-radio value="1">Option 1</sl-radio>
|
||||
<sl-radio value="2">Option 2</sl-radio>
|
||||
<sl-radio value="3">Option 3</sl-radio>
|
||||
</sl-radio-group>
|
||||
@@ -42,11 +40,193 @@ You can show a fieldset and legend that wraps the radio group using the `fieldse
|
||||
import { SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" fieldset>
|
||||
<SlRadio value="1" checked>Option 1</SlRadio>
|
||||
<SlRadioGroup label="Select an option" help-text="Choose the most appropriate option." name="a" value="1">
|
||||
<SlRadio value="1">Option 1</SlRadio>
|
||||
<SlRadio value="2">Option 2</SlRadio>
|
||||
<SlRadio value="3">Option 3</SlRadio>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
### Radio Buttons
|
||||
|
||||
[Radio buttons](/components/radio-button) offer an alternate way to display radio controls. In this case, an internal [button group](/components/button-group) is used to group the buttons into a single, cohesive control.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" help-text="Select an option that makes you proud." name="a" value="1">
|
||||
<sl-radio-button value="1">Option 1</sl-radio-button>
|
||||
<sl-radio-button value="2">Option 2</sl-radio-button>
|
||||
<sl-radio-button value="3">Option 3</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRadioButton, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadioButton value="1">Option 1</SlRadioButton>
|
||||
<SlRadioButton value="2">Option 2</SlRadioButton>
|
||||
<SlRadioButton value="3">Option 3</SlRadioButton>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
### Disabling Options
|
||||
|
||||
Radios and radio buttons can be disabled by adding the `disabled` attribute to the respective options inside the radio group.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio value="1">Option 1</sl-radio>
|
||||
<sl-radio value="2" disabled>Option 2</sl-radio>
|
||||
<sl-radio value="3">Option 3</sl-radio>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadio value="1">Option 1</SlRadio>
|
||||
<SlRadio value="2" disabled>
|
||||
Option 2
|
||||
</SlRadio>
|
||||
<SlRadio value="3">Option 3</SlRadio>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
### Validation
|
||||
|
||||
Setting the `required` attribute to make selecting an option mandatory. If a value has not been selected, it will prevent the form from submitting and display an error message.
|
||||
|
||||
```html preview
|
||||
<form class="validation">
|
||||
<sl-radio-group label="Select an option" name="a" required>
|
||||
<sl-radio value="1">Option 1</sl-radio>
|
||||
<sl-radio value="2">Option 2</sl-radio>
|
||||
<sl-radio value="3">Option 3</sl-radio>
|
||||
</sl-radio-group>
|
||||
<br />
|
||||
<sl-button type="submit" variant="primary">Submit</sl-button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
const form = document.querySelector('.validation');
|
||||
|
||||
// Handle form submit
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlButton, SlIcon, SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
const App = () => {
|
||||
function handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!');
|
||||
}
|
||||
|
||||
return (
|
||||
<form class="custom-validity" onSubmit={handleSubmit}>
|
||||
<SlRadioGroup label="Select an option" name="a" required onSlChange={handleChange}>
|
||||
<SlRadio value="1">
|
||||
Option 1
|
||||
</SlRadio>
|
||||
<SlRadiovalue="2">
|
||||
Option 2
|
||||
</SlRadio>
|
||||
<SlRadio value="3">
|
||||
Option 3
|
||||
</SlRadio>
|
||||
</SlRadioGroup>
|
||||
<br />
|
||||
<SlButton type="submit" variant="primary">
|
||||
Submit
|
||||
</SlButton>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Validity
|
||||
|
||||
Use the `setCustomValidity()` method to set a custom validation message. This will prevent the form from submitting and make the browser display the error message you provide. To clear the error, call this function with an empty string.
|
||||
|
||||
```html preview
|
||||
<form class="custom-validity">
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio value="1">Not me</sl-radio>
|
||||
<sl-radio value="2">Me neither</sl-radio>
|
||||
<sl-radio value="3">Choose me</sl-radio>
|
||||
</sl-radio-group>
|
||||
<br />
|
||||
<sl-button type="submit" variant="primary">Submit</sl-button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
const form = document.querySelector('.custom-validity');
|
||||
const radioGroup = form.querySelector('sl-radio-group');
|
||||
const errorMessage = 'You must choose the last option';
|
||||
|
||||
// Set initial validity as soon as the element is defined
|
||||
customElements.whenDefined('sl-radio-group').then(() => {
|
||||
radioGroup.setCustomValidity(errorMessage);
|
||||
});
|
||||
|
||||
// Update validity when a selection is made
|
||||
form.addEventListener('sl-change', () => {
|
||||
const isValid = radioGroup.value === '3';
|
||||
radioGroup.setCustomValidity(isValid ? '' : errorMessage);
|
||||
});
|
||||
|
||||
// Handle form submit
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { SlButton, SlIcon, SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
const App = () => {
|
||||
const radioGroup = useRef(null);
|
||||
const errorMessage = 'You must choose this option';
|
||||
|
||||
function handleChange() {
|
||||
radioGroup.current.setCustomValidity(radioGroup.current.value === '3' ? '' : errorMessage);
|
||||
}
|
||||
|
||||
function handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
radio.current.setCustomValidity(errorMessage);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<form class="custom-validity" onSubmit={handleSubmit}>
|
||||
<SlRadioGroup ref={radioGroup} label="Select an option" name="a" value="1" onSlChange={handleChange}>
|
||||
<SlRadio value="1">Not me</SlRadio>
|
||||
<SlRadio value="2">Me neither</SlRadio>
|
||||
<SlRadio value="3">Choose me</SlRadio>
|
||||
</SlRadioGroup>
|
||||
<br />
|
||||
<SlButton type="submit" variant="primary">
|
||||
Submit
|
||||
</SlButton>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
[component-metadata:sl-radio-group]
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
|
||||
[component-header:sl-radio]
|
||||
|
||||
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.
|
||||
Radios are designed to be used with [radio groups](/components/radio-group).
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option">
|
||||
<sl-radio value="1" checked>Option 1</sl-radio>
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio value="1">Option 1</sl-radio>
|
||||
<sl-radio value="2">Option 2</sl-radio>
|
||||
<sl-radio value="3">Option 3</sl-radio>
|
||||
</sl-radio-group>
|
||||
@@ -18,8 +16,8 @@ Radios are designed to be used with [radio groups](/components/radio-group). As
|
||||
import { SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option">
|
||||
<SlRadio value="1" checked>Option 1</SlRadio>
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadio value="1">Option 1</SlRadio>
|
||||
<SlRadio value="2">Option 2</SlRadio>
|
||||
<SlRadio value="3">Option 3</SlRadio>
|
||||
</SlRadioGroup>
|
||||
@@ -30,16 +28,15 @@ const App = () => (
|
||||
|
||||
## Examples
|
||||
|
||||
### Disabled
|
||||
### Initial Value
|
||||
|
||||
Use the `disabled` attribute to disable a radio.
|
||||
To set the initial value and checked state, use the `value` attribute on the containing radio group.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option">
|
||||
<sl-radio value="1" checked>Option 1</sl-radio>
|
||||
<sl-radio-group label="Select an option" name="a" value="3">
|
||||
<sl-radio value="1">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>
|
||||
```
|
||||
|
||||
@@ -47,13 +44,62 @@ Use the `disabled` attribute to disable a radio.
|
||||
import { SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option">
|
||||
<SlRadio value="1" checked>Option 1</SlRadio>
|
||||
<SlRadioGroup label="Select an option" name="a" value="3">
|
||||
<SlRadio value="1">Option 1</SlRadio>
|
||||
<SlRadio value="2">Option 2</SlRadio>
|
||||
<SlRadio value="3">Option 3</SlRadio>
|
||||
<SlRadio value="4" disabled>Disabled</SlRadio>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` attribute to disable a radio.
|
||||
|
||||
```html preview
|
||||
<sl-radio-group label="Select an option" name="a" value="1">
|
||||
<sl-radio value="1">Option 1</sl-radio>
|
||||
<sl-radio value="2" disabled>Option 2</sl-radio>
|
||||
<sl-radio value="3">Option 3</sl-radio>
|
||||
</sl-radio-group>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRadioGroup label="Select an option" name="a" value="1">
|
||||
<SlRadio value="1">Option 1</SlRadio>
|
||||
<SlRadio value="2" disabled>
|
||||
Option 2
|
||||
</SlRadio>
|
||||
<SlRadio value="3">Option 3</SlRadio>
|
||||
</SlRadioGroup>
|
||||
);
|
||||
```
|
||||
|
||||
## Sizes
|
||||
|
||||
Use the `size` attribute to change a radio's size.
|
||||
|
||||
```html preview
|
||||
<sl-radio size="small">Small</sl-radio>
|
||||
<sl-radio size="medium">Medium</sl-radio>
|
||||
<sl-radio size="large">Large</sl-radio>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRadio } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlRadio size="small">Small</SlRadio>
|
||||
<br />
|
||||
<SlRadio size="medium">Medium</SlRadio>
|
||||
<br />
|
||||
<SlRadio size="large">Large</SlRadio>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
[component-metadata:sl-radio]
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-range]
|
||||
|
||||
Ranges allow the user to select a single value within a given range using a slider.
|
||||
|
||||
```html preview
|
||||
<sl-range></sl-range>
|
||||
```
|
||||
@@ -11,15 +9,41 @@ Ranges allow the user to select a single value within a given range using a slid
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange />
|
||||
);
|
||||
const App = () => <SlRange />;
|
||||
```
|
||||
|
||||
?> This component works with standard `<form>` elements. Please refer to the section on [form controls](/getting-started/form-controls) to learn more about form submission and client-side validation.
|
||||
|
||||
## Examples
|
||||
|
||||
### Labels
|
||||
|
||||
Use the `label` attribute to give the range an accessible label. For labels that contain HTML, use the `label` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-range label="Volume" min="0" max="100"></sl-range>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlRange label="Volume" min={0} max={100} />;
|
||||
```
|
||||
|
||||
### Help Text
|
||||
|
||||
Add descriptive help text to a range with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-range label="Volume" help-text="Controls the volume of the current song." min="0" max="100"></sl-range>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlRange label="Volume" help-text="Controls the volume of the current song." min={0} max={100} />;
|
||||
```
|
||||
|
||||
### Min, Max, and Step
|
||||
|
||||
Use the `min` and `max` attributes to set the range's minimum and maximum values, respectively. The `step` attribute determines the value's interval when increasing and decreasing.
|
||||
@@ -31,9 +55,7 @@ Use the `min` and `max` attributes to set the range's minimum and maximum values
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange min={0} max={10} step={1} />
|
||||
);
|
||||
const App = () => <SlRange min={0} max={10} step={1} />;
|
||||
```
|
||||
|
||||
### Disabled
|
||||
@@ -44,13 +66,10 @@ Use the `disabled` attribute to disable a slider.
|
||||
<sl-range disabled></sl-range>
|
||||
```
|
||||
|
||||
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange disabled />
|
||||
);
|
||||
const App = () => <SlRange disabled />;
|
||||
```
|
||||
|
||||
### Tooltip Placement
|
||||
@@ -64,9 +83,7 @@ By default, the tooltip is shown on top. Set `tooltip` to `bottom` to show it be
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange tooltip="bottom" />
|
||||
);
|
||||
const App = () => <SlRange tooltip="bottom" />;
|
||||
```
|
||||
|
||||
### Disable the Tooltip
|
||||
@@ -80,9 +97,7 @@ To disable the tooltip, set `tooltip` to `none`.
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange tooltip="none" />
|
||||
);
|
||||
const App = () => <SlRange tooltip="none" />;
|
||||
```
|
||||
|
||||
### Custom Track Colors
|
||||
@@ -90,17 +105,19 @@ const App = () => (
|
||||
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="
|
||||
<sl-range
|
||||
style="
|
||||
--track-color-active: var(--sl-color-primary-600);
|
||||
--track-color-inactive: var(--sl-color-primary-100);
|
||||
"></sl-range>
|
||||
"
|
||||
></sl-range>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange
|
||||
<SlRange
|
||||
style={{
|
||||
'--track-color-active': 'var(--sl-color-primary-600)',
|
||||
'--track-color-inactive': 'var(--sl-color-primary-200)'
|
||||
@@ -109,6 +126,38 @@ const App = () => (
|
||||
);
|
||||
```
|
||||
|
||||
### Custom Track Offset
|
||||
|
||||
You can customize the initial offset of the active track using the `--track-active-offset` custom property.
|
||||
|
||||
```html preview
|
||||
<sl-range
|
||||
min="-100"
|
||||
max="100"
|
||||
style="
|
||||
--track-color-active: var(--sl-color-primary-600);
|
||||
--track-color-inactive: var(--sl-color-primary-100);
|
||||
--track-active-offset: 50%;
|
||||
"
|
||||
></sl-range>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange
|
||||
min={-100}
|
||||
max={100}
|
||||
style={{
|
||||
'--track-color-active': 'var(--sl-color-primary-600)',
|
||||
'--track-color-inactive': 'var(--sl-color-primary-200)',
|
||||
'--track-active-offset': '50%'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Custom Tooltip Formatter
|
||||
|
||||
You can change the tooltip's content by setting the `tooltipFormatter` property to a function that accepts the range's value as an argument.
|
||||
@@ -125,56 +174,7 @@ You can change the tooltip's content by setting the `tooltipFormatter` property
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
tooltipFormatter={value => `Total - ${value}%`}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Labels
|
||||
|
||||
Use the `label` attribute to give the range an accessible label. For labels that contain HTML, use the `label` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-range label="Volume" min="0" max="100"></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange label="Volume" min={0} max={100} />
|
||||
);
|
||||
```
|
||||
|
||||
### Help Text
|
||||
|
||||
Add descriptive help text to a range with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-range
|
||||
label="Volume"
|
||||
help-text="Controls the volume of the current song."
|
||||
min="0"
|
||||
max="100"
|
||||
></sl-input>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRange } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRange
|
||||
label="Volume"
|
||||
help-text="Controls the volume of the current song."
|
||||
min={0}
|
||||
max={100}
|
||||
/>
|
||||
);
|
||||
const App = () => <SlRange min={0} max={100} step={1} tooltipFormatter={value => `Total - ${value}%`} />;
|
||||
```
|
||||
|
||||
[component-metadata:sl-range]
|
||||
|
||||
@@ -2,36 +2,44 @@
|
||||
|
||||
[component-header:sl-rating]
|
||||
|
||||
Ratings give users a way to quickly view and provide feedback.
|
||||
|
||||
```html preview
|
||||
<sl-rating></sl-rating>
|
||||
<sl-rating label="Rating"></sl-rating>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRating />
|
||||
);
|
||||
const App = () => <SlRating label="Rating" />;
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Labels
|
||||
|
||||
Ratings are commonly identified contextually, so labels aren't displayed. However, you should always provide one for assistive devices using the `label` attribute.
|
||||
|
||||
```html preview
|
||||
<sl-rating label="Rate this component"></sl-rating>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlRating label="Rate this component" />;
|
||||
```
|
||||
|
||||
### Maximum Value
|
||||
|
||||
Ratings are 0-5 by default. To change the maximum possible value, use the `max` attribute.
|
||||
|
||||
```html preview
|
||||
<sl-rating max="3"></sl-rating>
|
||||
<sl-rating label="Rating" max="3"></sl-rating>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRating max={3} />
|
||||
);
|
||||
const App = () => <SlRating label="Rating" max={3} />;
|
||||
```
|
||||
|
||||
### Precision
|
||||
@@ -39,31 +47,27 @@ const App = () => (
|
||||
Use the `precision` attribute to let users select fractional ratings.
|
||||
|
||||
```html preview
|
||||
<sl-rating precision="0.5" value="2.5"></sl-rating>
|
||||
<sl-rating label="Rating" precision="0.5" value="2.5"></sl-rating>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRating precision={0.5} value={2.5} />
|
||||
);
|
||||
const App = () => <SlRating label="Rating" precision={0.5} value={2.5} />;
|
||||
```
|
||||
|
||||
## Symbol Sizes
|
||||
### Symbol Sizes
|
||||
|
||||
Set the `--symbol-size` custom property to adjust the size.
|
||||
|
||||
```html preview
|
||||
<sl-rating style="--symbol-size: 2rem;"></sl-rating>
|
||||
<sl-rating label="Rating" style="--symbol-size: 2rem;"></sl-rating>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRating style={{ '--symbol-size': '2rem' }} />
|
||||
);
|
||||
const App = () => <SlRating label="Rating" style={{ '--symbol-size': '2rem' }} />;
|
||||
```
|
||||
|
||||
### Readonly
|
||||
@@ -71,15 +75,13 @@ const App = () => (
|
||||
Use the `readonly` attribute to display a rating that users can't change.
|
||||
|
||||
```html preview
|
||||
<sl-rating readonly value="3"></sl-rating>
|
||||
<sl-rating label="Rating" readonly value="3"></sl-rating>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRating readonly value={3} />
|
||||
);
|
||||
const App = () => <SlRating label="Rating" readonly value={3} />;
|
||||
```
|
||||
|
||||
### Disabled
|
||||
@@ -87,49 +89,144 @@ const App = () => (
|
||||
Use the `disable` attribute to disable the rating.
|
||||
|
||||
```html preview
|
||||
<sl-rating disabled value="3"></sl-rating>
|
||||
<sl-rating label="Rating" disabled value="3"></sl-rating>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRating disabled value={3} />
|
||||
);
|
||||
const App = () => <SlRating label="Rating" disabled value={3} />;
|
||||
```
|
||||
|
||||
### Detecting Hover
|
||||
|
||||
Use the `sl-hover` event to detect when the user hovers over (or touch and drag) the rating. This lets you hook into values as the user interacts with the rating, but before they select a value.
|
||||
|
||||
The event has a payload with `phase` and `value` properties. The `phase` property tells when hovering starts, moves to a new value, and ends. The `value` property tells what the rating's value would be if the user were to commit to the hovered value.
|
||||
|
||||
```html preview
|
||||
<div class="detect-hover">
|
||||
<sl-rating label="Rating"></sl-rating>
|
||||
<span></span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const rating = document.querySelector('.detect-hover > sl-rating');
|
||||
const span = rating.nextElementSibling;
|
||||
const terms = ['No rating', 'Terrible', 'Bad', 'OK', 'Good', 'Excellent'];
|
||||
|
||||
rating.addEventListener('sl-hover', event => {
|
||||
span.textContent = terms[event.detail.value];
|
||||
|
||||
// Clear feedback when hovering stops
|
||||
if (event.detail.phase === 'end') {
|
||||
span.textContent = '';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.detect-hover span {
|
||||
position: relative;
|
||||
top: -4px;
|
||||
left: 8px;
|
||||
border-radius: var(--sl-border-radius-small);
|
||||
background: var(--sl-color-neutral-900);
|
||||
color: var(--sl-color-neutral-0);
|
||||
text-align: center;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
.detect-hover span:empty {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { useState } from 'react';
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const terms = ['No rating', 'Terrible', 'Bad', 'OK', 'Good', 'Excellent'];
|
||||
const css = `
|
||||
.detect-hover span {
|
||||
position: relative;
|
||||
top: -4px;
|
||||
left: 8px;
|
||||
border-radius: var(--sl-border-radius-small);
|
||||
background: var(--sl-color-neutral-900);
|
||||
color: var(--sl-color-neutral-0);
|
||||
text-align: center;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
.detect-hover span:empty {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
function handleHover(event) {
|
||||
rating.addEventListener('sl-hover', event => {
|
||||
setFeedback(terms[event.detail.value]);
|
||||
|
||||
// Clear feedback when hovering stops
|
||||
if (event.detail.phase === 'end') {
|
||||
setFeedback('');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const App = () => {
|
||||
const [feedback, setFeedback] = useState(true);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class="detect-hover">
|
||||
<SlRating label="Rating" onSlHover={handleHover} />
|
||||
<span>{feedback}</span>
|
||||
</div>
|
||||
<style>{css}</style>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Icons
|
||||
|
||||
You can provide custom icons by passing a function to the `getSymbol` property.
|
||||
|
||||
```html preview
|
||||
<sl-rating class="rating-hearts" style="--symbol-color-active: #ff4136;"></sl-rating>
|
||||
<sl-rating label="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>';
|
||||
rating.getSymbol = () => '<sl-icon name="heart-fill"></sl-icon>';
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import '@shoelace-style/shoelace/dist/components/icon/icon';
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRating
|
||||
<SlRating
|
||||
label="Rating"
|
||||
getSymbol={() => '<sl-icon name="heart-fill"></sl-icon>'}
|
||||
style={{ '--symbol-color-active': '#ff4136' }}
|
||||
style={{ '--symbol-color-active': '#ff4136' }}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Value-based Icons
|
||||
|
||||
You can also use the `getSymbol` property to render different icons based on value.
|
||||
|
||||
```html preview
|
||||
<sl-rating class="rating-emojis"></sl-rating>
|
||||
<sl-rating label="Rating" class="rating-emojis"></sl-rating>
|
||||
|
||||
<script>
|
||||
const rating = document.querySelector('.rating-emojis');
|
||||
|
||||
rating.getSymbol = (value) => {
|
||||
rating.getSymbol = value => {
|
||||
const icons = ['emoji-angry', 'emoji-frown', 'emoji-expressionless', 'emoji-smile', 'emoji-laughing'];
|
||||
return `<sl-icon name="${icons[value - 1]}"></sl-icon>`;
|
||||
};
|
||||
@@ -137,7 +234,6 @@ const App = () => (
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import '@shoelace-style/shoelace/dist/components/icon/icon';
|
||||
import { SlRating } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
function getSymbol(value) {
|
||||
@@ -145,9 +241,7 @@ function getSymbol(value) {
|
||||
return `<sl-icon name="${icons[value - 1]}"></sl-icon>`;
|
||||
}
|
||||
|
||||
const App = () => (
|
||||
<SlRating getSymbol={getSymbol} />
|
||||
);
|
||||
const App = () => <SlRating label="Rating" getSymbol={getSymbol} />;
|
||||
```
|
||||
|
||||
[component-metadata:sl-rating]
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-relative-time]
|
||||
|
||||
Outputs a localized time phrase relative to the current date and time.
|
||||
|
||||
Localization is handled by the browser's [`Intl.RelativeTimeFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat). No language packs are required.
|
||||
|
||||
```html preview
|
||||
@@ -14,17 +12,13 @@ Localization is handled by the browser's [`Intl.RelativeTimeFormat` API](https:/
|
||||
```jsx react
|
||||
import { SlRelativeTime } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlRelativeTime date="2020-07-15T09:17:00-04:00" />
|
||||
);
|
||||
const App = () => <SlRelativeTime date="2020-07-15T09:17:00-04:00" />;
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
!> The `Intl.RelativeTimeFormat` API is available [in all major browsers](https://caniuse.com/mdn-javascript_builtins_intl_relativetimeformat), but it only became available to Safari in version 14. If you need to support Safari 13, you'll need to [use a polyfill](https://github.com/catamphetamine/relative-time-format).
|
||||
|
||||
## Examples
|
||||
|
||||
### Keeping Time in Sync
|
||||
@@ -49,9 +43,7 @@ import { SlRelativeTime } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const date = new Date(new Date().getTime() - 60000);
|
||||
|
||||
const App = () => (
|
||||
<SlRelativeTime date={date} sync />
|
||||
);
|
||||
const App = () => <SlRelativeTime date={date} sync />;
|
||||
```
|
||||
|
||||
### Formatting Styles
|
||||
@@ -59,8 +51,8 @@ const App = () => (
|
||||
You can change how the time is displayed using the `format` attribute. Note that some locales may display the same values for `narrow` and `short` formats.
|
||||
|
||||
```html preview
|
||||
<sl-relative-time date="2020-07-15T09:17:00-04:00" format="narrow"></sl-relative-time><br>
|
||||
<sl-relative-time date="2020-07-15T09:17:00-04:00" format="short"></sl-relative-time><br>
|
||||
<sl-relative-time date="2020-07-15T09:17:00-04:00" format="narrow"></sl-relative-time><br />
|
||||
<sl-relative-time date="2020-07-15T09:17:00-04:00" format="short"></sl-relative-time><br />
|
||||
<sl-relative-time date="2020-07-15T09:17:00-04:00" format="long"></sl-relative-time>
|
||||
```
|
||||
|
||||
@@ -69,8 +61,10 @@ import { SlRelativeTime } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlRelativeTime date="2020-07-15T09:17:00-04:00" format="narrow" /><br />
|
||||
<SlRelativeTime date="2020-07-15T09:17:00-04:00" format="short" /><br />
|
||||
<SlRelativeTime date="2020-07-15T09:17:00-04:00" format="narrow" />
|
||||
<br />
|
||||
<SlRelativeTime date="2020-07-15T09:17:00-04:00" format="short" />
|
||||
<br />
|
||||
<SlRelativeTime date="2020-07-15T09:17:00-04:00" format="long" />
|
||||
</>
|
||||
);
|
||||
@@ -81,10 +75,10 @@ const App = () => (
|
||||
Use the `lang` attribute to set the desired locale.
|
||||
|
||||
```html preview
|
||||
English: <sl-relative-time date="2020-07-15T09:17:00-04:00" lang="en-US"></sl-relative-time><br>
|
||||
Chinese: <sl-relative-time date="2020-07-15T09:17:00-04:00" lang="zh-CN"></sl-relative-time><br>
|
||||
German: <sl-relative-time date="2020-07-15T09:17:00-04:00" lang="de"></sl-relative-time><br>
|
||||
Greek: <sl-relative-time date="2020-07-15T09:17:00-04:00" lang="el"></sl-relative-time><br>
|
||||
English: <sl-relative-time date="2020-07-15T09:17:00-04:00" lang="en-US"></sl-relative-time><br />
|
||||
Chinese: <sl-relative-time date="2020-07-15T09:17:00-04:00" lang="zh-CN"></sl-relative-time><br />
|
||||
German: <sl-relative-time date="2020-07-15T09:17:00-04:00" lang="de"></sl-relative-time><br />
|
||||
Greek: <sl-relative-time date="2020-07-15T09:17:00-04:00" lang="el"></sl-relative-time><br />
|
||||
Russian: <sl-relative-time date="2020-07-15T09:17:00-04:00" lang="ru"></sl-relative-time>
|
||||
```
|
||||
|
||||
@@ -93,10 +87,14 @@ import { SlRelativeTime } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
English: <SlRelativeTime date="2020-07-15T09:17:00-04:00" lang="en-US" /><br />
|
||||
Chinese: <SlRelativeTime date="2020-07-15T09:17:00-04:00" lang="zh-CN" /><br />
|
||||
German: <SlRelativeTime date="2020-07-15T09:17:00-04:00" lang="de" /><br />
|
||||
Greek: <SlRelativeTime date="2020-07-15T09:17:00-04:00" lang="el" /><br />
|
||||
English: <SlRelativeTime date="2020-07-15T09:17:00-04:00" lang="en-US" />
|
||||
<br />
|
||||
Chinese: <SlRelativeTime date="2020-07-15T09:17:00-04:00" lang="zh-CN" />
|
||||
<br />
|
||||
German: <SlRelativeTime date="2020-07-15T09:17:00-04:00" lang="de" />
|
||||
<br />
|
||||
Greek: <SlRelativeTime date="2020-07-15T09:17:00-04:00" lang="el" />
|
||||
<br />
|
||||
Russian: <SlRelativeTime date="2020-07-15T09:17:00-04:00" lang="ru" />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,16 +2,12 @@
|
||||
|
||||
[component-header:sl-resize-observer]
|
||||
|
||||
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` that contains the target element and information about its dimensions.
|
||||
|
||||
```html preview
|
||||
<div class="resize-observer-overview">
|
||||
<sl-resize-observer>
|
||||
<div>
|
||||
Resize this box and watch the console 👉
|
||||
</div>
|
||||
<div>Resize this box and watch the console 👉</div>
|
||||
</sl-resize-observer>
|
||||
</div>
|
||||
|
||||
@@ -26,9 +22,9 @@ The resize observer will report changes to the dimensions of the elements it wra
|
||||
|
||||
<style>
|
||||
.resize-observer-overview div {
|
||||
display: flex;
|
||||
border: solid 2px var(--sl-input-border-color);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
border: solid 2px var(--sl-input-border-color);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
padding: 4rem 2rem;
|
||||
@@ -54,9 +50,7 @@ const App = () => (
|
||||
<>
|
||||
<div className="resize-observer-overview">
|
||||
<SlResizeObserver onSlResize={event => console.log(event.detail)}>
|
||||
<div>
|
||||
Resize this box and watch the console 👉
|
||||
</div>
|
||||
<div>Resize this box and watch the console 👉</div>
|
||||
</SlResizeObserver>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
# 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>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlResponsiveMedia } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlResponsiveMedia>
|
||||
<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."
|
||||
/>
|
||||
</SlResponsiveMedia>
|
||||
);
|
||||
```
|
||||
|
||||
## 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>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlResponsiveMedia } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlResponsiveMedia 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."
|
||||
/>
|
||||
</SlResponsiveMedia>
|
||||
);
|
||||
```
|
||||
|
||||
### 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>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlResponsiveMedia } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlResponsiveMedia aspect-ratio="16:9">
|
||||
<iframe src="https://player.vimeo.com/video/1053647?title=0&byline=0&portrait=0" frameborder="0" allow="autoplay; fullscreen" allowfullscreen />
|
||||
</SlResponsiveMedia>
|
||||
);
|
||||
```
|
||||
|
||||
[component-metadata:sl-responsive-media]
|
||||
@@ -2,32 +2,28 @@
|
||||
|
||||
[component-header:sl-select]
|
||||
|
||||
Selects allow you to choose one or more items from a dropdown menu.
|
||||
|
||||
```html preview
|
||||
<sl-select>
|
||||
<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-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-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
<sl-option value="option-4">Option 4</sl-option>
|
||||
<sl-option value="option-5">Option 5</sl-option>
|
||||
<sl-option value="option-6">Option 6</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlDivider, SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlDivider />
|
||||
<SlMenuItem value="option-4">Option 4</SlMenuItem>
|
||||
<SlMenuItem value="option-5">Option 5</SlMenuItem>
|
||||
<SlMenuItem value="option-6">Option 6</SlMenuItem>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
<SlOption value="option-4">Option 4</SlOption>
|
||||
<SlOption value="option-5">Option 5</SlOption>
|
||||
<SlOption value="option-6">Option 6</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
@@ -36,50 +32,98 @@ const App = () => (
|
||||
|
||||
## Examples
|
||||
|
||||
### Labels
|
||||
|
||||
Use the `label` attribute to give the select an accessible label. For labels that contain HTML, use the `label` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-select label="Select one">
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect label="Select one">
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
### Help Text
|
||||
|
||||
Add descriptive help text to a select with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-select label="Experience" help-text="Please tell us your skill level.">
|
||||
<sl-option value="1">Novice</sl-option>
|
||||
<sl-option value="2">Intermediate</sl-option>
|
||||
<sl-option value="3">Advanced</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect label="Experience" help-text="Please tell us your skill level.">
|
||||
<SlOption value="1">Novice</SlOption>
|
||||
<SlOption value="2">Intermediate</SlOption>
|
||||
<SlOption value="3">Advanced</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
### Placeholders
|
||||
|
||||
Use the `placeholder` attribute to add a placeholder.
|
||||
|
||||
```html preview
|
||||
<sl-select placeholder="Select one">
|
||||
<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-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect placeholder="Select one">
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
### Clearable
|
||||
|
||||
Use the `clearable` attribute to make the control clearable.
|
||||
Use the `clearable` attribute to make the control clearable. The clear button only appears when an option is selected.
|
||||
|
||||
```html preview
|
||||
<sl-select placeholder="Clearable" clearable>
|
||||
<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 clearable value="option-1">
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect placeholder="Clearable" clearable>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
@@ -90,20 +134,20 @@ 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-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect filled>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
@@ -114,20 +158,20 @@ Use the `pill` attribute to give selects rounded edges.
|
||||
|
||||
```html preview
|
||||
<sl-select pill>
|
||||
<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-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect pill>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
@@ -138,319 +182,250 @@ Use the `disabled` attribute to disable a select.
|
||||
|
||||
```html preview
|
||||
<sl-select placeholder="Disabled" disabled>
|
||||
<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-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect placeholder="Disabled" disabled>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
### Multiple
|
||||
|
||||
To allow multiple options to be selected, use the `multiple` attribute. It's a good practice to use `clearable` when this option is enabled. When using this option, the `value` property will be an array of strings instead of a string.
|
||||
To allow multiple options to be selected, use the `multiple` attribute. It's a good practice to use `clearable` when this option is enabled. To set multiple values at once, set `value` to a space-delimited list of values.
|
||||
|
||||
```html preview
|
||||
<sl-select placeholder="Select a few" multiple clearable>
|
||||
<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-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 label="Select a Few" value="option-1 option-2 option-3" multiple clearable>
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
<sl-option value="option-4">Option 4</sl-option>
|
||||
<sl-option value="option-5">Option 5</sl-option>
|
||||
<sl-option value="option-6">Option 6</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlDivider, SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect placeholder="Select a few" multiple clearable>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlDivider />
|
||||
<SlMenuItem value="option-4">Option 4</SlMenuItem>
|
||||
<SlMenuItem value="option-5">Option 5</SlMenuItem>
|
||||
<SlMenuItem value="option-6">Option 6</SlMenuItem>
|
||||
<SlSelect label="Select a Few" value="option-1 option-2 option-3" multiple clearable>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
<SlOption value="option-4">Option 4</SlOption>
|
||||
<SlOption value="option-5">Option 5</SlOption>
|
||||
<SlOption value="option-6">Option 6</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
?> When using the `multiple` attribute, the `value` property will be an array instead of a string. To set it in your HTML, obtain a reference to the element and set `value` to an array of strings.
|
||||
?> Note that multi-select options may wrap, causing the control to expand vertically. You can use the `max-options-visible` attribute to control the maximum number of selected options to show at once.
|
||||
|
||||
### Grouping Options
|
||||
### Setting Initial Values
|
||||
|
||||
Options can be grouped visually using menu labels and dividers.
|
||||
Use the `value` attribute to set the initial selection. When using `multiple`, use space-delimited values to select more than one option.
|
||||
|
||||
```html preview
|
||||
<sl-select placeholder="Select one">
|
||||
<sl-menu-label>Group 1</sl-menu-label>
|
||||
<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-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>
|
||||
<sl-menu-item value="option-6">Option 6</sl-menu-item>
|
||||
<sl-select value="option-1 option-2" multiple clearable>
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
<sl-option value="option-4">Option 4</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlDivider, SlMenuItem, SlMenuLabel, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlDivider, SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect placeholder="Select one">
|
||||
<SlMenuLabel>Group 1</SlMenuLabel>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlDivider></SlDivider>
|
||||
<SlMenuLabel>Group 2</SlMenuLabel>
|
||||
<SlMenuItem value="option-4">Option 4</SlMenuItem>
|
||||
<SlMenuItem value="option-5">Option 5</SlMenuItem>
|
||||
<SlMenuItem value="option-6">Option 6</SlMenuItem>
|
||||
<SlSelect value="option-1 option-2" multiple clearable>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
### Grouping Options
|
||||
|
||||
Use `<sl-divider>` to group listbox items visually. You can also use `<small>` to provide labels, but they won't be announced by most assistive devices.
|
||||
|
||||
```html preview
|
||||
<sl-select>
|
||||
<small>Section 1</small>
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
<sl-divider></sl-divider>
|
||||
<small>Section 2</small>
|
||||
<sl-option value="option-4">Option 4</sl-option>
|
||||
<sl-option value="option-5">Option 5</sl-option>
|
||||
<sl-option value="option-6">Option 6</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
<SlOption value="option-4">Option 4</SlOption>
|
||||
<SlOption value="option-5">Option 5</SlOption>
|
||||
<SlOption value="option-6">Option 6</SlOption>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
### Sizes
|
||||
|
||||
Use the `size` attribute to change a select's size.
|
||||
Use the `size` attribute to change a select's size. Note that size does not apply to listbox options.
|
||||
|
||||
```html preview
|
||||
<sl-select placeholder="Small" size="small" multiple>
|
||||
<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 placeholder="Small" size="small">
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<sl-select placeholder="Medium" size="medium" multiple>
|
||||
<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 placeholder="Medium" size="medium">
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<sl-select placeholder="Large" size="large" multiple>
|
||||
<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 placeholder="Large" size="large">
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlSelect placeholder="Small" size="small" multiple>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlSelect placeholder="Small" size="small">
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
|
||||
<br />
|
||||
|
||||
<SlSelect placeholder="Medium" size="medium" multiple>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlSelect placeholder="Medium" size="medium">
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
|
||||
<br />
|
||||
|
||||
<SlSelect placeholder="Large" size="large" multiple>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlSelect placeholder="Large" size="large">
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Selecting Options Programmatically
|
||||
### Placement
|
||||
|
||||
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.
|
||||
The preferred placement of the select's listbox can be set with the `placement` attribute. Note that the actual position may vary to ensure the panel remains in the viewport. Valid placements are `top` and `bottom`.
|
||||
|
||||
```html preview
|
||||
<div class="selecting-example">
|
||||
<sl-select>
|
||||
<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>
|
||||
|
||||
<br>
|
||||
|
||||
<sl-button data-option="option-1">Set 1</sl-button>
|
||||
<sl-button data-option="option-2">Set 2</sl-button>
|
||||
<sl-button data-option="option-3">Set 3</sl-button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.selecting-example');
|
||||
const select = container.querySelector('sl-select');
|
||||
|
||||
[...container.querySelectorAll('sl-button')].map(button => {
|
||||
button.addEventListener('click', () => {
|
||||
select.value = button.dataset.option;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { useState } from 'react';
|
||||
import { SlButton, SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const [value, setValue] = useState('option-1');
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlSelect value={value} onSlChange={event => setValue(event.target.value)}>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
</SlSelect>
|
||||
|
||||
<br />
|
||||
|
||||
<SlButton onClick={() => setValue('option-1')}>Set 1</SlButton>
|
||||
<SlButton onClick={() => setValue('option-2')}>Set 2</SlButton>
|
||||
<SlButton onClick={() => setValue('option-3')}>Set 3</SlButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Labels
|
||||
|
||||
Use the `label` attribute to give the select an accessible label. For labels that contain HTML, use the `label` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-select label="Select one">
|
||||
<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 placement="top">
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import {
|
||||
SlOption,
|
||||
SlSelect
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect label="Select one">
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
</SlSelect>
|
||||
<SlSelect placement="top">
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlDropdown>
|
||||
);
|
||||
```
|
||||
|
||||
### Help Text
|
||||
### Prefix Icons
|
||||
|
||||
Add descriptive help text to a select with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
Use the `prefix` slot to prepend an icon to the control.
|
||||
|
||||
```html preview
|
||||
<sl-select
|
||||
label="Experience"
|
||||
help-text="Please tell us your skill level."
|
||||
>
|
||||
<sl-menu-item value="1">Novice</sl-menu-item>
|
||||
<sl-menu-item value="2">Intermediate</sl-menu-item>
|
||||
<sl-menu-item value="3">Advanced</sl-menu-item>
|
||||
<sl-select placeholder="Small" size="small" clearable>
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
<br />
|
||||
<sl-select placeholder="Medium" size="medium" clearable>
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
<br />
|
||||
<sl-select placeholder="Large" size="large" clearable>
|
||||
<sl-icon name="house" slot="prefix"></sl-icon>
|
||||
<sl-option value="option-1">Option 1</sl-option>
|
||||
<sl-option value="option-2">Option 2</sl-option>
|
||||
<sl-option value="option-3">Option 3</sl-option>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSelect
|
||||
label="Experience"
|
||||
help-text="Please tell us your skill level."
|
||||
>
|
||||
<SlMenuItem value="1">Novice</SlMenuItem>
|
||||
<SlMenuItem value="2">Intermediate</SlMenuItem>
|
||||
<SlMenuItem value="3">Advanced</SlMenuItem>
|
||||
</SlSelect>
|
||||
);
|
||||
```
|
||||
|
||||
### 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>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlIcon, SlMenuItem, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlIcon, SlOption, SlSelect } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlSelect placeholder="Small" size="small">
|
||||
<SlIcon name="house" slot="prefix"></SlIcon>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlIcon name="chat" slot="suffix"></SlIcon>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
<br />
|
||||
<SlSelect placeholder="Medium" size="medium">
|
||||
<SlIcon name="house" slot="prefix"></SlIcon>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlIcon name="chat" slot="suffix"></SlIcon>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
<br />
|
||||
<SlSelect placeholder="Large" size="large">
|
||||
<SlIcon name="house" slot="prefix"></SlIcon>
|
||||
<SlMenuItem value="option-1">Option 1</SlMenuItem>
|
||||
<SlMenuItem value="option-2">Option 2</SlMenuItem>
|
||||
<SlMenuItem value="option-3">Option 3</SlMenuItem>
|
||||
<SlIcon name="chat" slot="suffix"></SlIcon>
|
||||
<SlOption value="option-1">Option 1</SlOption>
|
||||
<SlOption value="option-2">Option 2</SlOption>
|
||||
<SlOption value="option-3">Option 3</SlOption>
|
||||
</SlSelect>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-skeleton]
|
||||
|
||||
Skeletons are used to show where content will eventually be drawn.
|
||||
|
||||
These are simple containers for scaffolding layouts that mimic what users will see when content has finished loading. This prevents large areas of empty space during asynchronous operations.
|
||||
|
||||
Skeletons try not to be opinionated, as there are endless possibilities for designing layouts. Therefore, you'll likely use more than one skeleton to create the effect you want. If you find yourself using them frequently, consider creating a template that renders them with the desired arrangement and styles.
|
||||
@@ -101,7 +99,7 @@ const App = () => (
|
||||
<SlSkeleton />
|
||||
<SlSkeleton />
|
||||
<SlSkeleton />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>{css}</style>
|
||||
</>
|
||||
@@ -112,7 +110,7 @@ const App = () => (
|
||||
|
||||
### Effects
|
||||
|
||||
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.
|
||||
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">
|
||||
@@ -155,10 +153,8 @@ const App = () => (
|
||||
<div className="skeleton-effects">
|
||||
<SlSkeleton effect="none" />
|
||||
None
|
||||
|
||||
<SlSkeleton effect="sheen" />
|
||||
Sheen
|
||||
|
||||
<SlSkeleton effect="pulse" />
|
||||
Pulse
|
||||
</div>
|
||||
@@ -252,13 +248,13 @@ Set a matching width and height to make a circle, square, or rounded avatar skel
|
||||
display: inline-block;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
margin-right: .5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.skeleton-avatars sl-skeleton:nth-child(1) {
|
||||
--border-radius: 0;
|
||||
}
|
||||
|
||||
|
||||
.skeleton-avatars sl-skeleton:nth-child(2) {
|
||||
--border-radius: var(--sl-border-radius-medium);
|
||||
}
|
||||
@@ -333,7 +329,20 @@ Use the `--border-radius` custom property to make circles, squares, and rectangl
|
||||
|
||||
.skeleton-shapes .cross::part(indicator) {
|
||||
--border-radius: 0;
|
||||
clip-path: polygon(20% 0%, 0% 20%, 30% 50%, 0% 80%, 20% 100%, 50% 70%, 80% 100%, 100% 80%, 70% 50%, 100% 20%, 80% 0%, 50% 30%);
|
||||
clip-path: polygon(
|
||||
20% 0%,
|
||||
0% 20%,
|
||||
30% 50%,
|
||||
0% 80%,
|
||||
20% 100%,
|
||||
50% 70%,
|
||||
80% 100%,
|
||||
100% 80%,
|
||||
70% 50%,
|
||||
100% 20%,
|
||||
80% 0%,
|
||||
50% 30%
|
||||
);
|
||||
}
|
||||
|
||||
.skeleton-shapes .comment::part(indicator) {
|
||||
@@ -342,7 +351,7 @@ Use the `--border-radius` custom property to make circles, squares, and rectangl
|
||||
}
|
||||
|
||||
.skeleton-shapes sl-skeleton:not(:last-child) {
|
||||
margin-right: .5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
@@ -387,13 +396,13 @@ const css = `
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<div className="skeleton-shapes">
|
||||
<SlSkeleton className="square" />
|
||||
<SlSkeleton className="circle" />
|
||||
<SlSkeleton className="triangle" />
|
||||
<SlSkeleton className="cross" />
|
||||
<SlSkeleton className="comment" />
|
||||
</div>
|
||||
<div className="skeleton-shapes">
|
||||
<SlSkeleton className="square" />
|
||||
<SlSkeleton className="circle" />
|
||||
<SlSkeleton className="triangle" />
|
||||
<SlSkeleton className="cross" />
|
||||
<SlSkeleton className="comment" />
|
||||
</div>
|
||||
|
||||
<style>{css}</style>
|
||||
</>
|
||||
@@ -428,12 +437,7 @@ const css = `
|
||||
}
|
||||
`;
|
||||
|
||||
const App = () => (
|
||||
<SlSkeleton
|
||||
effect="sheen"
|
||||
style={{ '--color': 'tomato', '--sheen-color': '#ffb094' }}
|
||||
/>
|
||||
);
|
||||
const App = () => <SlSkeleton effect="sheen" style={{ '--color': 'tomato', '--sheen-color': '#ffb094' }} />;
|
||||
```
|
||||
|
||||
[component-metadata:sl-skeleton]
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-spinner]
|
||||
|
||||
Spinners are used to show the progress of an indeterminate operation.
|
||||
|
||||
```html preview
|
||||
<sl-spinner></sl-spinner>
|
||||
```
|
||||
@@ -11,9 +9,7 @@ Spinners are used to show the progress of an indeterminate operation.
|
||||
```jsx react
|
||||
import { SlSpinner } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSpinner />
|
||||
);
|
||||
const App = () => <SlSpinner />;
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -52,11 +48,11 @@ The width of the spinner's track can be changed by setting the `--track-width` c
|
||||
import { SlSpinner } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSpinner
|
||||
<SlSpinner
|
||||
style={{
|
||||
fontSize: '3rem',
|
||||
'--track-width': '6px'
|
||||
}}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
```
|
||||
@@ -73,12 +69,12 @@ The spinner's colors can be changed by setting the `--indicator-color` and `--tr
|
||||
import { SlSpinner } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSpinner
|
||||
<SlSpinner
|
||||
style={{
|
||||
fontSize: '3rem',
|
||||
'--indicator-color': 'deeppink',
|
||||
'--track-color': 'pink'
|
||||
}}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -2,14 +2,18 @@
|
||||
|
||||
[component-header:sl-split-panel]
|
||||
|
||||
Split panels display two adjacent panels, allowing the user to reposition them.
|
||||
|
||||
```html preview
|
||||
<sl-split-panel>
|
||||
<div slot="start" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
@@ -20,22 +24,28 @@ import { SlSplitPanel } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSplitPanel>
|
||||
<div slot="start" style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}>
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}>
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</SlSplitPanel>
|
||||
@@ -50,10 +60,16 @@ To set the initial position, use the `position` attribute. If no position is pro
|
||||
|
||||
```html preview
|
||||
<sl-split-panel position="75">
|
||||
<div slot="start" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
@@ -65,10 +81,16 @@ To set the initial position in pixels instead of a percentage, use the `position
|
||||
|
||||
```html preview
|
||||
<sl-split-panel position-in-pixels="150">
|
||||
<div slot="start" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
@@ -79,8 +101,8 @@ import { SlSplitPanel } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSplitPanel position="200">
|
||||
<div
|
||||
slot="start"
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -91,8 +113,8 @@ const App = () => (
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div
|
||||
slot="end"
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -113,10 +135,16 @@ Add the `vertical` attribute to render the split panel in a vertical orientation
|
||||
|
||||
```html preview
|
||||
<sl-split-panel vertical style="height: 400px;">
|
||||
<div slot="start" style="height: 100%; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 100%; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 100%; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 100%; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
@@ -127,26 +155,26 @@ import { SlSplitPanel } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSplitPanel vertical style={{ height: '400px' }}>
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '100%',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '100%',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '100%',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
style={{
|
||||
height: '100%',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
End
|
||||
@@ -162,10 +190,16 @@ To snap panels at specific positions while dragging, add the `snap` attribute wi
|
||||
```html preview
|
||||
<div class="split-panel-snapping">
|
||||
<sl-split-panel snap="100px 50%">
|
||||
<div slot="start" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
@@ -233,8 +267,8 @@ const App = () => (
|
||||
<>
|
||||
<div className="split-panel-snapping">
|
||||
<SlSplitPanel snap="100px 50%">
|
||||
<div
|
||||
slot="start"
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -245,8 +279,8 @@ const App = () => (
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div
|
||||
slot="end"
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -273,10 +307,16 @@ Add the `disabled` attribute to prevent the divider from being repositioned.
|
||||
|
||||
```html preview
|
||||
<sl-split-panel disabled>
|
||||
<div slot="start" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
@@ -287,8 +327,8 @@ import { SlSplitPanel } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSplitPanel disabled>
|
||||
<div
|
||||
slot="start"
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -299,8 +339,8 @@ const App = () => (
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div
|
||||
slot="end"
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -324,18 +364,24 @@ Try resizing the example below with each option and notice how the panels respon
|
||||
```html preview
|
||||
<div class="split-panel-primary">
|
||||
<sl-split-panel>
|
||||
<div slot="start" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
|
||||
<sl-select label="Primary Panel" value="" style="max-width: 200px; margin-top: 1rem;">
|
||||
<sl-menu-item value="">None</sl-menu-item>
|
||||
<sl-menu-item value="start">Start</sl-menu-item>
|
||||
<sl-menu-item value="end">End</sl-menu-item>
|
||||
<sl-option value="">None</sl-option>
|
||||
<sl-option value="start">Start</sl-option>
|
||||
<sl-option value="end">End</sl-option>
|
||||
</sl-select>
|
||||
</div>
|
||||
|
||||
@@ -344,7 +390,7 @@ Try resizing the example below with each option and notice how the panels respon
|
||||
const splitPanel = container.querySelector('sl-split-panel');
|
||||
const select = container.querySelector('sl-select');
|
||||
|
||||
select.addEventListener('sl-change', () => splitPanel.primary = select.value);
|
||||
select.addEventListener('sl-change', () => (splitPanel.primary = select.value));
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -358,8 +404,8 @@ const App = () => {
|
||||
return (
|
||||
<>
|
||||
<SlSplitPanel primary={primary}>
|
||||
<div
|
||||
slot="start"
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -370,8 +416,8 @@ const App = () => {
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div
|
||||
slot="end"
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -384,16 +430,16 @@ const App = () => {
|
||||
</div>
|
||||
</SlSplitPanel>
|
||||
|
||||
<SlSelect
|
||||
label="Primary Panel"
|
||||
value={primary}
|
||||
style={{ maxWidth: '200px', marginTop: '1rem' }}
|
||||
<SlSelect
|
||||
label="Primary Panel"
|
||||
value={primary}
|
||||
style={{ maxWidth: '200px', marginTop: '1rem' }}
|
||||
onSlChange={event => setPrimary(event.target.value)}
|
||||
>
|
||||
<SlMenuItem value="">None</SlMenuItem>
|
||||
<SlMenuItem value="start">Start</SlMenuItem>
|
||||
<SlMenuItem value="end">End</SlMenuItem>
|
||||
</SlSelect>
|
||||
</SlSelect>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -407,10 +453,16 @@ This examples demonstrates how you can ensure both panels are at least 150px usi
|
||||
|
||||
```html preview
|
||||
<sl-split-panel style="--min: 150px; --max: calc(100% - 150px);">
|
||||
<div slot="start" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
@@ -421,8 +473,8 @@ import { SlSplitPanel } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSplitPanel style={{ '--min': '150px', '--max': 'calc(100% - 150px)' }}>
|
||||
<div
|
||||
slot="start"
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -433,8 +485,8 @@ const App = () => (
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div
|
||||
slot="end"
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -455,18 +507,27 @@ Create complex layouts that can be repositioned independently by nesting split p
|
||||
|
||||
```html preview
|
||||
<sl-split-panel>
|
||||
<div slot="start" style="height: 400px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 400px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end">
|
||||
<sl-split-panel vertical style="height: 400px;">
|
||||
<div slot="start" style="height: 100%; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 100%; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Top
|
||||
</div>
|
||||
<div slot="end" style="height: 100%; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 100%; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Bottom
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
</sl-split-panel>
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
```
|
||||
@@ -476,8 +537,8 @@ import { SlSplitPanel } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSplitPanel>
|
||||
<div
|
||||
slot="start"
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '400px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
@@ -490,9 +551,9 @@ const App = () => (
|
||||
</div>
|
||||
<div slot="end">
|
||||
<SlSplitPanel vertical style={{ height: '400px' }}>
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '100%',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
@@ -502,15 +563,15 @@ const App = () => (
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '100%',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
}}
|
||||
>
|
||||
End
|
||||
</div>
|
||||
@@ -522,15 +583,21 @@ const App = () => (
|
||||
|
||||
### Customizing the Divider
|
||||
|
||||
You can target the `divider` part to apply CSS properties to the divider. To add a handle, slot an icon or another element into the `handle` slot. When customizing the divider, make sure to think about focus styles for keyboard users.
|
||||
You can target the `divider` part to apply CSS properties to the divider. To add a custom handle, slot an icon into the `divider` slot. When customizing the divider, make sure to think about focus styles for keyboard users.
|
||||
|
||||
```html preview
|
||||
<sl-split-panel style="--divider-width: 20px;">
|
||||
<sl-icon slot="handle" name="grip-vertical"></sl-icon>
|
||||
<div slot="start" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<sl-icon slot="divider" name="grip-vertical"></sl-icon>
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
@@ -541,23 +608,29 @@ import { SlSplitPanel, SlIcon } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSplitPanel style={{ '--divider-width': '20px' }}>
|
||||
<SlIcon slot="handle" name="grip-vertical" />
|
||||
<div slot="start" style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}>
|
||||
<SlIcon slot="divider" name="grip-vertical" />
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}>
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</SlSplitPanel>
|
||||
@@ -567,40 +640,46 @@ const App = () => (
|
||||
Here's a more elaborate example that changes the divider's color and width and adds a styled handle.
|
||||
|
||||
```html preview
|
||||
<div class="split-panel-handle">
|
||||
<div class="split-panel-divider">
|
||||
<sl-split-panel>
|
||||
<sl-icon slot="handle" name="grip-vertical"></sl-icon>
|
||||
<div slot="start" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<sl-icon slot="divider" name="grip-vertical"></sl-icon>
|
||||
<div
|
||||
slot="start"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;">
|
||||
<div
|
||||
slot="end"
|
||||
style="height: 200px; background: var(--sl-color-neutral-50); display: flex; align-items: center; justify-content: center;"
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</sl-split-panel>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.split-panel-handle sl-split-panel {
|
||||
.split-panel-divider sl-split-panel {
|
||||
--divider-width: 2px;
|
||||
}
|
||||
|
||||
.split-panel-handle sl-split-panel::part(divider) {
|
||||
.split-panel-divider sl-split-panel::part(divider) {
|
||||
background-color: var(--sl-color-pink-600);
|
||||
}
|
||||
|
||||
.split-panel-handle sl-icon {
|
||||
.split-panel-divider sl-icon {
|
||||
position: absolute;
|
||||
border-radius: var(--sl-border-radius-small);
|
||||
background: var(--sl-color-pink-600);
|
||||
color: var(--sl-color-neutral-0);
|
||||
padding: .5rem .125rem;
|
||||
padding: 0.5rem 0.125rem;
|
||||
}
|
||||
|
||||
.split-panel-handle sl-split-panel::part(divider):focus-visible {
|
||||
.split-panel-divider sl-split-panel::part(divider):focus-visible {
|
||||
background-color: var(--sl-color-primary-600);
|
||||
}
|
||||
|
||||
.split-panel-handle sl-split-panel:focus-within sl-icon {
|
||||
.split-panel-divider sl-split-panel:focus-within sl-icon {
|
||||
background-color: var(--sl-color-primary-600);
|
||||
color: var(--sl-color-neutral-0);
|
||||
}
|
||||
@@ -611,15 +690,15 @@ Here's a more elaborate example that changes the divider's color and width and a
|
||||
import { SlSplitPanel, SlIcon } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const css = `
|
||||
.split-panel-handle sl-split-panel {
|
||||
.split-panel-divider sl-split-panel {
|
||||
--divider-width: 2px;
|
||||
}
|
||||
|
||||
.split-panel-handle sl-split-panel::part(divider) {
|
||||
.split-panel-divider sl-split-panel::part(divider) {
|
||||
background-color: var(--sl-color-pink-600);
|
||||
}
|
||||
|
||||
.split-panel-handle sl-icon {
|
||||
.split-panel-divider sl-icon {
|
||||
position: absolute;
|
||||
border-radius: var(--sl-border-radius-small);
|
||||
background: var(--sl-color-pink-600);
|
||||
@@ -627,11 +706,11 @@ const css = `
|
||||
padding: .5rem .125rem;
|
||||
}
|
||||
|
||||
.split-panel-handle sl-split-panel::part(divider):focus-visible {
|
||||
.split-panel-divider sl-split-panel::part(divider):focus-visible {
|
||||
background-color: var(--sl-color-primary-600);
|
||||
}
|
||||
|
||||
.split-panel-handle sl-split-panel:focus-within sl-icon {
|
||||
.split-panel-divider sl-split-panel:focus-within sl-icon {
|
||||
background-color: var(--sl-color-primary-600);
|
||||
color: var(--sl-color-neutral-0);
|
||||
}
|
||||
@@ -639,29 +718,35 @@ const css = `
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<div className="split-panel-handle">
|
||||
<SlSplitPanel>
|
||||
<SlIcon slot="handle" name="grip-vertical" />
|
||||
<div slot="start" style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}>
|
||||
Start
|
||||
</div>
|
||||
<div slot="end" style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}>
|
||||
End
|
||||
</div>
|
||||
</SlSplitPanel>
|
||||
</div>
|
||||
<div className="split-panel-divider">
|
||||
<SlSplitPanel>
|
||||
<SlIcon slot="divider" name="grip-vertical" />
|
||||
<div
|
||||
slot="start"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
Start
|
||||
</div>
|
||||
<div
|
||||
slot="end"
|
||||
style={{
|
||||
height: '200px',
|
||||
background: 'var(--sl-color-neutral-50)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
End
|
||||
</div>
|
||||
</SlSplitPanel>
|
||||
</div>
|
||||
|
||||
<style>{css}</style>
|
||||
</>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-switch]
|
||||
|
||||
Switches allow the user to toggle an option on or off.
|
||||
|
||||
```html preview
|
||||
<sl-switch>Switch</sl-switch>
|
||||
```
|
||||
@@ -11,9 +9,7 @@ Switches allow the user to toggle an option on or off.
|
||||
```jsx react
|
||||
import { SlSwitch } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSwitch>Switch</SlSwitch>
|
||||
);
|
||||
const App = () => <SlSwitch>Switch</SlSwitch>;
|
||||
```
|
||||
|
||||
?> This component works with standard `<form>` elements. Please refer to the section on [form controls](/getting-started/form-controls) to learn more about form submission and client-side validation.
|
||||
@@ -31,9 +27,7 @@ Use the `checked` attribute to activate the switch.
|
||||
```jsx react
|
||||
import { SlSwitch } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSwitch checked>Checked</SlSwitch>
|
||||
);
|
||||
const App = () => <SlSwitch checked>Checked</SlSwitch>;
|
||||
```
|
||||
|
||||
### Disabled
|
||||
@@ -47,29 +41,53 @@ Use the `disabled` attribute to disable the switch.
|
||||
```jsx react
|
||||
import { SlSwitch } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSwitch disabled>Disabled</SlSwitch>
|
||||
);
|
||||
const App = () => <SlSwitch disabled>Disabled</SlSwitch>;
|
||||
```
|
||||
|
||||
### Custom Size
|
||||
## Sizes
|
||||
|
||||
Use the available custom properties to make the switch a different size.
|
||||
Use the `size` attribute to change a switch's size.
|
||||
|
||||
```html preview
|
||||
<sl-switch style="--width: 80px; --height: 32px; --thumb-size: 26px;"></sl-switch>
|
||||
<sl-switch size="small">Small</sl-switch>
|
||||
<br />
|
||||
<sl-switch size="medium">Medium</sl-switch>
|
||||
<br />
|
||||
<sl-switch size="large">Large</sl-switch>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlSwitch } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSwitch
|
||||
<>
|
||||
<SlSwitch size="small">Small</SlSwitch>
|
||||
<br />
|
||||
<SlSwitch size="medium">Medium</SlSwitch>
|
||||
<br />
|
||||
<SlSwitch size="large">Large</SlSwitch>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Custom Styles
|
||||
|
||||
Use the available custom properties to change how the switch is styled.
|
||||
|
||||
```html preview
|
||||
<sl-switch style="--width: 80px; --height: 40px; --thumb-size: 36px;">Really big</sl-switch>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlSwitch } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlSwitch
|
||||
style={{
|
||||
'--width': '80px',
|
||||
'--height': '32px',
|
||||
'--thumb-size': '26px'
|
||||
}}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-tab-group]
|
||||
|
||||
Tab groups organize content into a container that shows one section at a time.
|
||||
|
||||
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
|
||||
@@ -25,10 +23,18 @@ import { SlTab, SlTabGroup, SlTabPanel } from '@shoelace-style/shoelace/dist/rea
|
||||
|
||||
const App = () => (
|
||||
<SlTabGroup>
|
||||
<SlTab slot="nav" panel="general">General</SlTab>
|
||||
<SlTab slot="nav" panel="custom">Custom</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">Advanced</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>Disabled</SlTab>
|
||||
<SlTab slot="nav" panel="general">
|
||||
General
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="custom">
|
||||
Custom
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">
|
||||
Advanced
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>
|
||||
Disabled
|
||||
</SlTab>
|
||||
|
||||
<SlTabPanel name="general">This is the general tab panel.</SlTabPanel>
|
||||
<SlTabPanel name="custom">This is the custom tab panel.</SlTabPanel>
|
||||
@@ -63,10 +69,18 @@ import { SlTab, SlTabGroup, SlTabPanel } from '@shoelace-style/shoelace/dist/rea
|
||||
|
||||
const App = () => (
|
||||
<SlTabGroup placement="bottom">
|
||||
<SlTab slot="nav" panel="general">General</SlTab>
|
||||
<SlTab slot="nav" panel="custom">Custom</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">Advanced</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>Disabled</SlTab>
|
||||
<SlTab slot="nav" panel="general">
|
||||
General
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="custom">
|
||||
Custom
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">
|
||||
Advanced
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>
|
||||
Disabled
|
||||
</SlTab>
|
||||
|
||||
<SlTabPanel name="general">This is the general tab panel.</SlTabPanel>
|
||||
<SlTabPanel name="custom">This is the custom tab panel.</SlTabPanel>
|
||||
@@ -94,16 +108,23 @@ Tabs can be shown on the starting side by setting `placement` to `start`.
|
||||
</sl-tab-group>
|
||||
```
|
||||
|
||||
|
||||
```jsx react
|
||||
import { SlTab, SlTabGroup, SlTabPanel } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTabGroup placement="start">
|
||||
<SlTab slot="nav" panel="general">General</SlTab>
|
||||
<SlTab slot="nav" panel="custom">Custom</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">Advanced</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>Disabled</SlTab>
|
||||
<SlTab slot="nav" panel="general">
|
||||
General
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="custom">
|
||||
Custom
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">
|
||||
Advanced
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>
|
||||
Disabled
|
||||
</SlTab>
|
||||
|
||||
<SlTabPanel name="general">This is the general tab panel.</SlTabPanel>
|
||||
<SlTabPanel name="custom">This is the custom tab panel.</SlTabPanel>
|
||||
@@ -131,16 +152,23 @@ Tabs can be shown on the ending side by setting `placement` to `end`.
|
||||
</sl-tab-group>
|
||||
```
|
||||
|
||||
|
||||
```jsx react
|
||||
import { SlTab, SlTabGroup, SlTabPanel } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTabGroup placement="end">
|
||||
<SlTab slot="nav" panel="general">General</SlTab>
|
||||
<SlTab slot="nav" panel="custom">Custom</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">Advanced</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>Disabled</SlTab>
|
||||
<SlTab slot="nav" panel="general">
|
||||
General
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="custom">
|
||||
Custom
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">
|
||||
Advanced
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>
|
||||
Disabled
|
||||
</SlTab>
|
||||
|
||||
<SlTabPanel name="general">This is the general tab panel.</SlTabPanel>
|
||||
<SlTabPanel name="custom">This is the custom tab panel.</SlTabPanel>
|
||||
@@ -192,24 +220,32 @@ import { SlTab, SlTabGroup, SlTabPanel } from '@shoelace-style/shoelace/dist/rea
|
||||
const App = () => {
|
||||
function handleClose(event) {
|
||||
//
|
||||
// This is a crude example that removes the tab and its panel from the DOM.
|
||||
// This is a crude example that removes the tab and its panel from the DOM.
|
||||
// There are better ways to manage tab creation/removal in React, but that
|
||||
// would significantly complicate the example.
|
||||
//
|
||||
const tab = event.target;
|
||||
const tabGroup = tab.closest('sl-tab-group');
|
||||
const tabPanel = tabGroup.querySelector(`[aria-labelledby="${tab.id}"]`);
|
||||
|
||||
|
||||
tab.remove();
|
||||
tabPanel.remove();
|
||||
}
|
||||
|
||||
return (
|
||||
<SlTabGroup className="tabs-closable" onSlClose={handleClose}>
|
||||
<SlTab slot="nav" panel="general">General</SlTab>
|
||||
<SlTab slot="nav" panel="closable-1" closable onSlClose={handleClose}>Closable 1</SlTab>
|
||||
<SlTab slot="nav" panel="closable-2" closable onSlClose={handleClose}>Closable 2</SlTab>
|
||||
<SlTab slot="nav" panel="closable-3" closable onSlClose={handleClose}>Closable 3</SlTab>
|
||||
<SlTab slot="nav" panel="general">
|
||||
General
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="closable-1" closable onSlClose={handleClose}>
|
||||
Closable 1
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="closable-2" closable onSlClose={handleClose}>
|
||||
Closable 2
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="closable-3" closable onSlClose={handleClose}>
|
||||
Closable 3
|
||||
</SlTab>
|
||||
|
||||
<SlTabPanel name="general">This is the general tab panel.</SlTabPanel>
|
||||
<SlTabPanel name="closable-1">This is the first closable tab panel.</SlTabPanel>
|
||||
@@ -275,26 +311,66 @@ import { SlTab, SlTabGroup, SlTabPanel } from '@shoelace-style/shoelace/dist/rea
|
||||
|
||||
const App = () => (
|
||||
<SlTabGroup>
|
||||
<SlTab slot="nav" panel="tab-1">Tab 1</SlTab>
|
||||
<SlTab slot="nav" panel="tab-2">Tab 2</SlTab>
|
||||
<SlTab slot="nav" panel="tab-3">Tab 3</SlTab>
|
||||
<SlTab slot="nav" panel="tab-4">Tab 4</SlTab>
|
||||
<SlTab slot="nav" panel="tab-5">Tab 5</SlTab>
|
||||
<SlTab slot="nav" panel="tab-6">Tab 6</SlTab>
|
||||
<SlTab slot="nav" panel="tab-7">Tab 7</SlTab>
|
||||
<SlTab slot="nav" panel="tab-8">Tab 8</SlTab>
|
||||
<SlTab slot="nav" panel="tab-9">Tab 9</SlTab>
|
||||
<SlTab slot="nav" panel="tab-10">Tab 10</SlTab>
|
||||
<SlTab slot="nav" panel="tab-11">Tab 11</SlTab>
|
||||
<SlTab slot="nav" panel="tab-12">Tab 12</SlTab>
|
||||
<SlTab slot="nav" panel="tab-13">Tab 13</SlTab>
|
||||
<SlTab slot="nav" panel="tab-14">Tab 14</SlTab>
|
||||
<SlTab slot="nav" panel="tab-15">Tab 15</SlTab>
|
||||
<SlTab slot="nav" panel="tab-16">Tab 16</SlTab>
|
||||
<SlTab slot="nav" panel="tab-17">Tab 17</SlTab>
|
||||
<SlTab slot="nav" panel="tab-18">Tab 18</SlTab>
|
||||
<SlTab slot="nav" panel="tab-19">Tab 19</SlTab>
|
||||
<SlTab slot="nav" panel="tab-20">Tab 20</SlTab>
|
||||
<SlTab slot="nav" panel="tab-1">
|
||||
Tab 1
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-2">
|
||||
Tab 2
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-3">
|
||||
Tab 3
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-4">
|
||||
Tab 4
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-5">
|
||||
Tab 5
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-6">
|
||||
Tab 6
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-7">
|
||||
Tab 7
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-8">
|
||||
Tab 8
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-9">
|
||||
Tab 9
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-10">
|
||||
Tab 10
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-11">
|
||||
Tab 11
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-12">
|
||||
Tab 12
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-13">
|
||||
Tab 13
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-14">
|
||||
Tab 14
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-15">
|
||||
Tab 15
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-16">
|
||||
Tab 16
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-17">
|
||||
Tab 17
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-18">
|
||||
Tab 18
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-19">
|
||||
Tab 19
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="tab-20">
|
||||
Tab 20
|
||||
</SlTab>
|
||||
|
||||
<SlTabPanel name="tab-1">Tab panel 1</SlTabPanel>
|
||||
<SlTabPanel name="tab-2">Tab panel 2</SlTabPanel>
|
||||
@@ -343,10 +419,18 @@ import { SlTab, SlTabGroup, SlTabPanel } from '@shoelace-style/shoelace/dist/rea
|
||||
|
||||
const App = () => (
|
||||
<SlTabGroup activation="manual">
|
||||
<SlTab slot="nav" panel="general">General</SlTab>
|
||||
<SlTab slot="nav" panel="custom">Custom</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">Advanced</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>Disabled</SlTab>
|
||||
<SlTab slot="nav" panel="general">
|
||||
General
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="custom">
|
||||
Custom
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">
|
||||
Advanced
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>
|
||||
Disabled
|
||||
</SlTab>
|
||||
|
||||
<SlTabPanel name="general">This is the general tab panel.</SlTabPanel>
|
||||
<SlTabPanel name="custom">This is the custom tab panel.</SlTabPanel>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-tab-panel]
|
||||
|
||||
Tab panels are used inside [tab groups](/components/tab-group) to display tabbed content.
|
||||
|
||||
```html preview
|
||||
<sl-tab-group>
|
||||
<sl-tab slot="nav" panel="general">General</sl-tab>
|
||||
@@ -23,10 +21,18 @@ import { SlTab, SlTabGroup, SlTabPanel } from '@shoelace-style/shoelace/dist/rea
|
||||
|
||||
const App = () => (
|
||||
<SlTabGroup>
|
||||
<SlTab slot="nav" panel="general">General</SlTab>
|
||||
<SlTab slot="nav" panel="custom">Custom</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">Advanced</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>Disabled</SlTab>
|
||||
<SlTab slot="nav" panel="general">
|
||||
General
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="custom">
|
||||
Custom
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="advanced">
|
||||
Advanced
|
||||
</SlTab>
|
||||
<SlTab slot="nav" panel="disabled" disabled>
|
||||
Disabled
|
||||
</SlTab>
|
||||
|
||||
<SlTabPanel name="general">This is the general tab panel.</SlTabPanel>
|
||||
<SlTabPanel name="custom">This is the custom tab panel.</SlTabPanel>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-tab]
|
||||
|
||||
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>
|
||||
<sl-tab active>Active</sl-tab>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-tag]
|
||||
|
||||
Tags are used as labels to organize things or to indicate a selection.
|
||||
|
||||
```html preview
|
||||
<sl-tag variant="primary">Primary</sl-tag>
|
||||
<sl-tag variant="success">Success</sl-tag>
|
||||
@@ -12,7 +10,6 @@ Tags are used as labels to organize things or to indicate a selection.
|
||||
<sl-tag variant="danger">Danger</sl-tag>
|
||||
```
|
||||
|
||||
|
||||
```jsx react
|
||||
import { SlTag } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
@@ -22,7 +19,7 @@ const App = () => (
|
||||
<SlTag variant="success">Success</SlTag>
|
||||
<SlTag variant="neutral">Neutral</SlTag>
|
||||
<SlTag variant="warning">Warning</SlTag>
|
||||
<SlTag variant="danger">Danger</SlTag>
|
||||
<SlTag variant="danger">Danger</SlTag>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -66,9 +63,15 @@ import { SlTag } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlTag size="small" pill>Small</SlTag>
|
||||
<SlTag size="medium" pill>Medium</SlTag>
|
||||
<SlTag size="large" pill>Large</SlTag>
|
||||
<SlTag size="small" pill>
|
||||
Small
|
||||
</SlTag>
|
||||
<SlTag size="medium" pill>
|
||||
Medium
|
||||
</SlTag>
|
||||
<SlTag size="large" pill>
|
||||
Large
|
||||
</SlTag>
|
||||
</>
|
||||
);
|
||||
```
|
||||
@@ -90,7 +93,7 @@ Use the `removable` attribute to add a remove button to the tag.
|
||||
div.addEventListener('sl-remove', event => {
|
||||
const tag = event.target;
|
||||
tag.style.opacity = '0';
|
||||
setTimeout(() => tag.style.opacity = '1', 2000);
|
||||
setTimeout(() => (tag.style.opacity = '1'), 2000);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -114,7 +117,7 @@ const App = () => {
|
||||
function handleRemove(event) {
|
||||
const tag = event.target;
|
||||
tag.style.opacity = '0';
|
||||
setTimeout(() => tag.style.opacity = '1', 2000);
|
||||
setTimeout(() => (tag.style.opacity = '1'), 2000);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -135,7 +138,7 @@ const App = () => {
|
||||
|
||||
<style>{css}</style>
|
||||
</>
|
||||
)
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-textarea]
|
||||
|
||||
Textareas collect data from the user and allow multiple lines of text.
|
||||
|
||||
```html preview
|
||||
<sl-textarea></sl-textarea>
|
||||
```
|
||||
@@ -11,15 +9,41 @@ Textareas collect data from the user and allow multiple lines of text.
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTextarea />
|
||||
);
|
||||
const App = () => <SlTextarea />;
|
||||
```
|
||||
|
||||
?> This component works with standard `<form>` elements. Please refer to the section on [form controls](/getting-started/form-controls) to learn more about form submission and client-side validation.
|
||||
|
||||
## Examples
|
||||
|
||||
### Labels
|
||||
|
||||
Use the `label` attribute to give the textarea an accessible label. For labels that contain HTML, use the `label` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-textarea label="Comments"></sl-textarea>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlTextarea label="Comments" />;
|
||||
```
|
||||
|
||||
### Help Text
|
||||
|
||||
Add descriptive help text to a textarea with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-textarea label="Feedback" help-text="Please tell us what you think."> </sl-textarea>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => <SlTextarea label="Feedback" help-text="Please tell us what you think." />;
|
||||
```
|
||||
|
||||
### Rows
|
||||
|
||||
Use the `rows` attribute to change the number of text rows that get shown.
|
||||
@@ -31,9 +55,7 @@ Use the `rows` attribute to change the number of text rows that get shown.
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTextarea rows={2} />
|
||||
);
|
||||
const App = () => <SlTextarea rows={2} />;
|
||||
```
|
||||
|
||||
### Placeholders
|
||||
@@ -47,9 +69,7 @@ Use the `placeholder` attribute to add a placeholder.
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTextarea placeholder="Type something" />
|
||||
);
|
||||
const App = () => <SlTextarea placeholder="Type something" />;
|
||||
```
|
||||
|
||||
### Filled Textareas
|
||||
@@ -63,9 +83,7 @@ Add the `filled` attribute to draw a filled textarea.
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTextarea placeholder="Type something" filled />
|
||||
);
|
||||
const App = () => <SlTextarea placeholder="Type something" filled />;
|
||||
```
|
||||
|
||||
### Disabled
|
||||
@@ -79,9 +97,7 @@ Use the `disabled` attribute to disable a textarea.
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTextarea placeholder="Textarea" disabled />
|
||||
);
|
||||
const App = () => <SlTextarea placeholder="Textarea" disabled />;
|
||||
```
|
||||
|
||||
### Sizes
|
||||
@@ -90,9 +106,9 @@ Use the `size` attribute to change a textarea's size.
|
||||
|
||||
```html preview
|
||||
<sl-textarea placeholder="Small" size="small"></sl-textarea>
|
||||
<br>
|
||||
<br />
|
||||
<sl-textarea placeholder="Medium" size="medium"></sl-textarea>
|
||||
<br>
|
||||
<br />
|
||||
<sl-textarea placeholder="Large" size="large"></sl-textarea>
|
||||
```
|
||||
|
||||
@@ -110,45 +126,6 @@ const App = () => (
|
||||
);
|
||||
```
|
||||
|
||||
### Labels
|
||||
|
||||
Use the `label` attribute to give the textarea an accessible label. For labels that contain HTML, use the `label` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-textarea label="Comments"></sl-textarea>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTextarea label="Comments" />
|
||||
);
|
||||
```
|
||||
|
||||
### Help Text
|
||||
|
||||
Add descriptive help text to a textarea with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
||||
|
||||
```html preview
|
||||
<sl-textarea
|
||||
label="Feedback"
|
||||
help-text="Please tell us what you think."
|
||||
>
|
||||
</sl-textarea>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTextarea
|
||||
label="Feedback"
|
||||
help-text="Please tell us what you think."
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Prevent Resizing
|
||||
|
||||
By default, textareas can be resized vertically by the user. To prevent resizing, set the `resize` attribute to `none`.
|
||||
@@ -160,9 +137,7 @@ By default, textareas can be resized vertically by the user. To prevent resizing
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTextarea resize="none" />
|
||||
);
|
||||
const App = () => <SlTextarea resize="none" />;
|
||||
```
|
||||
|
||||
### Expand with Content
|
||||
@@ -176,9 +151,7 @@ Textareas will automatically resize to expand to fit their content when `resize`
|
||||
```jsx react
|
||||
import { SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTextarea resize="auto" />
|
||||
);
|
||||
const App = () => <SlTextarea resize="auto" />;
|
||||
```
|
||||
|
||||
[component-metadata:sl-textarea]
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[component-header:sl-tooltip]
|
||||
|
||||
Tooltips display additional information based on a specific action.
|
||||
|
||||
A tooltip's target is its _first child element_, so you should only wrap one element inside of the tooltip. If you need the tooltip to show up for multiple elements, nest them inside a container first.
|
||||
|
||||
Tooltips use `display: contents` so they won't interfere with how elements are positioned in a flex or grid layout.
|
||||
@@ -20,7 +18,7 @@ import { SlButton, SlTooltip } from '@shoelace-style/shoelace/dist/react';
|
||||
const App = () => (
|
||||
<SlTooltip content="This is a tooltip">
|
||||
<SlButton>Hover Me</SlButton>
|
||||
</SlTooltip>
|
||||
</SlTooltip>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -94,6 +92,7 @@ Use the `placement` attribute to set the preferred placement of the tooltip.
|
||||
<style>
|
||||
.tooltip-placement-example {
|
||||
width: 250px;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.tooltip-placement-example-row:after {
|
||||
@@ -238,7 +237,7 @@ import { SlButton, SlTooltip } from '@shoelace-style/shoelace/dist/react';
|
||||
const App = () => (
|
||||
<SlTooltip content="Click again to dismiss" trigger="click">
|
||||
<SlButton>Click to Toggle</SlButton>
|
||||
</SlTooltip>
|
||||
</SlTooltip>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -250,7 +249,7 @@ Tooltips can be controller programmatically by setting the `trigger` attribute t
|
||||
<sl-button style="margin-right: 4rem;">Toggle Manually</sl-button>
|
||||
|
||||
<sl-tooltip content="This is an avatar" trigger="manual" class="manual-tooltip">
|
||||
<sl-avatar></sl-avatar>
|
||||
<sl-avatar label="User"></sl-avatar>
|
||||
</sl-tooltip>
|
||||
|
||||
<script>
|
||||
@@ -270,10 +269,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlButton
|
||||
style={{ marginRight: '4rem' }}
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
<SlButton style={{ marginRight: '4rem' }} onClick={() => setOpen(!open)}>
|
||||
Toggle Manually
|
||||
</SlButton>
|
||||
|
||||
@@ -285,20 +281,14 @@ const App = () => {
|
||||
};
|
||||
```
|
||||
|
||||
### Remove Arrows
|
||||
### Removing Arrows
|
||||
|
||||
You can control the size of tooltip arrows by overriding the `--sl-tooltip-arrow-size` design token.
|
||||
You can control the size of tooltip arrows by overriding the `--sl-tooltip-arrow-size` design token. To remove them, set the value to `0` as shown below.
|
||||
|
||||
```html preview
|
||||
<div style="--sl-tooltip-arrow-size: 0;">
|
||||
<sl-tooltip content="This is a tooltip">
|
||||
<sl-button>Above</sl-button>
|
||||
</sl-tooltip>
|
||||
|
||||
<sl-tooltip content="This is a tooltip" placement="bottom">
|
||||
<sl-button>Below</sl-button>
|
||||
</sl-tooltip>
|
||||
</div>
|
||||
<sl-tooltip content="This is a tooltip" style="--sl-tooltip-arrow-size: 0;">
|
||||
<sl-button>No Arrow</sl-button>
|
||||
</sl-tooltip>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
@@ -331,10 +321,8 @@ Use the `content` slot to create tooltips with HTML content. Tooltips are design
|
||||
|
||||
```html preview
|
||||
<sl-tooltip>
|
||||
<div slot="content">
|
||||
I'm not <strong>just</strong> a tooltip, I'm a <em>tooltip</em> with HTML!
|
||||
</div>
|
||||
|
||||
<div slot="content">I'm not <strong>just</strong> a tooltip, I'm a <em>tooltip</em> with HTML!</div>
|
||||
|
||||
<sl-button>Hover me</sl-button>
|
||||
</sl-tooltip>
|
||||
```
|
||||
@@ -343,13 +331,33 @@ Use the `content` slot to create tooltips with HTML content. Tooltips are design
|
||||
import { SlButton, SlTooltip } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTooltip content="This is a tooltip">
|
||||
<SlTooltip>
|
||||
<div slot="content">
|
||||
I'm not <strong>just</strong> a tooltip, I'm a <em>tooltip</em> with HTML!
|
||||
</div>
|
||||
|
||||
<SlButton>Hover Me</SlButton>
|
||||
</SlTooltip>
|
||||
</SlTooltip>
|
||||
);
|
||||
```
|
||||
|
||||
### Setting a Maximum Width
|
||||
|
||||
Use the `--max-width` custom property to change the width the tooltip can grow to before wrapping occurs.
|
||||
|
||||
```html preview
|
||||
<sl-tooltip style="--max-width: 80px;" content="This tooltip will wrap after only 80 pixels.">
|
||||
<sl-button>Hover me</sl-button>
|
||||
</sl-tooltip>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlButton, SlTooltip } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTooltip style={{ '--max-width': '80px' }} content="This tooltip will wrap after only 80 pixels.">
|
||||
<SlButton>Hover Me</SlButton>
|
||||
</SlTooltip>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -370,10 +378,10 @@ Tooltips will be clipped if they're inside a container that has `overflow: auto|
|
||||
|
||||
<style>
|
||||
.tooltip-hoist {
|
||||
position: relative;
|
||||
border: solid 2px var(--sl-panel-border-color);
|
||||
overflow: hidden;
|
||||
padding: var(--sl-spacing-medium);
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
163
docs/components/tree-item.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# Tree Item
|
||||
|
||||
[component-header:sl-tree-item]
|
||||
|
||||
```html preview
|
||||
<sl-tree>
|
||||
<sl-tree-item>
|
||||
Item 1
|
||||
<sl-tree-item>Item A</sl-tree-item>
|
||||
<sl-tree-item>Item B</sl-tree-item>
|
||||
<sl-tree-item>Item C</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Item 2</sl-tree-item>
|
||||
<sl-tree-item>Item 3</sl-tree-item>
|
||||
</sl-tree>
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx react
|
||||
import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTree>
|
||||
<SlTreeItem>
|
||||
Item 1
|
||||
<SlTreeItem>Item A</SlTreeItem>
|
||||
<SlTreeItem>Item B</SlTreeItem>
|
||||
<SlTreeItem>Item C</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Item 2</SlTreeItem>
|
||||
<SlTreeItem>Item 3</SlTreeItem>
|
||||
</SlTree>
|
||||
);
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Nested tree items
|
||||
|
||||
A tree item can contain other tree items. This allows the node to be expanded or collapsed by the user.
|
||||
|
||||
```html preview
|
||||
<sl-tree>
|
||||
<sl-tree-item>
|
||||
Item 1
|
||||
<sl-tree-item>
|
||||
Item A
|
||||
<sl-tree-item>Item Z</sl-tree-item>
|
||||
<sl-tree-item>Item Y</sl-tree-item>
|
||||
<sl-tree-item>Item X</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Item B</sl-tree-item>
|
||||
<sl-tree-item>Item C</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Item 2</sl-tree-item>
|
||||
<sl-tree-item>Item 3</sl-tree-item>
|
||||
</sl-tree>
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx react
|
||||
import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTree>
|
||||
<SlTreeItem>
|
||||
Item 1
|
||||
<SlTreeItem>
|
||||
Item A
|
||||
<SlTreeItem>Item Z</SlTreeItem>
|
||||
<SlTreeItem>Item Y</SlTreeItem>
|
||||
<SlTreeItem>Item X</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Item B</SlTreeItem>
|
||||
<SlTreeItem>Item C</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Item 2</SlTreeItem>
|
||||
<SlTreeItem>Item 3</SlTreeItem>
|
||||
</SlTree>
|
||||
);
|
||||
```
|
||||
|
||||
### Selected
|
||||
|
||||
Use the `selected` attribute to select a tree item initially.
|
||||
|
||||
```html preview
|
||||
<sl-tree>
|
||||
<sl-tree-item selected>
|
||||
Item 1
|
||||
<sl-tree-item>Item A</sl-tree-item>
|
||||
<sl-tree-item>Item B</sl-tree-item>
|
||||
<sl-tree-item>Item C</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Item 2</sl-tree-item>
|
||||
<sl-tree-item>Item 3</sl-tree-item>
|
||||
</sl-tree>
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx react
|
||||
import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTree>
|
||||
<SlTreeItem selected>
|
||||
Item 1
|
||||
<SlTreeItem>Item A</SlTreeItem>
|
||||
<SlTreeItem>Item B</SlTreeItem>
|
||||
<SlTreeItem>Item C</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Item 2</SlTreeItem>
|
||||
<SlTreeItem>Item 3</SlTreeItem>
|
||||
</SlTree>
|
||||
);
|
||||
```
|
||||
|
||||
### Expanded
|
||||
|
||||
Use the `expanded` attribute to expand a tree item initially.
|
||||
|
||||
```html preview
|
||||
<sl-tree>
|
||||
<sl-tree-item expanded>
|
||||
Item 1
|
||||
<sl-tree-item expanded>
|
||||
Item A
|
||||
<sl-tree-item>Item Z</sl-tree-item>
|
||||
<sl-tree-item>Item Y</sl-tree-item>
|
||||
<sl-tree-item>Item X</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Item B</sl-tree-item>
|
||||
<sl-tree-item>Item C</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Item 2</sl-tree-item>
|
||||
<sl-tree-item>Item 3</sl-tree-item>
|
||||
</sl-tree>
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx react
|
||||
import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTree>
|
||||
<SlTreeItem expanded>
|
||||
Item 1
|
||||
<SlTreeItem expanded>
|
||||
Item A
|
||||
<SlTreeItem>Item Z</SlTreeItem>
|
||||
<SlTreeItem>Item Y</SlTreeItem>
|
||||
<SlTreeItem>Item X</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Item B</SlTreeItem>
|
||||
<SlTreeItem>Item C</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Item 2</SlTreeItem>
|
||||
<SlTreeItem>Item 3</SlTreeItem>
|
||||
</SlTree>
|
||||
);
|
||||
```
|
||||
|
||||
[component-metadata:sl-tree-item]
|
||||
464
docs/components/tree.md
Normal file
@@ -0,0 +1,464 @@
|
||||
# Tree
|
||||
|
||||
[component-header:sl-tree]
|
||||
|
||||
```html preview
|
||||
<sl-tree>
|
||||
<sl-tree-item>
|
||||
Deciduous
|
||||
<sl-tree-item>Birch</sl-tree-item>
|
||||
<sl-tree-item>
|
||||
Maple
|
||||
<sl-tree-item>Field maple</sl-tree-item>
|
||||
<sl-tree-item>Red maple</sl-tree-item>
|
||||
<sl-tree-item>Sugar maple</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Oak</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
|
||||
<sl-tree-item>
|
||||
Coniferous
|
||||
<sl-tree-item>Cedar</sl-tree-item>
|
||||
<sl-tree-item>Pine</sl-tree-item>
|
||||
<sl-tree-item>Spruce</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
|
||||
<sl-tree-item>
|
||||
Non-trees
|
||||
<sl-tree-item>Bamboo</sl-tree-item>
|
||||
<sl-tree-item>Cactus</sl-tree-item>
|
||||
<sl-tree-item>Fern</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
</sl-tree>
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx react
|
||||
import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTree>
|
||||
<SlTreeItem>
|
||||
Deciduous
|
||||
<SlTreeItem>Birch</SlTreeItem>
|
||||
<SlTreeItem>
|
||||
Maple
|
||||
<SlTreeItem>Field maple</SlTreeItem>
|
||||
<SlTreeItem>Red maple</SlTreeItem>
|
||||
<SlTreeItem>Sugar maple</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Oak</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
|
||||
<SlTreeItem>
|
||||
Coniferous
|
||||
<SlTreeItem>Cedar</SlTreeItem>
|
||||
<SlTreeItem>Pine</SlTreeItem>
|
||||
<SlTreeItem>Spruce</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
|
||||
<SlTreeItem>
|
||||
Non-trees
|
||||
<SlTreeItem>Bamboo</SlTreeItem>
|
||||
<SlTreeItem>Cactus</SlTreeItem>
|
||||
<SlTreeItem>Fern</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
</SlTree>
|
||||
);
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Selection Modes
|
||||
|
||||
The `selection` attribute lets you change the selection behavior of the tree.
|
||||
|
||||
- Use `single` to allow the selection of a single item (default).
|
||||
- Use `multiple` to allow the selection of multiple items.
|
||||
- Use `leaf` to only allow leaf nodes to be selected.
|
||||
|
||||
```html preview
|
||||
<sl-select id="selection-mode" value="single" label="Selection">
|
||||
<sl-option value="single">Single</sl-option>
|
||||
<sl-option value="multiple">Multiple</sl-option>
|
||||
<sl-option value="leaf">Leaf</sl-option>
|
||||
</sl-select>
|
||||
|
||||
<br />
|
||||
|
||||
<sl-tree class="tree-selectable">
|
||||
<sl-tree-item>
|
||||
Item 1
|
||||
<sl-tree-item>
|
||||
Item A
|
||||
<sl-tree-item>Item Z</sl-tree-item>
|
||||
<sl-tree-item>Item Y</sl-tree-item>
|
||||
<sl-tree-item>Item X</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Item B</sl-tree-item>
|
||||
<sl-tree-item>Item C</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Item 2</sl-tree-item>
|
||||
<sl-tree-item>Item 3</sl-tree-item>
|
||||
</sl-tree>
|
||||
|
||||
<script>
|
||||
const selectionMode = document.querySelector('#selection-mode');
|
||||
const tree = document.querySelector('.tree-selectable');
|
||||
|
||||
selectionMode.addEventListener('sl-change', () => {
|
||||
tree.querySelectorAll('sl-tree-item').forEach(item => (item.selected = false));
|
||||
tree.selection = selectionMode.value;
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx react
|
||||
import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const [selection, setSelection] = useState('single');
|
||||
|
||||
return (
|
||||
<>
|
||||
<SlSelect label="Selection" value={selection} onSlChange={event => setSelection(event.target.value)}>
|
||||
<SlMenuItem value="single">single</SlMenuItem>
|
||||
<SlMenuItem value="multiple">multiple</SlMenuItem>
|
||||
<SlMenuItem value="leaf">leaf</SlMenuItem>
|
||||
</SlSelect>
|
||||
|
||||
<br />
|
||||
|
||||
<SlTree selection={selection}>
|
||||
<SlTreeItem>
|
||||
Item 1
|
||||
<SlTreeItem>
|
||||
Item A
|
||||
<SlTreeItem>Item Z</SlTreeItem>
|
||||
<SlTreeItem>Item Y</SlTreeItem>
|
||||
<SlTreeItem>Item X</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Item B</SlTreeItem>
|
||||
<SlTreeItem>Item C</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Item 2</SlTreeItem>
|
||||
<SlTreeItem>Item 3</SlTreeItem>
|
||||
</SlTree>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Showing Indent Guides
|
||||
|
||||
Indent guides can be drawn by setting `--indent-guide-width`. You can also change the color, offset, and style, using `--indent-guide-color`, `--indent-guide-style`, and `--indent-guide-offset`, respectively.
|
||||
|
||||
```html preview
|
||||
<sl-tree class="tree-with-lines">
|
||||
<sl-tree-item expanded>
|
||||
Deciduous
|
||||
<sl-tree-item>Birch</sl-tree-item>
|
||||
<sl-tree-item expanded>
|
||||
Maple
|
||||
<sl-tree-item>Field maple</sl-tree-item>
|
||||
<sl-tree-item>Red maple</sl-tree-item>
|
||||
<sl-tree-item>Sugar maple</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Oak</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
|
||||
<sl-tree-item>
|
||||
Coniferous
|
||||
<sl-tree-item>Cedar</sl-tree-item>
|
||||
<sl-tree-item>Pine</sl-tree-item>
|
||||
<sl-tree-item>Spruce</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
|
||||
<sl-tree-item>
|
||||
Non-trees
|
||||
<sl-tree-item>Bamboo</sl-tree-item>
|
||||
<sl-tree-item>Cactus</sl-tree-item>
|
||||
<sl-tree-item>Fern</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
</sl-tree>
|
||||
|
||||
<style>
|
||||
.tree-with-lines {
|
||||
--indent-guide-width: 1px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx react
|
||||
import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTree class="tree-with-lines" style={{ '--indent-guide-width': '1px' }}>
|
||||
<SlTreeItem expanded>
|
||||
Deciduous
|
||||
<SlTreeItem>Birch</SlTreeItem>
|
||||
<SlTreeItem expanded>
|
||||
Maple
|
||||
<SlTreeItem>Field maple</SlTreeItem>
|
||||
<SlTreeItem>Red maple</SlTreeItem>
|
||||
<SlTreeItem>Sugar maple</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Oak</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
|
||||
<SlTreeItem>
|
||||
Coniferous
|
||||
<SlTreeItem>Cedar</SlTreeItem>
|
||||
<SlTreeItem>Pine</SlTreeItem>
|
||||
<SlTreeItem>Spruce</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
|
||||
<SlTreeItem>
|
||||
Non-trees
|
||||
<SlTreeItem>Bamboo</SlTreeItem>
|
||||
<SlTreeItem>Cactus</SlTreeItem>
|
||||
<SlTreeItem>Fern</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
</SlTree>
|
||||
);
|
||||
```
|
||||
|
||||
### Lazy Loading
|
||||
|
||||
Use the `lazy` attribute on a tree item to indicate that the content is not yet present and will be loaded later. When the user tries to expand the node, the `loading` state is set to `true` and the `sl-lazy-load` event will be emitted to allow you to load data asynchronously. The item will remain in a loading state until its content is changed.
|
||||
|
||||
If you want to disable this behavior after the first load, simply remove the `lazy` attribute and, on the next expand, the existing content will be shown instead.
|
||||
|
||||
```html preview
|
||||
<sl-tree>
|
||||
<sl-tree-item lazy>Available Trees</sl-tree-item>
|
||||
</sl-tree>
|
||||
|
||||
<script type="module">
|
||||
const lazyItem = document.querySelector('sl-tree-item[lazy]');
|
||||
|
||||
lazyItem.addEventListener('sl-lazy-load', () => {
|
||||
// Simulate asynchronous loading
|
||||
setTimeout(() => {
|
||||
const subItems = ['Birch', 'Cedar', 'Maple', 'Pine'];
|
||||
|
||||
for (const item of subItems) {
|
||||
const treeItem = document.createElement('sl-tree-item');
|
||||
treeItem.innerText = item;
|
||||
lazyItem.append(treeItem);
|
||||
}
|
||||
|
||||
// Disable lazy mode once the content has been loaded
|
||||
lazyItem.lazy = false;
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const [childItems, setChildItems] = useState([]);
|
||||
const [lazy, setLazy] = useState(true);
|
||||
|
||||
const handleLazyLoad = () => {
|
||||
// Simulate asynchronous loading
|
||||
setTimeout(() => {
|
||||
setChildItems(['Birch', 'Cedar', 'Maple', 'Pine']);
|
||||
|
||||
// Disable lazy mode once the content has been loaded
|
||||
setLazy(false);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
return (
|
||||
<SlTree>
|
||||
<SlTreeItem lazy={lazy} onSlLazyLoad={handleLazyLoad}>
|
||||
Available Trees
|
||||
{childItems.map(item => (
|
||||
<SlTreeItem>{item}</SlTreeItem>
|
||||
))}
|
||||
</SlTreeItem>
|
||||
</SlTree>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Customizing the Expand and Collapse Icons
|
||||
|
||||
Use the `expand-icon` and `collapse-icon` slots to change the expand and collapse icons, respectively. To disable the animation, override the `rotate` property on the `expand-button` part as shown below.
|
||||
|
||||
```html preview
|
||||
<sl-tree class="custom-icons">
|
||||
<sl-icon name="plus-square" slot="expand-icon"></sl-icon>
|
||||
<sl-icon name="dash-square" slot="collapse-icon"></sl-icon>
|
||||
|
||||
<sl-tree-item>
|
||||
Deciduous
|
||||
<sl-tree-item>Birch</sl-tree-item>
|
||||
<sl-tree-item>
|
||||
Maple
|
||||
<sl-tree-item>Field maple</sl-tree-item>
|
||||
<sl-tree-item>Red maple</sl-tree-item>
|
||||
<sl-tree-item>Sugar maple</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>Oak</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
|
||||
<sl-tree-item>
|
||||
Coniferous
|
||||
<sl-tree-item>Cedar</sl-tree-item>
|
||||
<sl-tree-item>Pine</sl-tree-item>
|
||||
<sl-tree-item>Spruce</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
|
||||
<sl-tree-item>
|
||||
Non-trees
|
||||
<sl-tree-item>Bamboo</sl-tree-item>
|
||||
<sl-tree-item>Cactus</sl-tree-item>
|
||||
<sl-tree-item>Fern</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
</sl-tree>
|
||||
|
||||
<style>
|
||||
.custom-icons sl-tree-item::part(expand-button) {
|
||||
/* Disable the expand/collapse animation */
|
||||
rotate: none;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx react
|
||||
import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlTree>
|
||||
<SlIcon name="plus-square" slot="expand-icon"></SlIcon>
|
||||
<SlIcon name="dash-square" slot="collapse-icon"></SlIcon>
|
||||
|
||||
<SlTreeItem>
|
||||
Deciduous
|
||||
<SlTreeItem>Birch</SlTreeItem>
|
||||
<SlTreeItem>
|
||||
Maple
|
||||
<SlTreeItem>Field maple</SlTreeItem>
|
||||
<SlTreeItem>Red maple</SlTreeItem>
|
||||
<SlTreeItem>Sugar maple</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>Oak</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
|
||||
<SlTreeItem>
|
||||
Coniferous
|
||||
<SlTreeItem>Cedar</SlTreeItem>
|
||||
<SlTreeItem>Pine</SlTreeItem>
|
||||
<SlTreeItem>Spruce</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
|
||||
<SlTreeItem>
|
||||
Non-trees
|
||||
<SlTreeItem>Bamboo</SlTreeItem>
|
||||
<SlTreeItem>Cactus</SlTreeItem>
|
||||
<SlTreeItem>Fern</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
</SlTree>
|
||||
);
|
||||
```
|
||||
|
||||
### With Icons
|
||||
|
||||
Decorative icons can be used before labels to provide hints for each node.
|
||||
|
||||
```html preview
|
||||
<sl-tree class="tree-with-icons">
|
||||
<sl-tree-item expanded>
|
||||
<sl-icon name="folder"></sl-icon>
|
||||
Documents
|
||||
|
||||
<sl-tree-item>
|
||||
<sl-icon name="folder"> </sl-icon>
|
||||
Photos
|
||||
<sl-tree-item>
|
||||
<sl-icon name="image"></sl-icon>
|
||||
birds.jpg
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>
|
||||
<sl-icon name="image"></sl-icon>
|
||||
kitten.jpg
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>
|
||||
<sl-icon name="image"></sl-icon>
|
||||
puppy.jpg
|
||||
</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
|
||||
<sl-tree-item>
|
||||
<sl-icon name="folder"></sl-icon>
|
||||
Writing
|
||||
<sl-tree-item>
|
||||
<sl-icon name="file"></sl-icon>
|
||||
draft.txt
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>
|
||||
<sl-icon name="file-pdf"></sl-icon>
|
||||
final.pdf
|
||||
</sl-tree-item>
|
||||
<sl-tree-item>
|
||||
<sl-icon name="file-bar-graph"></sl-icon>
|
||||
sales.xls
|
||||
</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
</sl-tree-item>
|
||||
</sl-tree>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlIcon, SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<SlTree class="tree-with-icons">
|
||||
<SlTreeItem expanded>
|
||||
<SlIcon name="folder" />
|
||||
Root
|
||||
<SlTreeItem>
|
||||
<SlIcon name="folder" />
|
||||
Folder 1<SlTreeItem>
|
||||
<SlIcon name="files" />
|
||||
File 1 - 1
|
||||
</SlTreeItem>
|
||||
<SlTreeItem disabled>
|
||||
<SlIcon name="files" />
|
||||
File 1 - 2
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>
|
||||
<SlIcon name="files" />
|
||||
File 1 - 3
|
||||
</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>
|
||||
<SlIcon name="files" />
|
||||
Folder 2<SlTreeItem>
|
||||
<SlIcon name="files" />
|
||||
File 2 - 1
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>
|
||||
<SlIcon name="files" />
|
||||
File 2 - 2
|
||||
</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
<SlTreeItem>
|
||||
<SlIcon name="files" />
|
||||
File 1
|
||||
</SlTreeItem>
|
||||
</SlTreeItem>
|
||||
</SlTree>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
[component-metadata:sl-tree]
|
||||
@@ -2,14 +2,12 @@
|
||||
|
||||
[component-header:sl-visually-hidden]
|
||||
|
||||
The visually hidden utility makes content accessible to assistive devices without displaying it on the screen.
|
||||
|
||||
According to [The A11Y Project](https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/), "there are real world situations where visually hiding content may be appropriate, while the content should remain available to assistive technologies, such as screen readers. For instance, hiding a search field's label as a common magnifying glass icon is used in its stead."
|
||||
|
||||
Since visually hidden content can receive focus when tabbing, the element will become visible when something inside receives focus. This behavior is intentional, as sighted keyboards user won't be able to determine where the focus indicator is without it.
|
||||
|
||||
```html preview
|
||||
<div style="min-height: 100px;">
|
||||
<div style="min-height: 1.875rem;">
|
||||
<sl-visually-hidden>
|
||||
<a href="#">Skip to main content</a>
|
||||
</sl-visually-hidden>
|
||||
@@ -32,7 +30,7 @@ In this example, the link will open a new window. Screen readers will announce "
|
||||
|
||||
### Content Conveyed By Context
|
||||
|
||||
Adding a title or label may seem redundant at times, but they're very helpful for unsighted users. Rather than omit them, you can provide context to unsighted users with visually hidden content.
|
||||
Adding a label may seem redundant at times, but they're very helpful for unsighted users. Rather than omit them, you can provide context to unsighted users with visually hidden content that will be announced by assistive devices such as screen readers.
|
||||
|
||||
```html preview
|
||||
<sl-card style="width: 100%; max-width: 360px;">
|
||||
|
||||
@@ -33,11 +33,7 @@ Every Shoelace component is available to import as a React component. Note that
|
||||
```jsx
|
||||
import { SlButton } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const MyComponent = () => (
|
||||
<SlButton variant="primary">
|
||||
Click me
|
||||
</SlButton>
|
||||
);
|
||||
const MyComponent = () => <SlButton variant="primary">Click me</SlButton>;
|
||||
|
||||
export default MyComponent;
|
||||
```
|
||||
@@ -57,13 +53,8 @@ import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
function MyComponent() {
|
||||
const [value, setValue] = useState('');
|
||||
|
||||
return (
|
||||
<SlInput
|
||||
value={value}
|
||||
onSlInput={event => setValue(event.target.value)}
|
||||
/>
|
||||
)
|
||||
};
|
||||
return <SlInput value={value} onSlInput={event => setValue(event.target.value)} />;
|
||||
}
|
||||
|
||||
export default MyComponent;
|
||||
```
|
||||
@@ -78,13 +69,8 @@ import type SlInputElement from '@shoelace-style/shoelace/dist/components/input/
|
||||
function MyComponent() {
|
||||
const [value, setValue] = useState('');
|
||||
|
||||
return (
|
||||
<SlInput
|
||||
value={value}
|
||||
onSlInput={event => setValue((event.target as SlInputElement).value)}
|
||||
/>
|
||||
)
|
||||
};
|
||||
return <SlInput value={value} onSlInput={event => setValue((event.target as SlInputElement).value)} />;
|
||||
}
|
||||
|
||||
export default MyComponent;
|
||||
```
|
||||
@@ -124,8 +110,8 @@ Object.defineProperty(window, 'matchMedia', {
|
||||
removeListener: jest.fn(), // deprecated
|
||||
addEventListener: jest.fn(),
|
||||
removeEventListener: jest.fn(),
|
||||
dispatchEvent: jest.fn(),
|
||||
})),
|
||||
dispatchEvent: jest.fn()
|
||||
}))
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
95
docs/frameworks/vue-2.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Vue (version 2)
|
||||
|
||||
Vue [plays nice](https://custom-elements-everywhere.com/#vue) with custom elements, so you can use Shoelace in your Vue apps with ease.
|
||||
|
||||
!> These instructions are for Vue 2. If you're using Vue 3 or above, please see the [Vue 3 instructions](/frameworks/vue).
|
||||
|
||||
## Installation
|
||||
|
||||
To add Shoelace to your Vue app, install the package from npm.
|
||||
|
||||
```bash
|
||||
npm install @shoelace-style/shoelace
|
||||
```
|
||||
|
||||
Next, [include a theme](/getting-started/themes) and set the [base path](/getting-started/installation#setting-the-base-path) for icons and other assets. In this example, we'll import the light theme and use the CDN as a base path.
|
||||
|
||||
```jsx
|
||||
import '@shoelace-style/shoelace/dist/themes/light.css';
|
||||
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path';
|
||||
|
||||
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/');
|
||||
```
|
||||
|
||||
?> If you'd rather not use the CDN for assets, you can create a build task that copies `node_modules/@shoelace-style/shoelace/dist/assets` into a public folder in your app. Then you can point the base path to that folder instead.
|
||||
|
||||
## Configuration
|
||||
|
||||
You'll need to tell Vue to ignore Shoelace components. This is pretty easy because they all start with `sl-`.
|
||||
|
||||
```js
|
||||
import Vue from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
Vue.config.ignoredElements = [/sl-/];
|
||||
|
||||
const app = new Vue({
|
||||
render: h => h(App)
|
||||
});
|
||||
|
||||
app.$mount('#app');
|
||||
```
|
||||
|
||||
Now you can start using Shoelace components in your app!
|
||||
|
||||
## Usage
|
||||
|
||||
### Binding Complex Data
|
||||
|
||||
When binding complex data such as objects and arrays, use the `.prop` modifier to make Vue bind them as a property instead of an attribute.
|
||||
|
||||
```html
|
||||
<sl-color-picker :swatches.prop="mySwatches" />
|
||||
```
|
||||
|
||||
### Two-way Binding
|
||||
|
||||
One caveat is there's currently [no support for v-model on custom elements](https://github.com/vuejs/vue/issues/7830), but you can still achieve two-way binding manually.
|
||||
|
||||
```html
|
||||
<!-- This doesn't work -->
|
||||
<sl-input v-model="name"></sl-input>
|
||||
<!-- This works, but it's a bit longer -->
|
||||
<sl-input :value="name" @input="name = $event.target.value"></sl-input>
|
||||
```
|
||||
|
||||
If that's too verbose for your liking, you can use a custom directive instead. [This utility](https://www.npmjs.com/package/@shoelace-style/vue-sl-model) adds 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@1
|
||||
```
|
||||
|
||||
Next, import the directive and enable it like this.
|
||||
|
||||
```js
|
||||
import Vue from 'vue';
|
||||
import ShoelaceModelDirective from '@shoelace-style/vue-sl-model';
|
||||
import App from './App.vue';
|
||||
|
||||
Vue.use(ShoelaceModelDirective);
|
||||
Vue.config.ignoredElements = [/sl-/];
|
||||
|
||||
const app = new Vue({
|
||||
render: h => h(App)
|
||||
});
|
||||
|
||||
app.$mount('#app');
|
||||
```
|
||||
|
||||
Now you can use the `v-sl-model` directive to keep your data in sync!
|
||||
|
||||
```html
|
||||
<sl-input v-sl-model="name"></sl-input>
|
||||
```
|
||||
|
||||
?> Are you using Shoelace with Vue? [Help us improve this page!](https://github.com/shoelace-style/shoelace/blob/next/docs/frameworks/vue-2.md)
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Vue [plays nice](https://custom-elements-everywhere.com/#vue) with custom elements, so you can use Shoelace in your Vue apps with ease.
|
||||
|
||||
?> These instructions are for Vue 2. If you're using Vue 3, [please help us update this page](https://github.com/shoelace-style/shoelace/blob/next/docs/frameworks/vue.md).
|
||||
?> These instructions are for Vue 3 and above. If you're using Vue 2, please see the [Vue 2 instructions](/frameworks/vue-2).
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -28,20 +28,67 @@ setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dis
|
||||
You'll need to tell Vue to ignore Shoelace components. This is pretty easy because they all start with `sl-`.
|
||||
|
||||
```js
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import { fileURLToPath, URL } from 'url';
|
||||
|
||||
const app = createApp(App);
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
|
||||
app.config.compilerOptions.isCustomElement = tag => tag.startsWith('sl-');
|
||||
|
||||
app.mount('#app');
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue({
|
||||
template: {
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag.startsWith('sl-')
|
||||
}
|
||||
}
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Now you can start using Shoelace components in your app!
|
||||
|
||||
## Usage
|
||||
|
||||
### QR code generator example
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="container">
|
||||
<h1>QR code generator</h1>
|
||||
|
||||
<sl-input maxlength="255" clearable label="Value" v-model="qrCode"></sl-input>
|
||||
|
||||
<sl-qr-code :value="qrCode"></sl-qr-code>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import '@shoelace-style/shoelace/dist/components/qr-code/qr-code.js';
|
||||
import '@shoelace-style/shoelace/dist/components/input/input.js';
|
||||
|
||||
const qrCode = ref();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
sl-input {
|
||||
margin: var(--sl-spacing-large) 0;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### Binding Complex Data
|
||||
|
||||
When binding complex data such as objects and arrays, use the `.prop` modifier to make Vue bind them as a property instead of an attribute.
|
||||
@@ -50,43 +97,4 @@ When binding complex data such as objects and arrays, use the `.prop` modifier t
|
||||
<sl-color-picker :swatches.prop="mySwatches" />
|
||||
```
|
||||
|
||||
### Two-way Binding
|
||||
|
||||
One caveat is there's currently [no support for v-model on custom elements](https://github.com/vuejs/vue/issues/7830), but you can still achieve two-way binding manually.
|
||||
|
||||
```html
|
||||
<!-- This doesn't work -->
|
||||
<sl-input v-model="name">
|
||||
|
||||
<!-- This works, but it's a bit longer -->
|
||||
<sl-input :value="name" @input="name = $event.target.value">
|
||||
```
|
||||
|
||||
If that's too verbose for your liking, you can use a custom directive instead. [This utility](https://www.npmjs.com/package/@shoelace-style/vue-sl-model) adds 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
|
||||
```
|
||||
|
||||
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';
|
||||
|
||||
const app = createApp(App);
|
||||
app.use(ShoelaceModelDirective);
|
||||
|
||||
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!
|
||||
|
||||
```html
|
||||
<sl-input v-sl-model="name">
|
||||
```
|
||||
|
||||
?> Are you using Shoelace with Vue? [Help us improve this page!](https://github.com/shoelace-style/shoelace/blob/next/docs/frameworks/vue.md)
|
||||
|
||||
@@ -29,7 +29,7 @@ To customize a design token, simply override it in your stylesheet using a `:roo
|
||||
}
|
||||
```
|
||||
|
||||
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).
|
||||
Many design tokens are described further along in this documentation. For a complete list, refer to `src/themes/light.css` in the project's [source code](https://github.com/shoelace-style/shoelace/blob/current/src/themes/light.css).
|
||||
|
||||
## Component Parts
|
||||
|
||||
@@ -108,7 +108,7 @@ Not all components expose CSS custom properties. For those that do, they can be
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
@@ -127,6 +127,8 @@ setDefaultAnimation('dialog.show', {
|
||||
});
|
||||
```
|
||||
|
||||
?> To support RTL languages in your animation, you can pass an additional property called `rtlKeyframes`. This property shares the same type as `keyframes` and will be automatically used when the component's directionality is RTL. If `rtlKeyframes` is not provided, `keyframes` will be used as a fallback.
|
||||
|
||||
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.
|
||||
|
||||
@@ -4,9 +4,9 @@ Every Shoelace component makes use of a [shadow DOM](https://developer.mozilla.o
|
||||
|
||||
Shoelace solves this problem by using the [`formdata`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/formdata_event) event, which is [available in all modern browsers](https://caniuse.com/mdn-api_htmlformelement_formdata_event). This means, when a form is submitted, Shoelace form controls will automatically append their values to the `FormData` object that's used to submit the form. In most cases, things will "just work." However, if you're using a form serialization library, it might need to be adapted to recognize Shoelace form controls.
|
||||
|
||||
?> If you're using an older browser that doesn't support the `formdata` event, a lightweight polyfill will be automatically applied to ensure forms submit as expected.
|
||||
?> Shoelace uses event listeners to intercept the form's `formdata` and `submit` events. This allows it to inject data and trigger validation as necessary. If you're also attaching an event listener to the form, _you must attach it after Shoelace form controls are connected to the DOM_, otherwise your logic will run before Shoelace has a chance to inject form data and validate form controls.
|
||||
|
||||
## Form Serialization
|
||||
## Data Serialization
|
||||
|
||||
Serialization is just a fancy word for collecting form data. If you're relying on standard form submissions, e.g. `<form action="...">`, you can probably skip this section. However, most modern apps use the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) or a library such as [axios](https://github.com/axios/axios) to submit forms using JavaScript.
|
||||
|
||||
@@ -32,56 +32,51 @@ const data = serialize(form);
|
||||
|
||||
This results in an object with name/value pairs that map to each form control. If more than one form control shares the same name, the values will be passed as an array, e.g. `{ name: ['value1', 'value2'] }`.
|
||||
|
||||
## Form Control Validation
|
||||
## Constraint Validation
|
||||
|
||||
Client-side validation can be enabled through the browser's [Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation) for Shoelace form controls. You can activate it using attributes such as `required`, `pattern`, `minlength`, and `maxlength`. Shoelace implements many of the same attributes as native form controls, but check each form control's documentation for a list of all supported properties.
|
||||
Client-side validation can be enabled through the browser's [Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation) for Shoelace form controls. You can activate it using attributes such as `required`, `pattern`, `minlength`, `maxlength`, etc. Shoelace implements many of the same attributes as native form controls, but check the documentation for a list of supported properties for each component.
|
||||
|
||||
As the user interacts with a form control, its `invalid` attribute will reflect its validity based on its current value and the constraints that have been defined. When a form control is invalid, the containing form will not be submitted. Instead, the browser will show the user a relevant error message. If you don't want to use client-side validation, you can suppress this behavior by adding `novalidate` to the surrounding `<form>` element.
|
||||
If you don't want to use client-side validation, you can suppress this behavior by adding `novalidate` to the surrounding `<form>` element.
|
||||
|
||||
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.
|
||||
?> If this syntax looks unfamiliar, don't worry! Most of what you're learning on this page is platform knowledge that applies to regular form controls, too.
|
||||
|
||||
!> 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
|
||||
|
||||
To make a field required, use the `required` prop. The form will not be submitted if a required form control is empty.
|
||||
To make a field required, use the `required` attribute. Required fields will automatically receive a `*` after their labels. This is configurable through the `--sl-input-required-content` custom property.
|
||||
|
||||
The form will not be submitted if a required field is incomplete.
|
||||
|
||||
```html preview
|
||||
<form class="input-validation-required">
|
||||
<sl-input name="name" label="Name" required></sl-input>
|
||||
<br>
|
||||
<br />
|
||||
<sl-select label="Favorite Animal" clearable required>
|
||||
<sl-menu-item value="birds">Birds</sl-menu-item>
|
||||
<sl-menu-item value="cats">Cats</sl-menu-item>
|
||||
<sl-menu-item value="dogs">Dogs</sl-menu-item>
|
||||
<sl-menu-item value="other">Other</sl-menu-item>
|
||||
<sl-option value="birds">Birds</sl-option>
|
||||
<sl-option value="cats">Cats</sl-option>
|
||||
<sl-option value="dogs">Dogs</sl-option>
|
||||
<sl-option value="other">Other</sl-option>
|
||||
</sl-select>
|
||||
<br>
|
||||
<br />
|
||||
<sl-textarea name="comment" label="Comment" required></sl-textarea>
|
||||
<br>
|
||||
<br />
|
||||
<sl-checkbox required>Check me before submitting</sl-checkbox>
|
||||
<br><br>
|
||||
<br /><br />
|
||||
<sl-button type="submit" variant="primary">Submit</sl-button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
<script type="module">
|
||||
const form = document.querySelector('.input-validation-required');
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!')
|
||||
alert('All fields are valid!');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import {
|
||||
SlButton,
|
||||
SlCheckbox,
|
||||
SlInput,
|
||||
SlMenuItem,
|
||||
SlSelect,
|
||||
SlTextarea
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
import { SlButton, SlCheckbox, SlInput, SlMenuItem, SlSelect, SlTextarea } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
function handleSubmit(event) {
|
||||
@@ -103,8 +98,11 @@ const App = () => {
|
||||
<SlTextarea name="comment" label="Comment" required></SlTextarea>
|
||||
<br />
|
||||
<SlCheckbox required>Check me before submitting</SlCheckbox>
|
||||
<br /><br />
|
||||
<SlButton type="submit" variant="primary">Submit</SlButton>
|
||||
<br />
|
||||
<br />
|
||||
<SlButton type="submit" variant="primary">
|
||||
Submit
|
||||
</SlButton>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -117,15 +115,16 @@ To restrict a value to a specific [pattern](https://developer.mozilla.org/en-US/
|
||||
```html preview
|
||||
<form class="input-validation-pattern">
|
||||
<sl-input name="letters" required label="Letters" pattern="[A-Za-z]+"></sl-input>
|
||||
<br>
|
||||
<br />
|
||||
<sl-button type="submit" variant="primary">Submit</sl-button>
|
||||
<sl-button type="reset" variant="default">Reset</sl-button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
<script type="module">
|
||||
const form = document.querySelector('.input-validation-pattern');
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!')
|
||||
alert('All fields are valid!');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -143,7 +142,9 @@ const App = () => {
|
||||
<form onSubmit={handleSubmit}>
|
||||
<SlInput name="letters" required label="Letters" pattern="[A-Za-z]+" />
|
||||
<br />
|
||||
<SlButton type="submit" variant="primary">Submit</SlButton>
|
||||
<SlButton type="submit" variant="primary">
|
||||
Submit
|
||||
</SlButton>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -155,18 +156,19 @@ Some input types will automatically trigger constraints, such as `email` and `ur
|
||||
|
||||
```html preview
|
||||
<form class="input-validation-type">
|
||||
<sl-input variant="email" label="Email" placeholder="you@example.com" required></sl-input>
|
||||
<br>
|
||||
<sl-input variant="url" label="URL" placeholder="https://example.com/" required></sl-input>
|
||||
<br>
|
||||
<sl-input type="email" label="Email" placeholder="you@example.com" required></sl-input>
|
||||
<br />
|
||||
<sl-input type="url" label="URL" placeholder="https://example.com/" required></sl-input>
|
||||
<br />
|
||||
<sl-button type="submit" variant="primary">Submit</sl-button>
|
||||
<sl-button type="reset" variant="default">Reset</sl-button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
<script type="module">
|
||||
const form = document.querySelector('.input-validation-type');
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!')
|
||||
alert('All fields are valid!');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -182,41 +184,44 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<SlInput variant="email" label="Email" placeholder="you@example.com" required />
|
||||
<SlInput type="email" label="Email" placeholder="you@example.com" required />
|
||||
<br />
|
||||
<SlInput variant="url" label="URL" placeholder="https://example.com/" required />
|
||||
<SlInput type="url" label="URL" placeholder="https://example.com/" required />
|
||||
<br />
|
||||
<SlButton type="submit" variant="primary">Submit</SlButton>
|
||||
<SlButton type="submit" variant="primary">
|
||||
Submit
|
||||
</SlButton>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Validation
|
||||
### Custom Error Messages
|
||||
|
||||
To create a custom validation error, use the `setCustomValidity` method. The form will not be submitted when this method is called with anything other than an empty string, and its message will be shown by the browser as the validation error. To make the input valid again, call the method a second time with an empty string as the argument.
|
||||
To create a custom validation error, pass a non-empty string to the `setCustomValidity()` method. This will override any existing validation constraints. The form will not be submitted when a custom validity is set and the browser will show a validation error when the containing form is submitted. To make the input valid again, call `setCustomValidity()` again with an empty string.
|
||||
|
||||
```html preview
|
||||
<form class="input-validation-custom">
|
||||
<sl-input label="Type 'shoelace'" required></sl-input>
|
||||
<br>
|
||||
<sl-input label="Type “shoelace”" required></sl-input>
|
||||
<br />
|
||||
<sl-button type="submit" variant="primary">Submit</sl-button>
|
||||
<sl-button type="reset" variant="default">Reset</sl-button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
<script type="module">
|
||||
const form = document.querySelector('.input-validation-custom');
|
||||
const input = form.querySelector('sl-input');
|
||||
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!')
|
||||
alert('All fields are valid!');
|
||||
});
|
||||
|
||||
input.addEventListener('sl-input', () => {
|
||||
if (input.value === 'shoelace') {
|
||||
input.setCustomValidity('');
|
||||
} else {
|
||||
input.setCustomValidity('Hey, you\'re supposed to type \'shoelace\' before submitting this!');
|
||||
input.setCustomValidity("Hey, you're supposed to type 'shoelace' before submitting this!");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -236,7 +241,7 @@ const App = () => {
|
||||
if (event.target.value === 'shoelace') {
|
||||
input.current.setCustomValidity('');
|
||||
} else {
|
||||
input.current.setCustomValidity('Hey, you\'re supposed to type \'shoelace\' before submitting this!');
|
||||
input.current.setCustomValidity("Hey, you're supposed to type 'shoelace' before submitting this!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,90 +252,249 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<SlInput
|
||||
ref={input}
|
||||
label="Type 'shoelace'"
|
||||
required
|
||||
value={value}
|
||||
onSlInput={handleInput}
|
||||
/>
|
||||
<SlInput ref={input} label="Type 'shoelace'" required value={value} onSlInput={handleInput} />
|
||||
<br />
|
||||
<SlButton type="submit" variant="primary">Submit</SlButton>
|
||||
<SlButton type="submit" variant="primary">
|
||||
Submit
|
||||
</SlButton>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Validation Styles
|
||||
?> Custom validation can be applied to any form control that supports the `setCustomValidity()` method. It is not limited to inputs and textareas.
|
||||
|
||||
The `invalid` attribute reflects the form control's validity, so you can style invalid fields using the `[invalid]` selector. The example below demonstrates how you can give erroneous fields a different appearance. Type something other than "shoelace" to demonstrate this.
|
||||
## Custom Validation Styles
|
||||
|
||||
Due to the many ways form controls are used, Shoelace doesn't provide out of the box validation styles for form controls as part of its default theme. Instead, the following attributes will be applied to reflect a control's validity as users interact with it. You can use them to create custom styles for any of the validation states you're interested in.
|
||||
|
||||
- `data-required` - the form control is required
|
||||
- `data-optional` - the form control is optional
|
||||
- `data-invalid` - the form control is currently invalid
|
||||
- `data-valid` - the form control is currently valid
|
||||
- `data-user-invalid` - the form control is currently invalid and the user has interacted with it
|
||||
- `data-user-valid` - the form control is currently valid and the user has interacted with it
|
||||
|
||||
These attributes map to the browser's built-in pseudo classes for validation: [`:required`](https://developer.mozilla.org/en-US/docs/Web/CSS/:required), [`:optional`](https://developer.mozilla.org/en-US/docs/Web/CSS/:optional), [`:invalid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:invalid), [`:valid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:valid), and the proposed [`:user-invalid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:user-invalid) and [`:user-valid`](https://developer.mozilla.org/en-US/docs/Web/CSS/:user-valid).
|
||||
|
||||
?> In the future, data attributes will be replaced with custom pseudo classes such as `:--valid` and `:--invalid`. Shoelace is using data attributes as a workaround until browsers support custom states through [`ElementInternals.states`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/states).
|
||||
|
||||
### Styling Invalid Form Controls
|
||||
|
||||
You can target validity using any of the aforementioned data attributes, but it's usually preferable to target `data-user-invalid` and `data-user-valid` since they get applied only after a user interaction such as typing or submitting. This prevents empty form controls from appearing invalid immediately, which often results in a poor user experience.
|
||||
|
||||
This example demonstrates custom validation styles using `data-user-invalid` and `data-user-valid`. Try Typing in the fields to see how validity changes with user input.
|
||||
|
||||
```html preview
|
||||
<sl-input class="custom-input" required pattern="shoelace">
|
||||
<small slot="help-text">Please enter "shoelace" to continue</small>
|
||||
</sl-input>
|
||||
<form class="validity-styles">
|
||||
<sl-input
|
||||
name="name"
|
||||
label="Name"
|
||||
help-text="What would you like people to call you?"
|
||||
autocomplete="off"
|
||||
required
|
||||
></sl-input>
|
||||
|
||||
<style>
|
||||
.custom-input[invalid]:not([disabled])::part(label),
|
||||
.custom-input[invalid]:not([disabled])::part(help-text) {
|
||||
color: var(--sl-color-danger-600);
|
||||
}
|
||||
<sl-select name="animal" label="Favorite Animal" help-text="Select the best option." clearable required>
|
||||
<sl-option value="birds">Birds</sl-option>
|
||||
<sl-option value="cats">Cats</sl-option>
|
||||
<sl-option value="dogs">Dogs</sl-option>
|
||||
<sl-option value="other">Other</sl-option>
|
||||
</sl-select>
|
||||
|
||||
.custom-input[invalid]:not([disabled])::part(base) {
|
||||
border-color: var(--sl-color-danger-500);
|
||||
}
|
||||
<sl-checkbox value="accept" required>Accept terms and conditions</sl-checkbox>
|
||||
|
||||
.custom-input[invalid]:focus-within::part(base) {
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-color-danger-500);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { SlInput } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const css = `
|
||||
.custom-input[invalid]:not([disabled])::part(label),
|
||||
.custom-input[invalid]:not([disabled])::part(help-text) {
|
||||
color: var(--sl-color-danger-600);
|
||||
}
|
||||
|
||||
.custom-input[invalid]:not([disabled])::part(base) {
|
||||
border-color: var(--sl-color-danger-500);
|
||||
}
|
||||
|
||||
.custom-input[invalid]:focus-within::part(base) {
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-color-danger-500);
|
||||
}
|
||||
`;
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<SlInput className="custom-input" required pattern="shoelace">
|
||||
<small slot="help-text">Please enter "shoelace" to continue</small>
|
||||
</SlInput>
|
||||
|
||||
<style>{css}</style>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Third-party Validation
|
||||
|
||||
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` 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.
|
||||
|
||||
```html
|
||||
<form novalidate>
|
||||
<sl-input class="invalid"></sl-input>
|
||||
<sl-button type="submit" variant="primary">Submit</sl-button>
|
||||
<sl-button type="reset" variant="default">Reset</sl-button>
|
||||
</form>
|
||||
|
||||
<script type="module">
|
||||
const form = document.querySelector('.validity-styles');
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
sl-input.invalid {
|
||||
...
|
||||
.validity-styles sl-input,
|
||||
.validity-styles sl-select,
|
||||
.validity-styles sl-checkbox {
|
||||
display: block;
|
||||
margin-bottom: var(--sl-spacing-medium);
|
||||
}
|
||||
|
||||
/* user invalid styles */
|
||||
.validity-styles sl-input[data-user-invalid]::part(base),
|
||||
.validity-styles sl-select[data-user-invalid]::part(combobox),
|
||||
.validity-styles sl-checkbox[data-user-invalid]::part(control) {
|
||||
border-color: var(--sl-color-danger-600);
|
||||
}
|
||||
|
||||
.validity-styles [data-user-invalid]::part(form-control-label),
|
||||
.validity-styles [data-user-invalid]::part(form-control-help-text),
|
||||
.validity-styles sl-checkbox[data-user-invalid]::part(label) {
|
||||
color: var(--sl-color-danger-700);
|
||||
}
|
||||
|
||||
.validity-styles sl-checkbox[data-user-invalid]::part(control) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.validity-styles sl-input:focus-within[data-user-invalid]::part(base),
|
||||
.validity-styles sl-select:focus-within[data-user-invalid]::part(combobox),
|
||||
.validity-styles sl-checkbox:focus-within[data-user-invalid]::part(control) {
|
||||
border-color: var(--sl-color-danger-600);
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-color-danger-300);
|
||||
}
|
||||
|
||||
/* User valid styles */
|
||||
.validity-styles sl-input[data-user-valid]::part(base),
|
||||
.validity-styles sl-select[data-user-valid]::part(combobox),
|
||||
.validity-styles sl-checkbox[data-user-valid]::part(control) {
|
||||
border-color: var(--sl-color-success-600);
|
||||
}
|
||||
|
||||
.validity-styles [data-user-valid]::part(form-control-label),
|
||||
.validity-styles [data-user-valid]::part(form-control-help-text),
|
||||
.validity-styles sl-checkbox[data-user-valid]::part(label) {
|
||||
color: var(--sl-color-success-700);
|
||||
}
|
||||
|
||||
.validity-styles sl-checkbox[data-user-valid]::part(control) {
|
||||
background-color: var(--sl-color-success-600);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.validity-styles sl-input:focus-within[data-user-valid]::part(base),
|
||||
.validity-styles sl-select:focus-within[data-user-valid]::part(combobox),
|
||||
.validity-styles sl-checkbox:focus-within[data-user-valid]::part(control) {
|
||||
border-color: var(--sl-color-success-600);
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-color-success-300);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
```
|
||||
|
||||
## Inline Form Validation
|
||||
|
||||
By default, Shoelace form controls use the browser's tooltip-style error messages. No mechanism is provided to show errors inline, as there are too many opinions on how that would work when combined with native form controls and other custom elements. You can, however, implement your own solution using the following technique.
|
||||
|
||||
To disable the browser's error messages, you need to cancel the `sl-invalid` event. Then you can apply your own inline validation errors. This example demonstrates a primitive way to do this.
|
||||
|
||||
```html preview
|
||||
<form class="inline-validation">
|
||||
<sl-input
|
||||
name="name"
|
||||
label="Name"
|
||||
help-text="What would you like people to call you?"
|
||||
autocomplete="off"
|
||||
required
|
||||
></sl-input>
|
||||
|
||||
<div id="name-error" aria-live="polite" hidden></div>
|
||||
|
||||
<sl-button type="submit" variant="primary">Submit</sl-button>
|
||||
<sl-button type="reset" variant="default">Reset</sl-button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
const form = document.querySelector('.inline-validation');
|
||||
const nameError = document.querySelector('#name-error');
|
||||
|
||||
// A form control is invalid
|
||||
form.addEventListener(
|
||||
'sl-invalid',
|
||||
event => {
|
||||
// Suppress the browser's constraint validation message
|
||||
event.preventDefault();
|
||||
|
||||
nameError.textContent = `Error: ${event.target.validationMessage}`;
|
||||
nameError.hidden = false;
|
||||
|
||||
event.target.focus();
|
||||
},
|
||||
{ capture: true } // you must use capture since sl-invalid doesn't bubble!
|
||||
);
|
||||
|
||||
// Handle form submit
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
nameError.hidden = true;
|
||||
nameError.textContent = '';
|
||||
setTimeout(() => alert('All fields are valid'), 50);
|
||||
});
|
||||
|
||||
// Handle form reset
|
||||
form.addEventListener('reset', event => {
|
||||
nameError.hidden = true;
|
||||
nameError.textContent = '';
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#name-error {
|
||||
font-size: var(--sl-input-help-text-font-size-medium);
|
||||
color: var(--sl-color-danger-700);
|
||||
}
|
||||
|
||||
#name-error ~ sl-button {
|
||||
margin-top: var(--sl-spacing-medium);
|
||||
}
|
||||
|
||||
.inline-validation sl-input {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* user invalid styles */
|
||||
.inline-validation sl-input[data-user-invalid]::part(base) {
|
||||
border-color: var(--sl-color-danger-600);
|
||||
}
|
||||
|
||||
.inline-validation [data-user-invalid]::part(form-control-label),
|
||||
.inline-validation [data-user-invalid]::part(form-control-help-text) {
|
||||
color: var(--sl-color-danger-700);
|
||||
}
|
||||
|
||||
.inline-validation sl-input:focus-within[data-user-invalid]::part(base) {
|
||||
border-color: var(--sl-color-danger-600);
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-color-danger-300);
|
||||
}
|
||||
|
||||
/* User valid styles */
|
||||
.inline-validation sl-input[data-user-valid]::part(base) {
|
||||
border-color: var(--sl-color-success-600);
|
||||
}
|
||||
|
||||
.inline-validation [data-user-valid]::part(form-control-label),
|
||||
.inline-validation [data-user-valid]::part(form-control-help-text) {
|
||||
color: var(--sl-color-success-700);
|
||||
}
|
||||
|
||||
.inline-validation sl-checkbox[data-user-valid]::part(control) {
|
||||
background-color: var(--sl-color-success-600);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.inline-validation sl-input:focus-within[data-user-valid]::part(base) {
|
||||
border-color: var(--sl-color-success-600);
|
||||
box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-color-success-300);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
!> This example is meant to demonstrate the concept of providing your own error messages inline. It is not intended to scale to more complex forms. Users who want this functionality are encouraged to build a more appropriate validation solution using the techniques shown below. Depending on how you implement this feature, custom error messages may affect the accessibility of your form controls.
|
||||
|
||||
## Getting Associated Form Controls
|
||||
|
||||
At this time, using [`HTMLFormElement.elements`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements) will not return Shoelace form controls because the browser is unaware of their status as custom element form controls. Fortunately, Shoelace provides an `elements()` function that does something very similar. However, instead of returning an [`HTMLFormControlsCollection`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormControlsCollection), it returns an array of HTML and Shoelace form controls in the order they appear in the DOM.
|
||||
|
||||
```js
|
||||
import { getFormControls } from '@shoelace-style/shoelace/dist/utilities/form.js';
|
||||
|
||||
const form = document.querySelector('#my-form');
|
||||
const formControls = getFormControls(form);
|
||||
|
||||
console.log(formControls); // e.g. [input, sl-input, ...]
|
||||
```
|
||||
|
||||
?> You probably don't need this function! If you're gathering form data for submission, you probably want to use [Data Serialization](#data-serializing) instead.
|
||||
|
||||
@@ -9,7 +9,7 @@ If you're using a framework, make sure to check out the pages for [React](/frame
|
||||
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/light.css">
|
||||
<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>
|
||||
```
|
||||
|
||||
@@ -20,7 +20,7 @@ The easiest way to install Shoelace is with the CDN. Just add the following tags
|
||||
If you prefer to use the [dark theme](/getting-started/themes#dark-theme) instead, use this code and add `<html class="sl-theme-dark">` to the page.
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/dark.css">
|
||||
<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>
|
||||
```
|
||||
|
||||
@@ -29,10 +29,17 @@ If you prefer to use the [dark theme](/getting-started/themes#dark-theme) instea
|
||||
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');">
|
||||
<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>
|
||||
```
|
||||
|
||||
@@ -51,7 +58,7 @@ It's up to you to make the source files available to your app. One way to do thi
|
||||
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="/shoelace/dist/themes/light.css">
|
||||
<link rel="stylesheet" href="/shoelace/dist/themes/light.css" />
|
||||
<script type="module" src="/shoelace/dist/shoelace.js"></script>
|
||||
```
|
||||
|
||||
@@ -83,12 +90,12 @@ 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 or if you're using most of the components, but it 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 component manually.
|
||||
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 components manually.
|
||||
|
||||
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
|
||||
<link rel="stylesheet" href="/path/to/shoelace/dist/themes/light.css">
|
||||
<link rel="stylesheet" href="/path/to/shoelace/dist/themes/light.css" />
|
||||
|
||||
<script type="module" data-shoelace="/path/to/shoelace/dist">
|
||||
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Localization
|
||||
|
||||
Components can be localized by importing the appropriate translation file and setting the desired [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) on the `<html>` element. Here's an example that renders Shoelace components in Spanish.
|
||||
Components can be localized by importing the appropriate translation file and setting the desired [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) and/or [`dir` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir) on the `<html>` element. Here's an example that renders Shoelace components in Spanish.
|
||||
|
||||
```html
|
||||
<html lang="es">
|
||||
@@ -16,23 +16,9 @@ Components can be localized by importing the appropriate translation file and se
|
||||
|
||||
Through the magic of a mutation observer, changing the `lang` attribute will automatically update all localized components to use the new locale.
|
||||
|
||||
?> Shoelace provides a localization mechanism for component internals. This is not designed to be used as localization tool for your entire application. You should use a more appropriate tool such as [i18next](https://www.i18next.com/) if you need to localize content in your app.
|
||||
|
||||
## Available Translations
|
||||
|
||||
Shoelace ships with the following translations. The default is English (US), which also serves as the fallback locale. As such, you do not need to import the English translation.
|
||||
|
||||
- `en` - English (US)
|
||||
- `de-CH` - German (Switzerland)
|
||||
- `de` - German
|
||||
- `es` - Spanish (Latin America)
|
||||
- `fr` - French
|
||||
- `he` - Hebrew
|
||||
- `ja` - Japanese
|
||||
- `nl` - Dutch
|
||||
- `pl` - Polish
|
||||
- `pt` - Portuguese
|
||||
- `ru` - Russian
|
||||
Shoelace ships with a number of translations. The default is English (US), which also serves as the fallback locale. As such, you do not need to import the English translation. To see a list of all available translations in the latest version, [refer to this directory](https://github.com/shoelace-style/shoelace/tree/current/src/translations).
|
||||
|
||||
The location of translations depends on how you're consuming Shoelace.
|
||||
|
||||
@@ -67,9 +53,11 @@ Regional translations are welcome! For example, if a German translation (`de`) e
|
||||
|
||||
If you have any questions, please start a [discussion](https://github.com/shoelace-style/shoelace/discussions) or ask in the [community chat](https://discord.gg/mg8f26C).
|
||||
|
||||
?> Shoelace provides a localization mechanism for component internals. This is not designed to be used as localization tool for your entire application. You should use a more appropriate tool such as [i18next](https://www.i18next.com/) if you need to localize content in your app.
|
||||
|
||||
## Multiple Locales Per Page
|
||||
|
||||
You can use a different locale for an individual component by setting its `lang` attribute. Here's a contrived example to demonstrate.
|
||||
You can use a different locale for an individual component by setting its `lang` and/or `dir` attributes. Here's a contrived example to demonstrate.
|
||||
|
||||
```html
|
||||
<html lang="es">
|
||||
@@ -82,7 +70,7 @@ You can use a different locale for an individual component by setting its `lang`
|
||||
</html>
|
||||
```
|
||||
|
||||
For performance reasons, the `lang` attribute must be on the component itself, not on an ancestor element.
|
||||
For performance reasons, the `lang` and `dir` attributes must be on the component itself, not on an ancestor element.
|
||||
|
||||
```html
|
||||
<html lang="es">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<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.
|
||||
# <sl-visually-hidden>Shoelace:</sl-visually-hidden> A forward-thinking library of web components.
|
||||
|
||||
- Works with all frameworks 🧩
|
||||
- Works with CDNs 🚛
|
||||
@@ -14,6 +14,7 @@
|
||||
- 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.">
|
||||
@@ -32,7 +33,7 @@ Designed in New Hampshire by [Cory LaViska](https://twitter.com/claviska).
|
||||
Add the following code to your page.
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/light.css">
|
||||
<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>
|
||||
```
|
||||
|
||||
@@ -44,7 +45,6 @@ Now you have access to all of Shoelace's components! Try adding a button:
|
||||
|
||||
?> This will load all of Shoelace's components, but you should probably only load the ones you're actually using. To learn how, or for other ways to install Shoelace, refer to the [installation instructions](getting-started/installation).
|
||||
|
||||
|
||||
## New to Web Components?
|
||||
|
||||
**TL;DR** – we finally have a way to create [our own HTML elements](https://html.spec.whatwg.org/multipage/custom-elements.html) and use them in any framework we want!
|
||||
@@ -73,11 +73,11 @@ With Shoelace, you can:
|
||||
- Incrementally adopt components as needed (no need to ditch your framework)
|
||||
- Upgrade or switch frameworks without rebuilding foundational components
|
||||
|
||||
If your organization is looking to build a design system, [Shoelace will save you thousands of dollars](https://medium.com/eightshapes-llc/and-you-thought-buttons-were-easy-26eb5b5c1871).* All the foundational components you need are right here, ready to be customized for your brand. And since it's built on web standards, browsers will continue to support it for many years to come.
|
||||
If your organization is looking to build a design system, [Shoelace will save you thousands of dollars](https://medium.com/eightshapes-llc/and-you-thought-buttons-were-easy-26eb5b5c1871).\* All the foundational components you need are right here, ready to be customized for your brand. And since it's built on web standards, browsers will continue to support it for many years to come.
|
||||
|
||||
Whether you use Shoelace as a starting point for your organization's design system or for a fun personal project, there's no limit to what you can do with it.
|
||||
|
||||
<small>*Please consider giving back some of what you save by [supporting this project with a sponsorship](https://github.com/sponsors/claviska).</small>
|
||||
<small>\*Please consider giving back some of what you save by [supporting this project with a sponsorship](https://github.com/sponsors/claviska).</small>
|
||||
|
||||
## Browser Support
|
||||
|
||||
@@ -106,7 +106,7 @@ Designing, developing, and supporting this library requires a lot of time, effor
|
||||
</sl-button>
|
||||
|
||||
<sl-button class="repo-button repo-button--github" href="https://github.com/shoelace-style/shoelace/stargazers" target="_blank">
|
||||
<sl-icon slot="prefix" name="github"></sl-icon> <span class="github-star-count">Star</span>
|
||||
<sl-icon slot="prefix" name="github"></sl-icon> Star
|
||||
</sl-button>
|
||||
|
||||
<sl-button class="repo-button repo-button--twitter" href="https://twitter.com/shoelace_style" target="_blank">
|
||||
@@ -117,14 +117,14 @@ Designing, developing, and supporting this library requires a lot of time, effor
|
||||
|
||||
Special thanks to the following projects and individuals that help make Shoelace possible.
|
||||
|
||||
- Components are built with [LitElement](https://lit-element.polymer-project.org/)
|
||||
- Components are built with [Lit](https://lit.dev/)
|
||||
- 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/)
|
||||
- Color primitives are inspired by [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/)
|
||||
- Positioning of dropdowns, tooltips, et al is handled by [Floating UI](https://floating-ui.com/)
|
||||
- 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/)
|
||||
|
||||
@@ -8,7 +8,7 @@ A theme is nothing more than a stylesheet that uses the Shoelace API to define d
|
||||
|
||||
## 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 a class called `sl-theme-purple-power`
|
||||
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 a class called `sl-theme-purple-power`
|
||||
|
||||
All selectors 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.
|
||||
|
||||
@@ -26,7 +26,7 @@ To activate a theme, import it and apply the theme's class to the `<html>` eleme
|
||||
```html
|
||||
<html class="sl-theme-dark">
|
||||
<head>
|
||||
<link rel="stylesheet" href="path/to/shoelace/dist/themes/dark.css">
|
||||
<link rel="stylesheet" href="path/to/shoelace/dist/themes/dark.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -44,15 +44,15 @@ You can activate themes on various containers throughout the page. This example
|
||||
```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">
|
||||
<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>
|
||||
@@ -71,8 +71,8 @@ The easiest way to customize Shoelace is to override one of the built-in themes.
|
||||
If you're customizing the light theme, you should scope your styles to the following selectors.
|
||||
|
||||
```css
|
||||
:root,
|
||||
:host,
|
||||
:root,
|
||||
:host,
|
||||
.sl-theme-light {
|
||||
/* your custom styles here */
|
||||
}
|
||||
@@ -117,7 +117,7 @@ The dark theme works by taking the light theme's [color tokens](/tokens/color) a
|
||||
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">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/dark.css" />
|
||||
```
|
||||
|
||||
To activate the theme, apply the `sl-theme-dark` class to the `<html>` element.
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
Shoelace components are just regular HTML elements, or [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) to be precise. You can use them like any other element. Each component has detailed documentation that describes its full API, including properties, events, methods, and more.
|
||||
|
||||
If you're new to custom elements, often referred to as "web components," this section will familiarize you with how to use them.
|
||||
If you're new to custom elements, often referred to as "web components," this section will familiarize you with how to use them.
|
||||
|
||||
## Properties
|
||||
## Attributes & Properties
|
||||
|
||||
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.
|
||||
|
||||
@@ -18,7 +18,7 @@ Some properties are boolean, so they only have true/false values. To activate a
|
||||
<sl-button disabled>Click me</sl-button>
|
||||
```
|
||||
|
||||
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.
|
||||
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 must be done with JavaScript.
|
||||
|
||||
```html
|
||||
<sl-color-picker></sl-color-picker>
|
||||
@@ -132,7 +132,7 @@ A clever way to use this method is to hide the `<body>` with `opacity: 0` and ad
|
||||
|
||||
body.ready {
|
||||
opacity: 1;
|
||||
transition: .25s opacity;
|
||||
transition: 0.25s opacity;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -149,15 +149,45 @@ A clever way to use this method is to hide the `<body>` with `opacity: 0` and ad
|
||||
</script>
|
||||
```
|
||||
|
||||
## Component Rendering and Updating
|
||||
|
||||
Shoelace components are built with [Lit](https://lit.dev/), a tiny library that makes authoring custom elements easier, more maintainable, and a lot of fun! As a Shoelace user, here is some helpful information about rendering and updating you should probably be aware of.
|
||||
|
||||
To optimize performance and reduce re-renders, Lit batches component updates. This means changing multiple attributes or properties at the same time will result in just a single re-render. In most cases, this isn't an issue, but there may be times you'll need to wait for the component to update before continuing.
|
||||
|
||||
Consider this example. We're going to change the `checked` property of the checkbox and observe its corresponding `checked` attribute, which happens to reflect.
|
||||
|
||||
```js
|
||||
const checkbox = document.querySelector('sl-checkbox');
|
||||
checkbox.checked = true;
|
||||
|
||||
console.log(checkbox.hasAttribute('checked')); // false
|
||||
```
|
||||
|
||||
Most developers will expect this to be `true` instead of `false`, but the component hasn't had a chance to re-render yet so the attribute doesn't exist when `hasAttribute()` is called. Since changes are batched, we need to wait for the update before proceeding. This can be done using the `updateComplete` property, which is available on all Lit-based components.
|
||||
|
||||
```js
|
||||
const checkbox = document.querySelector('sl-checkbox');
|
||||
checkbox.checked = true;
|
||||
|
||||
checkbox.updateComplete.then(() => {
|
||||
console.log(checkbox.hasAttribute('checked')); // true
|
||||
});
|
||||
```
|
||||
|
||||
This time we see an empty string, which means the boolean attribute is now present!
|
||||
|
||||
?> Avoid using `setTimeout()` or `requestAnimationFrame()` in situations like this. They might work, but it's far more reliable to use `updateComplete` instead.
|
||||
|
||||
## Code Completion
|
||||
|
||||
### VS Code
|
||||
|
||||
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.
|
||||
Shoelace ships with a file called `vscode.html-custom-data.json` that can be used to describe it's custom elements 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`
|
||||
2. If it doesn't already exist, create a folder called `.vscode` at the root of your project
|
||||
3. If it doesn't already exist, create a file inside that folder called `settings.json`
|
||||
4. Add the following to the file
|
||||
|
||||
```js
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
content="Shoelace provides a collection of professionally designed, every day UI components built on a framework-agnostic technology."
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="custom-elements-manifest" content="dist/custom-elements.json" />
|
||||
<meta name="custom-elements-manifest" content="/dist/custom-elements.json" />
|
||||
<meta property="og:title" content="Shoelace" />
|
||||
<meta
|
||||
property="og:description"
|
||||
@@ -62,7 +62,6 @@
|
||||
},
|
||||
coverpage: false,
|
||||
executeScript: true,
|
||||
ga: 'UA-6412891-16',
|
||||
homepage: '/getting-started/overview.md',
|
||||
loadSidebar: true,
|
||||
logo: '/assets/images/wordmark.svg',
|
||||
@@ -82,7 +81,6 @@
|
||||
};
|
||||
</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/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.25.0/components/prism-bash.min.js"></script>
|
||||
|
||||
@@ -15,4 +15,4 @@ I’m fully aware that I may not get it right every time for every user, so I in
|
||||
This is the path forward. Together, we will continue to make Shoelace accessible to as many users as possible.
|
||||
|
||||
— Cory LaViska<br>
|
||||
_Creator of Shoelace_
|
||||
_Creator of Shoelace_
|
||||
|
||||
@@ -4,7 +4,547 @@ Shoelace follows [Semantic Versioning](https://semver.org/). Breaking changes in
|
||||
|
||||
Components with the <sl-badge variant="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._ 🐛
|
||||
New versions of Shoelace are released as-needed and generally occur when a critical mass of changes have accumulated. At any time, you can see what's coming in the next release by visiting [next.shoelace.style](https://next.shoelace.style).
|
||||
|
||||
## 2.2.0
|
||||
|
||||
- Added TypeScript types to all custom events [#1183](https://github.com/shoelace-style/shoelace/pull/1183)
|
||||
- Added the `svg` part to `<sl-icon>`
|
||||
- Added the `getForm()` method to all form controls [#1180](https://github.com/shoelace-style/shoelace/issues/1180)
|
||||
- Fixed a bug in `<sl-select>` that caused the display label to render incorrectly in Chrome after form validation [#1197](https://github.com/shoelace-style/shoelace/discussions/1197)
|
||||
- Fixed a bug in `<sl-input>` that prevented users from applying their own value for `autocapitalize`, `autocomplete`, and `autocorrect` when using `type="password` [#1205](https://github.com/shoelace-style/shoelace/issues/1205)
|
||||
- Fixed a bug in `<sl-tab-group>` that prevented scroll controls from showing when dynamically adding tabs [#1208](https://github.com/shoelace-style/shoelace/issues/1208)
|
||||
- Fixed a big in `<sl-input>` that caused the calendar icon to be clipped in Firefox [#1213](https://github.com/shoelace-style/shoelace/pull/1213)
|
||||
- Fixed a bug in `<sl-tab>` that caused `sl-tab-show` to be emitted when activating the close button
|
||||
- Fixed a bug in `<sl-spinner>` that caused `--track-color` to be invisible with certain colors
|
||||
- Fixed a bug in `<sl-menu-item>` that caused the focus color to show when selecting menu items with a mouse or touch device
|
||||
- Fixed a bug in `<sl-select>` that caused `sl-change` and `sl-input` to be emitted too early [#1201](https://github.com/shoelace-style/shoelace/issues/1201)
|
||||
- Fixed a positioning edge case that caused `<sl-popup>` to positioned nested popups incorrectly [#1135](https://github.com/shoelace-style/shoelace/issues/1135)
|
||||
- Fixed a bug in `<sl-tree>` that caused the tree item to collapse when clicking a child item, dragging the mouse, and releasing it on the parent node [#1082](https://github.com/shoelace-style/shoelace/issues/1082)
|
||||
- Updated `@shoelace-style/localize` to 3.1.0
|
||||
- Updated `@floating-ui/dom` to 1.2.1
|
||||
|
||||
When using `<input type="password">` the default value for `autocapitalize`, `autocomplete`, and `autocorrect` may be affected due to the bug fixed in [#1205](https://github.com/shoelace-style/shoelace/issues/1205). For any affected users, setting these attributes to `off` will restore the previous behavior.
|
||||
|
||||
## 2.1.0
|
||||
|
||||
- Added the `sl-focus` and `sl-blur` events to `<sl-color-picker>`
|
||||
- Added the `focus()` and `blur()` methods to `<sl-color-picker>`
|
||||
- Added the `sl-invalid` event to all form controls to enable custom validation logic [#1167](https://github.com/shoelace-style/shoelace/pull/1167)
|
||||
- Added `validity` and `validationMessage` properties to all form controls [#1167](https://github.com/shoelace-style/shoelace/pull/1167)
|
||||
- Added the `rel` attribute to `<sl-button>` to allow users to create button links that point to specific targets [#1200](https://github.com/shoelace-style/shoelace/issues/1200)
|
||||
- Fixed a bug in `<sl-animated-image>` where the play and pause buttons were transposed [#1147](https://github.com/shoelace-style/shoelace/issues/1147)
|
||||
- Fixed a bug that prevented `web-types.json` from being generated [#1154](https://github.com/shoelace-style/shoelace/discussions/1154)
|
||||
- Fixed a bug in `<sl-color-picker>` that prevented `sl-change` and `sl-input` from emitting when using the eye dropper [#1157](https://github.com/shoelace-style/shoelace/issues/1157)
|
||||
- Fixed a bug in `<sl-dropdown>` that prevented keyboard users from selecting menu items when using the keyboard [#1165](https://github.com/shoelace-style/shoelace/issues/1165)
|
||||
- Fixed a bug in the template for `<sl-select>` that caused the `form-control-help-text` part to not be in the same location as other form controls [#1178](https://github.com/shoelace-style/shoelace/issues/1178)
|
||||
- Fixed a bug in `<sl-checkbox>` and `<sl-switch>` that caused the browser to scroll incorrectly when focusing on a control in a container with overflow [#1169](https://github.com/shoelace-style/shoelace/issues/1169)
|
||||
- Fixed a bug in `<sl-menu-item>` that caused the `click` event to be emitted when the item was disabled [#1113](https://github.com/shoelace-style/shoelace/issues/1113)
|
||||
- Fixed a bug in form controls that erroneously prevented validation states from being set when `novalidate` was used on the containing form [#1164](https://github.com/shoelace-style/shoelace/issues/1164)
|
||||
- Fixed a bug in `<sl-checkbox>` that caused the required asterisk to appear before the label in Chrome
|
||||
- Fixed a bug that prevented large form control labels from having the correct font size [#1195](https://github.com/shoelace-style/shoelace/pull/1195)
|
||||
- Improved the behavior of `<sl-dropdown>` in Safari so keyboard interaction works the same as in other browsers [#1177](https://github.com/shoelace-style/shoelace/issues/1177)
|
||||
- Improved the [icons](/components/icon) page so it's not as sluggish in Safari [#1122](https://github.com/shoelace-style/shoelace/issues/1122)
|
||||
- Improved the accessibility of `<sl-switch>` when used in forced-colors / Windows High Contrast mode [#1114](https://github.com/shoelace-style/shoelace/issues/1114)
|
||||
- Improved user interaction heuristics for all form controls [#1175](https://github.com/shoelace-style/shoelace/issues/1175)
|
||||
|
||||
## 2.0.0
|
||||
|
||||
This is the first stable release of Shoelace 2, meaning breaking changes to the API will no longer be accepted for this version. Development of Shoelace 2.0 started in January 2020. The first beta was released on [July 15, 2020](https://github.com/shoelace-style/shoelace/releases/tag/v2.0.0-beta.1). Since then, Shoelace has grown quite a bit! Here are some stats from the project as of January 24, 2023:
|
||||
|
||||
- 55 components have been built
|
||||
- [Over 2,500 commits](https://github.com/shoelace-style/shoelace/commits/next) have been made to the project
|
||||
- [88 beta versions](https://github.com/shoelace-style/shoelace/tags) have been released
|
||||
- [85 people](https://github.com/shoelace-style/shoelace/graphs/contributors) have contributed to the project
|
||||
- [669 issues](https://github.com/shoelace-style/shoelace/issues?q=is%3Aissue+is%3Aclosed) have been filed on GitHub
|
||||
- [274 pull requests](https://github.com/shoelace-style/shoelace/pulls) have been opened
|
||||
- [More than 150 discussions](https://github.com/shoelace-style/shoelace/discussions) have been started on GitHub
|
||||
- [Over 500 people](https://discord.com/invite/mg8f26C) have joined the Shoelace community on Discord
|
||||
- [Over 300 million CDN hits](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace) per month
|
||||
- [Over 13,000 npm downloads](https://www.npmjs.com/package/@shoelace-style/shoelace) per week
|
||||
- [73rd most popular project](https://www.jsdelivr.com/statistics) on jsDelivr
|
||||
- [#2 product of the day](https://www.producthunt.com/products/shoelace-css) on Product Hunt (July 25, 2020)
|
||||
|
||||
I'd like to extend a very special thank you to every single contributor who worked to make this possible. Everyone who's filed a bug, submitted a PR, requested a feature, started a discussion, helped with testing, and advocated for the project. You are just as responsible for Shoelace's success as I am. I'd also like to thank the folks at [Font Awesome](https://fontawesome.com/) for recognizing Shoelace's potential and [believing in me](https://blog.fontawesome.com/shoelace-joins-font-awesome/) to make it happen.
|
||||
|
||||
Thank you! And keep building _awesome_ stuff!
|
||||
|
||||
Without further ado, here are the notes for this release.
|
||||
|
||||
- Added support for the `inert` attribute on `<sl-menu-item>` to allow hidden menu items to not accept focus [#1107](https://github.com/shoelace-style/shoelace/issues/1107)
|
||||
- Added the `tag` part to `<sl-select>`
|
||||
- Added `sl-hover` event to `<sl-rating>` [#1125](https://github.com/shoelace-style/shoelace/issues/1125)
|
||||
- Added the `@documentation` tag with a link to the docs for each component
|
||||
- Added the `form` attribute to all form controls to allow placing them outside of a `<form>` element [#1130](https://github.com/shoelace-style/shoelace/issues/1130)
|
||||
- Added the `getFormControls()` function as an alternative to `HTMLFormElement.elements`
|
||||
- Added missing docs for the `header-actions` slot in `<sl-dialog>` and `<sl-drawer>`
|
||||
- Added `hue-slider-handle` and `opacity-slider-handle` parts to `<sl-color-picker>` and correct other part names in the docs [#1142](https://github.com/shoelace-style/shoelace/issues/1142)
|
||||
- Fixed a bug in `<sl-select>` that prevented placeholders from showing when `multiple` was used [#1109](https://github.com/shoelace-style/shoelace/issues/1109)
|
||||
- Fixed a bug in `<sl-select>` that caused tags to not be rounded when using the `pill` attribute [#1117](https://github.com/shoelace-style/shoelace/issues/1117)
|
||||
- Fixed a bug in `<sl-select>` where the `sl-change` and `sl-input` events didn't weren't emitted when removing tags [#1119](https://github.com/shoelace-style/shoelace/issues/1119)
|
||||
- Fixed a bug in `<sl-select>` that caused the listbox to scroll to the first selected item when selecting multiple items [#1138](https://github.com/shoelace-style/shoelace/issues/1138)
|
||||
- Fixed a bug in `<sl-select>` where the input color and input hover color wasn't using the correct design tokens [#1143](https://github.com/shoelace-style/shoelace/issues/1143)
|
||||
- Fixed a bug in `<sl-color-picker>` that logged a console error when parsing swatches with whitespace
|
||||
- Fixed a bug in `<sl-color-picker>` that caused selected colors to be wrong due to incorrect HSV calculations
|
||||
- Fixed a bug in `<sl-color-picker>` that prevented the initial value from being set correct when assigned as a property [#1141](https://github.com/shoelace-style/shoelace/issues/1141)
|
||||
- Fixed a bug in `<sl-radio-button>` that caused the checked button's right border to be incorrect [#1110](https://github.com/shoelace-style/shoelace/issues/1110)
|
||||
- Fixed a bug in `<sl-spinner>` that caused the animation to stop working correctly in Safari [#1121](https://github.com/shoelace-style/shoelace/issues/1121)
|
||||
- Fixed a bug that prevented the entire `<sl-tab-panel>` to be hidden when inactive
|
||||
- Fixed a bug that caused the value of `<sl-radio-group>` to be `undefined` depending on where the radio was activated [#1134](https://github.com/shoelace-style/shoelace/issues/1134)
|
||||
- Fixed a bug that caused body content to shift when scroll locking was enabled [#1132](https://github.com/shoelace-style/shoelace/issues/1132)
|
||||
- Fixed a bug in `<sl-icon>` that caused icons to sometimes be clipped in Safari
|
||||
- Fixed a bug that prevented label colors from inheriting by default in `<sl-checkbox>`, `<sl-radio>`, and `<sl-switch>`
|
||||
- Fixed a bug in `<sl-radio-group>` that caused an extra margin between the host element and the internal fieldset [#1139](https://github.com/shoelace-style/shoelace/issues/1139)
|
||||
- Refactored the `ShoelaceFormControl` interface to remove the `invalid` property, allowing a more intuitive API for controlling validation internally
|
||||
- Renamed the internal `FormSubmitController` to `FormControlController` to better reflect what it's used for
|
||||
- Updated Lit to 2.6.1
|
||||
- Updated Floating UI to 1.1.0
|
||||
- Updated all other dependencies to latest versions
|
||||
|
||||
## 2.0.0-beta.88
|
||||
|
||||
This release includes a complete rewrite of `<sl-select>` to improve accessibility and simplify its internals.
|
||||
|
||||
- 🚨 BREAKING: rewrote `<sl-select>`
|
||||
- Accessibility has been significantly improved, especially in screen readers
|
||||
- You must use `<sl-option>` instead of `<sl-menu-item>` for options now
|
||||
- The `suffix` slot was removed because it was confusing to users and its position made the clear button inaccessible
|
||||
- The `max-tags-visible` attribute has been renamed to `max-options-visible`
|
||||
- Many parts have been removed or renamed (please see the docs for more details)
|
||||
- 🚨 BREAKING: removed the `sl-label-change` event from `<sl-menu-item>` (listen for `slotchange` instead)
|
||||
- 🚨 BREAKING: removed type to select logic from `<sl-menu>` (this was added specifically for `<sl-select>` which no longer uses `<sl-menu>`)
|
||||
- 🚨 BREAKING: swatches in `<sl-color-picker>` are no longer present by default (but you can set them using the `swatches` attribute now)
|
||||
- 🚨 BREAKING: improved the accessibility of `<sl-menu-item>` so checked items are announced as such
|
||||
- Checkbox menu items must now have `type="checkbox"` before applying the `checked` attribute
|
||||
- Checkbox menu items will now toggle their `checked` state on their own when selected
|
||||
- Disabled menu items will now receive focus, but are still not selectable
|
||||
- Added the `<sl-option>` component
|
||||
- Added Traditional Chinese translation [#1086](https://github.com/shoelace-style/shoelace/pull/1086)
|
||||
- Added support for `swatches` to be an attribute of `<sl-color-picker>` so swatches can be defined declaratively (it was previously a property; use a `;` to separate color values)
|
||||
- Fixed a bug in `<sl-tree-item>` where the checked/indeterminate states could get out of sync when using the `multiple` option [#1076](https://github.com/shoelace-style/shoelace/issues/1076)
|
||||
- Fixed a bug in `<sl-tree>` that caused `sl-selection-change` to emit before the DOM updated [#1096](https://github.com/shoelace-style/shoelace/issues/1096)
|
||||
- Fixed a bug that prevented `<sl-switch>` from submitting a default value of `on` when no value was provided [#1103](https://github.com/shoelace-style/shoelace/discussions/1103)
|
||||
- Fixed a bug in `<sl-textarea>` that caused the scrollbar to show sometimes when using `resize="auto"`
|
||||
- Fixed a bug in `<sl-input>` and `<sl-textarea>` that caused its validation states to be out of sync in some cases [#1063](https://github.com/shoelace-style/shoelace/issues/1063)
|
||||
- Reorganized all components to make class structures more consistent
|
||||
- Updated some incorrect default values for design tokens in the docs [#1097](https://github.com/shoelace-style/shoelace/issues/1097)
|
||||
- Updated non-public fields to use the `private` keyword (these were previously private only by convention, but now TypeScript will warn you)
|
||||
- Updated the hover style of `<sl-menu-item>` to be consistent with `<sl-option>`
|
||||
- Updated the status of `<sl-tree>` and `<sl-tree-item>` from experimental to stable
|
||||
- Updated React wrappers to use the latest API from `@lit-labs/react` [#1090](https://github.com/shoelace-style/shoelace/pull/1090)
|
||||
- Updated Bootstrap Icons to 1.10.3
|
||||
|
||||
## 2.0.0-beta.87
|
||||
|
||||
- 🚨 BREAKING: changed the default size of medium checkboxes, radios, and switches to 18px instead of 16px
|
||||
- 🚨 BREAKING: renamed the `--sl-toggle-size` design token to `--sl-toggle-size-medium`
|
||||
- Added the `--sl-toggle-size-small` and `--sl-toggle-size-large` design tokens
|
||||
- Added the `size` attribute to `<sl-checkbox>`, `<sl-radio>`, and `<sl-switch>` [#1071](https://github.com/shoelace-style/shoelace/issues/1071)
|
||||
- Added the `sl-input` event to `<sl-checkbox>`, `<sl-color-picker>`, `<sl-radio>`, `<sl-range>`, and `<sl-switch>`
|
||||
- Added HSV format to `<sl-color-picker>` [#1072](https://github.com/shoelace-style/shoelace/pull/1072)
|
||||
- Fixed a bug in `<sl-color-picker>` that sometimes prevented the color from updating when clicking or tapping on the controls
|
||||
- Fixed a bug in `<sl-color-picker>` that prevented text from being entered in the color input
|
||||
- Fixed a bug in `<sl-input>` that caused the `sl-change` event to be incorrectly emitted when the value was set programmatically [#917](https://github.com/shoelace-style/shoelace/issues/917)
|
||||
- Fixed a bug in `<sl-input>` and `<sl-textarea>` that made it impossible to disable spell checking [#1061](https://github.com/shoelace-style/shoelace/issues/1061)
|
||||
- Fixed non-modal behaviors in `<sl-drawer>` when using the `contained` attribute [#1051](https://github.com/shoelace-style/shoelace/issues/1051)
|
||||
- Fixed a bug in `<sl-checkbox>` and `<sl-radio>` that caused the checked icons to not scale property when resized
|
||||
- Fixed a bug that broke React imports [#1050](https://github.com/shoelace-style/shoelace/pull/1050)
|
||||
- Refactored `<sl-color-picker>` to use `@ctrl/tinycolor` instead of `color` saving ~67KB [#1072](https://github.com/shoelace-style/shoelace/pull/1072)
|
||||
- Removed the `formdata` event polyfill since it's now available in the last two versions of all major browsers
|
||||
|
||||
## 2.0.0-beta.86
|
||||
|
||||
- 🚨 BREAKING: changed the default value of `date` in `<sl-relative-time>` to the current date instead of the Unix epoch
|
||||
- 🚨 BREAKING: removed the `handle-icon` part and slot from `<sl-image-comparer>` (use `handle` instead)
|
||||
- 🚨 BREAKING: removed the `handle` slot from `<sl-split-panel>` (use the `divider` slot instead)
|
||||
- 🚨 BREAKING: removed the `--box-shadow` custom property from `<sl-alert>` (apply a box shadow to `::part(base)` instead)
|
||||
- 🚨 BREAKING: removed the `play-icon` and `pause-icon` parts (use the `play-icon` and `pause-icon` slots instead)
|
||||
- Added `header-actions` slot to `<sl-dialog>` and `<sl-drawer>`
|
||||
- Added the `expand-icon` and `collapse-icon` slots to `<sl-details>` and refactored the icon animation [#1046](https://github.com/shoelace-style/shoelace/discussions/1046)
|
||||
- Added the `play-icon` and `pause-icon` slots to `<sl-animated-image>` so you can customize the default icons
|
||||
- Converted `isTreeItem()` export to a static method of `<sl-tree-item>`
|
||||
- Fixed a bug in `<sl-tree-item>` where `sl-selection-change` was emitted when the selection didn't change [#1030](https://github.com/shoelace-style/shoelace/pull/1030)
|
||||
- Fixed a bug in `<sl-button-group>` that caused the border to render incorrectly when hovering over icons inside buttons [#1035](https://github.com/shoelace-style/shoelace/issues/1035)
|
||||
- Fixed an incorrect default for `flip-fallback-strategy` in `<sl-popup>` that caused the fallback strategy to be `initial` instead of `best-fit`, which is inconsistent with Floating UI's default [#1036](https://github.com/shoelace-style/shoelace/issues/1036)
|
||||
- Fixed a bug where browser validation tooltips would show up when hovering over form controls [#1037](https://github.com/shoelace-style/shoelace/issues/1037)
|
||||
- Fixed a bug in `<sl-tab-group>` that sometimes caused the active tab indicator to not animate
|
||||
- Fixed a bug in `<sl-tree-item>` that caused the expand/collapse icon slot to be out of sync when the node is open initially
|
||||
- Fixed the mislabeled `handle-icon` slot in `<sl-image-comparer>` (it now points to the `<slot>`, not the slot's fallback content)
|
||||
- Fixed the border radius in `<sl-dropdown>` so it matches with nested `<sl-menu>` elements
|
||||
- Fixed a bug that caused all button values to appear in submitted form data even if they weren't the submitter
|
||||
- Improved IntelliSense in VS Code, courtesy of [Burton's amazing CEM Analyzer plugin](https://github.com/break-stuff/cem-plugin-vs-code-custom-data-generator)
|
||||
- Improved accessibility of `<sl-alert>` so the alert is announced and the close button has a label
|
||||
- Improved accessibility of `<sl-progress-ring>` so slotted labels are announced along with visually hidden labels
|
||||
- Refactored all styles and animations to use `translate`, `rotate`, and `scale` instead of `transform`
|
||||
- Removed slot wrappers from many components, allowing better control over user-applied styles
|
||||
- Removed unused aria attributes from `<sl-skeleton>`
|
||||
- Replaced the `x` icon in the system icon library with `x-lg` to improve icon consistency
|
||||
|
||||
## 2.0.0-beta.85
|
||||
|
||||
- Fixed a bug in `<sl-dropdown>` that caused containing dialogs, drawers, etc. to close when pressing <kbd>Escape</kbd> while focused [#1024](https://github.com/shoelace-style/shoelace/issues/1024)
|
||||
- Fixed a bug in `<sl-tree-item>` that allowed lazy nodes to be incorrectly selected [#1023](https://github.com/shoelace-style/shoelace/pull/1023)
|
||||
- Fixed a typing bug in `<sl-tree-item>` [#1026](https://github.com/shoelace-style/shoelace/pull/1026)
|
||||
- Updated Floating UI to 1.0.7 to fix a bug that prevented `hoist` from working correctly in `<sl-dropdown>` after a recent update [#1024](https://github.com/shoelace-style/shoelace/issues/1024)
|
||||
|
||||
## 2.0.0-beta.84
|
||||
|
||||
- 🚨 BREAKING: Removed the `fieldset` property from `<sl-radio-group>` (use CSS parts if you want to keep the border) [#965](https://github.com/shoelace-style/shoelace/issues/965)
|
||||
- 🚨 BREAKING: Removed `base` and `label` parts from `<sl-radio-group>` (use `form-control` and `form-control__label` instead) [#965](https://github.com/shoelace-style/shoelace/issues/965)
|
||||
- 🚨 BREAKING: Removed the `base` part from `<sl-icon>` (style the host element directly instead)
|
||||
- 🚨 BREAKING: Removed the `invalid` attribute from form controls (use `[data-invalid]` to target it with CSS)
|
||||
- Added validation states to all form controls to allow styling based on various validation states [#1011](https://github.com/shoelace-style/shoelace/issues/1011)
|
||||
- `data-required` - indicates that a value is required
|
||||
- `data-optional` - indicates that a value is NOT required
|
||||
- `data-invalid` - indicates that the form control is invalid
|
||||
- `data-valid` - indicates that the form control is valid
|
||||
- `data-user-invalid` - indicates the form control is invalid and the user has interacted with it
|
||||
- `data-user-valid` - indicates the form control is valid and the user has interacted with it
|
||||
- Added npm exports [#1020](https://github.com/shoelace-style/shoelace/pull/1020)
|
||||
- Added `checkValidity()` method to all form controls
|
||||
- Added `reportValidity()` method to `<sl-range>`
|
||||
- Added `button--checked` to `<sl-radio-button>` and `control--checked` to `<sl-radio>` to style just the checked state [#933](https://github.com/shoelace-style/shoelace/pull/933)
|
||||
- Added tests for `<sl-menu>`, `<sl-menu-item>`, `<sl-menu-label>`, `<sl-rating>`, `<sl-relative-time>`, `<sl-skeleton>`, `<sl-tab-panel>` and `<sl-tag>` [#935](https://github.com/shoelace-style/shoelace/pull/935)
|
||||
[#949](https://github.com/shoelace-style/shoelace/pull/949) [#951](https://github.com/shoelace-style/shoelace/pull/951) [#953](https://github.com/shoelace-style/shoelace/pull/953)
|
||||
[#956](https://github.com/shoelace-style/shoelace/pull/956) [#984](https://github.com/shoelace-style/shoelace/pull/984) [#991](https://github.com/shoelace-style/shoelace/pull/991)
|
||||
- Added translations for Hungarian, Turkish, English (United Kingdom) and German (Austria) [#982](https://github.com/shoelace-style/shoelace/pull/982) [#989](https://github.com/shoelace-style/shoelace/pull/989)
|
||||
- Added `--indicator-transition-duration` custom property to `<sl-progress-ring>` [#986](https://github.com/shoelace-style/shoelace/issues/986)
|
||||
- Added `--sl-input-required-content-color` custom property to all form controls [#948](https://github.com/shoelace-style/shoelace/pull/948)
|
||||
- Added the ability to cancel `sl-show` and `sl-hide` events in `<sl-details>` [#993](https://github.com/shoelace-style/shoelace/issues/993)
|
||||
- Added `focus()` and `blur()` methods to `<sl-radio-button>`
|
||||
- Added `stepUp()` and `stepDown()` methods to `<sl-input>` and `<sl-range>` [#1013](https://github.com/shoelace-style/shoelace/pull/1013)
|
||||
- Added `showPicker()` method to `<sl-input>` [#1013](https://github.com/shoelace-style/shoelace/pull/1013)
|
||||
- Added the `handle-icon` part to `<sl-image-comparer>`
|
||||
- Added `caret`, `check`, `grip-vertical`, `indeterminate`, and `radio` icons to the system library and removed `check-lg` [#985](https://github.com/shoelace-style/shoelace/issues/985)
|
||||
- Added the `loading` attribute to `<sl-avatar>` to allow lazy loading of image avatars [#1006](https://github.com/shoelace-style/shoelace/pull/1006)
|
||||
- Added `formenctype` attribute to `<sl-button>` [#1009](https://github.com/shoelace-style/shoelace/pull/1009)
|
||||
- Added `exports` to `package.json` and removed the `main` and `module` properties [#1007](https://github.com/shoelace-style/shoelace/pull/1007)
|
||||
- Fixed a bug in `<sl-card>` that prevented the border radius to apply correctly to the header [#934](https://github.com/shoelace-style/shoelace/pull/934)
|
||||
- Fixed a bug in `<sl-button-group>` where the inner border disappeared on focus [#980](https://github.com/shoelace-style/shoelace/pull/980)
|
||||
- Fixed a bug that caused prefix/suffix animations in `<sl-input>` to wobble [#996](https://github.com/shoelace-style/shoelace/issues/996)
|
||||
- Fixed a bug in `<sl-icon>` that prevented color from being set on the host element [#999](https://github.com/shoelace-style/shoelace/issues/999)
|
||||
- Fixed a bug in `<sl-dropdown>` where the `keydown` event erroneously propagated to ancestors when pressing <kbd>Escape</kbd> [#990](https://github.com/shoelace-style/shoelace/issues/990)
|
||||
- Fixed a bug that prevented arrow keys from scrolling content within `<sl-dialog>` and `<sl-drawer>` [#925](https://github.com/shoelace-style/shoelace/issues/925)
|
||||
- Fixed a bug that prevented <kbd>Escape</kbd> from closing `<sl-dialog>` and `<sl-drawer>` in some cases
|
||||
- Fixed a bug that caused forms to submit unexpectedly when selecting certain characters [#988](https://github.com/shoelace-style/shoelace/pull/988)
|
||||
- Fixed a bug in `<sl-radio-group>` that prevented the `invalid` property from correctly reflecting validity sometimes [#992](https://github.com/shoelace-style/shoelace/issues/992)
|
||||
- Fixed a bug in `<sl-tree>` that prevented selections from working correctly on dynamically added tree items [#963](https://github.com/shoelace-style/shoelace/issues/963)
|
||||
- Fixed module paths in `custom-elements.json` so they point to the dist file instead of the source file [#725](https://github.com/shoelace-style/shoelace/issues/725)
|
||||
- Fixed an incorrect return value for `reportValidity()` in `<sl-color-picker>`
|
||||
- Improved `<sl-badge>` to improve padding and render relative to the current font size
|
||||
- Improved how many components display in forced-colors mode / Windows High Contrast mode
|
||||
- Improved `<sl-color-picker>` so it's usable in forced-colors mode
|
||||
- Improved `<sl-dialog>` and `<sl-drawer>` so the panel is more visible in forced-colors mode
|
||||
- Improved `<sl-menu-item>` so selections are visible in forced-colors mode
|
||||
- Improved `<sl-progress-bar>` so it's visible in forced-colors mode
|
||||
- Improved `<sl-radio-button>` so checked states are visible in forced-colors mode
|
||||
- Improved `<sl-range>` so the thumb, track, and tooltips are visible in forced-colors mode
|
||||
- Improved `<sl-rating>` so icons are visible in forced-colors mode
|
||||
- Improved `<sl-split-panel>` so the divider is visible in forced-colors mode
|
||||
- Improved `<sl-tree-item>` so selected items are visible in forced-colors mode
|
||||
- Improved `<sl-tab-group>` so tabs are cleaner and easier to understand in forced-colors mode
|
||||
- Improved positioning of the menu in `<sl-select>` so you can customize the menu width [#1018](https://github.com/shoelace-style/shoelace/issues/1018)
|
||||
- Moved all component descriptions to `@summary` to get them within documentation tools [#962](https://github.com/shoelace-style/shoelace/pull/962)
|
||||
- Refactored form controls to use the `ShoelaceFormControl` interface to improve type safety and consistency
|
||||
- Updated Lit to 2.4.1
|
||||
- Updated `@shoelace-style/localize` t0 3.0.3 to support for extended language codes
|
||||
- Updated Bootstrap Icons to 1.10.2
|
||||
- Updated TypeScript to 4.8.4
|
||||
- Updated esbuild to 0.15.14
|
||||
- Updated all other dependencies to latest versions
|
||||
|
||||
## 2.0.0-beta.83
|
||||
|
||||
This release removes the `<sl-responsive-media>` component. When this component was introduced, support for [`aspect-ratio`](https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio)) wasn't great. These days, [the property is supported](https://caniuse.com/mdn-css_properties_aspect-ratio) by all of Shoelace's target browsers, making a dedicated component redundant.
|
||||
|
||||
- 🚨 BREAKING: Removed `<sl-responsive-media>` (use the well-supported `aspect-ratio` CSS property instead)
|
||||
- 🚨 BREAKING: Changed the `toggle-password` attribute of `<sl-input>` to `password-toggle` for consistency
|
||||
- Added an expand/collapse animation to `<sl-tree-item>`
|
||||
- Added `sl-lazy-change` event to `<sl-tree-item>`
|
||||
- Added `expand-button` part to `<sl-tree-item>` [#893](https://github.com/shoelace-style/shoelace/pull/893)
|
||||
- Added `password-visible` attribute to `<sl-input>` [#913](https://github.com/shoelace-style/shoelace/issues/913)
|
||||
- Fixed a bug in `<sl-popup>` that didn't account for the arrow's diagonal size
|
||||
- Fixed a bug in `<sl-popup>` that caused arrow placement to be incorrect with RTL
|
||||
- Fixed a bug in `<sl-progress-ring>` that caused the indeterminate animation to stop working in Safari [#891](https://github.com/shoelace-style/shoelace/issues/891)
|
||||
- Fixed a bug in `<sl-range>` that caused it to overflow a container at 100% width [#905](https://github.com/shoelace-style/shoelace/issues/905)
|
||||
- Fixed a bug in `<sl-tree-item>` that prevented custom expand/collapse icons from rendering
|
||||
- Fixed a bug in `<sl-tree-item>` where the `expand-icon` and `collapse-icon` slots were reversed
|
||||
- Fixed a bug in `<sl-tree-item>` that prevented the keyboard from working after lazy loading [#882](https://github.com/shoelace-style/shoelace/issues/882)
|
||||
- Fixed a bug in `<sl-textarea>` that prevented the textarea from resizing automatically when setting the value programmatically [#912](https://github.com/shoelace-style/shoelace/discussions/912)
|
||||
- Fixed a handful of paths to prevent TypeScript from getting upset [#886](https://github.com/shoelace-style/shoelace/issues/886)
|
||||
- Fixed a bug in `<sl-radio-group>` where the `button-group__base` part was documented but not exposed [#909](https://github.com/shoelace-style/shoelace/discussions/909)
|
||||
- Fixed a bug in `<sl-range>` that caused the active track color to render on the wrong side in RTL [#916](https://github.com/shoelace-style/shoelace/issues/916)
|
||||
- Refactored the internal event emitter to be part of `ShoelaceElement` to reduce imports and improve DX
|
||||
- Downgraded Floating UI from 1.0.1 to 1.0.0 due to new logic that makes positioning much slower for certain components [#915](https://github.com/shoelace-style/shoelace/issues/915)
|
||||
- Upgraded the status of `<sl-animated-image>`, `<sl-popup>`, and `<sl-split-panel>` from experimental to stable
|
||||
|
||||
## 2.0.0-beta.82
|
||||
|
||||
- Added the `sync` and `arrow-placement` attributes to `<sl-popup>`
|
||||
- Changed the `auto-size` attribute of the experimental `<sl-popup>` component so it accepts `horizontal`, `vertical`, and `both` instead of a boolean value
|
||||
- Changed the `flip-fallback-placement` attribute of the experimental `<sl-popup>` component to `flip-fallback-placements`
|
||||
- Changed the `flip-fallback-strategy` in the experimental `<sl-popup>` component to accept `best-fit` and `initial` instead of `bestFit` and `initialPlacement`
|
||||
- Fixed a bug in `<sl-dropdown>` that caused the panel to resize horizontally when the trigger is clipped by the viewport [#860](https://github.com/shoelace-style/shoelace/issues/860)
|
||||
- Fixed a bug in `<sl-tree>` where dynamically changing slotted items wouldn't update the tree properly
|
||||
- Fixed a bug in `<sl-split-panel>` that caused the panel to stack when clicking on the divider in mobile versions of Chrome [#862](https://github.com/shoelace-style/shoelace/issues/862)
|
||||
- Fixed a bug in `<sl-popup>` that prevented flip fallbacks from working as intended
|
||||
- Fixed a bug that caused concurrent animations to work incorrectly when the durations were different [#867](https://github.com/shoelace-style/shoelace/issues/867)
|
||||
- Fixed a bug in `<sl-color-picker>` that caused the trigger and color preview to ignore opacity on first render [#869](https://github.com/shoelace-style/shoelace/issues/869)
|
||||
- Fixed a bug in `<sl-tree>` that prevented the keyboard from working when the component was nested in a shadow root [#871](https://github.com/shoelace-style/shoelace/issues/871)
|
||||
- Fixed a bug in `<sl-tab-group>` that prevented the keyboard from working when the component was nested in a shadow root [#872](https://github.com/shoelace-style/shoelace/issues/872)
|
||||
- Fixed a bug in `<sl-tab>` that allowed disabled tabs to erroneously receive focus
|
||||
- Improved single selection in `<sl-tree>` so nodes expand and collapse and receive selection when clicking on the label
|
||||
- Renamed `expanded-icon` and `collapsed-icon` slots to `expand-icon` and `collapse-icon` in the experimental `<sl-tree>` and `<sl-tree-item>` components
|
||||
- Improved RTL support for `<sl-image-comparer>`
|
||||
- Refactored components to extend from `ShoelaceElement` to make `dir` and `lang` reactive properties in all components
|
||||
|
||||
## 2.0.0-beta.81
|
||||
|
||||
- 🚨 BREAKING: removed the `base` part from `<sl-menu>` and removed an unnecessary `<div>` that made styling more difficult
|
||||
- Added the `anchor` property to `<sl-popup>` to support external anchors
|
||||
- Added read-only custom properties `--auto-size-available-width` and `--auto-size-available-height` to `<sl-popup>` to improve support for overflowing popup content
|
||||
- Added `label` to `<sl-rating>` to improve accessibility for screen readers
|
||||
- Added the `base__popup` and `base__arrow` parts to `<sl-tooltip>` [#858](https://github.com/shoelace-style/shoelace/issues/858)
|
||||
- Fixed a bug where auto-size wasn't being applied to `<sl-dropdown>` and `<sl-select>`
|
||||
- Fixed a bug in `<sl-popup>` that caused auto-size to kick in before flip
|
||||
- Fixed a bug in `<sl-popup>` that prevented the `arrow-padding` attribute from working as expected
|
||||
- Fixed a bug in `<sl-tooltip>` that prevented the popup from appearing with the correct z-index [#854](https://github.com/shoelace-style/shoelace/issues/854)
|
||||
- Improved accessibility of `<sl-rating>` so keyboard nav works better and screen readers announce it properly
|
||||
- Improved accessibility of `<sl-spinner>` so screen readers no longer skip over it
|
||||
- Removed a user agent sniffing notice that appeared in Chrome [#855](https://github.com/shoelace-style/shoelace/issues/855)
|
||||
- Removed the default hover effect in `<sl-tree-items>` to make selections more obvious
|
||||
- Updated Floating UI to 1.0.1
|
||||
- Updated esbuild to 0.15.1
|
||||
- Updated all other dependencies to latest versions
|
||||
|
||||
## 2.0.0-beta.80
|
||||
|
||||
This release breaks radio buttons, which is something that needed to happen to solve a longstanding accessibility issue where screen readers announced an incorrect number of radios, e.g. "1 of 1" instead of "1 of 3." Many attempts to solve this without breaking the existing API were made, but none worked across the board. The new implementation upgrades `<sl-radio-group>` to serve as the "form control" while `<sl-radio>` and `<sl-radio-button>` serve as options within the form control.
|
||||
|
||||
To upgrade to this version, you will need to rework your radio controls by moving `name` up to the radio group. And instead of setting `checked` to select a specific radio, you can set `value` on the radio group and the checked item will update automatically.
|
||||
|
||||
- 🚨 BREAKING: improved accessibility of `<sl-radio-group>`, `<sl-radio>`, and `<sl-radio-button>` so they announce properly in screen readers
|
||||
- Added the `name` attribute to `<sl-radio-group>` and removed it from `<sl-radio>` and `<sl-radio-button>`
|
||||
- Added the `value` attribute to `<sl-radio-group>` (use this to control which radio is checked)
|
||||
- Added the `sl-change` event to `sl-radio-group`
|
||||
- Added `setCustomValidity()` and `reportValidity()` to `<sl-radio-group>`
|
||||
- Removed the `checked` attribute from `<sl-radio>` and `<sl-radio-button>` (use the radio group's `value` attribute instead)
|
||||
- Removed the `sl-change` event from `<sl-radio>` and `<sl-radio-button>` (listen for it on the radio group instead)
|
||||
- Removed the `invalid` attribute from `<sl-radio>` and `<sl-radio-button>`
|
||||
- Removed `setCustomValidity()` and `reportValidity()` from `<sl-radio>` and `<sl-radio-button>` (now available on the radio group)
|
||||
- Added the experimental `<sl-popup>` component
|
||||
- Fixed a bug in `<sl-menu-item>` where labels weren't always aligned correctly
|
||||
- Fixed a bug in `<sl-range>` that caused the tooltip to be positioned incorrectly when switching between LTR/RTL
|
||||
- Refactored `<sl-dropdown>` to use `<sl-popup>`
|
||||
- Refactored `<sl-tooltip>` to use `<sl-popup>` and added the `body` part
|
||||
- Revert disabled focus behavior in `<sl-tab-group>`, `<sl-menu>`, and `<sl-tree>` to be consistent with native form controls and menus [#845](https://github.com/shoelace-style/shoelace/issues/845)
|
||||
|
||||
## 2.0.0-beta.79
|
||||
|
||||
- Added experimental `<sl-tree>` and `<sl-tree-item>` components [#823](https://github.com/shoelace-style/shoelace/pull/823)
|
||||
- Added `--indicator-width` custom property to `<sl-progress-ring>` [#837](https://github.com/shoelace-style/shoelace/issues/837)
|
||||
- Added Swedish translation [#838](https://github.com/shoelace-style/shoelace/pull/838)
|
||||
- Added support for `step="any"` for `<sl-input type="number">` [#839](https://github.com/shoelace-style/shoelace/issues/839)
|
||||
- Changed the type of component styles from `CSSResult` to `CSSResultGroup` [#828](https://github.com/shoelace-style/shoelace/issues/828)
|
||||
- Fixed a bug in `<sl-color-picker>` where using <kbd>Left</kbd> and <kbd>Right</kbd> would select the wrong color
|
||||
- Fixed a bug in `<sl-dropdown>` that caused the position to be incorrect on the first show when using `hoist` [#843](https://github.com/shoelace-style/shoelace/issues/843)
|
||||
- Fixed a bug in `<sl-tab-group>` where the divider was on the wrong side when using `placement="end"`
|
||||
- Fixed a bug in `<sl-tab-group>` that caused nested tab groups to scroll when using `placement="start|end"` [#815](https://github.com/shoelace-style/shoelace/issues/815)
|
||||
- Fixed a bug in `<sl-tooltip>` that caused the target to be lost after a slot change [#831](https://github.com/shoelace-style/shoelace/pull/831)
|
||||
- Fixed a bug in `<sl-tooltip>` that caused the position to be incorrect on the first show when using `hoist`
|
||||
- Improved accessibility of `<sl-tab-group>`, `<sl-tab>`, and `<sl-tab-panel>` to announce better in screen readers and by allowing focus on disabled items
|
||||
- Improved accessibility of `<sl-menu>` and `<sl-menu-item>` by allowing focus on disabled items
|
||||
- Updated Lit to 2.2.8
|
||||
- Update esbuild to 0.14.50
|
||||
- Updated Bootstrap Icons to 1.9.1
|
||||
- Updated Floating UI to 1.0.0
|
||||
- Updated all other dependencies to latest versions
|
||||
|
||||
## 2.0.0-beta.78
|
||||
|
||||
- 🚨 BREAKING: Moved the `checked-icon` and `indeterminate-icon` parts from a wrapper `<span>` to the `<svg>` in `<sl-checkbox>` [#786](https://github.com/shoelace-style/shoelace/issues/786)
|
||||
- 🚨 BREAKING: Moved the `checked-icon` part from a wrapper `<span>` to the `<svg>` in `<sl-radio>` [#786](https://github.com/shoelace-style/shoelace/issues/786)
|
||||
- Added the `--track-active-offset` custom property to `<sl-range>` [#806](https://github.com/shoelace-style/shoelace/issues/806)
|
||||
- Fixed a bug that caused `<sl-select>` to sometimes have two vertical scrollbars [#814](https://github.com/shoelace-style/shoelace/issues/814)
|
||||
- Fixed a bug that caused a gray line to appear between radio buttons [#821](https://github.com/shoelace-style/shoelace/discussions/821)
|
||||
- Fixed a bug that caused `<sl-animated-image>` to not render anything when using the `play` attribute initially [#824](https://github.com/shoelace-style/shoelace/issues/824)
|
||||
- Removed `:focus-visible` shim now that the last two major versions of Safari support it
|
||||
- Updated Bootstrap Icons to 1.9.0
|
||||
- Updated esbuild to 0.14.49
|
||||
- Updated Floating UI to 0.5.4
|
||||
- Updated Lit to 2.2.7
|
||||
- Updated all other dependencies to latest versions
|
||||
|
||||
## 2.0.0-beta.77
|
||||
|
||||
- Added styles to required form controls so they show an asterisk next to the label by default
|
||||
- Added the `--sl-input-required-content` design token
|
||||
- Added the `required` attribute to `<sl-radio-group>` and fixed constraint validation logic to support custom validation
|
||||
- Added the `checked-icon` part to `<sl-menu-item>`
|
||||
- Added the `no-spin-buttons` attribute to `<sl-input type="number">` [#798](https://github.com/shoelace-style/shoelace/issues/798)
|
||||
- Added support for resetting forms using `<sl-button type="reset">` [#799](https://github.com/shoelace-style/shoelace/pull/799)
|
||||
- Fixed a bug where a duplicate clear button showed in Firefox [#791](https://github.com/shoelace-style/shoelace/issues/791)
|
||||
- Fixed a bug where setting `valueAsDate` or `valueAsNumber` too early on `<sl-input>` would throw an error [#796](https://github.com/shoelace-style/shoelace/issues/796)
|
||||
- Fixed a bug in `<sl-color-picker>` where empty values weren't properly supported [#797](https://github.com/shoelace-style/shoelace/issues/797)
|
||||
- Fixed a bug in `<sl-color-picker>` where values were logged to the console when using the keyboard
|
||||
- Fixed a bug in `<sl-input>` where password controls would try to autocorrect/autocomplete/autocapitalize when the password is visible
|
||||
- Fixed label alignment in `<sl-checkbox>` and `<sl-radio>` so they align to the top of the control instead of the center when wrapping
|
||||
- Fixed labels in `<sl-checkbox>` and `<sl-radio>` so they use the `--sl-input-label-color` design token
|
||||
- Improved performance of the tabbable utility which can prevent the browser from temporarily locking up in focus traps [#800](https://github.com/shoelace-style/shoelace/pull/800)
|
||||
- Updated the `fieldset` attribute so it reflects in `<sl-radio-group>`
|
||||
|
||||
## 2.0.0-beta.76
|
||||
|
||||
- Added support for RTL animations in the Animation Registry
|
||||
- Fixed a bug where the bottom border of `<sl-select>` could be cut off when the dropdown scrolls
|
||||
- Fixed a bug in `<sl-select>` that could result in the browser locking up due to an infinite positioning loop [#777](https://github.com/shoelace-style/shoelace/issues/777)
|
||||
- Improved RTL animations for `<sl-drawer>` [#784](https://github.com/shoelace-style/shoelace/issues/784)
|
||||
- Improved RTL styles for `<sl-button-group>` [#783](https://github.com/shoelace-style/shoelace/issues/783)
|
||||
- Improved RTL styles for the toast stack [#785](https://github.com/shoelace-style/shoelace/issues/785)
|
||||
- Improved typings for translations and localized terms
|
||||
- Upgraded @shoelace-style/localize to 3.0
|
||||
|
||||
## 2.0.0-beta.75
|
||||
|
||||
- Added Persian translation [#774](https://github.com/shoelace-style/shoelace/pull/774)
|
||||
- Added `color-scheme` to light and dark themes to improve rendering of browser-provided UI [#776](https://github.com/shoelace-style/shoelace/issues/776)
|
||||
- Added `--track-width` custom property to `<sl-tab-group>`
|
||||
- Fixed focus rings for `<sl-input>`, `<sl-select>`, and `<sl-textarea>` in Safari since they don't use `:focus-visible` [#767](https://github.com/shoelace-style/shoelace/issues/767)
|
||||
- Fixed a bug where calling `HTMLFormElement.reportValidity()` would skip Shoelace form controls [#772](https://github.com/shoelace-style/shoelace/issues/772)
|
||||
- Fixed a bug that prevented `<sl-tooltip>` from closing when disabled [#775](https://github.com/shoelace-style/shoelace/issues/775)
|
||||
- Fixed a bug that allowed `<sl-icon-button>` to emit a `click` event when disabled [#781](https://github.com/shoelace-style/shoelace/issues/781)
|
||||
- Improved the default icon for `<sl-image-comparer>` so it's more intuitive and removed `grip-vertical` from system icon library
|
||||
- Improved RTL styles for many components [#768](https://github.com/shoelace-style/shoelace/pull/768)
|
||||
- Improved base path logic to execute only when `getBasePath()` is first called to better support SSR [#778](https://github.com/shoelace-style/shoelace/issues/778)
|
||||
- Improved `DOMParser` instantiation in `<sl-icon>` to better support SSR [#778](https://github.com/shoelace-style/shoelace/issues/778)
|
||||
- Reverted menu item caching due to regression [#766](https://github.com/shoelace-style/shoelace/issues/766)
|
||||
- Updated Floating UI to 0.5.2
|
||||
|
||||
## 2.0.0-beta.74
|
||||
|
||||
- 🚨 BREAKING: reworked focus rings to use outlines instead of box shadows
|
||||
- Removed the `--sl-focus-ring-alpha` design token
|
||||
- Refactored `--sl-focus-ring` to be an `outline` property instead of a `box-shadow` property
|
||||
- Added `--sl-focus-ring-color`, `--sl-focus-ring-style`, and `--sl-focus-ring-offset`
|
||||
- 🚨 BREAKING: removed `variant` from `<sl-radio-button>`
|
||||
- Added `sl-label-change` event to `<sl-menu-item>`
|
||||
- Added `blur()`, `click()`, and `focus()` methods as well as `sl-blur` and `sl-focus` events to `<sl-icon-button>` [#730](https://github.com/shoelace-style/shoelace/issues/730)
|
||||
- Added Tabler Icons example to icons page
|
||||
- Fixed a bug where updating a menu item's label wouldn't update the display label in `<sl-select>` [#729](https://github.com/shoelace-style/shoelace/issues/729)
|
||||
- Fixed a bug where the FormData event polyfill was causing issues with older browsers [#747](https://github.com/shoelace-style/shoelace/issues/747)
|
||||
- Fixed a bug that caused a console error when setting `value` to `null` or `undefined` in `<sl-input>`, `<sl-select>`, and `<sl-textarea>` [#751](https://github.com/shoelace-style/shoelace/pull/751)
|
||||
- Fixed a bug that caused `<sl-checkbox>` and `<sl-radio>` controls without a `value` to submit as `null` instead of `on` like native inputs [#744](https://github.com/shoelace-style/shoelace/issues/744)
|
||||
- Fixed a bug that caused `<sl-dropdown>` and dependent components to add unexpected padding around the panel [#743](https://github.com/shoelace-style/shoelace/issues/743)
|
||||
- Fixed a bug that prevented `valueAsDate` and `valueAsNumber` from updating synchronously [#760](https://github.com/shoelace-style/shoelace/issues/760)
|
||||
- Fixed a bug that caused `<sl-menu-item>` to load icons from the default library instead of the system library [#765](https://github.com/shoelace-style/shoelace/issues/765)
|
||||
- Fixed a bug in `<sl-input>` that prevented a canceled `keydown` event from submitting the containing form when pressing enter [#764](https://github.com/shoelace-style/shoelace/issues/764)
|
||||
- Improved behavior of clearable and password toggle buttons in `<sl-input>` and `<sl-select>` [#745](https://github.com/shoelace-style/shoelace/issues/745)
|
||||
- Improved performance of `<sl-select>` by caching menu items instead of traversing for them each time
|
||||
- Improved drag utility so initial click/touch events can be accepted [#758](https://github.com/shoelace-style/shoelace/issues/758)
|
||||
- Improved `<sl-color-picker>` to use an HSB grid instead of HSL to be more consistent with existing color picker implementations [#762](https://github.com/shoelace-style/shoelace/issues/762)
|
||||
- Improved `<sl-color-picker>` so the cursor is hidden and the preview is larger when dragging the grid
|
||||
- Refactored `<sl-menu>` to be more performant by caching menu items on slot change
|
||||
- Reverted form submit logic [#718](https://github.com/shoelace-style/shoelace/issues/718)
|
||||
- Updated the `disabled` attribute so it reflects in `<sl-dropdown>` [#741](https://github.com/shoelace-style/shoelace/discussions/741)
|
||||
- Updated the `name` and `icon` attribute so they reflect in `<sl-icon>` [#742](https://github.com/shoelace-style/shoelace/pull/742)
|
||||
- Updated Lit to 2.2.5
|
||||
- Updated Bootstrap Icons to 1.8.3
|
||||
- Updated TypeScript to 4.7.2
|
||||
- Updated esbuild to 0.14.40
|
||||
- Updated all other dependencies to latest versions
|
||||
|
||||
## 2.0.0-beta.73
|
||||
|
||||
- Added `button` part to `<sl-radio-button>`
|
||||
- Added custom validity examples and tests to `<sl-checkbox>`, `<sl-radio>`, and `<sl-radio-button>`
|
||||
- Added `enterkeyhint` attribute to `<sl-input>` and `<sl-textarea>`
|
||||
- Fixed a bug that prevented `setCustomValidity()` from working with `<sl-radio-button>`
|
||||
- Fixed a bug where the right border of a checked `<sl-radio-button>` was the wrong color
|
||||
- Fixed a bug that prevented a number of properties, methods, etc. from being documented in `<sl-radio>` and `<sl-radio-button>`
|
||||
- Fixed a bug in `<sl-avatar>` that prevented valid images from showing after an invalid or missing image was provided [#717](https://github.com/shoelace-style/shoelace/issues/717)
|
||||
- Fixed a bug that resulted in a console error being thrown on keydown in `<sl-dropdown>` [#719](https://github.com/shoelace-style/shoelace/issues/719)
|
||||
- Fixed a bug that prevented `<sl-dropdown>` from being closed when opened initially [#720](https://github.com/shoelace-style/shoelace/issues/720)
|
||||
- Fixed a bug that caused the test runner to fail when using a locale other than en-US [#726](https://github.com/shoelace-style/shoelace/issues/726)
|
||||
- Improved form submit logic so most user-added event listeners will run after form data is attached and validation occurs [#718](https://github.com/shoelace-style/shoelace/issues/718)
|
||||
- Improved accessibility of `<sl-tooltip>` so screen readers announce the content on hover/focus [#219](https://github.com/shoelace-style/shoelace/issues/219)
|
||||
- Improved accessibility of form controls by exposing clear buttons and password visibility buttons to screen readers while keeping them out of the tab order [#727](https://github.com/shoelace-style/shoelace/issues/727)
|
||||
- Updated `<sl-tab-group>` and `<sl-menu>` to cycle through tabs and menu items instead of stopping at the first/last when using the keyboard
|
||||
- Removed path aliasing (again) because it doesn't work with Web Test Runner's esbuild plugin
|
||||
|
||||
## 2.0.0-beta.72
|
||||
|
||||
- 🚨 BREAKING: refactored parts in `<sl-input>`, `<sl-range>`, `<sl-select>`, and `<sl-textarea>` to allow you to customize the label and help text position
|
||||
- Added `form-control-input` part
|
||||
- Renamed `label` to `form-control-label`
|
||||
- Renamed `help-text` to `form-control-help-text`
|
||||
- 🚨 BREAKING: removed status from the `sl-error` event payload in `<sl-icon>`
|
||||
- Added the experimental `<sl-radio-button>` component
|
||||
- Added `button-group` and `button-group__base` parts to `<sl-radio-group>`
|
||||
- Added the `label` attribute and slot to `<sl-color-picker>` to improve accessibility with screen readers
|
||||
- Fixed a bug that prevented form submission from working as expected in some cases
|
||||
- Fixed a bug that prevented `<sl-split-panel>` from toggling `vertical` properly [#703](https://github.com/shoelace-style/shoelace/issues/703)
|
||||
- Fixed a bug that prevented `<sl-color-picker>` from rendering a color initially [#704](https://github.com/shoelace-style/shoelace/issues/704)
|
||||
- Fixed a bug that caused focus trapping to fail when used inside a shadow root [#709](https://github.com/shoelace-style/shoelace/issues/709)
|
||||
- Improved accessibility throughout the docs
|
||||
- Improved accessibility of `<sl-dropdown>` so the trigger's expanded state is announced correctly
|
||||
- Improved accessibility of `<sl-format-date>` but rendering a `<time>` element instead of plain text
|
||||
- Improved accessibility of `<sl-select>` so disabled controls announce correct
|
||||
- Improved accessibility in `<sl-tag>` so remove buttons have labels
|
||||
- Refactored `<sl-radio>` to move selection logic into `<sl-radio-group>`
|
||||
- Updated slot detection logic so it ignores visually hidden elements
|
||||
- Upgraded the status of `<sl-visually-hidden>` from experimental to stable
|
||||
|
||||
## 2.0.0-beta.71
|
||||
|
||||
- 🚨 BREAKING: refactored exported parts to ensure composed components and their parts can be targeted via CSS
|
||||
- Refactored the `eye-dropper-button` part and added `eye-dropper-button__base`, `eye-dropper-button__prefix`, `eye-dropper-button__label`, `eye-dropper-button__suffix`, and `eye-dropper-button__caret` parts to `<sl-color-picker>`
|
||||
- Refactored the `format-button` part and added `format-button__base`, `format-button__prefix`, `format-button__label`, `format-button__suffix`, and `format-button__caret` parts to `<sl-color-picker>`
|
||||
- Moved the `close-button` part in `<sl-alert>` to the internal `<sl-icon-button>` and removed the `<span>` that wrapped it
|
||||
- Moved the `close-button` part in `<sl-dialog>` and `<sl-drawer>` to point to the host element and added the `close-button__base` part
|
||||
- Renamed parts in `<sl-select>` from `tag-base` to `tag__base`, `tag-content` to `tag__content`, and `tag-remove-button` to `tag__remove-button`
|
||||
- Moved the `close-button` part in `<sl-tab>` to the internal `<sl-icon-button>` and added the `close-button__base` part
|
||||
- Moved the `scroll-button` part in `<sl-tab-group>` to the internal `<sl-icon-button>` and added the `scroll-button__base`, `scroll-button--start`, and `scroll-button--end` parts
|
||||
- Moved the `remove-button` part in `<sl-tag>` to the internal `<sl-icon-button>` and added the `remove-button__base` part
|
||||
- 🚨 BREAKING: removed `checked-icon` part from `<sl-menu-item>` in preparation for parts refactor
|
||||
- 🚨 BREAKING: changed the `typeToSelect()` method's argument from `String` to `KeyboardEvent` in `<sl-menu>` to support more advanced key combinations
|
||||
- Added `form`, `formaction`, `formmethod`, `formnovalidate`, and `formtarget` attributes to `<sl-button>` [#699](https://github.com/shoelace-style/shoelace/issues/699)
|
||||
- Added Prettier and ESLint to markdown files
|
||||
- Added background color and border to `<sl-menu>`
|
||||
- Added more tests for `<sl-input>`, `<sl-select>`, and `<sl-textarea>`
|
||||
- Fixed a bug that prevented forms from submitting when pressing <kbd>Enter</kbd> inside of an `<sl-input>` [#700](https://github.com/shoelace-style/shoelace/issues/700)
|
||||
- Fixed a bug in `<sl-input>` that prevented the `valueAsDate` and `valueAsNumber` properties from working when set before the component was initialized
|
||||
- Fixed a bug in `<sl-dropdown>` where pressing <kbd>Home</kbd> or <kbd>End</kbd> wouldn't select the first or last menu items, respectively
|
||||
- Improved `autofocus` behavior in Safari for `<sl-dialog>` and `<sl-drawer>` [#693](https://github.com/shoelace-style/shoelace/issues/693)
|
||||
- Improved type to select logic in `<sl-menu>` so it supports <kbd>Backspace</kbd> and gives users more time before resetting
|
||||
- Improved checkmark size and positioning in `<sl-menu-item>`
|
||||
- Improved accessibility in form controls that have help text so they're announced correctly in various screen readers
|
||||
- Removed feature detection for `focus({ preventScroll })` since it no longer works in Safari
|
||||
- Removed the `--sl-tooltip-arrow-start-end-offset` design token
|
||||
- Removed the `pattern` attribute from `<sl-textarea>` as it was documented incorrectly and never supported
|
||||
- Replaced Popper positioning dependency with Floating UI in `<sl-dropdown>` and `<sl-tooltip>`
|
||||
|
||||
## 2.0.0-beta.70
|
||||
|
||||
- Added `tag-base`, `tag-content`, and `tag-remove-button` parts to `<sl-select>` [#682](https://github.com/shoelace-style/shoelace/discussions/682)
|
||||
- Added support for focusing elements with `autofocus` when `<sl-dialog>` and `<sl-drawer>` open [#688](https://github.com/shoelace-style/shoelace/issues/688)
|
||||
- Added the `placement` attribute to `<sl-select>` [#687](https://github.com/shoelace-style/shoelace/pull/687)
|
||||
- Added Danish translation [#690](https://github.com/shoelace-style/shoelace/pull/690)
|
||||
- Fixed a bug that allowed `<sl-dropdown>` to go into an incorrect state when activating the trigger while disabled [#684](https://github.com/shoelace-style/shoelace/pull/684)
|
||||
- Fixed a bug where Safari would sometimes not focus after preventing `sl-initial-focus` [#688](https://github.com/shoelace-style/shoelace/issues/688)
|
||||
- Fixed a bug where the active tab indicator in `<sl-tab-group>` would be misaligned when using disabled tabs [#695](https://github.com/shoelace-style/shoelace/pull/695)
|
||||
- Improved the size of the remove button in `<sl-tag>`
|
||||
- Removed Google Analytics from the docs
|
||||
|
||||
## 2.0.0-beta.69
|
||||
|
||||
- Added `web-types.json` to improve the dev experience for WebStorm/PHPStorm users [#328](https://github.com/shoelace-style/shoelace/issues/328)
|
||||
- Fixed a bug that caused an error when pressing up/down in `<sl-select>`
|
||||
- Fixed a bug that caused `<sl-details>` to not show when double clicking the summary while open [#662](https://github.com/shoelace-style/shoelace/issues/662)
|
||||
- Fixed a bug that prevented the first/last menu item from receiving focus when pressing up/down in `<sl-dropdown>`
|
||||
- Fixed a bug that caused the active tab indicator in `<sl-tab-group>` to render incorrectly when used inside an element that animates [#671](https://github.com/shoelace-style/shoelace/pull/671)
|
||||
- Fixed a bug that allowed values in `<sl-range>` to be invalid according to its `min|max|step` [#674](https://github.com/shoelace-style/shoelace/issues/674)
|
||||
- Updated Lit to 2.1.4
|
||||
- Updated all other dependencies to latest versions
|
||||
|
||||
## 2.0.0-beta.68
|
||||
|
||||
@@ -22,7 +562,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
|
||||
|
||||
- 🚨 BREAKING: the `unit` property of `<sl-format-bytes>` has changed to `byte | bit` instead of `bytes | bits`
|
||||
- Added `display-label` part to `<sl-select>` [#650](https://github.com/shoelace-style/shoelace/issues/650)
|
||||
- Added `--spacing` CSS custom property to `<sl-divider>` [#664](https://github.com/shoelace-style/shoelace/pull/664)
|
||||
- Added `--spacing` custom property to `<sl-divider>` [#664](https://github.com/shoelace-style/shoelace/pull/664)
|
||||
- Added `event.detail.source` to the `sl-request-close` event in `<sl-dialog>` and `<sl-drawer>`
|
||||
- Fixed a bug that caused `<sl-progress-ring>` to render the wrong size when `--track-width` was increased [#656](https://github.com/shoelace-style/shoelace/issues/656)
|
||||
- Fixed a bug that allowed `<sl-details>` to open and close when disabled using a screen reader [#658](https://github.com/shoelace-style/shoelace/issues/658)
|
||||
@@ -33,7 +573,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
|
||||
- Refactored `<sl-format-byte>` to use `Intl.NumberFormat` so it supports localization
|
||||
- Refactored themes so utility styles are no longer injected as `<style>` elements to support stricter CSP rules [#571](https://github.com/shoelace-style/shoelace/issues/571)
|
||||
- Restored the nicer animation on `<sl-spinner>` and verified it works in Safari
|
||||
- Updated Feather icon example to use Lucide [#657](https://github.com/shoelace-style/shoelace/issues/657)
|
||||
- Updated Feather icon example to use Lucide [#657](https://github.com/shoelace-style/shoelace/issues/657)
|
||||
- Updated minimum Node version to 14.17
|
||||
- Updated Lit to 2.1.2
|
||||
- Updated to Bootstrap Icons to 1.8.1
|
||||
@@ -65,7 +605,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
|
||||
|
||||
- 🚨 BREAKING: changed the `type` attribute to `variant` in `<sl-alert>`, `<sl-badge>`, `<sl-button>`, and `<sl-tag>` since it's more appropriate and to disambiguate from other `type` attributes
|
||||
- 🚨 BREAKING: removed `base` part from `<sl-divider>` to simplify the styling API
|
||||
- Added experimental `<sl-split-panel>` component
|
||||
- Added the experimental `<sl-split-panel>` component
|
||||
- Added `focus()` and `blur()` methods to `<sl-select>` [#625](https://github.com/shoelace-style/shoelace/pull/625)
|
||||
- Fixed a bug where setting `tooltipFormatter` on `<sl-range>` in JSX causes React@experimental to error out
|
||||
- Fixed a bug where clicking on a slotted icon in `<sl-button>` wouldn't submit forms [#626](https://github.com/shoelace-style/shoelace/issues/626)
|
||||
@@ -122,7 +662,7 @@ Thank you for your help and patience with testing Shoelace. I promise, we're not
|
||||
- Improved a11y of the scroll buttons in `<sl-tab-group>`
|
||||
- Improved a11y of the close button in `<sl-tab>`
|
||||
- Improved a11y of `<sl-tab-panel>` by removing an invalid `aria-selected` attribute [#579](https://github.com/shoelace-style/shoelace/issues/579)
|
||||
- Improved a11y of `<sl-icon>` by not using a variation of the `name` attribute for labels (use the `label` prop instead)
|
||||
- Improved a11y of `<sl-icon>` by not using a variation of the `name` attribute for labels (use the `label` attribute instead)
|
||||
- Moved `role` from the shadow root to the host element in `<sl-menu>`
|
||||
- Removed redundant `role="menu"` in `<sl-dropdown>`
|
||||
- Slightly faster animations for showing and hiding `<sl-dropdown>`
|
||||
@@ -184,7 +724,7 @@ This release is the second attempt at unbundling dependencies. This will be a br
|
||||
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>`
|
||||
- Added the `disabled` attribute 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
|
||||
|
||||
|
||||