Create a show / hide transition with Tailwind and Next - css

Is there any way to create a display or visibility transition using Tailwind and a conditional code at Next? I'm trying something like this, what I would like to achieve is a smooth fade in effect when the backend returns a exception message under the responseError object (using Context in Next) but there's no transition effect at all:
{
responseError ?
<span className={`${ responseError ? "visible transition-all ease-in-out delay-150 duration-300" : "invisible"} pt-4 text-sm text-red-500 font-['Poppins'] font-bold `}>
username or password incorrect
</span>
: null
}
or
{
responseError ?
<span className={`${ responseError ? "visible transition-all ease-in-out delay-150 duration-300" : "invisible"} pt-4 text-sm text-red-500 font-['Poppins'] font-bold `}>
{ responseError.message }
</span>
: null
}

Use opacity instead of visibility.
This stack overflow answer goes over a similar issue you are facing. In short, the visibility property has two possible values: visible or hidden. On the other hand, opacity can be between 0 and 1, so proper keyframes can be applied when using the transition property.
As a side note, I noticed you are checking for the responseError twice, once to render the <span> and again to apply tailwind classes. This will cause your fade in transition to only work when fading in because the <span> is only rendered when responseError exists. Instead, try something like this:
<span className={`${ responseError ? "opacity-100" : "opacity-0"} transition-opacity ease-in-out delay-150 duration-300 pt-4 text-sm text-red-500 font-['Poppins'] font-bold `}>
{ responseError ? responseError.message : '' }
</span>

Related

Tailwind css break-word not working in input field

Now my reactjs input field looked like this.
As you can see the text just keeps going straight and not moving down to the next line. How do I solve this? Here is my code for this input field.
<input className="bg-slate-50 text-main-blue border border-gray-300 drop-shadow-lg text-sm rounded-md my-5 block w-full p-2.5 whitespace-normal word-break:break-word" type="text" name="eventName" placeholder="Event Name" required onChange={event => setEventName(event.target.value)} value={eventName}/>
Change word-break:break-word to break-words
There is no class word-break:break-word in tailwind-css
This is actually work of textarea not text, Use type = "textarea" to get the desired result .
Tailwind Work around:
Use contenteditable prop of div and use break-words property
Code:
<div class="m-4 max-w-full overflow-y-hidden break-words border border-solid border-black text-4xl" contenteditable="true"></div>
Output:
Like : Tailwind Play

Image slider - While rendering img using {#each} by clicking buttons that change visible image, transitions and animations don't work

It's my first time asking question on stack overflow and from what I'm feeling I'm missing something very small or don't understand the logic correctly. I show images by {#each} block and slice by adding and subtracting from variables: selected, prevSelected. From what I understood in svelte tutorial on transitions it should work (https://svelte.dev/tutorial/local-transitions), for some reason images just show up in a blink without transitions. I tried remaking the logic in the function, timeouts and restarting and none seemed working.
Please explain to me what I'am missing.
Sorry for little knowledge, picked up svelte as my first frontend framework to learn yesterday.
I'm using the latest sveltekit version.
Edit: I'm also using latest tailwind css.
<script>
import { slide,fade } from 'svelte/transition';
let images = [
{
Index: 0,
src: 'src/images/img2.jpeg',
alt: 'znaki ewakuacyjne',
class: 'show'
},
{
Index: 1,
src: 'src/images/img3.jpeg',
alt: 'buty',
class: ''
},
{
Index: 2,
src: 'src/images/img4.jpeg',
alt: 'znaki informacyjne',
class: ''
}
];
let selected = 1;
let prevSelected = 0;
let shown=true;
function handleClick() {
if (selected == 3) {
return;
}
prevSelected = selected;
selected += 1;
}
function handleBack() {
if (selected == 1) {
return;
}
prevSelected -= 1;
selected -= 1;
}
</script>
<h3 class="text-center font-semibold text-xl m-3">Galeria</h3>
<div class="image-gallery flex flex-col justify-center items-center">
{#if shown}
{#each images.slice(prevSelected, selected) as img}
<img
transition:fade
src={img.src}
alt={img.alt}
class="h-80 w-50 rounded-lg"
/>
{/each}
{/if}
<div class="flex flex-row gap-12">
<button
on:click={handleBack}
type="button"
class="text-white bg-red-700 hover:bg-red-800 focus:outline-none focus:ring-4 focus:ring-red-300 font-medium rounded-full text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900 m-3"
>⬅️</button
>
<button
on:click={handleClick}
type="button"
class="text-white bg-blue-700 hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300 font-medium rounded-full text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 m-3"
>➡️</button
>
</div>
</div>
<style lang="scss">
</style>
You need to key the {#each} (see docs), e.g.
{#each images.slice(prevSelected, selected) as img (img)}
Otherwise the same component is reused and only its properties get changed.
Note that you may have to adjust the layout to make both images take the same place, otherwise the image that fades out will push away the one that fades in.
By the way, if you only ever show one image, you do not need an each at all, only {#key} and the index.
{#key selected}
<img
transition:fade
src={images[selected - 1].src}
alt={images[selected - 1].alt}
class="h-80 w-50 rounded-lg"
/>
{/key}
Could be simplified even further via a reactive statement that always resolves to images[selected - 1]. prevSelected is redundant and I would change the logic of selected to be 0-based instead of 1-based.

Tailwindcss box shadow not showing

I'm trying to use Tailwindcss in a React project where I am replicating the Star Wars website mobile menu. However, the box shadow that I am adding to the hamburger icon segments is not showing up when the nav drawer is opened.
Link to sandbox: https://play.tailwindcss.com/upmiAWTcso
index.js:
const toggleDrawer = (event) => {
document.querySelector("#drawer").classList.toggle("left-[-100%]");
document.querySelector("#drawer").classList.toggle("left-0");
document.querySelector("#bar-1").classList.toggle("hidden");
document.querySelector("#bar-2").classList.toggle("active-2");
document.querySelector("#bar-3").classList.toggle("active-3");
};
<div
onClick={toggleDrawer}
className="h-full flex flex-col justify-center items-center space-y-[8px]"
>
<span
id="bar-1"
className="block h-[2px] w-[30px] border-zinc-500 border-l-[4px] border-r-[20px] rounded-full transition-all duration-300"
></span>
<span
id="bar-2"
className="block h-[2px] w-[30px] border-zinc-500 shadow-md border-l-[20px] border-r-[4px] rounded-full origin-bottom-right transition-all duration-300"
></span>
<span
id="bar-3"
className="block h-[2px] w-[30px] border-zinc-500 shadow-md border-l-[4px] border-r-[20px] rounded-full origin-bottom-left transition-all duration-300"
></span>
</div>;
global.css:
#layer components {
.active-2 {
#apply
rotate-45
-translate-x-2
translate-y-[530%]
!w-[34px]
!border-l-[25px]
!border-r-[5px]
!border-white
shadow-[#d50032];
}
.active-3 {
#apply
-rotate-45
translate-x-1
!w-[34px]
!border-l-[5px]
!border-r-[25px]
!border-white
shadow-[#106ae0] !important;
}
}
You only have a shadow color declared. You also need a shadow size like shadow-md.
Here's an example on Tailwind Play showing the difference https://play.tailwindcss.com/gxG7cir5EQ
You are applying !important the wrong way. To add !important to a tailwind class just add ! add the start like this:
#layer components {
.active-2 {
#apply
rotate-45
-translate-x-2
translate-y-[530%]
w-[34px]
border-l-[25px]
border-r-[5px]
border-white
!shadow-[#d50032];
}
.active-3 {
#apply
-rotate-45
translate-x-1
w-[34px]
border-l-[5px]
border-r-[25px]
border-white
!shadow-[#106ae0];
}
}
It's an browser support issue
The problem is an combination of border-radius and box-shadow if you open
https://play.tailwindcss.com/gxG7cir5EQ in opera it doesn't work but in Chrome for example it does. If you remove the rounded corners it shows the shadow.

Tailwind animation on display

I am trying to learn how to use animation with Tailwind. The animation that I am trying hopelessly to make is:
Entering: "duration-200 ease-out"
From: "opacity-0 scale-95"
To: "opacity-100 scale-100"
Leaving: "duration-100 ease-in"
From: "opacity-100 scale-100"
To: "opacity-0 scale-95"
The element I'm trying to animate is:
<div class="absolute top-0 inset-x-0 p-2 duration-200 ease-out transition transform origin-top-right">
Now I'm not quite sure exactly what to do since this animation should only run as soon as it is displayed I've attempted:
<div class="absolute top-0 inset-x-0 p-2 duration-200
ease-out transition transform origin-top-right" style="${this.showMenu ? '' : 'display:none'}">
However this doesn't really give me an animated result. What can I try next?
Using dynamic style is not usually recommeded. Instead you could use && operator and display only if the showMenu is set to true
{ this.showMenu && <div class="absolute top-0 inset-x-0 p-2 duration-200
ease-out transition transform origin-top-right"> }

Tailwind css don't show hover state when input is in focus

On the following div:
<div className='border border-gray-400
text-gray-600
hover:border-gray-600
focus:border-green-500
focus-within:border-green-500'>
I want the hover state not to happen when an element is an in-focus state. How can I make it so?
Thanks!
Use the css :not selector, e.g. hover(:not focus):border-gray-600
Try this, border need to define width, so in this example I gave just 2 when it hovered.
check official Doc
<div className='hover:border-2 border-gray-400 text-gray-600
hover:border-gray-600
focus:border-green-500 focus-within:border-green-500'>
export const FramelessInput = ({ name }) => {
const [focused, setFocused] = useState(false);
return (
<div
className={classNames(
'w-[200px] rounded-sm border border-transparent text-gray-600 focus-within:border-green-500',
!focused && 'hover:border-gray-600'
)}
>
<input
type="text"
placeholder={name}
onFocus={(e) => setFocused(true)}
onBlur={(e) => setFocused(false)}
className="block text-sm leading-4 font-sans p-3 h-10 focus:outline-none"
/>
</div>
);
};
Try use property "ring"
<div className='border border-gray-400
text-gray-600
ring-green-500
focus-within:ring-2'>

Resources