I want to display a spinner before loading the react component in Astro - astrojs

How can I display a spinner or Skeleton CSS before loading the component
I use client-only for react components in Astro page
my spinner code
<div role="status">
<svg aria-hidden="true" class="w-8 h-8 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
</svg>
<span class="sr-only">Loading...</span>
my component
<ToolsDescription client:load/>

Solution
place both components "Spinner" and "ClientComponent" and give them default classes so that only the Spinner is visible.
then once the client component loads, in the client js script, you hide the spinner and show the Client Component by toggling the display property of their style
Simplified example
For the sake of example simplification, I placed the script in the same file, but you can place the styles display toggling once your client component is ready and adapt the proper selector
the <script> will execute on client side
Here how it would look in the .astro component
<>
<div class="spinner">
<Spinner/>
</div>
<div class="mycomponent">
<ClientComponent client:load/>
</div>
</>
<style>
.spinner{
display:block;
}
.card {
display: none;
}
</style>
<script>
document.querySelector(".card").style.display = "block"
document.querySelector(".spinner").style.display = "none"
</script>
Reference Example
Here a reference to a complete example showing the "Spinner" pattern while waiting for client side js component which is intentionally deferred 2 seconds for demo purpose
https://github.com/MicroWebStacks/astro-examples#09_dynamic-imports

Related

Correct way of changing svg image in svelte

In svelte, I have the option of switching between two images, or using css to change the color of the svg image. Which is "better/ best practice"? (also we use tailwind css).
<div class='w-2 h-2'>
{#if condition}
<Image1/> <--white image
{:else}
<Image2/> <--red image
{/if}
</div>
OR
If the default image is white, this passes red to it. The color variable would be text-red or text-white based on some condition.
<div class='w-2 h-2 ${color}'>
<Image1/>
</div>
Svelte's reactivity can take over colour conditions via CSS. We can avoid the if condition.
App.svelte
<script>
import Icon from "./Icon.svelte"
let stroke = "green";
function changeStroke(){
stroke = "red"
}
</script>
<Icon {stroke}/>
<button on:click={changeStroke}>Change</button>
Icon.svelte
<script>
export let stroke = 'white';
</script>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" {stroke} stroke-width="2">
<!-- Big SVG -->
</svg>
See this example REPL

Next js <Image/> component doesnt overflow while making carousel like regular <img> tag

when I use one image inside the container carousel div the image occupies 100vw. But when I add multiple images inside the container it was supposed to be overflown but rather images get shrunk and act weird. I tried the same thing with regular HTML tag and it works perfectly.
My question is how to make a carousel in Next js without using any library where on each slide there is only one Image covering 100% view width.
#code
<div className="embla" >
<div className="embla__container">
<Product_3
src="/lifestyle/14.jpg"
details="Discover the support you need to power through gaming marathons."
name="CHAIRS"
/>
</div>
</div>
#CSS part
.embla {
overflow: hidden;
}
.embla__container {
display: flex;
}
.embla__slide {
width:100vw;
height:10rem;
display: flex;
flex-shrink: none;
}
#Product_3 component
function Product_3({ src, name, details }) {
return (
<div className="product_3">
<div className="product3_img">
<Image src={src} layout="fill" />
</div>
<div className="product2_details">
<h3 className="product2_name">{name}</h3>
<div style={{fontSize:"2rem",color:"#999999",margin:"1rem 0 2rem 0"}}>
{details}.
</div>
<button className="learn_more product2_btn">Learn More {">"}</button>
</div>
</div>
);
}

Image mask in Mozilla + foreignObject + Ajax

http://continent-news.info/page_20.html
In the left column of news, they opens in a popup window, and loaded with Ajax.
<div class="ukraine_mask1">
<svg height="116px" width="142px">
<defs>
<mask id="ukraine_mask1" maskContentUnits="userSpaceOnUse" maskUnits="userSpaceOnUse">
<image xlink:href="mask/ukraine_mask1.png" height="116px" width="142px">
</mask>
</defs>
<foreignObject class="recov_ukraine_mask1" style="mask: url(#ukraine_mask1);" height="100%" width="100%">
<div class="element_mask mask1_ukraine">
<img src="../inf_images/small/7812_8926.jpeg">
</div>
</foreignObject>
</svg>
</div>
problem in Mozilla:
Some news used map with a mask, the first time the mask works well. But if I click another news with mask, they does not want to re-use mask... =( If I press again the first news, it will work.
The second time, does not want to re-use =(
If in firebug disable / apply
mask: url ("# ukraine_mask1")
in
foreignObject class = "recov_ukraine_mask1"
it will work again ...
Maybe someone have an idea how to solve this problem?
I tried to add a simple style in СSS, but does not help = (

onload image go from 0 width to 100px width with easing

I need to "slide in" a (background-)image in a div.
When I load the page, some div with a bg image or image inside it (and overflow?) needs to go from invisible/width=0 to 100px width. This needs to ease in.
Can anyone please help me out with the js?
<div style="overflow:hidden; width:100px; height:40px;">
<img src="someimg.png" height="40" width="100" />
</div>
This uses jquery on document ready.. For easing can use the standard jquery 'linear' but I included the jquery.easing plugin where you can have different easing options.
http://jsfiddle.net/DyW7M/1/
$(document).ready(function () {
$('#makeitlong').animate({ width: '400'}, 2000, 'linear');
});​

jqMobi - Scroller div inside Carousel?

So, I'm putting together the framework for a web app that allows people to swipe horizontally between views. I'm looking for a layout similar to that of ubersocial, an app for android. I've tried a few different frameworks over the last couple of days (including the beginnings of a custom framework, which won't work due to poor overflow:auto support on mobile). JqMobi seems to get me closest.
Here's some code:
<script>
//jqMobi & jqUI scripts omitted for brevity
var carousel;
var scroller;
function init_carousel ()
{
carousel = $("#carousel").carousel({
preventDefaults: false
});
scroller = $('newContainer').scroller();
}
window.addEventListener("load", init_carousel, false);
</script>
<div id="jQUi">
<div id="header"></div>
<div id="content">
<!--scrolling="no" because I don't want the whole carousel to move-->
<div title="Main" id="main" class="panel" data-tab="navbar_home" scrolling="no">
<div id="carousel" style="height:100%;width:100%;">
<div id="View1" class="MainView" style="background: yellow;">
<div id="newContainer" style="width: 100%;height: 100%; overflow: auto;>
<!--Lots of Content-->
</div>
</div>
<div id="View2" class="MainView" style="background: green;"></div>
<div id="View3" class="MainView" style="background: blue;"></div>
<div id="View4" class="MainView" style="background: pink;"></div>
<div id="View5" class="MainView" style="background: orange;"></div>
</div>
</div>
</div>
</div>
So I've got my carousel working for all devices and I was able to get perfect functionality in iOS 5. However, Android (2.2, 2.3, & 4.0) is not giving me a scrollable div for my .MainView elements, nor are older iOS devices. The best I can get is the carousel on a panel that scrolls, but the elements within the panel won't scroll together. This makes me wonder if the iOS 5 success I've had was just support for overflow:auto.
Anyway, I've looked at the following docs:
jqMobi CheatSheet = (http://www.appmobi.com/amdocs/lib/jqMobi_Cheat.pdf?r=9170)
jqMobi Kitchen Sink = (http://jqmobi.com/testdrive/#webslider)
jqMobi API Doc = (http://api.jqmobi.com/#jqUi)
But I've had trouble really getting the answer I'm looking for. Using the documented methods, I can't really seem to get anywhere. It seems like if I could get an independently scrollable div into a .MainView element without breaking the carousel, I'd be good to go. Suggestions?
/*****************FIXED*****************/
After a tangled web of confusion and frustration, I eventually got it to work by adding a second buffer to the .MainDiv elements so that the scroller doesn't affect the carousel.
I also had a bad run-in with iOS 5 (which, as you may recall, worked before) which probably could have been fixed by simply adding overflow:auto to the .MainView elements and giving them a fixed height. I tried disabling nativeTouchScroll first, and the scrolling is actually pretty good, so I'll stick with that instead of adding a browser detect conditional.
<script>
//Native touch disabled or iOS 5 breaks.
$.feat.nativeTouchScroll = false;
var carousel;
//var scroller;
function init_carousel ()
{
carousel = $("#carousel").carousel({
preventDefaults: false
});
}
$.ui.ready(init_carousel);
var scroller;
$.ui.ready(function ()
{
//Fetch the scroller from cache
scroller = $("#containerContainer").scroller();
});
</script>
<style>
.MainView
{
height: 100%;
overflow: hidden;
}
</style>
<div id="carousel" style="height:100%;width:100%;">
<div id="View1" class="MainView" style="background: yellow;">
<div id="containerContainer"><div id="newContainer"></div></div>
</div>
<div id="View2" class="MainView" style="background: green;"></div>
<div id="View3" class="MainView" style="background: blue;"></div>
<div id="View4" class="MainView" style="background: pink;"></div>
<div id="View5" class="MainView" style="background: orange;"></div>
</div>
Posted in the forums at appMobi - but we are a US based company in the Eastern Standard Time Zone - so we were asleep while you were working on this...glad you wrote the following :)
Not that anyone seems to care

Resources