Applying Tailwind overflow behavior to only one child element - javascript

I'm using Tailwind to style a React component called "BlurImage" which displays an image by default and then on hover removes the image and displays a button at the bottom of the component and a text box at the top that has overflow-y-auto behavior to allow for scrolling if the text grows too long.
By default, the overflow responsibility is given to the body as discussed here and so I need to give the parent top-level div of BlurImage overflow as well. This causes both the text and the button to be scrollable. Is there a way to avoid having the button scroll?
This seems like it should be a common situation - I can imagine using this concept to write self-contained components that have a header/footer and some scrollable content as well. Unfortunately, I can't find much addressing this in the Tailwind docs or online.
I appreciate any suggestions! Here is the component code that I currently have:
import Image from 'next/image';
import cn from 'classnames';
import { useState } from 'react';
import { ImageInfo } from '../../types/images';
import Button from './button';
import { useRouter } from 'next/router';
type BlurImageProps = {
image: ImageInfo;
};
const BlurImage = ({ image }: BlurImageProps): JSX.Element => {
const [isLoading, setLoading] = useState(true);
return (
<div className="group shrink-0 h-40 w-40 relative aspect-w-1 aspect-h-1 overflow-hidden rounded-lg xl:aspect-w-7 xl:aspect-h-8 drop-shadow-xl bg-black">
<Image
alt=""
src={image.url}
width={512}
height={512}
className={cn(
'flex h-full duration-700 ease-in-out group-hover:opacity-20',
{
'scale-110 blur-2xl grayscale': isLoading,
'scale-100 blur-0 grayscale-0': !isLoading,
},
)}
onLoadingComplete={() => setLoading(false)}
/>
{!isLoading && (
<div className="absolute bottom-0 left-0 overflow-y-scroll items-center justify-center w-full h-full align-middle text-center px-2 opacity-0 duration-700 ease-in-out group-hover:opacity-100">
<a href={image.url}>
<p className="text-base text-white mb-2">
{image.prompt}
</p>
</a>
<Button
className="flex-shrink-0 px-2 py-2 text-sm font-bold text-white rounded bg-green-500"
type="button"
text="click me"
isSubmit={true}
onClick={() => console.log("clicked")}
/>
</div>
)}
</div>
);
};
export default BlurImage;

Related

NextJs nesting a component into another (not FC)

I built a module, then broke it up into components and trying to put it back together.
The components work. Some components go inside the div of another component.
I have tried putting them into a div scaffold, but i was then writing more css to bring the module together.
I thought we just do this:
<CompOne>
<CompTwo />
</CompOne>
This gives an error:
Type '{ children: Element; }' has no properties in common with type 'IntrinsicAttributes'.
So maybe the above is write i need to typescript? sorry couldnt find a working example on this.
function WaldoEye() {
return (
<WaldoEyeball>
<WaldoRetina/>
</WaldoEyeball>
)
}
export default WaldoEye
function WaldoEyeball() {
return (
<div className="
flex
relative
items-center
opacity-90
w-40 h-40
rounded-full
shadow-[inset_0_-15px_15px_-3px_rgba(5,10,255,0.3)]
bg-gradient-to-r
from-slate-50
via-slate-100
to-slate-50
">
<div className="
absolute
flex
items-center
opacity-90
w-40 h-40
rounded-full
shadow-[0_60px_55px_-25px_rgba(255,255,255,0.4)]
">
</div>
</div>
)
}
export default WaldoEyeball
function WaldoRetina() {
return (
<>
<div className="
flex
items-center
relative
mx-auto
w-16
h-16
rounded-full
border-2
border-sky-500
bg-gradient-radial
from-cyan-500
via-sky-300
to-sky-500
">
</div>
</>
)
}
export default WaldoRetina
So maybe the above is write i need to typescript? sorry couldnt find a working example on this.
Currently the WaldoEyeball component doesn't expect any children. You will need to adjust the props in the WaldoEyeball component so it accepts children.
const WaldoEyeball: FC = ({ children }) => {
return (
<div className="
flex
relative
items-center
opacity-90
w-40 h-40
rounded-full
shadow-[inset_0_-15px_15px_-3px_rgba(5,10,255,0.3)]
bg-gradient-to-r
from-slate-50
via-slate-100
to-slate-50
">
<div className="
absolute
flex
items-center
opacity-90
w-40 h-40
rounded-full
shadow-[0_60px_55px_-25px_rgba(255,255,255,0.4)]
">
{children} // drop children somewhere to render it
</div>
</div>
);
}

How can I setState of an Image component with useState hook when the html DOMelement's classlist contains the string "dark"?

I'm new to React and I wish building a portfolio website.
I need an image to be changed when a button is being toggled to lightMode (this button is in another component called Switcher).
I'm using tailwind so when the button is toggled the html DOMelement's classlist is set to "dark", and reset to ""(empty string) when toggling back...
Inside a a component called "Home" the image should switch every time the button is clicked.
So to get it switching I'm testing if classlist of html DOMelement contains "dark" like so:
Home.js
import React, {useEffect, useRef, useState} from 'react';
import {AiFillGithub} from "react-icons/ai";
import {SiFacebook, SiCodepen, SiLinkedin} from "react-icons/si";
import darkImg from "../images/bg.jpg";
import lightImg from "../images/bg-light.jpg";
function Home(props) {
const html = document.querySelector("html");
const [imgg, setImgg] = useState(<img className="ml-14" src={darkImg} alt="home"/>);
useEffect(() => {
if (html.classList.contains("dark")){
setImgg(<img className="ml-14" src={lightImg} alt="home"/>);
}
else {
setImgg(<img className="ml-14" src={darkImg} alt="home"/>);
}
})
return (
<div className="h-full mt-[2px] flex-row">
<Img path={imgg}/>
<div className="font-arvo tracking-wider text-center text-7xl">PORTFOLIO</div>
<div className="text-center text-4xl">Software Engineer</div>
<div className="flex flex-row items-center justify-center mt-5 space-x-7">
<AiFillGithub className="social-icons" size="30"/>
<SiFacebook className="social-icons" size="30"/>
<SiCodepen className="social-icons" size="30"/>
<SiLinkedin className="social-icons" size="30"/>
</div>
</div>
);
}
const Img = (props) => {
return props.path;
}
export default Home;
Switcher.js
import React, {useEffect, useRef, useState} from 'react';
import {HiLightBulb} from "react-icons/hi";
import {MdDarkMode} from "react-icons/md";
function Switcher(props) {
const [foo, setFoo] = useState(
{
decor: "flex flex-row w-6 h-6 md:w-7 md:h-7 relative rounded-full transition duration-500 transform bg-two -translate-x-2 pt-1 pl-0.5 text-black",
icon: <MdDarkMode size="20"/>
}
);
const [isDark, setIsDark] = useState(true);
let Style1 = "flex flex-row w-6 h-6 md:w-7 md:h-7 relative rounded-full transition duration-500 transform bg-two -translate-x-2 pt-1 pl-0.5 text-black dark:bg-nine dark:text-seven";
let Style2 = "flex flex-row w-6 h-6 md:w-7 md:h-7 relative rounded-full transition duration-500 transform bg-two translate-x-full pt-1 pl-0.5 text-black dark:bg-nine dark:text-seven";
let icon1 = <MdDarkMode size="20"/>;
let icon2 = <HiLightBulb size="20"/>;
const html = document.querySelector("html");
function switchTheme() {
setIsDark(!isDark);
if(!isDark){
html.classList.add("dark");
setFoo({decor: Style2, icon: icon2});
}else{
html.classList.remove("dark");
setFoo({decor: Style1, icon: icon1});
}
}
return (
<Toggler decor={foo.decor} icon={foo.icon} onToggle={switchTheme}/>
);
}
const Toggler = (props) => {
return (
<button onClick={props.onToggle} className="absolute top-9 right-10 w-14 h-5 rounded-2xl flex items-center transition duration-300 focus:outline-none shadow bg-four dark:bg-white">
<div id="switch-toggle" className={props.decor}>
{props.icon}
</div>
</button>
);
};
export default Switcher;
On the browser's console I got this warning saying :
Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
at Home (http://localhost:3000/main.428ce48dfed5fa0fec8a.hot-update.js:38:74)
at div
at App
I can see the image switching on Toggle but i don't think it's a clean use of hooks in Home.js
Can Somebody provide any ideas... Thanks.

Issue with Changing state from 1 React Component inside of another React component

I've been trying to change the 'ModalOn' state which is created inside of the medCardSong.js file, and I've been trying to change that state from inside of the 'SongModal.js' file, which is a child component inside of medCardSong.js.
I've inputted the changeState function 'SetModalOn' as a prop to the SongModal.js component, and i've tried changing the state through that.
Here's medCardSong.js:
import React, { useEffect } from 'react';
import { useState} from 'react';
import SongModal from '../modals/SongModal';
function MediumCardSong(props) {
const [ModalOn, SetModalOn] = useState(false);
function killme() {
SetModalOn(false);
console.log(7)
}
console.log(ModalOn)
return (
<div className={" flex flex-col m-2 overflow-hidden duration-300 w-52 " + (ModalOn
? 'transition-none' : 'hover:scale-105 transition-all')} onClick={() =>
{SetModalOn(true);}}>
<img className='object-cover rounded-3xl'
src="https://i0.wp.com/coolhunting.com/wp-content/uploads/2022/07/steve-lacy-
bad-habit.jpg?fit=586%2C586&ssl=1" alt="" />
<div className='pb-2'>
<div className='flex'>
<div className='px-2 pt-2 text-2xl font-bold text-gray-400'>#1</div>
<div className='pl-3 text-xl pt-2 text-white'>Mercury</div>
</div>
<div className='text-left pl-5 text-gray-500'>Steve Lacy</div>
</div>
{ModalOn && <SongModal CloseModal={killme} />}
</div>
);
}
export default MediumCardSong;
and here's SongModal.js:
import React from 'react'
function SongModal(props) {
// setTimeout(() => {props.CloseModal(false)}, 1000)
return (
<div className="bg-neutral-800 bg-opacity-60 fixed inset-0 z-50 backdrop-blur-sm">
<div className="flex h-screen justify-center items-center">
<div className="justify-center bg-neutral-700 py-12 px-24 border-4 border-
pearmint rounded-xl text-xl text-white" >
<button className='text-3xl text-white pr-24 pb-24'
onClick={() => {props.CloseModal()}} >X</button>
sad
</div>
</div>
</div>
)
};
export default SongModal;
The imported CloseModal function works as intended when it's applied outside of the jsx. For example, the "SetTimeOut" piece of code would work properly if it's uncommmented. However this doesn't happen when I call "CloseModal" inside of an Onclick event-handler, such as the call I did for the 'x' Button.
I've also used console.log to see if the button has been registering the clicks I make and it has been. So I'm confused as to why the props.CloseModal function does not work as intended inside the OnClick event listener. Please give advice if you can.
try to call it inside of a hook
function SongModal(props) {
const close = () => {
props.CloseModal()
}
return (
<div>
<button onClick={close}>Close Btn</button>
</div>
)
};
also check the following acritical
link

Prevent react from restarting the css animation on route change

In my react app I have a file called SecondaryLayout.js
const SecondaryLayout = ({children, className, ...rest}) => {
return (
<>
<Sidebar />
<main className={['seconday_layout__container', className].join('')} {...rest}>
{children}
</main>
</>
);
};
Sidebar.js:
const Sidebar = () => {
const {user} = useSelector(state => state.auth);
return (
<div className="bg-white py-4 px-2 fixed h-screen shadow-lg secondary_layout__sidebar">
<div className="h-full flex flex-col justify-between items-center">
<Link to="/"><h1 className="font-pacifico text-white px-2.5 py-1 bg-blue-700 rounded-full text-xl -mb-5">P</h1></Link>
<div className="flex flex-col space-y-2">
<NavLink to="/user/dashboard" className="px-2.5 py-1.5 rounded-lg shadow-md" activeClassName="bg-blue-700 shadow-lg text-white"><TemplateIcon className="inline w-4 h-4 -mt-1"/></NavLink>
<NavLink to="/user/listings" className="px-2.5 py-1.5 rounded-lg shadow-md" activeClassName="bg-blue-700 shadow-lg text-white"><ViewListIcon className="inline w-4 h-4 -mt-1"/></NavLink>
<NavLink to="/user/address" className="px-2.5 py-1.5 rounded-lg shadow-md" activeClassName="bg-blue-700 shadow-lg text-white"><LocationMarkerIcon className="inline w-4 h-4 -mt-1"/></NavLink>
<NavLink to="/user/profile" className="px-2.5 py-1.5 rounded-lg shadow-md" activeClassName="bg-blue-700 shadow-lg text-white"><CogIcon className="inline w-4 h-4 -mt-1"/></NavLink>
</div>
<Avatar name={user.username} image={user.image} />
</div>
</div>
);
};
The sidebar has a css animation, and 3 NavLinks, every time I click on a link, the css animation restarts, the behavior that I want is the sidebar to only fade in once, and stay fixed even when I click on a navlink, I tried to wrap my sidebar component with React.memo() but that didn't fix the issue
Edit:
Let's say the user navigates to /user/dashboard, or /user/profile, all these routes should always render the sidebar
Example
Dashboard.js
import React from 'react';
import { Helmet } from 'react-helmet';
import SecondaryLayout from '../../layouts/SecondaryLayout';
const Dashboard = () => {
return (
<SecondaryLayout>
<Helmet>
<title>My Dashboard</title>
</Helmet>
Dashboard
</SecondaryLayout>
);
};
export default Dashboard;
I think I managed to fix the issue, what I was doing is to wrap every component by the secondary layout, what I have done is to move the Secondary Layout to wrap around the route component itself, and not around the component being rendered by the route, i.e: <Route .... /></Route .... />

Collapsible Card Component tailwind

I'm trying to use tailwindcss to create a collapsible card component similar to the pre-made component in Material-UI (reference).
I'm new to tailwindcss and can't quite figure out how to make the transition smooth. I have toggled the card using state.
The I am having trouble with is underneath the 'Image' component.
import Image from "next/image";
import { useRouter } from "next/router";
import { useState } from "react";
import { ChevronDownIcon } from "#heroicons/react/solid";
const ProjectCard = ({
title,
descriptionStart,
descriptionFull,
link,
image,
}) => {
const router = useRouter();
const [readMore, setReadMore] = useState(false);
return (
<div className='relative shadow-md flex flex-col bg-white rounded-lg p-4 m-4 space-y-8'>
<h1>{title}</h1>
<Image
src={image}
alt={title}
height={100}
width={100}
objectFit='contain'
/>
<div className='transition-all duration-200 ease-in-out'>
<p>{descriptionStart}</p>
<p
className={` ${
readMore
? "inline-flex transition-all ease-in-out duration-150"
: " hidden transition-all ease-in-out duration-150"
} `}>
{descriptionFull}
</p>
</div>
<button
className='bg-gray-100 w-[150px] h-[30px] rounded-lg shadow-lg mx-auto'
onClick={() => router.push(`${link}`)}>
View Project
</button>
<button
onClick={() => setReadMore(!readMore)}
className='absolute bottom-[16px] right-[16px]'>
{readMore ? (
<ChevronDownIcon className='rotate-180 h-6 transition-all duration-150 ease-in' />
) : (
<ChevronDownIcon className='h-6 transition-all duration-150 ease-in' />
)}
</button>
</div>
);
};
export default ProjectCard;

Categories

Resources