Video_downloader/web/src/components/save/OmniboxIcon.svelte
2025-03-06 17:22:08 +06:00

99 lines
2.3 KiB
Svelte

<script lang="ts">
import IconLink from "@tabler/icons-svelte/IconLink.svelte";
import IconLoader2 from "@tabler/icons-svelte/IconLoader2.svelte";
export let loading: boolean;
export let animated = !!loading;
/*
initial spinner state is equal to loading state,
just so it's animated on init (or not).
on transition start, it overrides the value
to start spinning (to prevent zooming in with no spinning).
then, on transition end, when the spinner is hidden,
and if loading state is false, the class is removed
and the spinner doesn't spin in background while being invisible.
if loading state is true, then it will just stay spinning
(aka when it's visible and should be spinning).
the spin on transition start is needed for the whirlpool effect
of the link icon being sucked into the spinner.
this may be unnecessarily complicated but i think it looks neat.
*/
</script>
<div id="input-icons" class:loading>
<div
class="input-icon spinner-icon"
class:animated
on:transitionstart={() => {
animated = true;
}}
on:transitionend={() => {
animated = !!loading;
}}
>
<IconLoader2 />
</div>
<div class="input-icon link-icon">
<IconLink />
</div>
</div>
<style>
#input-icons {
display: flex;
position: relative;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
}
#input-icons :global(svg) {
stroke: var(--gray);
width: 18px;
height: 18px;
stroke-width: 2px;
}
.input-icon {
display: flex;
position: absolute;
transition:
transform 0.25s,
opacity 0.25s;
}
.link-icon {
transform: none;
opacity: 1;
}
.spinner-icon {
transform: scale(0.4);
opacity: 0;
}
.spinner-icon.animated :global(svg) {
animation: spinner 0.7s infinite linear;
}
.loading .link-icon :global(svg) {
animation: spinner 0.7s linear;
}
.loading .link-icon {
transform: scale(0.4);
opacity: 0;
}
.loading .spinner-icon {
transform: none;
opacity: 1;
}
</style>