Fishies 0.8.1
This commit is contained in:
commit
5821ce9f4d
76 changed files with 2198 additions and 0 deletions
54
src/loader.css
Normal file
54
src/loader.css
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* The Fishies loader: spinner, progress bar, and pictures that never paint half-loaded.
|
||||
Unlayered on purpose, so a surface's own layered image rules cannot put a waiting picture's
|
||||
pixels back on screen. See fx-image.ts and FishiesLoader.tsx. */
|
||||
|
||||
.fx-spinner {
|
||||
display: inline-grid; place-items: center; flex: none;
|
||||
width: var(--fx-size, 32px); height: var(--fx-size, 32px);
|
||||
filter: drop-shadow(0 4px 10px rgb(1 8 20 / 45%));
|
||||
}
|
||||
.fx-spinner > svg { display: block; width: 100%; height: 100%; }
|
||||
|
||||
.fx-progress {
|
||||
position: relative; display: block; overflow: hidden;
|
||||
width: min(280px, 100%); height: 10px; border-radius: 999px;
|
||||
border: 1px solid rgb(196 236 250 / 20%);
|
||||
background: linear-gradient(180deg, rgb(4 16 26 / 72%), rgb(12 38 56 / 72%));
|
||||
box-shadow: inset 0 1px 3px rgb(0 0 0 / 50%), 0 1px 0 rgb(255 255 255 / 7%);
|
||||
}
|
||||
.fx-progress > i {
|
||||
position: absolute; top: 1px; bottom: 1px; left: 1px;
|
||||
width: max(8px, calc((100% - 2px) * var(--fx-value, 0)));
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(180deg, var(--fx-gold-face), var(--fx-gold) 55%, var(--fx-gold-deep));
|
||||
box-shadow: 0 0 8px var(--fx-gold-rim);
|
||||
transition: width 320ms cubic-bezier(.2, .8, .2, 1);
|
||||
}
|
||||
/* The bubble riding the gold's leading edge. */
|
||||
.fx-progress > i::after {
|
||||
content: ''; position: absolute; top: 50%; right: 1px; width: 6px; height: 6px; margin-top: -3px;
|
||||
border-radius: 50%; background: radial-gradient(circle at 35% 35%, #fff, rgb(255 255 255 / 35%) 70%);
|
||||
}
|
||||
.fx-progress[data-indeterminate] > i { width: 34%; animation: fx-sweep 1.4s cubic-bezier(.45, 0, .55, 1) infinite; }
|
||||
@keyframes fx-sweep { from { transform: translateX(-105%); } to { transform: translateX(300%); } }
|
||||
|
||||
/* A waiting picture keeps its box, draws its pixels outside it (clipped, so never seen, however
|
||||
the file arrives), and shows the spinner on glass in their place. */
|
||||
:is(img, video)[data-fx='wait'], img[data-fx='error'] { object-position: -99999px -99999px !important; }
|
||||
:is(img, video)[data-fx='wait'] {
|
||||
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cstyle%3E.a%7Btransform-origin:24px 24px;animation:s 1.1s linear infinite%7D.b%7Bopacity:0;animation:u 1.8s ease-in infinite%7D.c%7Banimation-delay:.6s%7D.d%7Banimation-delay:1.2s%7D@keyframes s%7Bto%7Btransform:rotate(360deg)%7D%7D@keyframes u%7B0%25%7Bopacity:0;transform:translateY(7px)%7D30%25%7Bopacity:.95%7D100%25%7Bopacity:0;transform:translateY(-9px)%7D%7D@media (prefers-reduced-motion:reduce)%7B.a%7Banimation-duration:3.6s%7D.b%7Banimation:none;opacity:.8%7D%7D%3C/style%3E%3Ccircle cx='24' cy='24' r='21' fill='%230b2a3c' fill-opacity='.74' stroke='%23c4ecfa' stroke-opacity='.24'/%3E%3Ccircle cx='24' cy='24' r='16' fill='none' stroke='%23c4ecfa' stroke-opacity='.13' stroke-width='3'/%3E%3Ccircle class='a' cx='24' cy='24' r='16' fill='none' stroke='%23ffc46b' stroke-width='3' stroke-linecap='round' stroke-dasharray='25 76'/%3E%3Cg fill='%23dff6ff' fill-opacity='.16' stroke='%23dff6ff' stroke-width='1.1'%3E%3Ccircle class='b' cx='21.5' cy='26' r='2.7'/%3E%3Ccircle class='b c' cx='27' cy='27.5' r='1.9'/%3E%3Ccircle class='b d' cx='23.5' cy='30' r='1.3'/%3E%3C/g%3E%3C/svg%3E") center / clamp(12px, 36%, 40px) no-repeat,
|
||||
radial-gradient(closest-side, rgb(196 236 250 / 10%), rgb(196 236 250 / 4%)) !important;
|
||||
}
|
||||
img[data-fx='error'] { background: rgb(196 236 250 / 5%) !important; }
|
||||
:is(img, video)[data-fx='fade'] { animation: fx-in 240ms cubic-bezier(.2, .8, .2, 1); }
|
||||
@keyframes fx-in { from { opacity: 0; } }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.fx-progress > i { transition: none; }
|
||||
.fx-progress[data-indeterminate] > i { animation-duration: 4s; }
|
||||
:is(img, video)[data-fx='fade'] { animation: none; }
|
||||
:is(img, video)[data-fx='wait'] {
|
||||
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Ccircle cx='24' cy='24' r='21' fill='%230b2a3c' fill-opacity='.74' stroke='%23c4ecfa' stroke-opacity='.24'/%3E%3Ccircle cx='24' cy='24' r='16' fill='none' stroke='%23c4ecfa' stroke-opacity='.13' stroke-width='3'/%3E%3Ccircle class='a' cx='24' cy='24' r='16' fill='none' stroke='%23ffc46b' stroke-width='3' stroke-linecap='round' stroke-dasharray='25 76'/%3E%3Cg fill='%23dff6ff' fill-opacity='.16' stroke='%23dff6ff' stroke-width='1.1'%3E%3Ccircle class='b' cx='21.5' cy='26' r='2.7'/%3E%3Ccircle class='b c' cx='27' cy='27.5' r='1.9'/%3E%3Ccircle class='b d' cx='23.5' cy='30' r='1.3'/%3E%3C/g%3E%3C/svg%3E") center / clamp(12px, 36%, 40px) no-repeat,
|
||||
radial-gradient(closest-side, rgb(196 236 250 / 10%), rgb(196 236 250 / 4%)) !important;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue